aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/maps
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/maps')
-rw-r--r--drivers/mtd/maps/Kconfig663
-rw-r--r--drivers/mtd/maps/Makefile73
-rw-r--r--drivers/mtd/maps/amd76xrom.c332
-rw-r--r--drivers/mtd/maps/arctic-mtd.c135
-rw-r--r--drivers/mtd/maps/autcpu12-nvram.c127
-rw-r--r--drivers/mtd/maps/bast-flash.c227
-rw-r--r--drivers/mtd/maps/beech-mtd.c112
-rw-r--r--drivers/mtd/maps/cdb89712.c268
-rw-r--r--drivers/mtd/maps/ceiva.c350
-rw-r--r--drivers/mtd/maps/cfi_flagadm.c139
-rw-r--r--drivers/mtd/maps/cstm_mips_ixx.c270
-rw-r--r--drivers/mtd/maps/db1550-flash.c187
-rw-r--r--drivers/mtd/maps/db1x00-flash.c226
-rw-r--r--drivers/mtd/maps/dbox2-flash.c126
-rw-r--r--drivers/mtd/maps/dc21285.c253
-rw-r--r--drivers/mtd/maps/dilnetpc.c495
-rw-r--r--drivers/mtd/maps/dmv182.c149
-rw-r--r--drivers/mtd/maps/ebony.c163
-rw-r--r--drivers/mtd/maps/edb7312.c147
-rw-r--r--drivers/mtd/maps/elan-104nc.c228
-rw-r--r--drivers/mtd/maps/epxa10db-flash.c176
-rw-r--r--drivers/mtd/maps/fortunet.c271
-rw-r--r--drivers/mtd/maps/h720x-flash.c144
-rw-r--r--drivers/mtd/maps/ichxrom.c383
-rw-r--r--drivers/mtd/maps/impa7.c161
-rw-r--r--drivers/mtd/maps/integrator-flash.c217
-rw-r--r--drivers/mtd/maps/ipaq-flash.c464
-rw-r--r--drivers/mtd/maps/iq80310.c119
-rw-r--r--drivers/mtd/maps/ixp2000.c280
-rw-r--r--drivers/mtd/maps/ixp4xx.c259
-rw-r--r--drivers/mtd/maps/l440gx.c157
-rw-r--r--drivers/mtd/maps/lasat.c102
-rw-r--r--drivers/mtd/maps/lubbock-flash.c168
-rw-r--r--drivers/mtd/maps/map_funcs.c44
-rw-r--r--drivers/mtd/maps/mbx860.c100
-rw-r--r--drivers/mtd/maps/mpc1211.c81
-rw-r--r--drivers/mtd/maps/netsc520.c140
-rw-r--r--drivers/mtd/maps/nettel.c496
-rw-r--r--drivers/mtd/maps/ocelot.c175
-rw-r--r--drivers/mtd/maps/ocotea.c154
-rw-r--r--drivers/mtd/maps/octagon-5066.c248
-rw-r--r--drivers/mtd/maps/omap-toto-flash.c137
-rw-r--r--drivers/mtd/maps/pb1550-flash.c203
-rw-r--r--drivers/mtd/maps/pb1xxx-flash.c178
-rw-r--r--drivers/mtd/maps/pci.c388
-rw-r--r--drivers/mtd/maps/pcmciamtd.c860
-rw-r--r--drivers/mtd/maps/physmap.c125
-rw-r--r--drivers/mtd/maps/pnc2000.c93
-rw-r--r--drivers/mtd/maps/redwood.c169
-rw-r--r--drivers/mtd/maps/rpxlite.c66
-rw-r--r--drivers/mtd/maps/sa1100-flash.c453
-rw-r--r--drivers/mtd/maps/sbc8240.c247
-rw-r--r--drivers/mtd/maps/sbc_gxx.c239
-rw-r--r--drivers/mtd/maps/sc520cdp.c304
-rw-r--r--drivers/mtd/maps/scb2_flash.c256
-rw-r--r--drivers/mtd/maps/scx200_docflash.c233
-rw-r--r--drivers/mtd/maps/sharpsl-flash.c101
-rw-r--r--drivers/mtd/maps/solutionengine.c137
-rw-r--r--drivers/mtd/maps/sun_uflash.c177
-rw-r--r--drivers/mtd/maps/tqm8xxl.c263
-rw-r--r--drivers/mtd/maps/ts5500_flash.c141
-rw-r--r--drivers/mtd/maps/tsunami_flash.c108
-rw-r--r--drivers/mtd/maps/uclinux.c127
-rw-r--r--drivers/mtd/maps/vmax301.c198
-rw-r--r--drivers/mtd/maps/walnut.c122
-rw-r--r--drivers/mtd/maps/wr_sbc82xx_flash.c181
66 files changed, 14515 insertions, 0 deletions
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
new file mode 100644
index 000000000000..8480057eadb4
--- /dev/null
+++ b/drivers/mtd/maps/Kconfig
@@ -0,0 +1,663 @@
1# drivers/mtd/maps/Kconfig
2# $Id: Kconfig,v 1.42 2005/01/05 16:59:50 dwmw2 Exp $
3
4menu "Mapping drivers for chip access"
5 depends on MTD!=n
6
7config MTD_COMPLEX_MAPPINGS
8 bool "Support non-linear mappings of flash chips"
9 depends on MTD
10 help
11 This causes the chip drivers to allow for complicated
12 paged mappings of flash chips.
13
14config MTD_PHYSMAP
15 tristate "CFI Flash device in physical memory map"
16 depends on MTD_CFI
17 help
18 This provides a 'mapping' driver which allows the CFI probe and
19 command set driver code to communicate with flash chips which
20 are mapped physically into the CPU's memory. You will need to
21 configure the physical address and size of the flash chips on
22 your particular board as well as the bus width, either statically
23 with config options or at run-time.
24
25config MTD_PHYSMAP_START
26 hex "Physical start address of flash mapping"
27 depends on MTD_PHYSMAP
28 default "0x8000000"
29 help
30 This is the physical memory location at which the flash chips
31 are mapped on your particular target board. Refer to the
32 memory map which should hopefully be in the documentation for
33 your board.
34 Ignore this option if you use run-time physmap configuration
35 (i.e., run-time calling physmap_configure()).
36
37config MTD_PHYSMAP_LEN
38 hex "Physical length of flash mapping"
39 depends on MTD_PHYSMAP
40 default "0x4000000"
41 help
42 This is the total length of the mapping of the flash chips on
43 your particular board. If there is space, or aliases, in the
44 physical memory map between the chips, this could be larger
45 than the total amount of flash present. Refer to the memory
46 map which should hopefully be in the documentation for your
47 board.
48 Ignore this option if you use run-time physmap configuration
49 (i.e., run-time calling physmap_configure()).
50
51config MTD_PHYSMAP_BANKWIDTH
52 int "Bank width in octets"
53 depends on MTD_PHYSMAP
54 default "2"
55 help
56 This is the total width of the data bus of the flash devices
57 in octets. For example, if you have a data bus width of 32
58 bits, you would set the bus width octect value to 4. This is
59 used internally by the CFI drivers.
60 Ignore this option if you use run-time physmap configuration
61 (i.e., run-time calling physmap_configure()).
62
63config MTD_SUN_UFLASH
64 tristate "Sun Microsystems userflash support"
65 depends on (SPARC32 || SPARC64) && MTD_CFI
66 help
67 This provides a 'mapping' driver which supports the way in
68 which user-programmable flash chips are connected on various
69 Sun Microsystems boardsets. This driver will require CFI support
70 in the kernel, so if you did not enable CFI previously, do that now.
71
72config MTD_PNC2000
73 tristate "CFI Flash device mapped on Photron PNC-2000"
74 depends on X86 && MTD_CFI && MTD_PARTITIONS
75 help
76 PNC-2000 is the name of Network Camera product from PHOTRON
77 Ltd. in Japan. It uses CFI-compliant flash.
78
79config MTD_SC520CDP
80 tristate "CFI Flash device mapped on AMD SC520 CDP"
81 depends on X86 && MTD_CFI
82 help
83 The SC520 CDP board has two banks of CFI-compliant chips and one
84 Dual-in-line JEDEC chip. This 'mapping' driver supports that
85 arrangement, implementing three MTD devices.
86
87config MTD_NETSC520
88 tristate "CFI Flash device mapped on AMD NetSc520"
89 depends on X86 && MTD_CFI && MTD_PARTITIONS
90 help
91 This enables access routines for the flash chips on the AMD NetSc520
92 demonstration board. If you have one of these boards and would like
93 to use the flash chips on it, say 'Y'.
94
95config MTD_TS5500
96 tristate "JEDEC Flash device mapped on Technologic Systems TS-5500"
97 depends on X86 && MTD_JEDECPROBE && MTD_PARTITIONS
98 help
99 This provides a driver for the on-board flash of the Technologic
100 System's TS-5500 board. The flash is split into 3 partitions
101 which are accessed as separate MTD devices.
102
103 mtd0 and mtd2 are the two BIOS drives. Unfortunately the BIOS
104 uses a proprietary flash translation layer from General Software,
105 which is not supported (the drives cannot be mounted). You can
106 create your own file system (jffs for example), but the BIOS
107 won't be able to boot from it.
108
109 mtd1 allows you to reprogram your BIOS. BE VERY CAREFUL.
110
111 Note that jumper 3 ("Write Enable Drive A") must be set
112 otherwise detection won't succeeed.
113
114config MTD_SBC_GXX
115 tristate "CFI Flash device mapped on Arcom SBC-GXx boards"
116 depends on X86 && MTD_CFI_INTELEXT && MTD_PARTITIONS && MTD_COMPLEX_MAPPINGS
117 help
118 This provides a driver for the on-board flash of Arcom Control
119 Systems' SBC-GXn family of boards, formerly known as SBC-MediaGX.
120 By default the flash is split into 3 partitions which are accessed
121 as separate MTD devices. This board utilizes Intel StrataFlash.
122 More info at
123 <http://www.arcomcontrols.com/products/icp/pc104/processors/SBC_GX1.htm>.
124
125config MTD_ELAN_104NC
126 tristate "CFI Flash device mapped on Arcom ELAN-104NC"
127 depends on X86 && MTD_CFI_INTELEXT && MTD_PARTITIONS && MTD_COMPLEX_MAPPINGS
128 help
129 This provides a driver for the on-board flash of the Arcom Control
130 System's ELAN-104NC development board. By default the flash
131 is split into 3 partitions which are accessed as separate MTD
132 devices. This board utilizes Intel StrataFlash. More info at
133 <http://www.arcomcontrols.com/products/icp/pc104/processors/ELAN104NC.htm>.
134
135config MTD_LUBBOCK
136 tristate "CFI Flash device mapped on Intel Lubbock XScale eval board"
137 depends on ARCH_LUBBOCK && MTD_CFI_INTELEXT && MTD_PARTITIONS
138 help
139 This provides a driver for the on-board flash of the Intel
140 'Lubbock' XScale evaluation board.
141
142config MTD_OCTAGON
143 tristate "JEDEC Flash device mapped on Octagon 5066 SBC"
144 depends on X86 && MTD_JEDEC && MTD_COMPLEX_MAPPINGS
145 help
146 This provides a 'mapping' driver which supports the way in which
147 the flash chips are connected in the Octagon-5066 Single Board
148 Computer. More information on the board is available at
149 <http://www.octagonsystems.com/CPUpages/5066.html>.
150
151config MTD_VMAX
152 tristate "JEDEC Flash device mapped on Tempustech VMAX SBC301"
153 depends on X86 && MTD_JEDEC && MTD_COMPLEX_MAPPINGS
154 help
155 This provides a 'mapping' driver which supports the way in which
156 the flash chips are connected in the Tempustech VMAX SBC301 Single
157 Board Computer. More information on the board is available at
158 <http://www.tempustech.com/>.
159
160config MTD_SCx200_DOCFLASH
161 tristate "Flash device mapped with DOCCS on NatSemi SCx200"
162 depends on SCx200 && MTD_CFI && MTD_PARTITIONS
163 help
164 Enable support for a flash chip mapped using the DOCCS signal on a
165 National Semiconductor SCx200 processor.
166
167 If you don't know what to do here, say N.
168
169 If compiled as a module, it will be called scx200_docflash.
170
171config MTD_AMD76XROM
172 tristate "BIOS flash chip on AMD76x southbridge"
173 depends on X86 && MTD_JEDECPROBE
174 help
175 Support for treating the BIOS flash chip on AMD76x motherboards
176 as an MTD device - with this you can reprogram your BIOS.
177
178 BE VERY CAREFUL.
179
180config MTD_ICHXROM
181 tristate "BIOS flash chip on Intel Controller Hub 2/3/4/5"
182 depends on X86 && MTD_JEDECPROBE
183 help
184 Support for treating the BIOS flash chip on ICHX motherboards
185 as an MTD device - with this you can reprogram your BIOS.
186
187 BE VERY CAREFUL.
188
189config MTD_SCB2_FLASH
190 tristate "BIOS flash chip on Intel SCB2 boards"
191 depends on X86 && MTD_JEDECPROBE
192 help
193 Support for treating the BIOS flash chip on Intel SCB2 boards
194 as an MTD device - with this you can reprogram your BIOS.
195
196 BE VERY CAREFUL.
197
198config MTD_TSUNAMI
199 tristate "Flash chips on Tsunami TIG bus"
200 depends on ALPHA_TSUNAMI && MTD_COMPLEX_MAPPINGS
201 help
202 Support for the flash chip on Tsunami TIG bus.
203
204config MTD_LASAT
205 tristate "Flash chips on LASAT board"
206 depends on LASAT
207 help
208 Support for the flash chips on the Lasat 100 and 200 boards.
209
210config MTD_NETtel
211 tristate "CFI flash device on SnapGear/SecureEdge"
212 depends on X86 && MTD_PARTITIONS && MTD_JEDECPROBE
213 help
214 Support for flash chips on NETtel/SecureEdge/SnapGear boards.
215
216config MTD_PB1XXX
217 tristate "Flash devices on Alchemy PB1xxx boards"
218 depends on MIPS && ( MIPS_PB1000 || MIPS_PB1100 || MIPS_PB1500 )
219 help
220 Flash memory access on Alchemy Pb1000/Pb1100/Pb1500 boards
221
222config MTD_PB1XXX_BOOT
223 bool "PB1x00 boot flash device"
224 depends on MTD_PB1XXX && ( MIPS_PB1100 || MIPS_PB1500 )
225 help
226 Use the first of the two 32MiB flash banks on Pb1100/Pb1500 board.
227 You can say 'Y' to both this and 'MTD_PB1XXX_USER' below, to use
228 both banks.
229
230config MTD_PB1XXX_USER
231 bool "PB1x00 user flash device"
232 depends on MTD_PB1XXX && ( MIPS_PB1100 || MIPS_PB1500 )
233 default y if MTD_PB1XX_BOOT = n
234 help
235 Use the second of the two 32MiB flash banks on Pb1100/Pb1500 board.
236 You can say 'Y' to both this and 'MTD_PB1XXX_BOOT' above, to use
237 both banks.
238
239config MTD_PB1550
240 tristate "Flash devices on Alchemy PB1550 board"
241 depends on MIPS && MIPS_PB1550
242 help
243 Flash memory access on Alchemy Pb1550 board
244
245config MTD_PB1550_BOOT
246 bool "PB1550 boot flash device"
247 depends on MTD_PB1550
248 help
249 Use the first of the two 64MiB flash banks on Pb1550 board.
250 You can say 'Y' to both this and 'MTD_PB1550_USER' below, to use
251 both banks.
252
253config MTD_PB1550_USER
254 bool "PB1550 user flash device"
255 depends on MTD_PB1550
256 default y if MTD_PB1550_BOOT = n
257 help
258 Use the second of the two 64MiB flash banks on Pb1550 board.
259 You can say 'Y' to both this and 'MTD_PB1550_BOOT' above, to use
260 both banks.
261
262config MTD_DB1550
263 tristate "Flash devices on Alchemy DB1550 board"
264 depends on MIPS && MIPS_DB1550
265 help
266 Flash memory access on Alchemy Db1550 board
267
268config MTD_DB1550_BOOT
269 bool "DB1550 boot flash device"
270 depends on MTD_DB1550
271 help
272 Use the first of the two 64MiB flash banks on Db1550 board.
273 You can say 'Y' to both this and 'MTD_DB1550_USER' below, to use
274 both banks.
275
276config MTD_DB1550_USER
277 bool "DB1550 user flash device"
278 depends on MTD_DB1550
279 default y if MTD_DB1550_BOOT = n
280 help
281 Use the second of the two 64MiB flash banks on Db1550 board.
282 You can say 'Y' to both this and 'MTD_DB1550_BOOT' above, to use
283 both banks.
284
285config MTD_DILNETPC
286 tristate "CFI Flash device mapped on DIL/Net PC"
287 depends on X86 && MTD_CONCAT && MTD_PARTITIONS && MTD_CFI_INTELEXT
288 help
289 MTD map driver for SSV DIL/Net PC Boards "DNP" and "ADNP".
290 For details, see <http://www.ssv-embedded.de/ssv/pc104/p169.htm>
291 and <http://www.ssv-embedded.de/ssv/pc104/p170.htm>
292
293config MTD_DILNETPC_BOOTSIZE
294 hex "Size of DIL/Net PC flash boot partition"
295 depends on MTD_DILNETPC
296 default "0x80000"
297 help
298 The amount of space taken up by the kernel or Etherboot
299 on the DIL/Net PC flash chips.
300
301config MTD_L440GX
302 tristate "BIOS flash chip on Intel L440GX boards"
303 depends on X86 && MTD_JEDECPROBE
304 help
305 Support for treating the BIOS flash chip on Intel L440GX motherboards
306 as an MTD device - with this you can reprogram your BIOS.
307
308 BE VERY CAREFUL.
309
310config MTD_SBC8240
311 tristate "Flash device on SBC8240"
312 depends on PPC32 && MTD_JEDECPROBE && 6xx && 8260
313 help
314 Flash access on the SBC8240 board from Wind River. See
315 <http://www.windriver.com/products/sbc8240/>
316
317config MTD_TQM8XXL
318 tristate "CFI Flash device mapped on TQM8XXL"
319 depends on MTD_CFI && PPC32 && 8xx && TQM8xxL
320 help
321 The TQM8xxL PowerPC board has up to two banks of CFI-compliant
322 chips, currently uses AMD one. This 'mapping' driver supports
323 that arrangement, allowing the CFI probe and command set driver
324 code to communicate with the chips on the TQM8xxL board. More at
325 <http://www.denx.de/embedded-ppc-en.html>.
326
327config MTD_RPXLITE
328 tristate "CFI Flash device mapped on RPX Lite or CLLF"
329 depends on MTD_CFI && PPC32 && 8xx && (RPXCLASSIC || RPXLITE)
330 help
331 The RPXLite PowerPC board has CFI-compliant chips mapped in
332 a strange sparse mapping. This 'mapping' driver supports that
333 arrangement, allowing the CFI probe and command set driver code
334 to communicate with the chips on the RPXLite board. More at
335 <http://www.embeddedplanet.com/>.
336
337config MTD_MBX860
338 tristate "System flash on MBX860 board"
339 depends on MTD_CFI && PPC32 && 8xx && MBX
340 help
341 This enables access routines for the flash chips on the Motorola
342 MBX860 board. If you have one of these boards and would like
343 to use the flash chips on it, say 'Y'.
344
345config MTD_DBOX2
346 tristate "CFI Flash device mapped on D-Box2"
347 depends on PPC32 && 8xx && DBOX2 && MTD_CFI_INTELSTD && MTD_CFI_INTELEXT && MTD_CFI_AMDSTD
348 help
349 This enables access routines for the flash chips on the Nokia/Sagem
350 D-Box 2 board. If you have one of these boards and would like to use
351 the flash chips on it, say 'Y'.
352
353config MTD_CFI_FLAGADM
354 tristate "CFI Flash device mapping on FlagaDM"
355 depends on PPC32 && 8xx && MTD_CFI
356 help
357 Mapping for the Flaga digital module. If you don't have one, ignore
358 this setting.
359
360config MTD_BEECH
361 tristate "CFI Flash device mapped on IBM 405LP Beech"
362 depends on MTD_CFI && PPC32 && 40x && BEECH
363 help
364 This enables access routines for the flash chips on the IBM
365 405LP Beech board. If you have one of these boards and would like
366 to use the flash chips on it, say 'Y'.
367
368config MTD_ARCTIC
369 tristate "CFI Flash device mapped on IBM 405LP Arctic"
370 depends on MTD_CFI && PPC32 && 40x && ARCTIC2
371 help
372 This enables access routines for the flash chips on the IBM 405LP
373 Arctic board. If you have one of these boards and would like to
374 use the flash chips on it, say 'Y'.
375
376config MTD_WALNUT
377 tristate "Flash device mapped on IBM 405GP Walnut"
378 depends on MTD_JEDECPROBE && PPC32 && 40x && WALNUT
379 help
380 This enables access routines for the flash chips on the IBM 405GP
381 Walnut board. If you have one of these boards and would like to
382 use the flash chips on it, say 'Y'.
383
384config MTD_EBONY
385 tristate "Flash devices mapped on IBM 440GP Ebony"
386 depends on MTD_JEDECPROBE && PPC32 && 44x && EBONY
387 help
388 This enables access routines for the flash chips on the IBM 440GP
389 Ebony board. If you have one of these boards and would like to
390 use the flash chips on it, say 'Y'.
391
392config MTD_OCOTEA
393 tristate "Flash devices mapped on IBM 440GX Ocotea"
394 depends on MTD_CFI && PPC32 && 44x && OCOTEA
395 help
396 This enables access routines for the flash chips on the IBM 440GX
397 Ocotea board. If you have one of these boards and would like to
398 use the flash chips on it, say 'Y'.
399
400config MTD_REDWOOD
401 tristate "CFI Flash devices mapped on IBM Redwood"
402 depends on MTD_CFI && PPC32 && 4xx && 40x && ( REDWOOD_4 || REDWOOD_5 || REDWOOD_6 )
403 help
404 This enables access routines for the flash chips on the IBM
405 Redwood board. If you have one of these boards and would like to
406 use the flash chips on it, say 'Y'.
407
408config MTD_CSTM_MIPS_IXX
409 tristate "Flash chip mapping on ITE QED-4N-S01B, Globespan IVR or custom board"
410 depends on MIPS && MTD_CFI && MTD_JEDECPROBE && MTD_PARTITIONS
411 help
412 This provides a mapping driver for the Integrated Technology
413 Express, Inc (ITE) QED-4N-S01B eval board and the Globespan IVR
414 Reference Board. It provides the necessary addressing, length,
415 buswidth, vpp code and addition setup of the flash device for
416 these boards. In addition, this mapping driver can be used for
417 other boards via setting of the CONFIG_MTD_CSTM_MIPS_IXX_START/
418 LEN/BUSWIDTH parameters. This mapping will provide one mtd device
419 using one partition. The start address can be offset from the
420 beginning of flash and the len can be less than the total flash
421 device size to allow a window into the flash. Both CFI and JEDEC
422 probes are called.
423
424config MTD_CSTM_MIPS_IXX_START
425 hex "Physical start address of flash mapping"
426 depends on MTD_CSTM_MIPS_IXX
427 default "0x8000000"
428 help
429 This is the physical memory location that the MTD driver will
430 use for the flash chips on your particular target board.
431 Refer to the memory map which should hopefully be in the
432 documentation for your board.
433
434config MTD_CSTM_MIPS_IXX_LEN
435 hex "Physical length of flash mapping"
436 depends on MTD_CSTM_MIPS_IXX
437 default "0x4000000"
438 help
439 This is the total length that the MTD driver will use for the
440 flash chips on your particular board. Refer to the memory
441 map which should hopefully be in the documentation for your
442 board.
443
444config MTD_CSTM_MIPS_IXX_BUSWIDTH
445 int "Bus width in octets"
446 depends on MTD_CSTM_MIPS_IXX
447 default "2"
448 help
449 This is the total bus width of the mapping of the flash chips
450 on your particular board.
451
452config MTD_OCELOT
453 tristate "Momenco Ocelot boot flash device"
454 depends on MIPS && MOMENCO_OCELOT
455 help
456 This enables access routines for the boot flash device and for the
457 NVRAM on the Momenco Ocelot board. If you have one of these boards
458 and would like access to either of these, say 'Y'.
459
460config MTD_SOLUTIONENGINE
461 tristate "CFI Flash device mapped on Hitachi SolutionEngine"
462 depends on SUPERH && MTD_CFI && MTD_REDBOOT_PARTS
463 help
464 This enables access to the flash chips on the Hitachi SolutionEngine and
465 similar boards. Say 'Y' if you are building a kernel for such a board.
466
467config MTD_ARM_INTEGRATOR
468 tristate "CFI Flash device mapped on ARM Integrator/P720T"
469 depends on ARM && MTD_CFI
470
471config MTD_CDB89712
472 tristate "Cirrus CDB89712 evaluation board mappings"
473 depends on ARM && MTD_CFI && ARCH_CDB89712
474 help
475 This enables access to the flash or ROM chips on the CDB89712 board.
476 If you have such a board, say 'Y'.
477
478config MTD_SA1100
479 tristate "CFI Flash device mapped on StrongARM SA11x0"
480 depends on ARM && MTD_CFI && ARCH_SA1100 && MTD_PARTITIONS
481 help
482 This enables access to the flash chips on most platforms based on
483 the SA1100 and SA1110, including the Assabet and the Compaq iPAQ.
484 If you have such a board, say 'Y'.
485
486config MTD_IPAQ
487 tristate "CFI Flash device mapped on Compaq/HP iPAQ"
488 depends on ARM && IPAQ_HANDHELD && MTD_CFI
489 help
490 This provides a driver for the on-board flash of the iPAQ.
491
492config MTD_DC21285
493 tristate "CFI Flash device mapped on DC21285 Footbridge"
494 depends on ARM && MTD_CFI && ARCH_FOOTBRIDGE && MTD_COMPLEX_MAPPINGS
495 help
496 This provides a driver for the flash accessed using Intel's
497 21285 bridge used with Intel's StrongARM processors. More info at
498 <http://www.intel.com/design/bridge/docs/21285_documentation.htm>.
499
500config MTD_IQ80310
501 tristate "CFI Flash device mapped on the XScale IQ80310 board"
502 depends on ARM && MTD_CFI && ARCH_IQ80310
503 help
504 This enables access routines for the flash chips on the Intel XScale
505 IQ80310 evaluation board. If you have one of these boards and would
506 like to use the flash chips on it, say 'Y'.
507
508config MTD_IXP4XX
509 tristate "CFI Flash device mapped on Intel IXP4xx based systems"
510 depends on ARM && MTD_CFI && MTD_COMPLEX_MAPPINGS && ARCH_IXP4XX
511 help
512 This enables MTD access to flash devices on platforms based
513 on Intel's IXP4xx family of network processors such as the
514 IXDP425 and Coyote. If you have an IXP4xx based board and
515 would like to use the flash chips on it, say 'Y'.
516
517config MTD_IXP2000
518 tristate "CFI Flash device mapped on Intel IXP2000 based systems"
519 depends on ARM && MTD_CFI && MTD_COMPLEX_MAPPINGS && ARCH_IXP2000
520 help
521 This enables MTD access to flash devices on platforms based
522 on Intel's IXP2000 family of network processors such as the
523 IXDP425 and Coyote. If you have an IXP2000 based board and
524 would like to use the flash chips on it, say 'Y'.
525
526config MTD_EPXA10DB
527 tristate "CFI Flash device mapped on Epxa10db"
528 depends on ARM && MTD_CFI && MTD_PARTITIONS && ARCH_CAMELOT
529 help
530 This enables support for the flash devices on the Altera
531 Excalibur XA10 Development Board. If you are building a kernel
532 for on of these boards then you should say 'Y' otherwise say 'N'.
533
534config MTD_FORTUNET
535 tristate "CFI Flash device mapped on the FortuNet board"
536 depends on ARM && MTD_CFI && MTD_PARTITIONS && SA1100_FORTUNET
537 help
538 This enables access to the Flash on the FortuNet board. If you
539 have such a board, say 'Y'.
540
541config MTD_AUTCPU12
542 tristate "NV-RAM mapping AUTCPU12 board"
543 depends on ARM && ARCH_AUTCPU12
544 help
545 This enables access to the NV-RAM on autronix autcpu12 board.
546 If you have such a board, say 'Y'.
547
548config MTD_EDB7312
549 tristate "CFI Flash device mapped on EDB7312"
550 depends on ARM && MTD_CFI
551 help
552 This enables access to the CFI Flash on the Cogent EDB7312 board.
553 If you have such a board, say 'Y' here.
554
555config MTD_IMPA7
556 tristate "JEDEC Flash device mapped on impA7"
557 depends on ARM && MTD_JEDECPROBE
558 help
559 This enables access to the NOR Flash on the impA7 board of
560 implementa GmbH. If you have such a board, say 'Y' here.
561
562config MTD_CEIVA
563 tristate "JEDEC Flash device mapped on Ceiva/Polaroid PhotoMax Digital Picture Frame"
564 depends on ARM && MTD_JEDECPROBE && ARCH_CEIVA
565 help
566 This enables access to the flash chips on the Ceiva/Polaroid
567 PhotoMax Digital Picture Frame.
568 If you have such a device, say 'Y'.
569
570config MTD_NOR_TOTO
571 tristate "NOR Flash device on TOTO board"
572 depends on ARM && ARCH_OMAP && OMAP_TOTO
573 help
574 This enables access to the NOR flash on the Texas Instruments
575 TOTO board.
576
577config MTD_H720X
578 tristate "Hynix evaluation board mappings"
579 depends on ARM && MTD_CFI && ( ARCH_H7201 || ARCH_H7202 )
580 help
581 This enables access to the flash chips on the Hynix evaluation boards.
582 If you have such a board, say 'Y'.
583
584config MTD_MPC1211
585 tristate "CFI Flash device mapped on Interface MPC-1211"
586 depends on SUPERH && SH_MPC1211 && MTD_CFI
587 help
588 This enables access to the flash chips on the Interface MPC-1211(CTP/PCI/MPC-SH02).
589 If you have such a board, say 'Y'.
590
591# This needs CFI or JEDEC, depending on the cards found.
592config MTD_PCI
593 tristate "PCI MTD driver"
594 depends on MTD && PCI && MTD_COMPLEX_MAPPINGS
595 help
596 Mapping for accessing flash devices on add-in cards like the Intel XScale
597 IQ80310 card, and the Intel EBSA285 card in blank ROM programming mode
598 (please see the manual for the link settings).
599
600 If you are not sure, say N.
601
602config MTD_PCMCIA
603 tristate "PCMCIA MTD driver"
604 depends on MTD && PCMCIA && MTD_COMPLEX_MAPPINGS && BROKEN
605 help
606 Map driver for accessing PCMCIA linear flash memory cards. These
607 cards are usually around 4-16MiB in size. This does not include
608 Compact Flash cards which are treated as IDE devices.
609
610config MTD_UCLINUX
611 tristate "Generic uClinux RAM/ROM filesystem support"
612 depends on MTD_PARTITIONS && !MMU
613 help
614 Map driver to support image based filesystems for uClinux.
615
616config MTD_WRSBC8260
617 tristate "Map driver for WindRiver PowerQUICC II MPC82xx board"
618 depends on (SBC82xx || SBC8560)
619 select MTD_PARTITIONS
620 select MTD_MAP_BANK_WIDTH_4
621 select MTD_MAP_BANK_WIDTH_1
622 select MTD_CFI_I1
623 select MTD_CFI_I4
624 help
625 Map driver for WindRiver PowerQUICC II MPC82xx board. Drives
626 all three flash regions on CS0, CS1 and CS6 if they are configured
627 correctly by the boot loader.
628
629config MTD_DMV182
630 tristate "Map driver for Dy-4 SVME/DMV-182 board."
631 depends on DMV182
632 select MTD_PARTITIONS
633 select MTD_MAP_BANK_WIDTH_32
634 select MTD_CFI_I8
635 select MTD_CFI_AMDSTD
636 help
637 Map driver for Dy-4 SVME/DMV-182 board.
638
639config MTD_BAST
640 tristate "Map driver for Simtec BAST (EB2410ITX)"
641 depends on ARCH_BAST
642 select MTD_PARTITIONS
643 select MTD_MAP_BANK_WIDTH_16
644 select MTD_JEDECPROBE
645 help
646 Map driver for NOR flash on the Simtec BAST (EB2410ITX).
647
648 Note, this driver *cannot* over-ride the WP link on the
649 board, or currently detect the state of the link.
650
651config MTD_BAST_MAXSIZE
652 int "Maximum size for BAST flash area (MiB)"
653 depends on MTD_BAST
654 default "4"
655
656config MTD_SHARP_SL
657 bool "ROM maped on Sharp SL Series"
658 depends on MTD && ARCH_PXA
659 help
660 This enables access to the flash chip on the Sharp SL Series of PDAs.
661
662endmenu
663
diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile
new file mode 100644
index 000000000000..7ffe02b85301
--- /dev/null
+++ b/drivers/mtd/maps/Makefile
@@ -0,0 +1,73 @@
1#
2# linux/drivers/maps/Makefile
3#
4# $Id: Makefile.common,v 1.23 2005/01/05 17:06:36 dwmw2 Exp $
5
6ifeq ($(CONFIG_MTD_COMPLEX_MAPPINGS),y)
7obj-$(CONFIG_MTD) += map_funcs.o
8endif
9
10# Chip mappings
11obj-$(CONFIG_MTD_CDB89712) += cdb89712.o
12obj-$(CONFIG_MTD_ARM_INTEGRATOR)+= integrator-flash.o
13obj-$(CONFIG_MTD_BAST) += bast-flash.o
14obj-$(CONFIG_MTD_CFI_FLAGADM) += cfi_flagadm.o
15obj-$(CONFIG_MTD_CSTM_MIPS_IXX) += cstm_mips_ixx.o
16obj-$(CONFIG_MTD_DC21285) += dc21285.o
17obj-$(CONFIG_MTD_DILNETPC) += dilnetpc.o
18obj-$(CONFIG_MTD_ELAN_104NC) += elan-104nc.o
19obj-$(CONFIG_MTD_EPXA10DB) += epxa10db-flash.o
20obj-$(CONFIG_MTD_IQ80310) += iq80310.o
21obj-$(CONFIG_MTD_L440GX) += l440gx.o
22obj-$(CONFIG_MTD_AMD76XROM) += amd76xrom.o
23obj-$(CONFIG_MTD_ICHXROM) += ichxrom.o
24obj-$(CONFIG_MTD_TSUNAMI) += tsunami_flash.o
25obj-$(CONFIG_MTD_LUBBOCK) += lubbock-flash.o
26obj-$(CONFIG_MTD_MBX860) += mbx860.o
27obj-$(CONFIG_MTD_CEIVA) += ceiva.o
28obj-$(CONFIG_MTD_OCTAGON) += octagon-5066.o
29obj-$(CONFIG_MTD_PHYSMAP) += physmap.o
30obj-$(CONFIG_MTD_PNC2000) += pnc2000.o
31obj-$(CONFIG_MTD_PCMCIA) += pcmciamtd.o
32obj-$(CONFIG_MTD_RPXLITE) += rpxlite.o
33obj-$(CONFIG_MTD_TQM8XXL) += tqm8xxl.o
34obj-$(CONFIG_MTD_SA1100) += sa1100-flash.o
35obj-$(CONFIG_MTD_IPAQ) += ipaq-flash.o
36obj-$(CONFIG_MTD_SBC_GXX) += sbc_gxx.o
37obj-$(CONFIG_MTD_SC520CDP) += sc520cdp.o
38obj-$(CONFIG_MTD_NETSC520) += netsc520.o
39obj-$(CONFIG_MTD_TS5500) += ts5500_flash.o
40obj-$(CONFIG_MTD_SUN_UFLASH) += sun_uflash.o
41obj-$(CONFIG_MTD_VMAX) += vmax301.o
42obj-$(CONFIG_MTD_SCx200_DOCFLASH)+= scx200_docflash.o
43obj-$(CONFIG_MTD_DBOX2) += dbox2-flash.o
44obj-$(CONFIG_MTD_OCELOT) += ocelot.o
45obj-$(CONFIG_MTD_SOLUTIONENGINE)+= solutionengine.o
46obj-$(CONFIG_MTD_PCI) += pci.o
47obj-$(CONFIG_MTD_PB1XXX) += pb1xxx-flash.o
48obj-$(CONFIG_MTD_DB1X00) += db1x00-flash.o
49obj-$(CONFIG_MTD_PB1550) += pb1550-flash.o
50obj-$(CONFIG_MTD_DB1550) += db1550-flash.o
51obj-$(CONFIG_MTD_LASAT) += lasat.o
52obj-$(CONFIG_MTD_AUTCPU12) += autcpu12-nvram.o
53obj-$(CONFIG_MTD_EDB7312) += edb7312.o
54obj-$(CONFIG_MTD_IMPA7) += impa7.o
55obj-$(CONFIG_MTD_FORTUNET) += fortunet.o
56obj-$(CONFIG_MTD_REDWOOD) += redwood.o
57obj-$(CONFIG_MTD_UCLINUX) += uclinux.o
58obj-$(CONFIG_MTD_NETtel) += nettel.o
59obj-$(CONFIG_MTD_SCB2_FLASH) += scb2_flash.o
60obj-$(CONFIG_MTD_EBONY) += ebony.o
61obj-$(CONFIG_MTD_OCOTEA) += ocotea.o
62obj-$(CONFIG_MTD_BEECH) += beech-mtd.o
63obj-$(CONFIG_MTD_ARCTIC) += arctic-mtd.o
64obj-$(CONFIG_MTD_WALNUT) += walnut.o
65obj-$(CONFIG_MTD_H720X) += h720x-flash.o
66obj-$(CONFIG_MTD_SBC8240) += sbc8240.o
67obj-$(CONFIG_MTD_NOR_TOTO) += omap-toto-flash.o
68obj-$(CONFIG_MTD_MPC1211) += mpc1211.o
69obj-$(CONFIG_MTD_IXP4XX) += ixp4xx.o
70obj-$(CONFIG_MTD_IXP2000) += ixp2000.o
71obj-$(CONFIG_MTD_WRSBC8260) += wr_sbc82xx_flash.o
72obj-$(CONFIG_MTD_DMV182) += dmv182.o
73obj-$(CONFIG_MTD_SHARP_SL) += sharpsl-flash.o
diff --git a/drivers/mtd/maps/amd76xrom.c b/drivers/mtd/maps/amd76xrom.c
new file mode 100644
index 000000000000..51e97b05304e
--- /dev/null
+++ b/drivers/mtd/maps/amd76xrom.c
@@ -0,0 +1,332 @@
1/*
2 * amd76xrom.c
3 *
4 * Normal mappings of chips in physical memory
5 * $Id: amd76xrom.c,v 1.19 2004/11/28 09:40:39 dwmw2 Exp $
6 */
7
8#include <linux/module.h>
9#include <linux/types.h>
10#include <linux/kernel.h>
11#include <linux/init.h>
12#include <asm/io.h>
13#include <linux/mtd/mtd.h>
14#include <linux/mtd/map.h>
15#include <linux/mtd/cfi.h>
16#include <linux/mtd/flashchip.h>
17#include <linux/config.h>
18#include <linux/pci.h>
19#include <linux/pci_ids.h>
20#include <linux/list.h>
21
22
23#define xstr(s) str(s)
24#define str(s) #s
25#define MOD_NAME xstr(KBUILD_BASENAME)
26
27#define ADDRESS_NAME_LEN 18
28
29#define ROM_PROBE_STEP_SIZE (64*1024) /* 64KiB */
30
31struct amd76xrom_window {
32 void __iomem *virt;
33 unsigned long phys;
34 unsigned long size;
35 struct list_head maps;
36 struct resource rsrc;
37 struct pci_dev *pdev;
38};
39
40struct amd76xrom_map_info {
41 struct list_head list;
42 struct map_info map;
43 struct mtd_info *mtd;
44 struct resource rsrc;
45 char map_name[sizeof(MOD_NAME) + 2 + ADDRESS_NAME_LEN];
46};
47
48static struct amd76xrom_window amd76xrom_window = {
49 .maps = LIST_HEAD_INIT(amd76xrom_window.maps),
50};
51
52static void amd76xrom_cleanup(struct amd76xrom_window *window)
53{
54 struct amd76xrom_map_info *map, *scratch;
55 u8 byte;
56
57 if (window->pdev) {
58 /* Disable writes through the rom window */
59 pci_read_config_byte(window->pdev, 0x40, &byte);
60 pci_write_config_byte(window->pdev, 0x40, byte & ~1);
61 }
62
63 /* Free all of the mtd devices */
64 list_for_each_entry_safe(map, scratch, &window->maps, list) {
65 if (map->rsrc.parent) {
66 release_resource(&map->rsrc);
67 }
68 del_mtd_device(map->mtd);
69 map_destroy(map->mtd);
70 list_del(&map->list);
71 kfree(map);
72 }
73 if (window->rsrc.parent)
74 release_resource(&window->rsrc);
75
76 if (window->virt) {
77 iounmap(window->virt);
78 window->virt = NULL;
79 window->phys = 0;
80 window->size = 0;
81 window->pdev = NULL;
82 }
83}
84
85
86static int __devinit amd76xrom_init_one (struct pci_dev *pdev,
87 const struct pci_device_id *ent)
88{
89 static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL };
90 u8 byte;
91 struct amd76xrom_window *window = &amd76xrom_window;
92 struct amd76xrom_map_info *map = NULL;
93 unsigned long map_top;
94
95 /* Remember the pci dev I find the window in */
96 window->pdev = pdev;
97
98 /* Assume the rom window is properly setup, and find it's size */
99 pci_read_config_byte(pdev, 0x43, &byte);
100 if ((byte & ((1<<7)|(1<<6))) == ((1<<7)|(1<<6))) {
101 window->phys = 0xffb00000; /* 5MiB */
102 }
103 else if ((byte & (1<<7)) == (1<<7)) {
104 window->phys = 0xffc00000; /* 4MiB */
105 }
106 else {
107 window->phys = 0xffff0000; /* 64KiB */
108 }
109 window->size = 0xffffffffUL - window->phys + 1UL;
110
111 /*
112 * Try to reserve the window mem region. If this fails then
113 * it is likely due to a fragment of the window being
114 * "reseved" by the BIOS. In the case that the
115 * request_mem_region() fails then once the rom size is
116 * discovered we will try to reserve the unreserved fragment.
117 */
118 window->rsrc.name = MOD_NAME;
119 window->rsrc.start = window->phys;
120 window->rsrc.end = window->phys + window->size - 1;
121 window->rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
122 if (request_resource(&iomem_resource, &window->rsrc)) {
123 window->rsrc.parent = NULL;
124 printk(KERN_ERR MOD_NAME
125 " %s(): Unable to register resource"
126 " 0x%.08lx-0x%.08lx - kernel bug?\n",
127 __func__,
128 window->rsrc.start, window->rsrc.end);
129 }
130
131#if 0
132
133 /* Enable the selected rom window */
134 pci_read_config_byte(pdev, 0x43, &byte);
135 pci_write_config_byte(pdev, 0x43, byte | rwindow->segen_bits);
136#endif
137
138 /* Enable writes through the rom window */
139 pci_read_config_byte(pdev, 0x40, &byte);
140 pci_write_config_byte(pdev, 0x40, byte | 1);
141
142 /* FIXME handle registers 0x80 - 0x8C the bios region locks */
143
144 /* For write accesses caches are useless */
145 window->virt = ioremap_nocache(window->phys, window->size);
146 if (!window->virt) {
147 printk(KERN_ERR MOD_NAME ": ioremap(%08lx, %08lx) failed\n",
148 window->phys, window->size);
149 goto out;
150 }
151
152 /* Get the first address to look for an rom chip at */
153 map_top = window->phys;
154#if 1
155 /* The probe sequence run over the firmware hub lock
156 * registers sets them to 0x7 (no access).
157 * Probe at most the last 4M of the address space.
158 */
159 if (map_top < 0xffc00000) {
160 map_top = 0xffc00000;
161 }
162#endif
163 /* Loop through and look for rom chips */
164 while((map_top - 1) < 0xffffffffUL) {
165 struct cfi_private *cfi;
166 unsigned long offset;
167 int i;
168
169 if (!map) {
170 map = kmalloc(sizeof(*map), GFP_KERNEL);
171 }
172 if (!map) {
173 printk(KERN_ERR MOD_NAME ": kmalloc failed");
174 goto out;
175 }
176 memset(map, 0, sizeof(*map));
177 INIT_LIST_HEAD(&map->list);
178 map->map.name = map->map_name;
179 map->map.phys = map_top;
180 offset = map_top - window->phys;
181 map->map.virt = (void __iomem *)
182 (((unsigned long)(window->virt)) + offset);
183 map->map.size = 0xffffffffUL - map_top + 1UL;
184 /* Set the name of the map to the address I am trying */
185 sprintf(map->map_name, "%s @%08lx",
186 MOD_NAME, map->map.phys);
187
188 /* There is no generic VPP support */
189 for(map->map.bankwidth = 32; map->map.bankwidth;
190 map->map.bankwidth >>= 1)
191 {
192 char **probe_type;
193 /* Skip bankwidths that are not supported */
194 if (!map_bankwidth_supported(map->map.bankwidth))
195 continue;
196
197 /* Setup the map methods */
198 simple_map_init(&map->map);
199
200 /* Try all of the probe methods */
201 probe_type = rom_probe_types;
202 for(; *probe_type; probe_type++) {
203 map->mtd = do_map_probe(*probe_type, &map->map);
204 if (map->mtd)
205 goto found;
206 }
207 }
208 map_top += ROM_PROBE_STEP_SIZE;
209 continue;
210 found:
211 /* Trim the size if we are larger than the map */
212 if (map->mtd->size > map->map.size) {
213 printk(KERN_WARNING MOD_NAME
214 " rom(%u) larger than window(%lu). fixing...\n",
215 map->mtd->size, map->map.size);
216 map->mtd->size = map->map.size;
217 }
218 if (window->rsrc.parent) {
219 /*
220 * Registering the MTD device in iomem may not be possible
221 * if there is a BIOS "reserved" and BUSY range. If this
222 * fails then continue anyway.
223 */
224 map->rsrc.name = map->map_name;
225 map->rsrc.start = map->map.phys;
226 map->rsrc.end = map->map.phys + map->mtd->size - 1;
227 map->rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
228 if (request_resource(&window->rsrc, &map->rsrc)) {
229 printk(KERN_ERR MOD_NAME
230 ": cannot reserve MTD resource\n");
231 map->rsrc.parent = NULL;
232 }
233 }
234
235 /* Make the whole region visible in the map */
236 map->map.virt = window->virt;
237 map->map.phys = window->phys;
238 cfi = map->map.fldrv_priv;
239 for(i = 0; i < cfi->numchips; i++) {
240 cfi->chips[i].start += offset;
241 }
242
243 /* Now that the mtd devices is complete claim and export it */
244 map->mtd->owner = THIS_MODULE;
245 if (add_mtd_device(map->mtd)) {
246 map_destroy(map->mtd);
247 map->mtd = NULL;
248 goto out;
249 }
250
251
252 /* Calculate the new value of map_top */
253 map_top += map->mtd->size;
254
255 /* File away the map structure */
256 list_add(&map->list, &window->maps);
257 map = NULL;
258 }
259
260 out:
261 /* Free any left over map structures */
262 if (map) {
263 kfree(map);
264 }
265 /* See if I have any map structures */
266 if (list_empty(&window->maps)) {
267 amd76xrom_cleanup(window);
268 return -ENODEV;
269 }
270 return 0;
271}
272
273
274static void __devexit amd76xrom_remove_one (struct pci_dev *pdev)
275{
276 struct amd76xrom_window *window = &amd76xrom_window;
277
278 amd76xrom_cleanup(window);
279}
280
281static struct pci_device_id amd76xrom_pci_tbl[] = {
282 { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7410,
283 PCI_ANY_ID, PCI_ANY_ID, },
284 { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7440,
285 PCI_ANY_ID, PCI_ANY_ID, },
286 { PCI_VENDOR_ID_AMD, 0x7468 }, /* amd8111 support */
287 { 0, }
288};
289
290MODULE_DEVICE_TABLE(pci, amd76xrom_pci_tbl);
291
292#if 0
293static struct pci_driver amd76xrom_driver = {
294 .name = MOD_NAME,
295 .id_table = amd76xrom_pci_tbl,
296 .probe = amd76xrom_init_one,
297 .remove = amd76xrom_remove_one,
298};
299#endif
300
301static int __init init_amd76xrom(void)
302{
303 struct pci_dev *pdev;
304 struct pci_device_id *id;
305 pdev = NULL;
306 for(id = amd76xrom_pci_tbl; id->vendor; id++) {
307 pdev = pci_find_device(id->vendor, id->device, NULL);
308 if (pdev) {
309 break;
310 }
311 }
312 if (pdev) {
313 return amd76xrom_init_one(pdev, &amd76xrom_pci_tbl[0]);
314 }
315 return -ENXIO;
316#if 0
317 return pci_module_init(&amd76xrom_driver);
318#endif
319}
320
321static void __exit cleanup_amd76xrom(void)
322{
323 amd76xrom_remove_one(amd76xrom_window.pdev);
324}
325
326module_init(init_amd76xrom);
327module_exit(cleanup_amd76xrom);
328
329MODULE_LICENSE("GPL");
330MODULE_AUTHOR("Eric Biederman <ebiederman@lnxi.com>");
331MODULE_DESCRIPTION("MTD map driver for BIOS chips on the AMD76X southbridge");
332
diff --git a/drivers/mtd/maps/arctic-mtd.c b/drivers/mtd/maps/arctic-mtd.c
new file mode 100644
index 000000000000..777276fd0e15
--- /dev/null
+++ b/drivers/mtd/maps/arctic-mtd.c
@@ -0,0 +1,135 @@
1/*
2 * $Id: arctic-mtd.c,v 1.13 2004/11/04 13:24:14 gleixner Exp $
3 *
4 * drivers/mtd/maps/arctic-mtd.c MTD mappings and partition tables for
5 * IBM 405LP Arctic boards.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 * Copyright (C) 2002, International Business Machines Corporation
22 * All Rights Reserved.
23 *
24 * Bishop Brock
25 * IBM Research, Austin Center for Low-Power Computing
26 * bcbrock@us.ibm.com
27 * March 2002
28 *
29 * modified for Arctic by,
30 * David Gibson
31 * IBM OzLabs, Canberra, Australia
32 * <arctic@gibson.dropbear.id.au>
33 */
34
35#include <linux/kernel.h>
36#include <linux/module.h>
37#include <linux/types.h>
38#include <linux/init.h>
39
40#include <linux/mtd/mtd.h>
41#include <linux/mtd/map.h>
42#include <linux/mtd/partitions.h>
43
44#include <asm/io.h>
45#include <asm/ibm4xx.h>
46
47/*
48 * 0 : 0xFE00 0000 - 0xFEFF FFFF : Filesystem 1 (16MiB)
49 * 1 : 0xFF00 0000 - 0xFF4F FFFF : kernel (5.12MiB)
50 * 2 : 0xFF50 0000 - 0xFFF5 FFFF : Filesystem 2 (10.624MiB) (if non-XIP)
51 * 3 : 0xFFF6 0000 - 0xFFFF FFFF : PIBS Firmware (640KiB)
52 */
53
54#define FFS1_SIZE 0x01000000 /* 16MiB */
55#define KERNEL_SIZE 0x00500000 /* 5.12MiB */
56#define FFS2_SIZE 0x00a60000 /* 10.624MiB */
57#define FIRMWARE_SIZE 0x000a0000 /* 640KiB */
58
59
60#define NAME "Arctic Linux Flash"
61#define PADDR SUBZERO_BOOTFLASH_PADDR
62#define BUSWIDTH 2
63#define SIZE SUBZERO_BOOTFLASH_SIZE
64#define PARTITIONS 4
65
66/* Flash memories on these boards are memory resources, accessed big-endian. */
67
68{
69 /* do nothing for now */
70}
71
72static struct map_info arctic_mtd_map = {
73 .name = NAME,
74 .size = SIZE,
75 .bankwidth = BUSWIDTH,
76 .phys = PADDR,
77};
78
79static struct mtd_info *arctic_mtd;
80
81static struct mtd_partition arctic_partitions[PARTITIONS] = {
82 { .name = "Filesystem",
83 .size = FFS1_SIZE,
84 .offset = 0,},
85 { .name = "Kernel",
86 .size = KERNEL_SIZE,
87 .offset = FFS1_SIZE,},
88 { .name = "Filesystem",
89 .size = FFS2_SIZE,
90 .offset = FFS1_SIZE + KERNEL_SIZE,},
91 { .name = "Firmware",
92 .size = FIRMWARE_SIZE,
93 .offset = SUBZERO_BOOTFLASH_SIZE - FIRMWARE_SIZE,},
94};
95
96static int __init
97init_arctic_mtd(void)
98{
99 printk("%s: 0x%08x at 0x%08x\n", NAME, SIZE, PADDR);
100
101 arctic_mtd_map.virt = ioremap(PADDR, SIZE);
102
103 if (!arctic_mtd_map.virt) {
104 printk("%s: failed to ioremap 0x%x\n", NAME, PADDR);
105 return -EIO;
106 }
107 simple_map_init(&arctic_mtd_map);
108
109 printk("%s: probing %d-bit flash bus\n", NAME, BUSWIDTH * 8);
110 arctic_mtd = do_map_probe("cfi_probe", &arctic_mtd_map);
111
112 if (!arctic_mtd)
113 return -ENXIO;
114
115 arctic_mtd->owner = THIS_MODULE;
116
117 return add_mtd_partitions(arctic_mtd, arctic_partitions, PARTITIONS);
118}
119
120static void __exit
121cleanup_arctic_mtd(void)
122{
123 if (arctic_mtd) {
124 del_mtd_partitions(arctic_mtd);
125 map_destroy(arctic_mtd);
126 iounmap((void *) arctic_mtd_map.virt);
127 }
128}
129
130module_init(init_arctic_mtd);
131module_exit(cleanup_arctic_mtd);
132
133MODULE_LICENSE("GPL");
134MODULE_AUTHOR("David Gibson <arctic@gibson.dropbear.id.au>");
135MODULE_DESCRIPTION("MTD map and partitions for IBM 405LP Arctic boards");
diff --git a/drivers/mtd/maps/autcpu12-nvram.c b/drivers/mtd/maps/autcpu12-nvram.c
new file mode 100644
index 000000000000..cf362ccc3c8e
--- /dev/null
+++ b/drivers/mtd/maps/autcpu12-nvram.c
@@ -0,0 +1,127 @@
1/*
2 * NV-RAM memory access on autcpu12
3 * (C) 2002 Thomas Gleixner (gleixner@autronix.de)
4 *
5 * $Id: autcpu12-nvram.c,v 1.8 2004/11/04 13:24:14 gleixner Exp $
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 */
22
23#include <linux/module.h>
24#include <linux/types.h>
25#include <linux/kernel.h>
26#include <linux/ioport.h>
27#include <linux/init.h>
28#include <asm/io.h>
29#include <asm/sizes.h>
30#include <asm/hardware.h>
31#include <asm/arch/autcpu12.h>
32#include <linux/mtd/mtd.h>
33#include <linux/mtd/map.h>
34#include <linux/mtd/partitions.h>
35
36
37static struct mtd_info *sram_mtd;
38
39struct map_info autcpu12_sram_map = {
40 .name = "SRAM",
41 .size = 32768,
42 .bankwidth = 4,
43 .phys = 0x12000000,
44};
45
46static int __init init_autcpu12_sram (void)
47{
48 int err, save0, save1;
49
50 autcpu12_sram_map.virt = ioremap(0x12000000, SZ_128K);
51 if (!autcpu12_sram_map.virt) {
52 printk("Failed to ioremap autcpu12 NV-RAM space\n");
53 err = -EIO;
54 goto out;
55 }
56 simple_map_init(&autcpu_sram_map);
57
58 /*
59 * Check for 32K/128K
60 * read ofs 0
61 * read ofs 0x10000
62 * Write complement to ofs 0x100000
63 * Read and check result on ofs 0x0
64 * Restore contents
65 */
66 save0 = map_read32(&autcpu12_sram_map,0);
67 save1 = map_read32(&autcpu12_sram_map,0x10000);
68 map_write32(&autcpu12_sram_map,~save0,0x10000);
69 /* if we find this pattern on 0x0, we have 32K size
70 * restore contents and exit
71 */
72 if ( map_read32(&autcpu12_sram_map,0) != save0) {
73 map_write32(&autcpu12_sram_map,save0,0x0);
74 goto map;
75 }
76 /* We have a 128K found, restore 0x10000 and set size
77 * to 128K
78 */
79 map_write32(&autcpu12_sram_map,save1,0x10000);
80 autcpu12_sram_map.size = SZ_128K;
81
82map:
83 sram_mtd = do_map_probe("map_ram", &autcpu12_sram_map);
84 if (!sram_mtd) {
85 printk("NV-RAM probe failed\n");
86 err = -ENXIO;
87 goto out_ioremap;
88 }
89
90 sram_mtd->owner = THIS_MODULE;
91 sram_mtd->erasesize = 16;
92
93 if (add_mtd_device(sram_mtd)) {
94 printk("NV-RAM device addition failed\n");
95 err = -ENOMEM;
96 goto out_probe;
97 }
98
99 printk("NV-RAM device size %ldKiB registered on AUTCPU12\n",autcpu12_sram_map.size/SZ_1K);
100
101 return 0;
102
103out_probe:
104 map_destroy(sram_mtd);
105 sram_mtd = 0;
106
107out_ioremap:
108 iounmap((void *)autcpu12_sram_map.virt);
109out:
110 return err;
111}
112
113static void __exit cleanup_autcpu12_maps(void)
114{
115 if (sram_mtd) {
116 del_mtd_device(sram_mtd);
117 map_destroy(sram_mtd);
118 iounmap((void *)autcpu12_sram_map.virt);
119 }
120}
121
122module_init(init_autcpu12_sram);
123module_exit(cleanup_autcpu12_maps);
124
125MODULE_AUTHOR("Thomas Gleixner");
126MODULE_DESCRIPTION("autcpu12 NV-RAM map driver");
127MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/maps/bast-flash.c b/drivers/mtd/maps/bast-flash.c
new file mode 100644
index 000000000000..44de3a81b277
--- /dev/null
+++ b/drivers/mtd/maps/bast-flash.c
@@ -0,0 +1,227 @@
1/* linux/drivers/mtd/maps/bast_flash.c
2 *
3 * Copyright (c) 2004 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 *
6 * Simtec Bast (EB2410ITX) NOR MTD Mapping driver
7 *
8 * Changelog:
9 * 20-Sep-2004 BJD Initial version
10 *
11 * $Id: bast-flash.c,v 1.1 2004/09/21 14:29:04 bjd Exp $
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26*/
27
28#include <linux/module.h>
29#include <linux/types.h>
30#include <linux/init.h>
31#include <linux/kernel.h>
32#include <linux/string.h>
33#include <linux/ioport.h>
34#include <linux/device.h>
35
36#include <linux/mtd/mtd.h>
37#include <linux/mtd/map.h>
38#include <linux/mtd/partitions.h>
39
40#include <asm/io.h>
41#include <asm/mach-types.h>
42#include <asm/mach/flash.h>
43
44#include <asm/arch/map.h>
45#include <asm/arch/bast-map.h>
46#include <asm/arch/bast-cpld.h>
47
48#ifdef CONFIG_MTD_BAST_MAXSIZE
49#define AREA_MAXSIZE (CONFIG_MTD_BAST_MAXSIZE * (1024*1024))
50#else
51#define AREA_MAXSIZE (32*1024*1024)
52#endif
53
54#define PFX "bast-flash: "
55
56struct bast_flash_info {
57 struct mtd_info *mtd;
58 struct map_info map;
59 struct mtd_partition *partitions;
60 struct resource *area;
61};
62
63static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
64
65static struct bast_flash_info *to_bast_info(struct device *dev)
66{
67 return (struct bast_flash_info *)dev_get_drvdata(dev);
68}
69
70static void bast_flash_setrw(int to)
71{
72 unsigned int val;
73 unsigned long flags;
74
75 local_irq_save(flags);
76 val = __raw_readb(BAST_VA_CTRL3);
77
78 if (to)
79 val |= BAST_CPLD_CTRL3_ROMWEN;
80 else
81 val &= ~BAST_CPLD_CTRL3_ROMWEN;
82
83 pr_debug("new cpld ctrl3=%02x\n", val);
84
85 __raw_writeb(val, BAST_VA_CTRL3);
86 local_irq_restore(flags);
87}
88
89static int bast_flash_remove(struct device *dev)
90{
91 struct bast_flash_info *info = to_bast_info(dev);
92
93 dev_set_drvdata(dev, NULL);
94
95 if (info == NULL)
96 return 0;
97
98 if (info->map.virt != NULL)
99 iounmap(info->map.virt);
100
101 if (info->mtd) {
102 del_mtd_partitions(info->mtd);
103 map_destroy(info->mtd);
104 }
105
106 if (info->partitions)
107 kfree(info->partitions);
108
109 if (info->area) {
110 release_resource(info->area);
111 kfree(info->area);
112 }
113
114 kfree(info);
115
116 return 0;
117}
118
119static int bast_flash_probe(struct device *dev)
120{
121 struct platform_device *pdev = to_platform_device(dev);
122 struct bast_flash_info *info;
123 struct resource *res;
124 int err = 0;
125
126 info = kmalloc(sizeof(*info), GFP_KERNEL);
127 if (info == NULL) {
128 printk(KERN_ERR PFX "no memory for flash info\n");
129 err = -ENOMEM;
130 goto exit_error;
131 }
132
133 memzero(info, sizeof(*info));
134 dev_set_drvdata(dev, info);
135
136 res = pdev->resource; /* assume that the flash has one resource */
137
138 info->map.phys = res->start;
139 info->map.size = res->end - res->start + 1;
140 info->map.name = dev->bus_id;
141 info->map.bankwidth = 2;
142
143 if (info->map.size > AREA_MAXSIZE)
144 info->map.size = AREA_MAXSIZE;
145
146 pr_debug("%s: area %08lx, size %ld\n", __FUNCTION__,
147 info->map.phys, info->map.size);
148
149 info->area = request_mem_region(res->start, info->map.size,
150 pdev->name);
151 if (info->area == NULL) {
152 printk(KERN_ERR PFX "cannot reserve flash memory region\n");
153 err = -ENOENT;
154 goto exit_error;
155 }
156
157 info->map.virt = ioremap(res->start, info->map.size);
158 pr_debug("%s: virt at %08x\n", __FUNCTION__, (int)info->map.virt);
159
160 if (info->map.virt == 0) {
161 printk(KERN_ERR PFX "failed to ioremap() region\n");
162 err = -EIO;
163 goto exit_error;
164 }
165
166 simple_map_init(&info->map);
167
168 /* enable the write to the flash area */
169
170 bast_flash_setrw(1);
171
172 /* probe for the device(s) */
173
174 info->mtd = do_map_probe("jedec_probe", &info->map);
175 if (info->mtd == NULL)
176 info->mtd = do_map_probe("cfi_probe", &info->map);
177
178 if (info->mtd == NULL) {
179 printk(KERN_ERR PFX "map_probe() failed\n");
180 err = -ENXIO;
181 goto exit_error;
182 }
183
184 /* mark ourselves as the owner */
185 info->mtd->owner = THIS_MODULE;
186
187 err = parse_mtd_partitions(info->mtd, probes, &info->partitions, 0);
188 if (err > 0) {
189 err = add_mtd_partitions(info->mtd, info->partitions, err);
190 if (err)
191 printk(KERN_ERR PFX "cannot add/parse partitions\n");
192 }
193
194 if (err == 0)
195 return 0;
196
197 /* fall through to exit error */
198
199 exit_error:
200 bast_flash_remove(dev);
201 return err;
202}
203
204static struct device_driver bast_flash_driver = {
205 .name = "bast-nor",
206 .bus = &platform_bus_type,
207 .probe = bast_flash_probe,
208 .remove = bast_flash_remove,
209};
210
211static int __init bast_flash_init(void)
212{
213 printk("BAST NOR-Flash Driver, (c) 2004 Simtec Electronics\n");
214 return driver_register(&bast_flash_driver);
215}
216
217static void __exit bast_flash_exit(void)
218{
219 driver_unregister(&bast_flash_driver);
220}
221
222module_init(bast_flash_init);
223module_exit(bast_flash_exit);
224
225MODULE_LICENSE("GPL");
226MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
227MODULE_DESCRIPTION("BAST MTD Map driver");
diff --git a/drivers/mtd/maps/beech-mtd.c b/drivers/mtd/maps/beech-mtd.c
new file mode 100644
index 000000000000..5e79c9d5da2b
--- /dev/null
+++ b/drivers/mtd/maps/beech-mtd.c
@@ -0,0 +1,112 @@
1/*
2 * $Id: beech-mtd.c,v 1.10 2004/11/04 13:24:14 gleixner Exp $
3 *
4 * drivers/mtd/maps/beech-mtd.c MTD mappings and partition tables for
5 * IBM 405LP Beech boards.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 * Copyright (C) 2002, International Business Machines Corporation
22 * All Rights Reserved.
23 *
24 * Bishop Brock
25 * IBM Research, Austin Center for Low-Power Computing
26 * bcbrock@us.ibm.com
27 * March 2002
28 *
29 */
30
31#include <linux/kernel.h>
32#include <linux/module.h>
33#include <linux/types.h>
34#include <linux/init.h>
35
36#include <linux/mtd/mtd.h>
37#include <linux/mtd/map.h>
38#include <linux/mtd/partitions.h>
39
40#include <asm/io.h>
41#include <asm/ibm4xx.h>
42
43#define NAME "Beech Linux Flash"
44#define PADDR BEECH_BIGFLASH_PADDR
45#define SIZE BEECH_BIGFLASH_SIZE
46#define BUSWIDTH 1
47
48/* Flash memories on these boards are memory resources, accessed big-endian. */
49
50
51static struct map_info beech_mtd_map = {
52 .name = NAME,
53 .size = SIZE,
54 .bankwidth = BUSWIDTH,
55 .phys = PADDR
56};
57
58static struct mtd_info *beech_mtd;
59
60static struct mtd_partition beech_partitions[2] = {
61 {
62 .name = "Linux Kernel",
63 .size = BEECH_KERNEL_SIZE,
64 .offset = BEECH_KERNEL_OFFSET
65 }, {
66 .name = "Free Area",
67 .size = BEECH_FREE_AREA_SIZE,
68 .offset = BEECH_FREE_AREA_OFFSET
69 }
70};
71
72static int __init
73init_beech_mtd(void)
74{
75 printk("%s: 0x%08x at 0x%08x\n", NAME, SIZE, PADDR);
76
77 beech_mtd_map.virt = ioremap(PADDR, SIZE);
78
79 if (!beech_mtd_map.virt) {
80 printk("%s: failed to ioremap 0x%x\n", NAME, PADDR);
81 return -EIO;
82 }
83
84 simple_map_init(&beech_mtd_map);
85
86 printk("%s: probing %d-bit flash bus\n", NAME, BUSWIDTH * 8);
87 beech_mtd = do_map_probe("cfi_probe", &beech_mtd_map);
88
89 if (!beech_mtd)
90 return -ENXIO;
91
92 beech_mtd->owner = THIS_MODULE;
93
94 return add_mtd_partitions(beech_mtd, beech_partitions, 2);
95}
96
97static void __exit
98cleanup_beech_mtd(void)
99{
100 if (beech_mtd) {
101 del_mtd_partitions(beech_mtd);
102 map_destroy(beech_mtd);
103 iounmap((void *) beech_mtd_map.virt);
104 }
105}
106
107module_init(init_beech_mtd);
108module_exit(cleanup_beech_mtd);
109
110MODULE_LICENSE("GPL");
111MODULE_AUTHOR("Bishop Brock <bcbrock@us.ibm.com>");
112MODULE_DESCRIPTION("MTD map and partitions for IBM 405LP Beech boards");
diff --git a/drivers/mtd/maps/cdb89712.c b/drivers/mtd/maps/cdb89712.c
new file mode 100644
index 000000000000..ab15dac2f936
--- /dev/null
+++ b/drivers/mtd/maps/cdb89712.c
@@ -0,0 +1,268 @@
1/*
2 * Flash on Cirrus CDB89712
3 *
4 * $Id: cdb89712.c,v 1.10 2004/11/04 13:24:14 gleixner Exp $
5 */
6
7#include <linux/module.h>
8#include <linux/types.h>
9#include <linux/kernel.h>
10#include <linux/ioport.h>
11#include <linux/init.h>
12#include <asm/io.h>
13#include <asm/arch/hardware.h>
14#include <linux/mtd/mtd.h>
15#include <linux/mtd/map.h>
16#include <linux/mtd/partitions.h>
17
18
19
20
21static struct mtd_info *flash_mtd;
22
23struct map_info cdb89712_flash_map = {
24 .name = "flash",
25 .size = FLASH_SIZE,
26 .bankwidth = FLASH_WIDTH,
27 .phys = FLASH_START,
28};
29
30struct resource cdb89712_flash_resource = {
31 .name = "Flash",
32 .start = FLASH_START,
33 .end = FLASH_START + FLASH_SIZE - 1,
34 .flags = IORESOURCE_IO | IORESOURCE_BUSY,
35};
36
37static int __init init_cdb89712_flash (void)
38{
39 int err;
40
41 if (request_resource (&ioport_resource, &cdb89712_flash_resource)) {
42 printk(KERN_NOTICE "Failed to reserve Cdb89712 FLASH space\n");
43 err = -EBUSY;
44 goto out;
45 }
46
47 cdb89712_flash_map.virt = ioremap(FLASH_START, FLASH_SIZE);
48 if (!cdb89712_flash_map.virt) {
49 printk(KERN_NOTICE "Failed to ioremap Cdb89712 FLASH space\n");
50 err = -EIO;
51 goto out_resource;
52 }
53 simple_map_init(&cdb89712_flash_map);
54 flash_mtd = do_map_probe("cfi_probe", &cdb89712_flash_map);
55 if (!flash_mtd) {
56 flash_mtd = do_map_probe("map_rom", &cdb89712_flash_map);
57 if (flash_mtd)
58 flash_mtd->erasesize = 0x10000;
59 }
60 if (!flash_mtd) {
61 printk("FLASH probe failed\n");
62 err = -ENXIO;
63 goto out_ioremap;
64 }
65
66 flash_mtd->owner = THIS_MODULE;
67
68 if (add_mtd_device(flash_mtd)) {
69 printk("FLASH device addition failed\n");
70 err = -ENOMEM;
71 goto out_probe;
72 }
73
74 return 0;
75
76out_probe:
77 map_destroy(flash_mtd);
78 flash_mtd = 0;
79out_ioremap:
80 iounmap((void *)cdb89712_flash_map.virt);
81out_resource:
82 release_resource (&cdb89712_flash_resource);
83out:
84 return err;
85}
86
87
88
89
90
91static struct mtd_info *sram_mtd;
92
93struct map_info cdb89712_sram_map = {
94 .name = "SRAM",
95 .size = SRAM_SIZE,
96 .bankwidth = SRAM_WIDTH,
97 .phys = SRAM_START,
98};
99
100struct resource cdb89712_sram_resource = {
101 .name = "SRAM",
102 .start = SRAM_START,
103 .end = SRAM_START + SRAM_SIZE - 1,
104 .flags = IORESOURCE_IO | IORESOURCE_BUSY,
105};
106
107static int __init init_cdb89712_sram (void)
108{
109 int err;
110
111 if (request_resource (&ioport_resource, &cdb89712_sram_resource)) {
112 printk(KERN_NOTICE "Failed to reserve Cdb89712 SRAM space\n");
113 err = -EBUSY;
114 goto out;
115 }
116
117 cdb89712_sram_map.virt = ioremap(SRAM_START, SRAM_SIZE);
118 if (!cdb89712_sram_map.virt) {
119 printk(KERN_NOTICE "Failed to ioremap Cdb89712 SRAM space\n");
120 err = -EIO;
121 goto out_resource;
122 }
123 simple_map_init(&cdb89712_sram_map);
124 sram_mtd = do_map_probe("map_ram", &cdb89712_sram_map);
125 if (!sram_mtd) {
126 printk("SRAM probe failed\n");
127 err = -ENXIO;
128 goto out_ioremap;
129 }
130
131 sram_mtd->owner = THIS_MODULE;
132 sram_mtd->erasesize = 16;
133
134 if (add_mtd_device(sram_mtd)) {
135 printk("SRAM device addition failed\n");
136 err = -ENOMEM;
137 goto out_probe;
138 }
139
140 return 0;
141
142out_probe:
143 map_destroy(sram_mtd);
144 sram_mtd = 0;
145out_ioremap:
146 iounmap((void *)cdb89712_sram_map.virt);
147out_resource:
148 release_resource (&cdb89712_sram_resource);
149out:
150 return err;
151}
152
153
154
155
156
157
158
159static struct mtd_info *bootrom_mtd;
160
161struct map_info cdb89712_bootrom_map = {
162 .name = "BootROM",
163 .size = BOOTROM_SIZE,
164 .bankwidth = BOOTROM_WIDTH,
165 .phys = BOOTROM_START,
166};
167
168struct resource cdb89712_bootrom_resource = {
169 .name = "BootROM",
170 .start = BOOTROM_START,
171 .end = BOOTROM_START + BOOTROM_SIZE - 1,
172 .flags = IORESOURCE_IO | IORESOURCE_BUSY,
173};
174
175static int __init init_cdb89712_bootrom (void)
176{
177 int err;
178
179 if (request_resource (&ioport_resource, &cdb89712_bootrom_resource)) {
180 printk(KERN_NOTICE "Failed to reserve Cdb89712 BOOTROM space\n");
181 err = -EBUSY;
182 goto out;
183 }
184
185 cdb89712_bootrom_map.virt = ioremap(BOOTROM_START, BOOTROM_SIZE);
186 if (!cdb89712_bootrom_map.virt) {
187 printk(KERN_NOTICE "Failed to ioremap Cdb89712 BootROM space\n");
188 err = -EIO;
189 goto out_resource;
190 }
191 simple_map_init(&cdb89712_bootrom_map);
192 bootrom_mtd = do_map_probe("map_rom", &cdb89712_bootrom_map);
193 if (!bootrom_mtd) {
194 printk("BootROM probe failed\n");
195 err = -ENXIO;
196 goto out_ioremap;
197 }
198
199 bootrom_mtd->owner = THIS_MODULE;
200 bootrom_mtd->erasesize = 0x10000;
201
202 if (add_mtd_device(bootrom_mtd)) {
203 printk("BootROM device addition failed\n");
204 err = -ENOMEM;
205 goto out_probe;
206 }
207
208 return 0;
209
210out_probe:
211 map_destroy(bootrom_mtd);
212 bootrom_mtd = 0;
213out_ioremap:
214 iounmap((void *)cdb89712_bootrom_map.virt);
215out_resource:
216 release_resource (&cdb89712_bootrom_resource);
217out:
218 return err;
219}
220
221
222
223
224
225static int __init init_cdb89712_maps(void)
226{
227
228 printk(KERN_INFO "Cirrus CDB89712 MTD mappings:\n Flash 0x%x at 0x%x\n SRAM 0x%x at 0x%x\n BootROM 0x%x at 0x%x\n",
229 FLASH_SIZE, FLASH_START, SRAM_SIZE, SRAM_START, BOOTROM_SIZE, BOOTROM_START);
230
231 init_cdb89712_flash();
232 init_cdb89712_sram();
233 init_cdb89712_bootrom();
234
235 return 0;
236}
237
238
239static void __exit cleanup_cdb89712_maps(void)
240{
241 if (sram_mtd) {
242 del_mtd_device(sram_mtd);
243 map_destroy(sram_mtd);
244 iounmap((void *)cdb89712_sram_map.virt);
245 release_resource (&cdb89712_sram_resource);
246 }
247
248 if (flash_mtd) {
249 del_mtd_device(flash_mtd);
250 map_destroy(flash_mtd);
251 iounmap((void *)cdb89712_flash_map.virt);
252 release_resource (&cdb89712_flash_resource);
253 }
254
255 if (bootrom_mtd) {
256 del_mtd_device(bootrom_mtd);
257 map_destroy(bootrom_mtd);
258 iounmap((void *)cdb89712_bootrom_map.virt);
259 release_resource (&cdb89712_bootrom_resource);
260 }
261}
262
263module_init(init_cdb89712_maps);
264module_exit(cleanup_cdb89712_maps);
265
266MODULE_AUTHOR("Ray L");
267MODULE_DESCRIPTION("ARM CDB89712 map driver");
268MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/maps/ceiva.c b/drivers/mtd/maps/ceiva.c
new file mode 100644
index 000000000000..da8584a662f4
--- /dev/null
+++ b/drivers/mtd/maps/ceiva.c
@@ -0,0 +1,350 @@
1/*
2 * Ceiva flash memory driver.
3 * Copyright (C) 2002 Rob Scott <rscott@mtrob.fdns.net>
4 *
5 * Note: this driver supports jedec compatible devices. Modification
6 * for CFI compatible devices should be straight forward: change
7 * jedec_probe to cfi_probe.
8 *
9 * Based on: sa1100-flash.c, which has the following copyright:
10 * Flash memory access on SA11x0 based devices
11 *
12 * (C) 2000 Nicolas Pitre <nico@cam.org>
13 *
14 * $Id: ceiva.c,v 1.11 2004/09/16 23:27:12 gleixner Exp $
15 */
16
17#include <linux/config.h>
18#include <linux/module.h>
19#include <linux/types.h>
20#include <linux/ioport.h>
21#include <linux/kernel.h>
22#include <linux/init.h>
23
24#include <linux/mtd/mtd.h>
25#include <linux/mtd/map.h>
26#include <linux/mtd/partitions.h>
27#include <linux/mtd/concat.h>
28
29#include <asm/hardware.h>
30#include <asm/mach-types.h>
31#include <asm/io.h>
32#include <asm/sizes.h>
33
34/*
35 * This isn't complete yet, so...
36 */
37#define CONFIG_MTD_CEIVA_STATICMAP
38
39#ifdef CONFIG_MTD_CEIVA_STATICMAP
40/*
41 * See include/linux/mtd/partitions.h for definition of the mtd_partition
42 * structure.
43 *
44 * Please note:
45 * 1. The flash size given should be the largest flash size that can
46 * be accomodated.
47 *
48 * 2. The bus width must defined in clps_setup_flash.
49 *
50 * The MTD layer will detect flash chip aliasing and reduce the size of
51 * the map accordingly.
52 *
53 */
54
55#ifdef CONFIG_ARCH_CEIVA
56/* Flash / Partition sizing */
57/* For the 28F8003, we use the block mapping to calcuate the sizes */
58#define MAX_SIZE_KiB (16 + 8 + 8 + 96 + (7*128))
59#define BOOT_PARTITION_SIZE_KiB (16)
60#define PARAMS_PARTITION_SIZE_KiB (8)
61#define KERNEL_PARTITION_SIZE_KiB (4*128)
62/* Use both remaing portion of first flash, and all of second flash */
63#define ROOT_PARTITION_SIZE_KiB (3*128) + (8*128)
64
65static struct mtd_partition ceiva_partitions[] = {
66 {
67 .name = "Ceiva BOOT partition",
68 .size = BOOT_PARTITION_SIZE_KiB*1024,
69 .offset = 0,
70
71 },{
72 .name = "Ceiva parameters partition",
73 .size = PARAMS_PARTITION_SIZE_KiB*1024,
74 .offset = (16 + 8) * 1024,
75 },{
76 .name = "Ceiva kernel partition",
77 .size = (KERNEL_PARTITION_SIZE_KiB)*1024,
78 .offset = 0x20000,
79
80 },{
81 .name = "Ceiva root filesystem partition",
82 .offset = MTDPART_OFS_APPEND,
83 .size = (ROOT_PARTITION_SIZE_KiB)*1024,
84 }
85};
86#endif
87
88static int __init clps_static_partitions(struct mtd_partition **parts)
89{
90 int nb_parts = 0;
91
92#ifdef CONFIG_ARCH_CEIVA
93 if (machine_is_ceiva()) {
94 *parts = ceiva_partitions;
95 nb_parts = ARRAY_SIZE(ceiva_partitions);
96 }
97#endif
98 return nb_parts;
99}
100#endif
101
102struct clps_info {
103 unsigned long base;
104 unsigned long size;
105 int width;
106 void *vbase;
107 struct map_info *map;
108 struct mtd_info *mtd;
109 struct resource *res;
110};
111
112#define NR_SUBMTD 4
113
114static struct clps_info info[NR_SUBMTD];
115
116static int __init clps_setup_mtd(struct clps_info *clps, int nr, struct mtd_info **rmtd)
117{
118 struct mtd_info *subdev[nr];
119 struct map_info *maps;
120 int i, found = 0, ret = 0;
121
122 /*
123 * Allocate the map_info structs in one go.
124 */
125 maps = kmalloc(sizeof(struct map_info) * nr, GFP_KERNEL);
126 if (!maps)
127 return -ENOMEM;
128 memset(maps, 0, sizeof(struct map_info) * nr);
129 /*
130 * Claim and then map the memory regions.
131 */
132 for (i = 0; i < nr; i++) {
133 if (clps[i].base == (unsigned long)-1)
134 break;
135
136 clps[i].res = request_mem_region(clps[i].base, clps[i].size, "clps flash");
137 if (!clps[i].res) {
138 ret = -EBUSY;
139 break;
140 }
141
142 clps[i].map = maps + i;
143
144 clps[i].map->name = "clps flash";
145 clps[i].map->phys = clps[i].base;
146
147 clps[i].vbase = ioremap(clps[i].base, clps[i].size);
148 if (!clps[i].vbase) {
149 ret = -ENOMEM;
150 break;
151 }
152
153 clps[i].map->virt = (void __iomem *)clps[i].vbase;
154 clps[i].map->bankwidth = clps[i].width;
155 clps[i].map->size = clps[i].size;
156
157 simple_map_init(&clps[i].map);
158
159 clps[i].mtd = do_map_probe("jedec_probe", clps[i].map);
160 if (clps[i].mtd == NULL) {
161 ret = -ENXIO;
162 break;
163 }
164 clps[i].mtd->owner = THIS_MODULE;
165 subdev[i] = clps[i].mtd;
166
167 printk(KERN_INFO "clps flash: JEDEC device at 0x%08lx, %dMiB, "
168 "%d-bit\n", clps[i].base, clps[i].mtd->size >> 20,
169 clps[i].width * 8);
170 found += 1;
171 }
172
173 /*
174 * ENXIO is special. It means we didn't find a chip when
175 * we probed. We need to tear down the mapping, free the
176 * resource and mark it as such.
177 */
178 if (ret == -ENXIO) {
179 iounmap(clps[i].vbase);
180 clps[i].vbase = NULL;
181 release_resource(clps[i].res);
182 clps[i].res = NULL;
183 }
184
185 /*
186 * If we found one device, don't bother with concat support.
187 * If we found multiple devices, use concat if we have it
188 * available, otherwise fail.
189 */
190 if (ret == 0 || ret == -ENXIO) {
191 if (found == 1) {
192 *rmtd = subdev[0];
193 ret = 0;
194 } else if (found > 1) {
195 /*
196 * We detected multiple devices. Concatenate
197 * them together.
198 */
199#ifdef CONFIG_MTD_CONCAT
200 *rmtd = mtd_concat_create(subdev, found,
201 "clps flash");
202 if (*rmtd == NULL)
203 ret = -ENXIO;
204#else
205 printk(KERN_ERR "clps flash: multiple devices "
206 "found but MTD concat support disabled.\n");
207 ret = -ENXIO;
208#endif
209 }
210 }
211
212 /*
213 * If we failed, clean up.
214 */
215 if (ret) {
216 do {
217 if (clps[i].mtd)
218 map_destroy(clps[i].mtd);
219 if (clps[i].vbase)
220 iounmap(clps[i].vbase);
221 if (clps[i].res)
222 release_resource(clps[i].res);
223 } while (i--);
224
225 kfree(maps);
226 }
227
228 return ret;
229}
230
231static void __exit clps_destroy_mtd(struct clps_info *clps, struct mtd_info *mtd)
232{
233 int i;
234
235 del_mtd_partitions(mtd);
236
237 if (mtd != clps[0].mtd)
238 mtd_concat_destroy(mtd);
239
240 for (i = NR_SUBMTD; i >= 0; i--) {
241 if (clps[i].mtd)
242 map_destroy(clps[i].mtd);
243 if (clps[i].vbase)
244 iounmap(clps[i].vbase);
245 if (clps[i].res)
246 release_resource(clps[i].res);
247 }
248 kfree(clps[0].map);
249}
250
251/*
252 * We define the memory space, size, and width for the flash memory
253 * space here.
254 */
255
256static int __init clps_setup_flash(void)
257{
258 int nr;
259
260#ifdef CONFIG_ARCH_CEIVA
261 if (machine_is_ceiva()) {
262 info[0].base = CS0_PHYS_BASE;
263 info[0].size = SZ_32M;
264 info[0].width = CEIVA_FLASH_WIDTH;
265 info[1].base = CS1_PHYS_BASE;
266 info[1].size = SZ_32M;
267 info[1].width = CEIVA_FLASH_WIDTH;
268 nr = 2;
269 }
270#endif
271 return nr;
272}
273
274static struct mtd_partition *parsed_parts;
275static const char *probes[] = { "cmdlinepart", "RedBoot", NULL };
276
277static void __init clps_locate_partitions(struct mtd_info *mtd)
278{
279 const char *part_type = NULL;
280 int nr_parts = 0;
281 do {
282 /*
283 * Partition selection stuff.
284 */
285 nr_parts = parse_mtd_partitions(mtd, probes, &parsed_parts, 0);
286 if (nr_parts > 0) {
287 part_type = "command line";
288 break;
289 }
290#ifdef CONFIG_MTD_CEIVA_STATICMAP
291 nr_parts = clps_static_partitions(&parsed_parts);
292 if (nr_parts > 0) {
293 part_type = "static";
294 break;
295 }
296 printk("found: %d partitions\n", nr_parts);
297#endif
298 } while (0);
299
300 if (nr_parts == 0) {
301 printk(KERN_NOTICE "clps flash: no partition info "
302 "available, registering whole flash\n");
303 add_mtd_device(mtd);
304 } else {
305 printk(KERN_NOTICE "clps flash: using %s partition "
306 "definition\n", part_type);
307 add_mtd_partitions(mtd, parsed_parts, nr_parts);
308 }
309
310 /* Always succeeds. */
311}
312
313static void __exit clps_destroy_partitions(void)
314{
315 if (parsed_parts)
316 kfree(parsed_parts);
317}
318
319static struct mtd_info *mymtd;
320
321static int __init clps_mtd_init(void)
322{
323 int ret;
324 int nr;
325
326 nr = clps_setup_flash();
327 if (nr < 0)
328 return nr;
329
330 ret = clps_setup_mtd(info, nr, &mymtd);
331 if (ret)
332 return ret;
333
334 clps_locate_partitions(mymtd);
335
336 return 0;
337}
338
339static void __exit clps_mtd_cleanup(void)
340{
341 clps_destroy_mtd(info, mymtd);
342 clps_destroy_partitions();
343}
344
345module_init(clps_mtd_init);
346module_exit(clps_mtd_cleanup);
347
348MODULE_AUTHOR("Rob Scott");
349MODULE_DESCRIPTION("Cirrus Logic JEDEC map driver");
350MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/maps/cfi_flagadm.c b/drivers/mtd/maps/cfi_flagadm.c
new file mode 100644
index 000000000000..f72e4f894b32
--- /dev/null
+++ b/drivers/mtd/maps/cfi_flagadm.c
@@ -0,0 +1,139 @@
1/*
2 * Copyright © 2001 Flaga hf. Medical Devices, Kári Davíðsson <kd@flaga.is>
3 *
4 * $Id: cfi_flagadm.c,v 1.14 2004/11/04 13:24:14 gleixner Exp $
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 *
11 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
12 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
14 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
15 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
16 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
17 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
18 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
19 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
20 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
21 *
22 * You should have received a copy of the GNU General Public License along
23 * with this program; if not, write to the Free Software Foundation, Inc.,
24 * 675 Mass Ave, Cambridge, MA 02139, USA.
25 */
26
27#include <linux/module.h>
28#include <linux/types.h>
29#include <linux/kernel.h>
30#include <linux/init.h>
31#include <asm/io.h>
32#include <linux/mtd/mtd.h>
33#include <linux/mtd/map.h>
34#include <linux/mtd/partitions.h>
35
36
37/* We split the flash chip up into four parts.
38 * 1: bootloader firts 128k (0x00000000 - 0x0001FFFF) size 0x020000
39 * 2: kernel 640k (0x00020000 - 0x000BFFFF) size 0x0A0000
40 * 3: compressed 1536k root ramdisk (0x000C0000 - 0x0023FFFF) size 0x180000
41 * 4: writeable diskpartition (jffs)(0x00240000 - 0x003FFFFF) size 0x1C0000
42 */
43
44#define FLASH_PHYS_ADDR 0x40000000
45#define FLASH_SIZE 0x400000
46
47#define FLASH_PARTITION0_ADDR 0x00000000
48#define FLASH_PARTITION0_SIZE 0x00020000
49
50#define FLASH_PARTITION1_ADDR 0x00020000
51#define FLASH_PARTITION1_SIZE 0x000A0000
52
53#define FLASH_PARTITION2_ADDR 0x000C0000
54#define FLASH_PARTITION2_SIZE 0x00180000
55
56#define FLASH_PARTITION3_ADDR 0x00240000
57#define FLASH_PARTITION3_SIZE 0x001C0000
58
59
60struct map_info flagadm_map = {
61 .name = "FlagaDM flash device",
62 .size = FLASH_SIZE,
63 .bankwidth = 2,
64};
65
66struct mtd_partition flagadm_parts[] = {
67 {
68 .name = "Bootloader",
69 .offset = FLASH_PARTITION0_ADDR,
70 .size = FLASH_PARTITION0_SIZE
71 },
72 {
73 .name = "Kernel image",
74 .offset = FLASH_PARTITION1_ADDR,
75 .size = FLASH_PARTITION1_SIZE
76 },
77 {
78 .name = "Initial ramdisk image",
79 .offset = FLASH_PARTITION2_ADDR,
80 .size = FLASH_PARTITION2_SIZE
81 },
82 {
83 .name = "Persistant storage",
84 .offset = FLASH_PARTITION3_ADDR,
85 .size = FLASH_PARTITION3_SIZE
86 }
87};
88
89#define PARTITION_COUNT (sizeof(flagadm_parts)/sizeof(struct mtd_partition))
90
91static struct mtd_info *mymtd;
92
93int __init init_flagadm(void)
94{
95 printk(KERN_NOTICE "FlagaDM flash device: %x at %x\n",
96 FLASH_SIZE, FLASH_PHYS_ADDR);
97
98 flagadm_map.phys = FLASH_PHYS_ADDR;
99 flagadm_map.virt = ioremap(FLASH_PHYS_ADDR,
100 FLASH_SIZE);
101
102 if (!flagadm_map.virt) {
103 printk("Failed to ioremap\n");
104 return -EIO;
105 }
106
107 simple_map_init(&flagadm_map);
108
109 mymtd = do_map_probe("cfi_probe", &flagadm_map);
110 if (mymtd) {
111 mymtd->owner = THIS_MODULE;
112 add_mtd_partitions(mymtd, flagadm_parts, PARTITION_COUNT);
113 printk(KERN_NOTICE "FlagaDM flash device initialized\n");
114 return 0;
115 }
116
117 iounmap((void *)flagadm_map.virt);
118 return -ENXIO;
119}
120
121static void __exit cleanup_flagadm(void)
122{
123 if (mymtd) {
124 del_mtd_partitions(mymtd);
125 map_destroy(mymtd);
126 }
127 if (flagadm_map.virt) {
128 iounmap((void *)flagadm_map.virt);
129 flagadm_map.virt = 0;
130 }
131}
132
133module_init(init_flagadm);
134module_exit(cleanup_flagadm);
135
136
137MODULE_LICENSE("GPL");
138MODULE_AUTHOR("Kári Davíðsson <kd@flaga.is>");
139MODULE_DESCRIPTION("MTD map driver for Flaga digital module");
diff --git a/drivers/mtd/maps/cstm_mips_ixx.c b/drivers/mtd/maps/cstm_mips_ixx.c
new file mode 100644
index 000000000000..ae9252fbf176
--- /dev/null
+++ b/drivers/mtd/maps/cstm_mips_ixx.c
@@ -0,0 +1,270 @@
1/*
2 * $Id: cstm_mips_ixx.c,v 1.12 2004/11/04 13:24:14 gleixner Exp $
3 *
4 * Mapping of a custom board with both AMD CFI and JEDEC flash in partitions.
5 * Config with both CFI and JEDEC device support.
6 *
7 * Basically physmap.c with the addition of partitions and
8 * an array of mapping info to accomodate more than one flash type per board.
9 *
10 * Copyright 2000 MontaVista Software Inc.
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version.
16 *
17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
20 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
24 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * You should have received a copy of the GNU General Public License along
29 * with this program; if not, write to the Free Software Foundation, Inc.,
30 * 675 Mass Ave, Cambridge, MA 02139, USA.
31 */
32
33#include <linux/module.h>
34#include <linux/types.h>
35#include <linux/kernel.h>
36#include <linux/init.h>
37#include <asm/io.h>
38#include <linux/mtd/mtd.h>
39#include <linux/mtd/map.h>
40#include <linux/mtd/partitions.h>
41#include <linux/config.h>
42#include <linux/delay.h>
43
44#if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR)
45#define CC_GCR 0xB4013818
46#define CC_GPBCR 0xB401380A
47#define CC_GPBDR 0xB4013808
48#define CC_M68K_DEVICE 1
49#define CC_M68K_FUNCTION 6
50#define CC_CONFADDR 0xB8004000
51#define CC_CONFDATA 0xB8004004
52#define CC_FC_FCR 0xB8002004
53#define CC_FC_DCR 0xB8002008
54#define CC_GPACR 0xB4013802
55#define CC_GPAICR 0xB4013804
56#endif /* defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) */
57
58#if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR)
59void cstm_mips_ixx_set_vpp(struct map_info *map,int vpp)
60{
61 static DEFINE_SPINLOCK(vpp_lock);
62 static int vpp_count = 0;
63 unsigned long flags;
64
65 spin_lock_irqsave(&vpp_lock, flags);
66
67 if (vpp) {
68 if (!vpp_count++) {
69 __u16 data;
70 __u8 data1;
71 static u8 first = 1;
72
73 // Set GPIO port B pin3 to high
74 data = *(__u16 *)(CC_GPBCR);
75 data = (data & 0xff0f) | 0x0040;
76 *(__u16 *)CC_GPBCR = data;
77 *(__u8 *)CC_GPBDR = (*(__u8*)CC_GPBDR) | 0x08;
78 if (first) {
79 first = 0;
80 /* need to have this delay for first
81 enabling vpp after powerup */
82 udelay(40);
83 }
84 }
85 } else {
86 if (!--vpp_count) {
87 __u16 data;
88
89 // Set GPIO port B pin3 to high
90 data = *(__u16 *)(CC_GPBCR);
91 data = (data & 0xff3f) | 0x0040;
92 *(__u16 *)CC_GPBCR = data;
93 *(__u8 *)CC_GPBDR = (*(__u8*)CC_GPBDR) & 0xf7;
94 }
95 }
96 spin_unlock_irqrestore(&vpp_lock, flags);
97}
98#endif
99
100/* board and partition description */
101
102#define MAX_PHYSMAP_PARTITIONS 8
103struct cstm_mips_ixx_info {
104 char *name;
105 unsigned long window_addr;
106 unsigned long window_size;
107 int bankwidth;
108 int num_partitions;
109};
110
111#if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR)
112#define PHYSMAP_NUMBER 1 // number of board desc structs needed, one per contiguous flash type
113const struct cstm_mips_ixx_info cstm_mips_ixx_board_desc[PHYSMAP_NUMBER] =
114{
115 { // 28F128J3A in 2x16 configuration
116 "big flash", // name
117 0x08000000, // window_addr
118 0x02000000, // window_size
119 4, // bankwidth
120 1, // num_partitions
121 }
122
123};
124static struct mtd_partition cstm_mips_ixx_partitions[PHYSMAP_NUMBER][MAX_PHYSMAP_PARTITIONS] = {
125{ // 28F128J3A in 2x16 configuration
126 {
127 .name = "main partition ",
128 .size = 0x02000000, // 128 x 2 x 128k byte sectors
129 .offset = 0,
130 },
131},
132};
133#else /* defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) */
134#define PHYSMAP_NUMBER 1 // number of board desc structs needed, one per contiguous flash type
135const struct cstm_mips_ixx_info cstm_mips_ixx_board_desc[PHYSMAP_NUMBER] =
136{
137 {
138 "MTD flash", // name
139 CONFIG_MTD_CSTM_MIPS_IXX_START, // window_addr
140 CONFIG_MTD_CSTM_MIPS_IXX_LEN, // window_size
141 CONFIG_MTD_CSTM_MIPS_IXX_BUSWIDTH, // bankwidth
142 1, // num_partitions
143 },
144
145};
146static struct mtd_partition cstm_mips_ixx_partitions[PHYSMAP_NUMBER][MAX_PHYSMAP_PARTITIONS] = {
147{
148 {
149 .name = "main partition",
150 .size = CONFIG_MTD_CSTM_MIPS_IXX_LEN,
151 .offset = 0,
152 },
153},
154};
155#endif /* defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) */
156
157struct map_info cstm_mips_ixx_map[PHYSMAP_NUMBER];
158
159int __init init_cstm_mips_ixx(void)
160{
161 int i;
162 int jedec;
163 struct mtd_info *mymtd;
164 struct mtd_partition *parts;
165
166 /* Initialize mapping */
167 for (i=0;i<PHYSMAP_NUMBER;i++) {
168 printk(KERN_NOTICE "cstm_mips_ixx flash device: 0x%lx at 0x%lx\n",
169 cstm_mips_ixx_board_desc[i].window_size, cstm_mips_ixx_board_desc[i].window_addr);
170
171
172 cstm_mips_ixx_map[i].phys = cstm_mips_ixx_board_desc[i].window_addr;
173 cstm_mips_ixx_map[i].virt = ioremap(cstm_mips_ixx_board_desc[i].window_addr, cstm_mips_ixx_board_desc[i].window_size);
174 if (!cstm_mips_ixx_map[i].virt) {
175 printk(KERN_WARNING "Failed to ioremap\n");
176 return -EIO;
177 }
178 cstm_mips_ixx_map[i].name = cstm_mips_ixx_board_desc[i].name;
179 cstm_mips_ixx_map[i].size = cstm_mips_ixx_board_desc[i].window_size;
180 cstm_mips_ixx_map[i].bankwidth = cstm_mips_ixx_board_desc[i].bankwidth;
181#if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR)
182 cstm_mips_ixx_map[i].set_vpp = cstm_mips_ixx_set_vpp;
183#endif
184 simple_map_init(&cstm_mips_ixx_map[i]);
185 //printk(KERN_NOTICE "cstm_mips_ixx: ioremap is %x\n",(unsigned int)(cstm_mips_ixx_map[i].virt));
186 }
187
188#if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR)
189 setup_ITE_IVR_flash();
190#endif /* defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) */
191
192 for (i=0;i<PHYSMAP_NUMBER;i++) {
193 parts = &cstm_mips_ixx_partitions[i][0];
194 jedec = 0;
195 mymtd = (struct mtd_info *)do_map_probe("cfi_probe", &cstm_mips_ixx_map[i]);
196 //printk(KERN_NOTICE "phymap %d cfi_probe: mymtd is %x\n",i,(unsigned int)mymtd);
197 if (!mymtd) {
198 jedec = 1;
199 mymtd = (struct mtd_info *)do_map_probe("jedec", &cstm_mips_ixx_map[i]);
200 printk(KERN_NOTICE "cstm_mips_ixx %d jedec: mymtd is %x\n",i,(unsigned int)mymtd);
201 }
202 if (mymtd) {
203 mymtd->owner = THIS_MODULE;
204
205 cstm_mips_ixx_map[i].map_priv_2 = (unsigned long)mymtd;
206 add_mtd_partitions(mymtd, parts, cstm_mips_ixx_board_desc[i].num_partitions);
207 }
208 else
209 return -ENXIO;
210 }
211 return 0;
212}
213
214static void __exit cleanup_cstm_mips_ixx(void)
215{
216 int i;
217 struct mtd_info *mymtd;
218
219 for (i=0;i<PHYSMAP_NUMBER;i++) {
220 mymtd = (struct mtd_info *)cstm_mips_ixx_map[i].map_priv_2;
221 if (mymtd) {
222 del_mtd_partitions(mymtd);
223 map_destroy(mymtd);
224 }
225 if (cstm_mips_ixx_map[i].virt) {
226 iounmap((void *)cstm_mips_ixx_map[i].virt);
227 cstm_mips_ixx_map[i].virt = 0;
228 }
229 }
230}
231#if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR)
232void PCISetULongByOffset(__u32 DevNumber, __u32 FuncNumber, __u32 Offset, __u32 data)
233{
234 __u32 offset;
235
236 offset = ( unsigned long )( 0x80000000 | ( DevNumber << 11 ) + ( FuncNumber << 8 ) + Offset) ;
237
238 *(__u32 *)CC_CONFADDR = offset;
239 *(__u32 *)CC_CONFDATA = data;
240}
241void setup_ITE_IVR_flash()
242{
243 __u32 size, base;
244
245 size = 0x0e000000; // 32MiB
246 base = (0x08000000) >> 8 >>1; // Bug: we must shift one more bit
247
248 /* need to set ITE flash to 32 bits instead of default 8 */
249#ifdef CONFIG_MIPS_IVR
250 *(__u32 *)CC_FC_FCR = 0x55;
251 *(__u32 *)CC_GPACR = 0xfffc;
252#else
253 *(__u32 *)CC_FC_FCR = 0x77;
254#endif
255 /* turn bursting off */
256 *(__u32 *)CC_FC_DCR = 0x0;
257
258 /* setup for one chip 4 byte PCI access */
259 PCISetULongByOffset(CC_M68K_DEVICE, CC_M68K_FUNCTION, 0x60, size | base);
260 PCISetULongByOffset(CC_M68K_DEVICE, CC_M68K_FUNCTION, 0x64, 0x02);
261}
262#endif /* defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) */
263
264module_init(init_cstm_mips_ixx);
265module_exit(cleanup_cstm_mips_ixx);
266
267
268MODULE_LICENSE("GPL");
269MODULE_AUTHOR("Alice Hennessy <ahennessy@mvista.com>");
270MODULE_DESCRIPTION("MTD map driver for ITE 8172G and Globespan IVR boards");
diff --git a/drivers/mtd/maps/db1550-flash.c b/drivers/mtd/maps/db1550-flash.c
new file mode 100644
index 000000000000..d213888462a4
--- /dev/null
+++ b/drivers/mtd/maps/db1550-flash.c
@@ -0,0 +1,187 @@
1/*
2 * Flash memory access on Alchemy Db1550 board
3 *
4 * $Id: db1550-flash.c,v 1.7 2004/11/04 13:24:14 gleixner Exp $
5 *
6 * (C) 2004 Embedded Edge, LLC, based on db1550-flash.c:
7 * (C) 2003, 2004 Pete Popov <ppopov@embeddedalley.com>
8 *
9 */
10
11#include <linux/config.h>
12#include <linux/init.h>
13#include <linux/module.h>
14#include <linux/types.h>
15#include <linux/kernel.h>
16
17#include <linux/mtd/mtd.h>
18#include <linux/mtd/map.h>
19#include <linux/mtd/partitions.h>
20
21#include <asm/io.h>
22
23#ifdef DEBUG_RW
24#define DBG(x...) printk(x)
25#else
26#define DBG(x...)
27#endif
28
29static unsigned long window_addr;
30static unsigned long window_size;
31
32
33static struct map_info db1550_map = {
34 .name = "Db1550 flash",
35};
36
37static unsigned char flash_bankwidth = 4;
38
39/*
40 * Support only 64MB NOR Flash parts
41 */
42
43#if defined(CONFIG_MTD_DB1550_BOOT) && defined(CONFIG_MTD_DB1550_USER)
44#define DB1550_BOTH_BANKS
45#elif defined(CONFIG_MTD_DB1550_BOOT) && !defined(CONFIG_MTD_DB1550_USER)
46#define DB1550_BOOT_ONLY
47#elif !defined(CONFIG_MTD_DB1550_BOOT) && defined(CONFIG_MTD_DB1550_USER)
48#define DB1550_USER_ONLY
49#endif
50
51#ifdef DB1550_BOTH_BANKS
52/* both banks will be used. Combine the first bank and the first
53 * part of the second bank together into a single jffs/jffs2
54 * partition.
55 */
56static struct mtd_partition db1550_partitions[] = {
57 /* assume boot[2:0]:swap is '0000' or '1000', which translates to:
58 * 1C00 0000 1FFF FFFF CE0 64MB Boot NOR Flash
59 * 1800 0000 1BFF FFFF CE0 64MB Param NOR Flash
60 */
61 {
62 .name = "User FS",
63 .size = (0x1FC00000 - 0x18000000),
64 .offset = 0x0000000
65 },{
66 .name = "yamon",
67 .size = 0x0100000,
68 .offset = MTDPART_OFS_APPEND,
69 .mask_flags = MTD_WRITEABLE
70 },{
71 .name = "raw kernel",
72 .size = (0x300000 - 0x40000), /* last 256KB is yamon env */
73 .offset = MTDPART_OFS_APPEND,
74 }
75};
76#elif defined(DB1550_BOOT_ONLY)
77static struct mtd_partition db1550_partitions[] = {
78 /* assume boot[2:0]:swap is '0000' or '1000', which translates to:
79 * 1C00 0000 1FFF FFFF CE0 64MB Boot NOR Flash
80 */
81 {
82 .name = "User FS",
83 .size = 0x03c00000,
84 .offset = 0x0000000
85 },{
86 .name = "yamon",
87 .size = 0x0100000,
88 .offset = MTDPART_OFS_APPEND,
89 .mask_flags = MTD_WRITEABLE
90 },{
91 .name = "raw kernel",
92 .size = (0x300000-0x40000), /* last 256KB is yamon env */
93 .offset = MTDPART_OFS_APPEND,
94 }
95};
96#elif defined(DB1550_USER_ONLY)
97static struct mtd_partition db1550_partitions[] = {
98 /* assume boot[2:0]:swap is '0000' or '1000', which translates to:
99 * 1800 0000 1BFF FFFF CE0 64MB Param NOR Flash
100 */
101 {
102 .name = "User FS",
103 .size = (0x4000000 - 0x200000), /* reserve 2MB for raw kernel */
104 .offset = 0x0000000
105 },{
106 .name = "raw kernel",
107 .size = MTDPART_SIZ_FULL,
108 .offset = MTDPART_OFS_APPEND,
109 }
110};
111#else
112#error MTD_DB1550 define combo error /* should never happen */
113#endif
114
115#define NB_OF(x) (sizeof(x)/sizeof(x[0]))
116
117static struct mtd_info *mymtd;
118
119/*
120 * Probe the flash density and setup window address and size
121 * based on user CONFIG options. There are times when we don't
122 * want the MTD driver to be probing the boot or user flash,
123 * so having the option to enable only one bank is important.
124 */
125int setup_flash_params(void)
126{
127#if defined(DB1550_BOTH_BANKS)
128 window_addr = 0x18000000;
129 window_size = 0x8000000;
130#elif defined(DB1550_BOOT_ONLY)
131 window_addr = 0x1C000000;
132 window_size = 0x4000000;
133#else /* USER ONLY */
134 window_addr = 0x18000000;
135 window_size = 0x4000000;
136#endif
137 return 0;
138}
139
140int __init db1550_mtd_init(void)
141{
142 struct mtd_partition *parts;
143 int nb_parts = 0;
144
145 /* Default flash bankwidth */
146 db1550_map.bankwidth = flash_bankwidth;
147
148 if (setup_flash_params())
149 return -ENXIO;
150
151 /*
152 * Static partition definition selection
153 */
154 parts = db1550_partitions;
155 nb_parts = NB_OF(db1550_partitions);
156 db1550_map.size = window_size;
157
158 /*
159 * Now let's probe for the actual flash. Do it here since
160 * specific machine settings might have been set above.
161 */
162 printk(KERN_NOTICE "Db1550 flash: probing %d-bit flash bus\n",
163 db1550_map.bankwidth*8);
164 db1550_map.virt = ioremap(window_addr, window_size);
165 mymtd = do_map_probe("cfi_probe", &db1550_map);
166 if (!mymtd) return -ENXIO;
167 mymtd->owner = THIS_MODULE;
168
169 add_mtd_partitions(mymtd, parts, nb_parts);
170 return 0;
171}
172
173static void __exit db1550_mtd_cleanup(void)
174{
175 if (mymtd) {
176 del_mtd_partitions(mymtd);
177 map_destroy(mymtd);
178 iounmap((void *) db1550_map.virt);
179 }
180}
181
182module_init(db1550_mtd_init);
183module_exit(db1550_mtd_cleanup);
184
185MODULE_AUTHOR("Embedded Edge, LLC");
186MODULE_DESCRIPTION("Db1550 mtd map driver");
187MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/maps/db1x00-flash.c b/drivers/mtd/maps/db1x00-flash.c
new file mode 100644
index 000000000000..faa68ec56902
--- /dev/null
+++ b/drivers/mtd/maps/db1x00-flash.c
@@ -0,0 +1,226 @@
1/*
2 * Flash memory access on Alchemy Db1xxx boards
3 *
4 * $Id: db1x00-flash.c,v 1.6 2004/11/04 13:24:14 gleixner Exp $
5 *
6 * (C) 2003 Pete Popov <ppopov@embeddedalley.com>
7 *
8 */
9
10#include <linux/config.h>
11#include <linux/module.h>
12#include <linux/types.h>
13#include <linux/init.h>
14#include <linux/kernel.h>
15
16#include <linux/mtd/mtd.h>
17#include <linux/mtd/map.h>
18#include <linux/mtd/partitions.h>
19
20#include <asm/io.h>
21
22#ifdef DEBUG_RW
23#define DBG(x...) printk(x)
24#else
25#define DBG(x...)
26#endif
27
28/* MTD CONFIG OPTIONS */
29#if defined(CONFIG_MTD_DB1X00_BOOT) && defined(CONFIG_MTD_DB1X00_USER)
30#define DB1X00_BOTH_BANKS
31#elif defined(CONFIG_MTD_DB1X00_BOOT) && !defined(CONFIG_MTD_DB1X00_USER)
32#define DB1X00_BOOT_ONLY
33#elif !defined(CONFIG_MTD_DB1X00_BOOT) && defined(CONFIG_MTD_DB1X00_USER)
34#define DB1X00_USER_ONLY
35#endif
36
37static unsigned long window_addr;
38static unsigned long window_size;
39static unsigned long flash_size;
40
41static unsigned short *bcsr = (unsigned short *)0xAE000000;
42static unsigned char flash_bankwidth = 4;
43
44/*
45 * The Db1x boards support different flash densities. We setup
46 * the mtd_partition structures below for default of 64Mbit
47 * flash densities, and override the partitions sizes, if
48 * necessary, after we check the board status register.
49 */
50
51#ifdef DB1X00_BOTH_BANKS
52/* both banks will be used. Combine the first bank and the first
53 * part of the second bank together into a single jffs/jffs2
54 * partition.
55 */
56static struct mtd_partition db1x00_partitions[] = {
57 {
58 .name = "User FS",
59 .size = 0x1c00000,
60 .offset = 0x0000000
61 },{
62 .name = "yamon",
63 .size = 0x0100000,
64 .offset = MTDPART_OFS_APPEND,
65 .mask_flags = MTD_WRITEABLE
66 },{
67 .name = "raw kernel",
68 .size = (0x300000-0x40000), /* last 256KB is env */
69 .offset = MTDPART_OFS_APPEND,
70 }
71};
72#elif defined(DB1X00_BOOT_ONLY)
73static struct mtd_partition db1x00_partitions[] = {
74 {
75 .name = "User FS",
76 .size = 0x00c00000,
77 .offset = 0x0000000
78 },{
79 .name = "yamon",
80 .size = 0x0100000,
81 .offset = MTDPART_OFS_APPEND,
82 .mask_flags = MTD_WRITEABLE
83 },{
84 .name = "raw kernel",
85 .size = (0x300000-0x40000), /* last 256KB is env */
86 .offset = MTDPART_OFS_APPEND,
87 }
88};
89#elif defined(DB1X00_USER_ONLY)
90static struct mtd_partition db1x00_partitions[] = {
91 {
92 .name = "User FS",
93 .size = 0x0e00000,
94 .offset = 0x0000000
95 },{
96 .name = "raw kernel",
97 .size = MTDPART_SIZ_FULL,
98 .offset = MTDPART_OFS_APPEND,
99 }
100};
101#else
102#error MTD_DB1X00 define combo error /* should never happen */
103#endif
104#define NB_OF(x) (sizeof(x)/sizeof(x[0]))
105
106#define NAME "Db1x00 Linux Flash"
107
108static struct map_info db1xxx_mtd_map = {
109 .name = NAME,
110};
111
112static struct mtd_partition *parsed_parts;
113static struct mtd_info *db1xxx_mtd;
114
115/*
116 * Probe the flash density and setup window address and size
117 * based on user CONFIG options. There are times when we don't
118 * want the MTD driver to be probing the boot or user flash,
119 * so having the option to enable only one bank is important.
120 */
121int setup_flash_params(void)
122{
123 switch ((bcsr[2] >> 14) & 0x3) {
124 case 0: /* 64Mbit devices */
125 flash_size = 0x800000; /* 8MB per part */
126#if defined(DB1X00_BOTH_BANKS)
127 window_addr = 0x1E000000;
128 window_size = 0x2000000;
129#elif defined(DB1X00_BOOT_ONLY)
130 window_addr = 0x1F000000;
131 window_size = 0x1000000;
132#else /* USER ONLY */
133 window_addr = 0x1E000000;
134 window_size = 0x1000000;
135#endif
136 break;
137 case 1:
138 /* 128 Mbit devices */
139 flash_size = 0x1000000; /* 16MB per part */
140#if defined(DB1X00_BOTH_BANKS)
141 window_addr = 0x1C000000;
142 window_size = 0x4000000;
143 /* USERFS from 0x1C00 0000 to 0x1FC0 0000 */
144 db1x00_partitions[0].size = 0x3C00000;
145#elif defined(DB1X00_BOOT_ONLY)
146 window_addr = 0x1E000000;
147 window_size = 0x2000000;
148 /* USERFS from 0x1E00 0000 to 0x1FC0 0000 */
149 db1x00_partitions[0].size = 0x1C00000;
150#else /* USER ONLY */
151 window_addr = 0x1C000000;
152 window_size = 0x2000000;
153 /* USERFS from 0x1C00 0000 to 0x1DE00000 */
154 db1x00_partitions[0].size = 0x1DE0000;
155#endif
156 break;
157 case 2:
158 /* 256 Mbit devices */
159 flash_size = 0x4000000; /* 64MB per part */
160#if defined(DB1X00_BOTH_BANKS)
161 return 1;
162#elif defined(DB1X00_BOOT_ONLY)
163 /* Boot ROM flash bank only; no user bank */
164 window_addr = 0x1C000000;
165 window_size = 0x4000000;
166 /* USERFS from 0x1C00 0000 to 0x1FC00000 */
167 db1x00_partitions[0].size = 0x3C00000;
168#else /* USER ONLY */
169 return 1;
170#endif
171 break;
172 default:
173 return 1;
174 }
175 db1xxx_mtd_map.size = window_size;
176 db1xxx_mtd_map.bankwidth = flash_bankwidth;
177 db1xxx_mtd_map.phys = window_addr;
178 db1xxx_mtd_map.bankwidth = flash_bankwidth;
179 return 0;
180}
181
182int __init db1x00_mtd_init(void)
183{
184 struct mtd_partition *parts;
185 int nb_parts = 0;
186
187 if (setup_flash_params())
188 return -ENXIO;
189
190 /*
191 * Static partition definition selection
192 */
193 parts = db1x00_partitions;
194 nb_parts = NB_OF(db1x00_partitions);
195
196 /*
197 * Now let's probe for the actual flash. Do it here since
198 * specific machine settings might have been set above.
199 */
200 printk(KERN_NOTICE "Db1xxx flash: probing %d-bit flash bus\n",
201 db1xxx_mtd_map.bankwidth*8);
202 db1xxx_mtd_map.virt = ioremap(window_addr, window_size);
203 db1xxx_mtd = do_map_probe("cfi_probe", &db1xxx_mtd_map);
204 if (!db1xxx_mtd) return -ENXIO;
205 db1xxx_mtd->owner = THIS_MODULE;
206
207 add_mtd_partitions(db1xxx_mtd, parts, nb_parts);
208 return 0;
209}
210
211static void __exit db1x00_mtd_cleanup(void)
212{
213 if (db1xxx_mtd) {
214 del_mtd_partitions(db1xxx_mtd);
215 map_destroy(db1xxx_mtd);
216 if (parsed_parts)
217 kfree(parsed_parts);
218 }
219}
220
221module_init(db1x00_mtd_init);
222module_exit(db1x00_mtd_cleanup);
223
224MODULE_AUTHOR("Pete Popov");
225MODULE_DESCRIPTION("Db1x00 mtd map driver");
226MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/maps/dbox2-flash.c b/drivers/mtd/maps/dbox2-flash.c
new file mode 100644
index 000000000000..d850a27a4b59
--- /dev/null
+++ b/drivers/mtd/maps/dbox2-flash.c
@@ -0,0 +1,126 @@
1/*
2 * $Id: dbox2-flash.c,v 1.13 2004/11/04 13:24:14 gleixner Exp $
3 *
4 * D-Box 2 flash driver
5 */
6
7#include <linux/module.h>
8#include <linux/types.h>
9#include <linux/kernel.h>
10#include <linux/init.h>
11#include <asm/io.h>
12#include <linux/mtd/mtd.h>
13#include <linux/mtd/map.h>
14#include <linux/mtd/partitions.h>
15#include <linux/config.h>
16#include <linux/errno.h>
17
18/* partition_info gives details on the logical partitions that the split the
19 * single flash device into. If the size if zero we use up to the end of the
20 * device. */
21static struct mtd_partition partition_info[]= {
22 {
23 .name = "BR bootloader",
24 .size = 128 * 1024,
25 .offset = 0,
26 .mask_flags = MTD_WRITEABLE
27 },
28 {
29 .name = "FLFS (U-Boot)",
30 .size = 128 * 1024,
31 .offset = MTDPART_OFS_APPEND,
32 .mask_flags = 0
33 },
34 {
35 .name = "Root (SquashFS)",
36 .size = 7040 * 1024,
37 .offset = MTDPART_OFS_APPEND,
38 .mask_flags = 0
39 },
40 {
41 .name = "var (JFFS2)",
42 .size = 896 * 1024,
43 .offset = MTDPART_OFS_APPEND,
44 .mask_flags = 0
45 },
46 {
47 .name = "Flash without bootloader",
48 .size = MTDPART_SIZ_FULL,
49 .offset = 128 * 1024,
50 .mask_flags = 0
51 },
52 {
53 .name = "Complete Flash",
54 .size = MTDPART_SIZ_FULL,
55 .offset = 0,
56 .mask_flags = MTD_WRITEABLE
57 }
58};
59
60#define NUM_PARTITIONS (sizeof(partition_info) / sizeof(partition_info[0]))
61
62#define WINDOW_ADDR 0x10000000
63#define WINDOW_SIZE 0x800000
64
65static struct mtd_info *mymtd;
66
67
68struct map_info dbox2_flash_map = {
69 .name = "D-Box 2 flash memory",
70 .size = WINDOW_SIZE,
71 .bankwidth = 4,
72 .phys = WINDOW_ADDR,
73};
74
75int __init init_dbox2_flash(void)
76{
77 printk(KERN_NOTICE "D-Box 2 flash driver (size->0x%X mem->0x%X)\n", WINDOW_SIZE, WINDOW_ADDR);
78 dbox2_flash_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE);
79
80 if (!dbox2_flash_map.virt) {
81 printk("Failed to ioremap\n");
82 return -EIO;
83 }
84 simple_map_init(&dbox2_flash_map);
85
86 // Probe for dual Intel 28F320 or dual AMD
87 mymtd = do_map_probe("cfi_probe", &dbox2_flash_map);
88 if (!mymtd) {
89 // Probe for single Intel 28F640
90 dbox2_flash_map.bankwidth = 2;
91
92 mymtd = do_map_probe("cfi_probe", &dbox2_flash_map);
93 }
94
95 if (mymtd) {
96 mymtd->owner = THIS_MODULE;
97
98 /* Create MTD devices for each partition. */
99 add_mtd_partitions(mymtd, partition_info, NUM_PARTITIONS);
100
101 return 0;
102 }
103
104 iounmap((void *)dbox2_flash_map.virt);
105 return -ENXIO;
106}
107
108static void __exit cleanup_dbox2_flash(void)
109{
110 if (mymtd) {
111 del_mtd_partitions(mymtd);
112 map_destroy(mymtd);
113 }
114 if (dbox2_flash_map.virt) {
115 iounmap((void *)dbox2_flash_map.virt);
116 dbox2_flash_map.virt = 0;
117 }
118}
119
120module_init(init_dbox2_flash);
121module_exit(cleanup_dbox2_flash);
122
123
124MODULE_LICENSE("GPL");
125MODULE_AUTHOR("Kári Davíðsson <kd@flaga.is>, Bastian Blank <waldi@tuxbox.org>, Alexander Wild <wild@te-elektronik.com>");
126MODULE_DESCRIPTION("MTD map driver for D-Box 2 board");
diff --git a/drivers/mtd/maps/dc21285.c b/drivers/mtd/maps/dc21285.c
new file mode 100644
index 000000000000..938c41f2f056
--- /dev/null
+++ b/drivers/mtd/maps/dc21285.c
@@ -0,0 +1,253 @@
1/*
2 * MTD map driver for flash on the DC21285 (the StrongARM-110 companion chip)
3 *
4 * (C) 2000 Nicolas Pitre <nico@cam.org>
5 *
6 * This code is GPL
7 *
8 * $Id: dc21285.c,v 1.22 2004/11/01 13:39:21 rmk Exp $
9 */
10#include <linux/config.h>
11#include <linux/module.h>
12#include <linux/types.h>
13#include <linux/kernel.h>
14#include <linux/init.h>
15#include <linux/delay.h>
16
17#include <linux/mtd/mtd.h>
18#include <linux/mtd/map.h>
19#include <linux/mtd/partitions.h>
20
21#include <asm/io.h>
22#include <asm/hardware/dec21285.h>
23#include <asm/mach-types.h>
24
25
26static struct mtd_info *dc21285_mtd;
27
28#ifdef CONFIG_ARCH_NETWINDER
29/*
30 * This is really ugly, but it seams to be the only
31 * realiable way to do it, as the cpld state machine
32 * is unpredictible. So we have a 25us penalty per
33 * write access.
34 */
35static void nw_en_write(void)
36{
37 extern spinlock_t gpio_lock;
38 unsigned long flags;
39
40 /*
41 * we want to write a bit pattern XXX1 to Xilinx to enable
42 * the write gate, which will be open for about the next 2ms.
43 */
44 spin_lock_irqsave(&gpio_lock, flags);
45 cpld_modify(1, 1);
46 spin_unlock_irqrestore(&gpio_lock, flags);
47
48 /*
49 * let the ISA bus to catch on...
50 */
51 udelay(25);
52}
53#else
54#define nw_en_write() do { } while (0)
55#endif
56
57static map_word dc21285_read8(struct map_info *map, unsigned long ofs)
58{
59 map_word val;
60 val.x[0] = *(uint8_t*)(map->virt + ofs);
61 return val;
62}
63
64static map_word dc21285_read16(struct map_info *map, unsigned long ofs)
65{
66 map_word val;
67 val.x[0] = *(uint16_t*)(map->virt + ofs);
68 return val;
69}
70
71static map_word dc21285_read32(struct map_info *map, unsigned long ofs)
72{
73 map_word val;
74 val.x[0] = *(uint32_t*)(map->virt + ofs);
75 return val;
76}
77
78static void dc21285_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
79{
80 memcpy(to, (void*)(map->virt + from), len);
81}
82
83static void dc21285_write8(struct map_info *map, const map_word d, unsigned long adr)
84{
85 if (machine_is_netwinder())
86 nw_en_write();
87 *CSR_ROMWRITEREG = adr & 3;
88 adr &= ~3;
89 *(uint8_t*)(map->virt + adr) = d.x[0];
90}
91
92static void dc21285_write16(struct map_info *map, const map_word d, unsigned long adr)
93{
94 if (machine_is_netwinder())
95 nw_en_write();
96 *CSR_ROMWRITEREG = adr & 3;
97 adr &= ~3;
98 *(uint16_t*)(map->virt + adr) = d.x[0];
99}
100
101static void dc21285_write32(struct map_info *map, const map_word d, unsigned long adr)
102{
103 if (machine_is_netwinder())
104 nw_en_write();
105 *(uint32_t*)(map->virt + adr) = d.x[0];
106}
107
108static void dc21285_copy_to_32(struct map_info *map, unsigned long to, const void *from, ssize_t len)
109{
110 while (len > 0) {
111 map_word d;
112 d.x[0] = *((uint32_t*)from)++;
113 dc21285_write32(map, d, to);
114 to += 4;
115 len -= 4;
116 }
117}
118
119static void dc21285_copy_to_16(struct map_info *map, unsigned long to, const void *from, ssize_t len)
120{
121 while (len > 0) {
122 map_word d;
123 d.x[0] = *((uint16_t*)from)++;
124 dc21285_write16(map, d, to);
125 to += 2;
126 len -= 2;
127 }
128}
129
130static void dc21285_copy_to_8(struct map_info *map, unsigned long to, const void *from, ssize_t len)
131{
132 map_word d;
133 d.x[0] = *((uint8_t*)from)++;
134 dc21285_write8(map, d, to);
135 to++;
136 len--;
137}
138
139static struct map_info dc21285_map = {
140 .name = "DC21285 flash",
141 .phys = NO_XIP,
142 .size = 16*1024*1024,
143 .copy_from = dc21285_copy_from,
144};
145
146
147/* Partition stuff */
148#ifdef CONFIG_MTD_PARTITIONS
149static struct mtd_partition *dc21285_parts;
150static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
151#endif
152
153static int __init init_dc21285(void)
154{
155
156#ifdef CONFIG_MTD_PARTITIONS
157 int nrparts;
158#endif
159
160 /* Determine bankwidth */
161 switch (*CSR_SA110_CNTL & (3<<14)) {
162 case SA110_CNTL_ROMWIDTH_8:
163 dc21285_map.bankwidth = 1;
164 dc21285_map.read = dc21285_read8;
165 dc21285_map.write = dc21285_write8;
166 dc21285_map.copy_to = dc21285_copy_to_8;
167 break;
168 case SA110_CNTL_ROMWIDTH_16:
169 dc21285_map.bankwidth = 2;
170 dc21285_map.read = dc21285_read16;
171 dc21285_map.write = dc21285_write16;
172 dc21285_map.copy_to = dc21285_copy_to_16;
173 break;
174 case SA110_CNTL_ROMWIDTH_32:
175 dc21285_map.bankwidth = 4;
176 dc21285_map.read = dc21285_read32;
177 dc21285_map.write = dc21285_write32;
178 dc21285_map.copy_to = dc21285_copy_to_32;
179 break;
180 default:
181 printk (KERN_ERR "DC21285 flash: undefined bankwidth\n");
182 return -ENXIO;
183 }
184 printk (KERN_NOTICE "DC21285 flash support (%d-bit bankwidth)\n",
185 dc21285_map.bankwidth*8);
186
187 /* Let's map the flash area */
188 dc21285_map.virt = ioremap(DC21285_FLASH, 16*1024*1024);
189 if (!dc21285_map.virt) {
190 printk("Failed to ioremap\n");
191 return -EIO;
192 }
193
194 if (machine_is_ebsa285()) {
195 dc21285_mtd = do_map_probe("cfi_probe", &dc21285_map);
196 } else {
197 dc21285_mtd = do_map_probe("jedec_probe", &dc21285_map);
198 }
199
200 if (!dc21285_mtd) {
201 iounmap(dc21285_map.virt);
202 return -ENXIO;
203 }
204
205 dc21285_mtd->owner = THIS_MODULE;
206
207#ifdef CONFIG_MTD_PARTITIONS
208 nrparts = parse_mtd_partitions(dc21285_mtd, probes, &dc21285_parts, 0);
209 if (nrparts > 0)
210 add_mtd_partitions(dc21285_mtd, dc21285_parts, nrparts);
211 else
212#endif
213 add_mtd_device(dc21285_mtd);
214
215 if(machine_is_ebsa285()) {
216 /*
217 * Flash timing is determined with bits 19-16 of the
218 * CSR_SA110_CNTL. The value is the number of wait cycles, or
219 * 0 for 16 cycles (the default). Cycles are 20 ns.
220 * Here we use 7 for 140 ns flash chips.
221 */
222 /* access time */
223 *CSR_SA110_CNTL = ((*CSR_SA110_CNTL & ~0x000f0000) | (7 << 16));
224 /* burst time */
225 *CSR_SA110_CNTL = ((*CSR_SA110_CNTL & ~0x00f00000) | (7 << 20));
226 /* tristate time */
227 *CSR_SA110_CNTL = ((*CSR_SA110_CNTL & ~0x0f000000) | (7 << 24));
228 }
229
230 return 0;
231}
232
233static void __exit cleanup_dc21285(void)
234{
235#ifdef CONFIG_MTD_PARTITIONS
236 if (dc21285_parts) {
237 del_mtd_partitions(dc21285_mtd);
238 kfree(dc21285_parts);
239 } else
240#endif
241 del_mtd_device(dc21285_mtd);
242
243 map_destroy(dc21285_mtd);
244 iounmap(dc21285_map.virt);
245}
246
247module_init(init_dc21285);
248module_exit(cleanup_dc21285);
249
250
251MODULE_LICENSE("GPL");
252MODULE_AUTHOR("Nicolas Pitre <nico@cam.org>");
253MODULE_DESCRIPTION("MTD map driver for DC21285 boards");
diff --git a/drivers/mtd/maps/dilnetpc.c b/drivers/mtd/maps/dilnetpc.c
new file mode 100644
index 000000000000..0bc79c93a584
--- /dev/null
+++ b/drivers/mtd/maps/dilnetpc.c
@@ -0,0 +1,495 @@
1/* dilnetpc.c -- MTD map driver for SSV DIL/Net PC Boards "DNP" and "ADNP"
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
16 *
17 * $Id: dilnetpc.c,v 1.17 2004/11/28 09:40:39 dwmw2 Exp $
18 *
19 * The DIL/Net PC is a tiny embedded PC board made by SSV Embedded Systems
20 * featuring the AMD Elan SC410 processor. There are two variants of this
21 * board: DNP/1486 and ADNP/1486. The DNP version has 2 megs of flash
22 * ROM (Intel 28F016S3) and 8 megs of DRAM, the ADNP version has 4 megs
23 * flash and 16 megs of RAM.
24 * For details, see http://www.ssv-embedded.de/ssv/pc104/p169.htm
25 * and http://www.ssv-embedded.de/ssv/pc104/p170.htm
26 */
27
28#include <linux/config.h>
29#include <linux/module.h>
30#include <linux/types.h>
31#include <linux/kernel.h>
32#include <linux/init.h>
33#include <asm/io.h>
34#include <linux/mtd/mtd.h>
35#include <linux/mtd/map.h>
36#include <linux/mtd/partitions.h>
37#include <linux/mtd/concat.h>
38
39/*
40** The DIL/NetPC keeps its BIOS in two distinct flash blocks.
41** Destroying any of these blocks transforms the DNPC into
42** a paperweight (albeit not a very useful one, considering
43** it only weighs a few grams).
44**
45** Therefore, the BIOS blocks must never be erased or written to
46** except by people who know exactly what they are doing (e.g.
47** to install a BIOS update). These partitions are marked read-only
48** by default, but can be made read/write by undefining
49** DNPC_BIOS_BLOCKS_WRITEPROTECTED:
50*/
51#define DNPC_BIOS_BLOCKS_WRITEPROTECTED
52
53/*
54** The ID string (in ROM) is checked to determine whether we
55** are running on a DNP/1486 or ADNP/1486
56*/
57#define BIOSID_BASE 0x000fe100
58
59#define ID_DNPC "DNP1486"
60#define ID_ADNP "ADNP1486"
61
62/*
63** Address where the flash should appear in CPU space
64*/
65#define FLASH_BASE 0x2000000
66
67/*
68** Chip Setup and Control (CSC) indexed register space
69*/
70#define CSC_INDEX 0x22
71#define CSC_DATA 0x23
72
73#define CSC_MMSWAR 0x30 /* MMS window C-F attributes register */
74#define CSC_MMSWDSR 0x31 /* MMS window C-F device select register */
75
76#define CSC_RBWR 0xa7 /* GPIO Read-Back/Write Register B */
77
78#define CSC_CR 0xd0 /* internal I/O device disable/Echo */
79 /* Z-bus/configuration register */
80
81#define CSC_PCCMDCR 0xf1 /* PC card mode and DMA control register */
82
83
84/*
85** PC Card indexed register space:
86*/
87
88#define PCC_INDEX 0x3e0
89#define PCC_DATA 0x3e1
90
91#define PCC_AWER_B 0x46 /* Socket B Address Window enable register */
92#define PCC_MWSAR_1_Lo 0x58 /* memory window 1 start address low register */
93#define PCC_MWSAR_1_Hi 0x59 /* memory window 1 start address high register */
94#define PCC_MWEAR_1_Lo 0x5A /* memory window 1 stop address low register */
95#define PCC_MWEAR_1_Hi 0x5B /* memory window 1 stop address high register */
96#define PCC_MWAOR_1_Lo 0x5C /* memory window 1 address offset low register */
97#define PCC_MWAOR_1_Hi 0x5D /* memory window 1 address offset high register */
98
99
100/*
101** Access to SC4x0's Chip Setup and Control (CSC)
102** and PC Card (PCC) indexed registers:
103*/
104static inline void setcsc(int reg, unsigned char data)
105{
106 outb(reg, CSC_INDEX);
107 outb(data, CSC_DATA);
108}
109
110static inline unsigned char getcsc(int reg)
111{
112 outb(reg, CSC_INDEX);
113 return(inb(CSC_DATA));
114}
115
116static inline void setpcc(int reg, unsigned char data)
117{
118 outb(reg, PCC_INDEX);
119 outb(data, PCC_DATA);
120}
121
122static inline unsigned char getpcc(int reg)
123{
124 outb(reg, PCC_INDEX);
125 return(inb(PCC_DATA));
126}
127
128
129/*
130************************************************************
131** Enable access to DIL/NetPC's flash by mapping it into
132** the SC4x0's MMS Window C.
133************************************************************
134*/
135static void dnpc_map_flash(unsigned long flash_base, unsigned long flash_size)
136{
137 unsigned long flash_end = flash_base + flash_size - 1;
138
139 /*
140 ** enable setup of MMS windows C-F:
141 */
142 /* - enable PC Card indexed register space */
143 setcsc(CSC_CR, getcsc(CSC_CR) | 0x2);
144 /* - set PC Card controller to operate in standard mode */
145 setcsc(CSC_PCCMDCR, getcsc(CSC_PCCMDCR) & ~1);
146
147 /*
148 ** Program base address and end address of window
149 ** where the flash ROM should appear in CPU address space
150 */
151 setpcc(PCC_MWSAR_1_Lo, (flash_base >> 12) & 0xff);
152 setpcc(PCC_MWSAR_1_Hi, (flash_base >> 20) & 0x3f);
153 setpcc(PCC_MWEAR_1_Lo, (flash_end >> 12) & 0xff);
154 setpcc(PCC_MWEAR_1_Hi, (flash_end >> 20) & 0x3f);
155
156 /* program offset of first flash location to appear in this window (0) */
157 setpcc(PCC_MWAOR_1_Lo, ((0 - flash_base) >> 12) & 0xff);
158 setpcc(PCC_MWAOR_1_Hi, ((0 - flash_base)>> 20) & 0x3f);
159
160 /* set attributes for MMS window C: non-cacheable, write-enabled */
161 setcsc(CSC_MMSWAR, getcsc(CSC_MMSWAR) & ~0x11);
162
163 /* select physical device ROMCS0 (i.e. flash) for MMS Window C */
164 setcsc(CSC_MMSWDSR, getcsc(CSC_MMSWDSR) & ~0x03);
165
166 /* enable memory window 1 */
167 setpcc(PCC_AWER_B, getpcc(PCC_AWER_B) | 0x02);
168
169 /* now disable PC Card indexed register space again */
170 setcsc(CSC_CR, getcsc(CSC_CR) & ~0x2);
171}
172
173
174/*
175************************************************************
176** Disable access to DIL/NetPC's flash by mapping it into
177** the SC4x0's MMS Window C.
178************************************************************
179*/
180static void dnpc_unmap_flash(void)
181{
182 /* - enable PC Card indexed register space */
183 setcsc(CSC_CR, getcsc(CSC_CR) | 0x2);
184
185 /* disable memory window 1 */
186 setpcc(PCC_AWER_B, getpcc(PCC_AWER_B) & ~0x02);
187
188 /* now disable PC Card indexed register space again */
189 setcsc(CSC_CR, getcsc(CSC_CR) & ~0x2);
190}
191
192
193
194/*
195************************************************************
196** Enable/Disable VPP to write to flash
197************************************************************
198*/
199
200static DEFINE_SPINLOCK(dnpc_spin);
201static int vpp_counter = 0;
202/*
203** This is what has to be done for the DNP board ..
204*/
205static void dnp_set_vpp(struct map_info *not_used, int on)
206{
207 spin_lock_irq(&dnpc_spin);
208
209 if (on)
210 {
211 if(++vpp_counter == 1)
212 setcsc(CSC_RBWR, getcsc(CSC_RBWR) & ~0x4);
213 }
214 else
215 {
216 if(--vpp_counter == 0)
217 setcsc(CSC_RBWR, getcsc(CSC_RBWR) | 0x4);
218 else if(vpp_counter < 0)
219 BUG();
220 }
221 spin_unlock_irq(&dnpc_spin);
222}
223
224/*
225** .. and this the ADNP version:
226*/
227static void adnp_set_vpp(struct map_info *not_used, int on)
228{
229 spin_lock_irq(&dnpc_spin);
230
231 if (on)
232 {
233 if(++vpp_counter == 1)
234 setcsc(CSC_RBWR, getcsc(CSC_RBWR) & ~0x8);
235 }
236 else
237 {
238 if(--vpp_counter == 0)
239 setcsc(CSC_RBWR, getcsc(CSC_RBWR) | 0x8);
240 else if(vpp_counter < 0)
241 BUG();
242 }
243 spin_unlock_irq(&dnpc_spin);
244}
245
246
247
248#define DNP_WINDOW_SIZE 0x00200000 /* DNP flash size is 2MiB */
249#define ADNP_WINDOW_SIZE 0x00400000 /* ADNP flash size is 4MiB */
250#define WINDOW_ADDR FLASH_BASE
251
252static struct map_info dnpc_map = {
253 .name = "ADNP Flash Bank",
254 .size = ADNP_WINDOW_SIZE,
255 .bankwidth = 1,
256 .set_vpp = adnp_set_vpp,
257 .phys = WINDOW_ADDR
258};
259
260/*
261** The layout of the flash is somewhat "strange":
262**
263** 1. 960 KiB (15 blocks) : Space for ROM Bootloader and user data
264** 2. 64 KiB (1 block) : System BIOS
265** 3. 960 KiB (15 blocks) : User Data (DNP model) or
266** 3. 3008 KiB (47 blocks) : User Data (ADNP model)
267** 4. 64 KiB (1 block) : System BIOS Entry
268*/
269
270static struct mtd_partition partition_info[]=
271{
272 {
273 .name = "ADNP boot",
274 .offset = 0,
275 .size = 0xf0000,
276 },
277 {
278 .name = "ADNP system BIOS",
279 .offset = MTDPART_OFS_NXTBLK,
280 .size = 0x10000,
281#ifdef DNPC_BIOS_BLOCKS_WRITEPROTECTED
282 .mask_flags = MTD_WRITEABLE,
283#endif
284 },
285 {
286 .name = "ADNP file system",
287 .offset = MTDPART_OFS_NXTBLK,
288 .size = 0x2f0000,
289 },
290 {
291 .name = "ADNP system BIOS entry",
292 .offset = MTDPART_OFS_NXTBLK,
293 .size = MTDPART_SIZ_FULL,
294#ifdef DNPC_BIOS_BLOCKS_WRITEPROTECTED
295 .mask_flags = MTD_WRITEABLE,
296#endif
297 },
298};
299
300#define NUM_PARTITIONS (sizeof(partition_info)/sizeof(partition_info[0]))
301
302static struct mtd_info *mymtd;
303static struct mtd_info *lowlvl_parts[NUM_PARTITIONS];
304static struct mtd_info *merged_mtd;
305
306/*
307** "Highlevel" partition info:
308**
309** Using the MTD concat layer, we can re-arrange partitions to our
310** liking: we construct a virtual MTD device by concatenating the
311** partitions, specifying the sequence such that the boot block
312** is immediately followed by the filesystem block (i.e. the stupid
313** system BIOS block is mapped to a different place). When re-partitioning
314** this concatenated MTD device, we can set the boot block size to
315** an arbitrary (though erase block aligned) value i.e. not one that
316** is dictated by the flash's physical layout. We can thus set the
317** boot block to be e.g. 64 KB (which is fully sufficient if we want
318** to boot an etherboot image) or to -say- 1.5 MB if we want to boot
319** a large kernel image. In all cases, the remainder of the flash
320** is available as file system space.
321*/
322
323static struct mtd_partition higlvl_partition_info[]=
324{
325 {
326 .name = "ADNP boot block",
327 .offset = 0,
328 .size = CONFIG_MTD_DILNETPC_BOOTSIZE,
329 },
330 {
331 .name = "ADNP file system space",
332 .offset = MTDPART_OFS_NXTBLK,
333 .size = ADNP_WINDOW_SIZE-CONFIG_MTD_DILNETPC_BOOTSIZE-0x20000,
334 },
335 {
336 .name = "ADNP system BIOS + BIOS Entry",
337 .offset = MTDPART_OFS_NXTBLK,
338 .size = MTDPART_SIZ_FULL,
339#ifdef DNPC_BIOS_BLOCKS_WRITEPROTECTED
340 .mask_flags = MTD_WRITEABLE,
341#endif
342 },
343};
344
345#define NUM_HIGHLVL_PARTITIONS (sizeof(higlvl_partition_info)/sizeof(partition_info[0]))
346
347
348static int dnp_adnp_probe(void)
349{
350 char *biosid, rc = -1;
351
352 biosid = (char*)ioremap(BIOSID_BASE, 16);
353 if(biosid)
354 {
355 if(!strcmp(biosid, ID_DNPC))
356 rc = 1; /* this is a DNPC */
357 else if(!strcmp(biosid, ID_ADNP))
358 rc = 0; /* this is a ADNPC */
359 }
360 iounmap((void *)biosid);
361 return(rc);
362}
363
364
365static int __init init_dnpc(void)
366{
367 int is_dnp;
368
369 /*
370 ** determine hardware (DNP/ADNP/invalid)
371 */
372 if((is_dnp = dnp_adnp_probe()) < 0)
373 return -ENXIO;
374
375 /*
376 ** Things are set up for ADNP by default
377 ** -> modify all that needs to be different for DNP
378 */
379 if(is_dnp)
380 { /*
381 ** Adjust window size, select correct set_vpp function.
382 ** The partitioning scheme is identical on both DNP
383 ** and ADNP except for the size of the third partition.
384 */
385 int i;
386 dnpc_map.size = DNP_WINDOW_SIZE;
387 dnpc_map.set_vpp = dnp_set_vpp;
388 partition_info[2].size = 0xf0000;
389
390 /*
391 ** increment all string pointers so the leading 'A' gets skipped,
392 ** thus turning all occurrences of "ADNP ..." into "DNP ..."
393 */
394 ++dnpc_map.name;
395 for(i = 0; i < NUM_PARTITIONS; i++)
396 ++partition_info[i].name;
397 higlvl_partition_info[1].size = DNP_WINDOW_SIZE -
398 CONFIG_MTD_DILNETPC_BOOTSIZE - 0x20000;
399 for(i = 0; i < NUM_HIGHLVL_PARTITIONS; i++)
400 ++higlvl_partition_info[i].name;
401 }
402
403 printk(KERN_NOTICE "DIL/Net %s flash: 0x%lx at 0x%lx\n",
404 is_dnp ? "DNPC" : "ADNP", dnpc_map.size, dnpc_map.phys);
405
406 dnpc_map.virt = ioremap_nocache(dnpc_map.phys, dnpc_map.size);
407
408 dnpc_map_flash(dnpc_map.phys, dnpc_map.size);
409
410 if (!dnpc_map.virt) {
411 printk("Failed to ioremap_nocache\n");
412 return -EIO;
413 }
414 simple_map_init(&dnpc_map);
415
416 printk("FLASH virtual address: 0x%p\n", dnpc_map.virt);
417
418 mymtd = do_map_probe("jedec_probe", &dnpc_map);
419
420 if (!mymtd)
421 mymtd = do_map_probe("cfi_probe", &dnpc_map);
422
423 /*
424 ** If flash probes fail, try to make flashes accessible
425 ** at least as ROM. Ajust erasesize in this case since
426 ** the default one (128M) will break our partitioning
427 */
428 if (!mymtd)
429 if((mymtd = do_map_probe("map_rom", &dnpc_map)))
430 mymtd->erasesize = 0x10000;
431
432 if (!mymtd) {
433 iounmap(dnpc_map.virt);
434 return -ENXIO;
435 }
436
437 mymtd->owner = THIS_MODULE;
438
439 /*
440 ** Supply pointers to lowlvl_parts[] array to add_mtd_partitions()
441 ** -> add_mtd_partitions() will _not_ register MTD devices for
442 ** the partitions, but will instead store pointers to the MTD
443 ** objects it creates into our lowlvl_parts[] array.
444 ** NOTE: we arrange the pointers such that the sequence of the
445 ** partitions gets re-arranged: partition #2 follows
446 ** partition #0.
447 */
448 partition_info[0].mtdp = &lowlvl_parts[0];
449 partition_info[1].mtdp = &lowlvl_parts[2];
450 partition_info[2].mtdp = &lowlvl_parts[1];
451 partition_info[3].mtdp = &lowlvl_parts[3];
452
453 add_mtd_partitions(mymtd, partition_info, NUM_PARTITIONS);
454
455 /*
456 ** now create a virtual MTD device by concatenating the for partitions
457 ** (in the sequence given by the lowlvl_parts[] array.
458 */
459 merged_mtd = mtd_concat_create(lowlvl_parts, NUM_PARTITIONS, "(A)DNP Flash Concatenated");
460 if(merged_mtd)
461 { /*
462 ** now partition the new device the way we want it. This time,
463 ** we do not supply mtd pointers in higlvl_partition_info, so
464 ** add_mtd_partitions() will register the devices.
465 */
466 add_mtd_partitions(merged_mtd, higlvl_partition_info, NUM_HIGHLVL_PARTITIONS);
467 }
468
469 return 0;
470}
471
472static void __exit cleanup_dnpc(void)
473{
474 if(merged_mtd) {
475 del_mtd_partitions(merged_mtd);
476 mtd_concat_destroy(merged_mtd);
477 }
478
479 if (mymtd) {
480 del_mtd_partitions(mymtd);
481 map_destroy(mymtd);
482 }
483 if (dnpc_map.virt) {
484 iounmap(dnpc_map.virt);
485 dnpc_unmap_flash();
486 dnpc_map.virt = NULL;
487 }
488}
489
490module_init(init_dnpc);
491module_exit(cleanup_dnpc);
492
493MODULE_LICENSE("GPL");
494MODULE_AUTHOR("Sysgo Real-Time Solutions GmbH");
495MODULE_DESCRIPTION("MTD map driver for SSV DIL/NetPC DNP & ADNP");
diff --git a/drivers/mtd/maps/dmv182.c b/drivers/mtd/maps/dmv182.c
new file mode 100644
index 000000000000..b9bc63503e26
--- /dev/null
+++ b/drivers/mtd/maps/dmv182.c
@@ -0,0 +1,149 @@
1
2/*
3 * drivers/mtd/maps/svme182.c
4 *
5 * Flash map driver for the Dy4 SVME182 board
6 *
7 * $Id: dmv182.c,v 1.5 2004/11/04 13:24:14 gleixner Exp $
8 *
9 * Copyright 2003-2004, TimeSys Corporation
10 *
11 * Based on the SVME181 flash map, by Tom Nelson, Dot4, Inc. for TimeSys Corp.
12 *
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version.
17 */
18
19#include <linux/config.h>
20#include <linux/module.h>
21#include <linux/init.h>
22#include <linux/types.h>
23#include <linux/kernel.h>
24#include <asm/io.h>
25#include <linux/mtd/mtd.h>
26#include <linux/mtd/map.h>
27#include <linux/mtd/partitions.h>
28#include <linux/errno.h>
29
30/*
31 * This driver currently handles only the 16MiB user flash bank 1 on the
32 * board. It does not provide access to bank 0 (contains the Dy4 FFW), bank 2
33 * (VxWorks boot), or the optional 48MiB expansion flash.
34 *
35 * scott.wood@timesys.com: On the newer boards with 128MiB flash, it
36 * now supports the first 96MiB (the boot flash bank containing FFW
37 * is excluded). The VxWorks loader is in partition 1.
38 */
39
40#define FLASH_BASE_ADDR 0xf0000000
41#define FLASH_BANK_SIZE (128*1024*1024)
42
43MODULE_AUTHOR("Scott Wood, TimeSys Corporation <scott.wood@timesys.com>");
44MODULE_DESCRIPTION("User-programmable flash device on the Dy4 SVME182 board");
45MODULE_LICENSE("GPL");
46
47static struct map_info svme182_map = {
48 .name = "Dy4 SVME182",
49 .bankwidth = 32,
50 .size = 128 * 1024 * 1024
51};
52
53#define BOOTIMAGE_PART_SIZE ((6*1024*1024)-RESERVED_PART_SIZE)
54
55// Allow 6MiB for the kernel
56#define NEW_BOOTIMAGE_PART_SIZE (6 * 1024 * 1024)
57// Allow 1MiB for the bootloader
58#define NEW_BOOTLOADER_PART_SIZE (1024 * 1024)
59// Use the remaining 9MiB at the end of flash for the RFS
60#define NEW_RFS_PART_SIZE (0x01000000 - NEW_BOOTLOADER_PART_SIZE - \
61 NEW_BOOTIMAGE_PART_SIZE)
62
63static struct mtd_partition svme182_partitions[] = {
64 // The Lower PABS is only 128KiB, but the partition code doesn't
65 // like partitions that don't end on the largest erase block
66 // size of the device, even if all of the erase blocks in the
67 // partition are small ones. The hardware should prevent
68 // writes to the actual PABS areas.
69 {
70 name: "Lower PABS and CPU 0 bootloader or kernel",
71 size: 6*1024*1024,
72 offset: 0,
73 },
74 {
75 name: "Root Filesystem",
76 size: 10*1024*1024,
77 offset: MTDPART_OFS_NXTBLK
78 },
79 {
80 name: "CPU1 Bootloader",
81 size: 1024*1024,
82 offset: MTDPART_OFS_NXTBLK,
83 },
84 {
85 name: "Extra",
86 size: 110*1024*1024,
87 offset: MTDPART_OFS_NXTBLK
88 },
89 {
90 name: "Foundation Firmware and Upper PABS",
91 size: 1024*1024,
92 offset: MTDPART_OFS_NXTBLK,
93 mask_flags: MTD_WRITEABLE // read-only
94 }
95};
96
97static struct mtd_info *this_mtd;
98
99static int __init init_svme182(void)
100{
101 struct mtd_partition *partitions;
102 int num_parts = sizeof(svme182_partitions) / sizeof(struct mtd_partition);
103
104 partitions = svme182_partitions;
105
106 svme182_map.virt = ioremap(FLASH_BASE_ADDR, svme182_map.size);
107
108 if (svme182_map.virt == 0) {
109 printk("Failed to ioremap FLASH memory area.\n");
110 return -EIO;
111 }
112
113 simple_map_init(&svme182_map);
114
115 this_mtd = do_map_probe("cfi_probe", &svme182_map);
116 if (!this_mtd)
117 {
118 iounmap((void *)svme182_map.virt);
119 return -ENXIO;
120 }
121
122 printk(KERN_NOTICE "SVME182 flash device: %dMiB at 0x%08x\n",
123 this_mtd->size >> 20, FLASH_BASE_ADDR);
124
125 this_mtd->owner = THIS_MODULE;
126 add_mtd_partitions(this_mtd, partitions, num_parts);
127
128 return 0;
129}
130
131static void __exit cleanup_svme182(void)
132{
133 if (this_mtd)
134 {
135 del_mtd_partitions(this_mtd);
136 map_destroy(this_mtd);
137 }
138
139 if (svme182_map.virt)
140 {
141 iounmap((void *)svme182_map.virt);
142 svme182_map.virt = 0;
143 }
144
145 return;
146}
147
148module_init(init_svme182);
149module_exit(cleanup_svme182);
diff --git a/drivers/mtd/maps/ebony.c b/drivers/mtd/maps/ebony.c
new file mode 100644
index 000000000000..b9d9cf4854b6
--- /dev/null
+++ b/drivers/mtd/maps/ebony.c
@@ -0,0 +1,163 @@
1/*
2 * $Id: ebony.c,v 1.15 2004/12/09 18:39:54 holindho Exp $
3 *
4 * Mapping for Ebony user flash
5 *
6 * Matt Porter <mporter@kernel.crashing.org>
7 *
8 * Copyright 2002-2004 MontaVista Software Inc.
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
14 */
15
16#include <linux/module.h>
17#include <linux/types.h>
18#include <linux/kernel.h>
19#include <linux/init.h>
20#include <linux/mtd/mtd.h>
21#include <linux/mtd/map.h>
22#include <linux/mtd/partitions.h>
23#include <linux/config.h>
24#include <linux/version.h>
25#include <asm/io.h>
26#include <asm/ibm44x.h>
27#include <platforms/4xx/ebony.h>
28
29static struct mtd_info *flash;
30
31static struct map_info ebony_small_map = {
32 .name = "Ebony small flash",
33 .size = EBONY_SMALL_FLASH_SIZE,
34 .bankwidth = 1,
35};
36
37static struct map_info ebony_large_map = {
38 .name = "Ebony large flash",
39 .size = EBONY_LARGE_FLASH_SIZE,
40 .bankwidth = 1,
41};
42
43static struct mtd_partition ebony_small_partitions[] = {
44 {
45 .name = "OpenBIOS",
46 .offset = 0x0,
47 .size = 0x80000,
48 }
49};
50
51static struct mtd_partition ebony_large_partitions[] = {
52 {
53 .name = "fs",
54 .offset = 0,
55 .size = 0x380000,
56 },
57 {
58 .name = "firmware",
59 .offset = 0x380000,
60 .size = 0x80000,
61 }
62};
63
64int __init init_ebony(void)
65{
66 u8 fpga0_reg;
67 u8 __iomem *fpga0_adr;
68 unsigned long long small_flash_base, large_flash_base;
69
70 fpga0_adr = ioremap64(EBONY_FPGA_ADDR, 16);
71 if (!fpga0_adr)
72 return -ENOMEM;
73
74 fpga0_reg = readb(fpga0_adr);
75 iounmap(fpga0_adr);
76
77 if (EBONY_BOOT_SMALL_FLASH(fpga0_reg) &&
78 !EBONY_FLASH_SEL(fpga0_reg))
79 small_flash_base = EBONY_SMALL_FLASH_HIGH2;
80 else if (EBONY_BOOT_SMALL_FLASH(fpga0_reg) &&
81 EBONY_FLASH_SEL(fpga0_reg))
82 small_flash_base = EBONY_SMALL_FLASH_HIGH1;
83 else if (!EBONY_BOOT_SMALL_FLASH(fpga0_reg) &&
84 !EBONY_FLASH_SEL(fpga0_reg))
85 small_flash_base = EBONY_SMALL_FLASH_LOW2;
86 else
87 small_flash_base = EBONY_SMALL_FLASH_LOW1;
88
89 if (EBONY_BOOT_SMALL_FLASH(fpga0_reg) &&
90 !EBONY_ONBRD_FLASH_EN(fpga0_reg))
91 large_flash_base = EBONY_LARGE_FLASH_LOW;
92 else
93 large_flash_base = EBONY_LARGE_FLASH_HIGH;
94
95 ebony_small_map.phys = small_flash_base;
96 ebony_small_map.virt = ioremap64(small_flash_base,
97 ebony_small_map.size);
98
99 if (!ebony_small_map.virt) {
100 printk("Failed to ioremap flash\n");
101 return -EIO;
102 }
103
104 simple_map_init(&ebony_small_map);
105
106 flash = do_map_probe("jedec_probe", &ebony_small_map);
107 if (flash) {
108 flash->owner = THIS_MODULE;
109 add_mtd_partitions(flash, ebony_small_partitions,
110 ARRAY_SIZE(ebony_small_partitions));
111 } else {
112 printk("map probe failed for flash\n");
113 return -ENXIO;
114 }
115
116 ebony_large_map.phys = large_flash_base;
117 ebony_large_map.virt = ioremap64(large_flash_base,
118 ebony_large_map.size);
119
120 if (!ebony_large_map.virt) {
121 printk("Failed to ioremap flash\n");
122 return -EIO;
123 }
124
125 simple_map_init(&ebony_large_map);
126
127 flash = do_map_probe("jedec_probe", &ebony_large_map);
128 if (flash) {
129 flash->owner = THIS_MODULE;
130 add_mtd_partitions(flash, ebony_large_partitions,
131 ARRAY_SIZE(ebony_large_partitions));
132 } else {
133 printk("map probe failed for flash\n");
134 return -ENXIO;
135 }
136
137 return 0;
138}
139
140static void __exit cleanup_ebony(void)
141{
142 if (flash) {
143 del_mtd_partitions(flash);
144 map_destroy(flash);
145 }
146
147 if (ebony_small_map.virt) {
148 iounmap(ebony_small_map.virt);
149 ebony_small_map.virt = NULL;
150 }
151
152 if (ebony_large_map.virt) {
153 iounmap(ebony_large_map.virt);
154 ebony_large_map.virt = NULL;
155 }
156}
157
158module_init(init_ebony);
159module_exit(cleanup_ebony);
160
161MODULE_LICENSE("GPL");
162MODULE_AUTHOR("Matt Porter <mporter@kernel.crashing.org>");
163MODULE_DESCRIPTION("MTD map and partitions for IBM 440GP Ebony boards");
diff --git a/drivers/mtd/maps/edb7312.c b/drivers/mtd/maps/edb7312.c
new file mode 100644
index 000000000000..8b0da394f3fa
--- /dev/null
+++ b/drivers/mtd/maps/edb7312.c
@@ -0,0 +1,147 @@
1/*
2 * $Id: edb7312.c,v 1.13 2004/11/04 13:24:14 gleixner Exp $
3 *
4 * Handle mapping of the NOR flash on Cogent EDB7312 boards
5 *
6 * Copyright 2002 SYSGO Real-Time Solutions GmbH
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/module.h>
14#include <linux/types.h>
15#include <linux/kernel.h>
16#include <linux/init.h>
17#include <asm/io.h>
18#include <linux/mtd/mtd.h>
19#include <linux/mtd/map.h>
20#include <linux/config.h>
21
22#ifdef CONFIG_MTD_PARTITIONS
23#include <linux/mtd/partitions.h>
24#endif
25
26#define WINDOW_ADDR 0x00000000 /* physical properties of flash */
27#define WINDOW_SIZE 0x01000000
28#define BUSWIDTH 2
29#define FLASH_BLOCKSIZE_MAIN 0x20000
30#define FLASH_NUMBLOCKS_MAIN 128
31/* can be "cfi_probe", "jedec_probe", "map_rom", NULL }; */
32#define PROBETYPES { "cfi_probe", NULL }
33
34#define MSG_PREFIX "EDB7312-NOR:" /* prefix for our printk()'s */
35#define MTDID "edb7312-nor" /* for mtdparts= partitioning */
36
37static struct mtd_info *mymtd;
38
39struct map_info edb7312nor_map = {
40 .name = "NOR flash on EDB7312",
41 .size = WINDOW_SIZE,
42 .bankwidth = BUSWIDTH,
43 .phys = WINDOW_ADDR,
44};
45
46#ifdef CONFIG_MTD_PARTITIONS
47
48/*
49 * MTD partitioning stuff
50 */
51static struct mtd_partition static_partitions[3] =
52{
53 {
54 .name = "ARMboot",
55 .size = 0x40000,
56 .offset = 0
57 },
58 {
59 .name = "Kernel",
60 .size = 0x200000,
61 .offset = 0x40000
62 },
63 {
64 .name = "RootFS",
65 .size = 0xDC0000,
66 .offset = 0x240000
67 },
68};
69
70static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
71
72#endif
73
74static int mtd_parts_nb = 0;
75static struct mtd_partition *mtd_parts = 0;
76
77int __init init_edb7312nor(void)
78{
79 static const char *rom_probe_types[] = PROBETYPES;
80 const char **type;
81 const char *part_type = 0;
82
83 printk(KERN_NOTICE MSG_PREFIX "0x%08x at 0x%08x\n",
84 WINDOW_SIZE, WINDOW_ADDR);
85 edb7312nor_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE);
86
87 if (!edb7312nor_map.virt) {
88 printk(MSG_PREFIX "failed to ioremap\n");
89 return -EIO;
90 }
91
92 simple_map_init(&edb7312nor_map);
93
94 mymtd = 0;
95 type = rom_probe_types;
96 for(; !mymtd && *type; type++) {
97 mymtd = do_map_probe(*type, &edb7312nor_map);
98 }
99 if (mymtd) {
100 mymtd->owner = THIS_MODULE;
101
102#ifdef CONFIG_MTD_PARTITIONS
103 mtd_parts_nb = parse_mtd_partitions(mymtd, probes, &mtd_parts, MTDID);
104 if (mtd_parts_nb > 0)
105 part_type = "detected";
106
107 if (mtd_parts_nb == 0)
108 {
109 mtd_parts = static_partitions;
110 mtd_parts_nb = ARRAY_SIZE(static_partitions);
111 part_type = "static";
112 }
113#endif
114 add_mtd_device(mymtd);
115 if (mtd_parts_nb == 0)
116 printk(KERN_NOTICE MSG_PREFIX "no partition info available\n");
117 else
118 {
119 printk(KERN_NOTICE MSG_PREFIX
120 "using %s partition definition\n", part_type);
121 add_mtd_partitions(mymtd, mtd_parts, mtd_parts_nb);
122 }
123 return 0;
124 }
125
126 iounmap((void *)edb7312nor_map.virt);
127 return -ENXIO;
128}
129
130static void __exit cleanup_edb7312nor(void)
131{
132 if (mymtd) {
133 del_mtd_device(mymtd);
134 map_destroy(mymtd);
135 }
136 if (edb7312nor_map.virt) {
137 iounmap((void *)edb7312nor_map.virt);
138 edb7312nor_map.virt = 0;
139 }
140}
141
142module_init(init_edb7312nor);
143module_exit(cleanup_edb7312nor);
144
145MODULE_LICENSE("GPL");
146MODULE_AUTHOR("Marius Groeger <mag@sysgo.de>");
147MODULE_DESCRIPTION("Generic configurable MTD map driver");
diff --git a/drivers/mtd/maps/elan-104nc.c b/drivers/mtd/maps/elan-104nc.c
new file mode 100644
index 000000000000..e9465f5c069e
--- /dev/null
+++ b/drivers/mtd/maps/elan-104nc.c
@@ -0,0 +1,228 @@
1/* elan-104nc.c -- MTD map driver for Arcom Control Systems ELAN-104NC
2
3 Copyright (C) 2000 Arcom Control System Ltd
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
18
19 $Id: elan-104nc.c,v 1.25 2004/11/28 09:40:39 dwmw2 Exp $
20
21The ELAN-104NC has up to 8 Mibyte of Intel StrataFlash (28F320/28F640) in x16
22mode. This drivers uses the CFI probe and Intel Extended Command Set drivers.
23
24The flash is accessed as follows:
25
26 32 kbyte memory window at 0xb0000-0xb7fff
27
28 16 bit I/O port (0x22) for some sort of paging.
29
30The single flash device is divided into 3 partition which appear as separate
31MTD devices.
32
33Linux thinks that the I/O port is used by the PIC and hence check_region() will
34always fail. So we don't do it. I just hope it doesn't break anything.
35*/
36#include <linux/module.h>
37#include <linux/slab.h>
38#include <linux/ioport.h>
39#include <linux/init.h>
40#include <asm/io.h>
41
42#include <linux/mtd/map.h>
43#include <linux/mtd/mtd.h>
44#include <linux/mtd/partitions.h>
45
46#define WINDOW_START 0xb0000
47/* Number of bits in offset. */
48#define WINDOW_SHIFT 15
49#define WINDOW_LENGTH (1 << WINDOW_SHIFT)
50/* The bits for the offset into the window. */
51#define WINDOW_MASK (WINDOW_LENGTH-1)
52#define PAGE_IO 0x22
53#define PAGE_IO_SIZE 2
54
55static volatile int page_in_window = -1; // Current page in window.
56static void __iomem *iomapadr;
57static DEFINE_SPINLOCK(elan_104nc_spin);
58
59/* partition_info gives details on the logical partitions that the split the
60 * single flash device into. If the size if zero we use up to the end of the
61 * device. */
62static struct mtd_partition partition_info[]={
63 { .name = "ELAN-104NC flash boot partition",
64 .offset = 0,
65 .size = 640*1024 },
66 { .name = "ELAN-104NC flash partition 1",
67 .offset = 640*1024,
68 .size = 896*1024 },
69 { .name = "ELAN-104NC flash partition 2",
70 .offset = (640+896)*1024 }
71};
72#define NUM_PARTITIONS (sizeof(partition_info)/sizeof(partition_info[0]))
73
74/*
75 * If no idea what is going on here. This is taken from the FlashFX stuff.
76 */
77#define ROMCS 1
78
79static inline void elan_104nc_setup(void)
80{
81 u16 t;
82
83 outw( 0x0023 + ROMCS*2, PAGE_IO );
84 t=inb( PAGE_IO+1 );
85
86 t=(t & 0xf9) | 0x04;
87
88 outw( ((0x0023 + ROMCS*2) | (t << 8)), PAGE_IO );
89}
90
91static inline void elan_104nc_page(struct map_info *map, unsigned long ofs)
92{
93 unsigned long page = ofs >> WINDOW_SHIFT;
94
95 if( page!=page_in_window ) {
96 int cmd1;
97 int cmd2;
98
99 cmd1=(page & 0x700) + 0x0833 + ROMCS*0x4000;
100 cmd2=((page & 0xff) << 8) + 0x0032;
101
102 outw( cmd1, PAGE_IO );
103 outw( cmd2, PAGE_IO );
104
105 page_in_window = page;
106 }
107}
108
109
110static map_word elan_104nc_read16(struct map_info *map, unsigned long ofs)
111{
112 map_word ret;
113 spin_lock(&elan_104nc_spin);
114 elan_104nc_page(map, ofs);
115 ret.x[0] = readw(iomapadr + (ofs & WINDOW_MASK));
116 spin_unlock(&elan_104nc_spin);
117 return ret;
118}
119
120static void elan_104nc_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
121{
122 while (len) {
123 unsigned long thislen = len;
124 if (len > (WINDOW_LENGTH - (from & WINDOW_MASK)))
125 thislen = WINDOW_LENGTH-(from & WINDOW_MASK);
126
127 spin_lock(&elan_104nc_spin);
128 elan_104nc_page(map, from);
129 memcpy_fromio(to, iomapadr + (from & WINDOW_MASK), thislen);
130 spin_unlock(&elan_104nc_spin);
131 to += thislen;
132 from += thislen;
133 len -= thislen;
134 }
135}
136
137static void elan_104nc_write16(struct map_info *map, map_word d, unsigned long adr)
138{
139 spin_lock(&elan_104nc_spin);
140 elan_104nc_page(map, adr);
141 writew(d.x[0], iomapadr + (adr & WINDOW_MASK));
142 spin_unlock(&elan_104nc_spin);
143}
144
145static void elan_104nc_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
146{
147 while(len) {
148 unsigned long thislen = len;
149 if (len > (WINDOW_LENGTH - (to & WINDOW_MASK)))
150 thislen = WINDOW_LENGTH-(to & WINDOW_MASK);
151
152 spin_lock(&elan_104nc_spin);
153 elan_104nc_page(map, to);
154 memcpy_toio(iomapadr + (to & WINDOW_MASK), from, thislen);
155 spin_unlock(&elan_104nc_spin);
156 to += thislen;
157 from += thislen;
158 len -= thislen;
159 }
160}
161
162static struct map_info elan_104nc_map = {
163 .name = "ELAN-104NC flash",
164 .phys = NO_XIP,
165 .size = 8*1024*1024, /* this must be set to a maximum possible amount
166 of flash so the cfi probe routines find all
167 the chips */
168 .bankwidth = 2,
169 .read = elan_104nc_read16,
170 .copy_from = elan_104nc_copy_from,
171 .write = elan_104nc_write16,
172 .copy_to = elan_104nc_copy_to
173};
174
175/* MTD device for all of the flash. */
176static struct mtd_info *all_mtd;
177
178static void cleanup_elan_104nc(void)
179{
180 if( all_mtd ) {
181 del_mtd_partitions( all_mtd );
182 map_destroy( all_mtd );
183 }
184
185 iounmap(iomapadr);
186}
187
188static int __init init_elan_104nc(void)
189{
190 /* Urg! We use I/O port 0x22 without request_region()ing it,
191 because it's already allocated to the PIC. */
192
193 iomapadr = ioremap(WINDOW_START, WINDOW_LENGTH);
194 if (!iomapadr) {
195 printk( KERN_ERR"%s: failed to ioremap memory region\n",
196 elan_104nc_map.name );
197 return -EIO;
198 }
199
200 printk( KERN_INFO"%s: IO:0x%x-0x%x MEM:0x%x-0x%x\n",
201 elan_104nc_map.name,
202 PAGE_IO, PAGE_IO+PAGE_IO_SIZE-1,
203 WINDOW_START, WINDOW_START+WINDOW_LENGTH-1 );
204
205 elan_104nc_setup();
206
207 /* Probe for chip. */
208 all_mtd = do_map_probe("cfi_probe", &elan_104nc_map );
209 if( !all_mtd ) {
210 cleanup_elan_104nc();
211 return -ENXIO;
212 }
213
214 all_mtd->owner = THIS_MODULE;
215
216 /* Create MTD devices for each partition. */
217 add_mtd_partitions( all_mtd, partition_info, NUM_PARTITIONS );
218
219 return 0;
220}
221
222module_init(init_elan_104nc);
223module_exit(cleanup_elan_104nc);
224
225
226MODULE_LICENSE("GPL");
227MODULE_AUTHOR("Arcom Control Systems Ltd.");
228MODULE_DESCRIPTION("MTD map driver for Arcom Control Systems ELAN-104NC");
diff --git a/drivers/mtd/maps/epxa10db-flash.c b/drivers/mtd/maps/epxa10db-flash.c
new file mode 100644
index 000000000000..ab6dbe2b8cce
--- /dev/null
+++ b/drivers/mtd/maps/epxa10db-flash.c
@@ -0,0 +1,176 @@
1/*
2 * Flash memory access on EPXA based devices
3 *
4 * (C) 2000 Nicolas Pitre <nico@cam.org>
5 * Copyright (C) 2001 Altera Corporation
6 * Copyright (C) 2001 Red Hat, Inc.
7 *
8 * $Id: epxa10db-flash.c,v 1.13 2004/11/04 13:24:14 gleixner Exp $
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
24
25#include <linux/config.h>
26#include <linux/module.h>
27#include <linux/types.h>
28#include <linux/kernel.h>
29#include <linux/init.h>
30#include <asm/io.h>
31#include <linux/mtd/mtd.h>
32#include <linux/mtd/map.h>
33#include <linux/mtd/partitions.h>
34
35#include <asm/hardware.h>
36#ifdef CONFIG_EPXA10DB
37#define BOARD_NAME "EPXA10DB"
38#else
39#define BOARD_NAME "EPXA1DB"
40#endif
41
42static int nr_parts = 0;
43static struct mtd_partition *parts;
44
45static struct mtd_info *mymtd;
46
47static int epxa_default_partitions(struct mtd_info *master, struct mtd_partition **pparts);
48
49
50static struct map_info epxa_map = {
51 .name = "EPXA flash",
52 .size = FLASH_SIZE,
53 .bankwidth = 2,
54 .phys = FLASH_START,
55};
56
57static const char *probes[] = { "RedBoot", "afs", NULL };
58
59static int __init epxa_mtd_init(void)
60{
61 int i;
62
63 printk(KERN_NOTICE "%s flash device: 0x%x at 0x%x\n", BOARD_NAME, FLASH_SIZE, FLASH_START);
64
65 epxa_map.virt = ioremap(FLASH_START, FLASH_SIZE);
66 if (!epxa_map.virt) {
67 printk("Failed to ioremap %s flash\n",BOARD_NAME);
68 return -EIO;
69 }
70 simple_map_init(&epxa_map);
71
72 mymtd = do_map_probe("cfi_probe", &epxa_map);
73 if (!mymtd) {
74 iounmap((void *)epxa_map.virt);
75 return -ENXIO;
76 }
77
78 mymtd->owner = THIS_MODULE;
79
80 /* Unlock the flash device. */
81 if(mymtd->unlock){
82 for (i=0; i<mymtd->numeraseregions;i++){
83 int j;
84 for(j=0;j<mymtd->eraseregions[i].numblocks;j++){
85 mymtd->unlock(mymtd,mymtd->eraseregions[i].offset + j * mymtd->eraseregions[i].erasesize,mymtd->eraseregions[i].erasesize);
86 }
87 }
88 }
89
90#ifdef CONFIG_MTD_PARTITIONS
91 nr_parts = parse_mtd_partitions(mymtd, probes, &parts, 0);
92
93 if (nr_parts > 0) {
94 add_mtd_partitions(mymtd, parts, nr_parts);
95 return 0;
96 }
97#endif
98 /* No recognised partitioning schemes found - use defaults */
99 nr_parts = epxa_default_partitions(mymtd, &parts);
100 if (nr_parts > 0) {
101 add_mtd_partitions(mymtd, parts, nr_parts);
102 return 0;
103 }
104
105 /* If all else fails... */
106 add_mtd_device(mymtd);
107 return 0;
108}
109
110static void __exit epxa_mtd_cleanup(void)
111{
112 if (mymtd) {
113 if (nr_parts)
114 del_mtd_partitions(mymtd);
115 else
116 del_mtd_device(mymtd);
117 map_destroy(mymtd);
118 }
119 if (epxa_map.virt) {
120 iounmap((void *)epxa_map.virt);
121 epxa_map.virt = 0;
122 }
123}
124
125
126/*
127 * This will do for now, once we decide which bootldr we're finally
128 * going to use then we'll remove this function and do it properly
129 *
130 * Partions are currently (as offsets from base of flash):
131 * 0x00000000 - 0x003FFFFF - bootloader (!)
132 * 0x00400000 - 0x00FFFFFF - Flashdisk
133 */
134
135static int __init epxa_default_partitions(struct mtd_info *master, struct mtd_partition **pparts)
136{
137 struct mtd_partition *parts;
138 int ret, i;
139 int npartitions = 0;
140 char *names;
141 const char *name = "jffs";
142
143 printk("Using default partitions for %s\n",BOARD_NAME);
144 npartitions=1;
145 parts = kmalloc(npartitions*sizeof(*parts)+strlen(name), GFP_KERNEL);
146 memzero(parts,npartitions*sizeof(*parts)+strlen(name));
147 if (!parts) {
148 ret = -ENOMEM;
149 goto out;
150 }
151 i=0;
152 names = (char *)&parts[npartitions];
153 parts[i].name = names;
154 names += strlen(name) + 1;
155 strcpy(parts[i].name, name);
156
157#ifdef CONFIG_EPXA10DB
158 parts[i].size = FLASH_SIZE-0x00400000;
159 parts[i].offset = 0x00400000;
160#else
161 parts[i].size = FLASH_SIZE-0x00180000;
162 parts[i].offset = 0x00180000;
163#endif
164
165 out:
166 *pparts = parts;
167 return npartitions;
168}
169
170
171module_init(epxa_mtd_init);
172module_exit(epxa_mtd_cleanup);
173
174MODULE_AUTHOR("Clive Davies");
175MODULE_DESCRIPTION("Altera epxa mtd flash map");
176MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/maps/fortunet.c b/drivers/mtd/maps/fortunet.c
new file mode 100644
index 000000000000..068bb6a54520
--- /dev/null
+++ b/drivers/mtd/maps/fortunet.c
@@ -0,0 +1,271 @@
1/* fortunet.c memory map
2 *
3 * $Id: fortunet.c,v 1.9 2004/11/04 13:24:14 gleixner Exp $
4 */
5
6#include <linux/module.h>
7#include <linux/types.h>
8#include <linux/kernel.h>
9#include <linux/init.h>
10#include <asm/io.h>
11#include <linux/mtd/mtd.h>
12#include <linux/mtd/map.h>
13#include <linux/mtd/partitions.h>
14
15#define MAX_NUM_REGIONS 4
16#define MAX_NUM_PARTITIONS 8
17
18#define DEF_WINDOW_ADDR_PHY 0x00000000
19#define DEF_WINDOW_SIZE 0x00800000 // 8 Mega Bytes
20
21#define MTD_FORTUNET_PK "MTD FortuNet: "
22
23#define MAX_NAME_SIZE 128
24
25struct map_region
26{
27 int window_addr_physical;
28 int altbankwidth;
29 struct map_info map_info;
30 struct mtd_info *mymtd;
31 struct mtd_partition parts[MAX_NUM_PARTITIONS];
32 char map_name[MAX_NAME_SIZE];
33 char parts_name[MAX_NUM_PARTITIONS][MAX_NAME_SIZE];
34};
35
36static struct map_region map_regions[MAX_NUM_REGIONS];
37static int map_regions_set[MAX_NUM_REGIONS] = {0,0,0,0};
38static int map_regions_parts[MAX_NUM_REGIONS] = {0,0,0,0};
39
40
41
42struct map_info default_map = {
43 .size = DEF_WINDOW_SIZE,
44 .bankwidth = 4,
45};
46
47static char * __init get_string_option(char *dest,int dest_size,char *sor)
48{
49 if(!dest_size)
50 return sor;
51 dest_size--;
52 while(*sor)
53 {
54 if(*sor==',')
55 {
56 sor++;
57 break;
58 }
59 else if(*sor=='\"')
60 {
61 sor++;
62 while(*sor)
63 {
64 if(*sor=='\"')
65 {
66 sor++;
67 break;
68 }
69 *dest = *sor;
70 dest++;
71 sor++;
72 dest_size--;
73 if(!dest_size)
74 {
75 *dest = 0;
76 return sor;
77 }
78 }
79 }
80 else
81 {
82 *dest = *sor;
83 dest++;
84 sor++;
85 dest_size--;
86 if(!dest_size)
87 {
88 *dest = 0;
89 return sor;
90 }
91 }
92 }
93 *dest = 0;
94 return sor;
95}
96
97static int __init MTD_New_Region(char *line)
98{
99 char string[MAX_NAME_SIZE];
100 int params[6];
101 get_options (get_string_option(string,sizeof(string),line),6,params);
102 if(params[0]<1)
103 {
104 printk(MTD_FORTUNET_PK "Bad parameters for MTD Region "
105 " name,region-number[,base,size,bankwidth,altbankwidth]\n");
106 return 1;
107 }
108 if((params[1]<0)||(params[1]>=MAX_NUM_REGIONS))
109 {
110 printk(MTD_FORTUNET_PK "Bad region index of %d only have 0..%u regions\n",
111 params[1],MAX_NUM_REGIONS-1);
112 return 1;
113 }
114 memset(&map_regions[params[1]],0,sizeof(map_regions[params[1]]));
115 memcpy(&map_regions[params[1]].map_info,
116 &default_map,sizeof(map_regions[params[1]].map_info));
117 map_regions_set[params[1]] = 1;
118 map_regions[params[1]].window_addr_physical = DEF_WINDOW_ADDR_PHY;
119 map_regions[params[1]].altbankwidth = 2;
120 map_regions[params[1]].mymtd = NULL;
121 map_regions[params[1]].map_info.name = map_regions[params[1]].map_name;
122 strcpy(map_regions[params[1]].map_info.name,string);
123 if(params[0]>1)
124 {
125 map_regions[params[1]].window_addr_physical = params[2];
126 }
127 if(params[0]>2)
128 {
129 map_regions[params[1]].map_info.size = params[3];
130 }
131 if(params[0]>3)
132 {
133 map_regions[params[1]].map_info.bankwidth = params[4];
134 }
135 if(params[0]>4)
136 {
137 map_regions[params[1]].altbankwidth = params[5];
138 }
139 return 1;
140}
141
142static int __init MTD_New_Partition(char *line)
143{
144 char string[MAX_NAME_SIZE];
145 int params[4];
146 get_options (get_string_option(string,sizeof(string),line),4,params);
147 if(params[0]<3)
148 {
149 printk(MTD_FORTUNET_PK "Bad parameters for MTD Partition "
150 " name,region-number,size,offset\n");
151 return 1;
152 }
153 if((params[1]<0)||(params[1]>=MAX_NUM_REGIONS))
154 {
155 printk(MTD_FORTUNET_PK "Bad region index of %d only have 0..%u regions\n",
156 params[1],MAX_NUM_REGIONS-1);
157 return 1;
158 }
159 if(map_regions_parts[params[1]]>=MAX_NUM_PARTITIONS)
160 {
161 printk(MTD_FORTUNET_PK "Out of space for partition in this region\n");
162 return 1;
163 }
164 map_regions[params[1]].parts[map_regions_parts[params[1]]].name =
165 map_regions[params[1]]. parts_name[map_regions_parts[params[1]]];
166 strcpy(map_regions[params[1]].parts[map_regions_parts[params[1]]].name,string);
167 map_regions[params[1]].parts[map_regions_parts[params[1]]].size =
168 params[2];
169 map_regions[params[1]].parts[map_regions_parts[params[1]]].offset =
170 params[3];
171 map_regions[params[1]].parts[map_regions_parts[params[1]]].mask_flags = 0;
172 map_regions_parts[params[1]]++;
173 return 1;
174}
175
176__setup("MTD_Region=", MTD_New_Region);
177__setup("MTD_Partition=", MTD_New_Partition);
178
179/* Backwards-spelling-compatibility */
180__setup("MTD_Partion=", MTD_New_Partition);
181
182int __init init_fortunet(void)
183{
184 int ix,iy;
185 for(iy=ix=0;ix<MAX_NUM_REGIONS;ix++)
186 {
187 if(map_regions_parts[ix]&&(!map_regions_set[ix]))
188 {
189 printk(MTD_FORTUNET_PK "Region %d is not setup (Setting to default)\n",
190 ix);
191 memset(&map_regions[ix],0,sizeof(map_regions[ix]));
192 memcpy(&map_regions[ix].map_info,&default_map,
193 sizeof(map_regions[ix].map_info));
194 map_regions_set[ix] = 1;
195 map_regions[ix].window_addr_physical = DEF_WINDOW_ADDR_PHY;
196 map_regions[ix].altbankwidth = 2;
197 map_regions[ix].mymtd = NULL;
198 map_regions[ix].map_info.name = map_regions[ix].map_name;
199 strcpy(map_regions[ix].map_info.name,"FORTUNET");
200 }
201 if(map_regions_set[ix])
202 {
203 iy++;
204 printk(KERN_NOTICE MTD_FORTUNET_PK "%s flash device at physically "
205 " address %x size %x\n",
206 map_regions[ix].map_info.name,
207 map_regions[ix].window_addr_physical,
208 map_regions[ix].map_info.size);
209
210 map_regions[ix].map_info.phys = map_regions[ix].window_addr_physical,
211
212 map_regions[ix].map_info.virt =
213 ioremap_nocache(
214 map_regions[ix].window_addr_physical,
215 map_regions[ix].map_info.size);
216 if(!map_regions[ix].map_info.virt)
217 {
218 printk(MTD_FORTUNET_PK "%s flash failed to ioremap!\n",
219 map_regions[ix].map_info.name);
220 return -ENXIO;
221 }
222 simple_map_init(&map_regions[ix].map_info);
223
224 printk(KERN_NOTICE MTD_FORTUNET_PK "%s flash is virtually at: %x\n",
225 map_regions[ix].map_info.name,
226 map_regions[ix].map_info.virt);
227 map_regions[ix].mymtd = do_map_probe("cfi_probe",
228 &map_regions[ix].map_info);
229 if((!map_regions[ix].mymtd)&&(
230 map_regions[ix].altbankwidth!=map_regions[ix].map_info.bankwidth))
231 {
232 printk(KERN_NOTICE MTD_FORTUNET_PK "Trying alternate bankwidth "
233 "for %s flash.\n",
234 map_regions[ix].map_info.name);
235 map_regions[ix].map_info.bankwidth =
236 map_regions[ix].altbankwidth;
237 map_regions[ix].mymtd = do_map_probe("cfi_probe",
238 &map_regions[ix].map_info);
239 }
240 map_regions[ix].mymtd->owner = THIS_MODULE;
241 add_mtd_partitions(map_regions[ix].mymtd,
242 map_regions[ix].parts,map_regions_parts[ix]);
243 }
244 }
245 if(iy)
246 return 0;
247 return -ENXIO;
248}
249
250static void __exit cleanup_fortunet(void)
251{
252 int ix;
253 for(ix=0;ix<MAX_NUM_REGIONS;ix++)
254 {
255 if(map_regions_set[ix])
256 {
257 if( map_regions[ix].mymtd )
258 {
259 del_mtd_partitions( map_regions[ix].mymtd );
260 map_destroy( map_regions[ix].mymtd );
261 }
262 iounmap((void *)map_regions[ix].map_info.virt);
263 }
264 }
265}
266
267module_init(init_fortunet);
268module_exit(cleanup_fortunet);
269
270MODULE_AUTHOR("FortuNet, Inc.");
271MODULE_DESCRIPTION("MTD map driver for FortuNet boards");
diff --git a/drivers/mtd/maps/h720x-flash.c b/drivers/mtd/maps/h720x-flash.c
new file mode 100644
index 000000000000..c73828171d9b
--- /dev/null
+++ b/drivers/mtd/maps/h720x-flash.c
@@ -0,0 +1,144 @@
1/*
2 * Flash memory access on Hynix GMS30C7201/HMS30C7202 based
3 * evaluation boards
4 *
5 * $Id: h720x-flash.c,v 1.11 2004/11/04 13:24:14 gleixner Exp $
6 *
7 * (C) 2002 Jungjun Kim <jungjun.kim@hynix.com>
8 * 2003 Thomas Gleixner <tglx@linutronix.de>
9 */
10
11#include <linux/config.h>
12#include <linux/module.h>
13#include <linux/types.h>
14#include <linux/kernel.h>
15#include <linux/init.h>
16#include <linux/errno.h>
17#include <linux/slab.h>
18
19#include <linux/mtd/mtd.h>
20#include <linux/mtd/map.h>
21#include <linux/mtd/partitions.h>
22#include <asm/hardware.h>
23#include <asm/io.h>
24
25static struct mtd_info *mymtd;
26
27static struct map_info h720x_map = {
28 .name = "H720X",
29 .bankwidth = 4,
30 .size = FLASH_SIZE,
31 .phys = FLASH_PHYS,
32};
33
34static struct mtd_partition h720x_partitions[] = {
35 {
36 .name = "ArMon",
37 .size = 0x00080000,
38 .offset = 0,
39 .mask_flags = MTD_WRITEABLE
40 },{
41 .name = "Env",
42 .size = 0x00040000,
43 .offset = 0x00080000,
44 .mask_flags = MTD_WRITEABLE
45 },{
46 .name = "Kernel",
47 .size = 0x00180000,
48 .offset = 0x000c0000,
49 .mask_flags = MTD_WRITEABLE
50 },{
51 .name = "Ramdisk",
52 .size = 0x00400000,
53 .offset = 0x00240000,
54 .mask_flags = MTD_WRITEABLE
55 },{
56 .name = "jffs2",
57 .size = MTDPART_SIZ_FULL,
58 .offset = MTDPART_OFS_APPEND
59 }
60};
61
62#define NUM_PARTITIONS (sizeof(h720x_partitions)/sizeof(h720x_partitions[0]))
63
64static int nr_mtd_parts;
65static struct mtd_partition *mtd_parts;
66static const char *probes[] = { "cmdlinepart", NULL };
67
68/*
69 * Initialize FLASH support
70 */
71int __init h720x_mtd_init(void)
72{
73
74 char *part_type = NULL;
75
76 h720x_map.virt = ioremap(FLASH_PHYS, FLASH_SIZE);
77
78 if (!h720x_map.virt) {
79 printk(KERN_ERR "H720x-MTD: ioremap failed\n");
80 return -EIO;
81 }
82
83 simple_map_init(&h720x_map);
84
85 // Probe for flash bankwidth 4
86 printk (KERN_INFO "H720x-MTD probing 32bit FLASH\n");
87 mymtd = do_map_probe("cfi_probe", &h720x_map);
88 if (!mymtd) {
89 printk (KERN_INFO "H720x-MTD probing 16bit FLASH\n");
90 // Probe for bankwidth 2
91 h720x_map.bankwidth = 2;
92 mymtd = do_map_probe("cfi_probe", &h720x_map);
93 }
94
95 if (mymtd) {
96 mymtd->owner = THIS_MODULE;
97
98#ifdef CONFIG_MTD_PARTITIONS
99 nr_mtd_parts = parse_mtd_partitions(mymtd, probes, &mtd_parts, 0);
100 if (nr_mtd_parts > 0)
101 part_type = "command line";
102#endif
103 if (nr_mtd_parts <= 0) {
104 mtd_parts = h720x_partitions;
105 nr_mtd_parts = NUM_PARTITIONS;
106 part_type = "builtin";
107 }
108 printk(KERN_INFO "Using %s partition table\n", part_type);
109 add_mtd_partitions(mymtd, mtd_parts, nr_mtd_parts);
110 return 0;
111 }
112
113 iounmap((void *)h720x_map.virt);
114 return -ENXIO;
115}
116
117/*
118 * Cleanup
119 */
120static void __exit h720x_mtd_cleanup(void)
121{
122
123 if (mymtd) {
124 del_mtd_partitions(mymtd);
125 map_destroy(mymtd);
126 }
127
128 /* Free partition info, if commandline partition was used */
129 if (mtd_parts && (mtd_parts != h720x_partitions))
130 kfree (mtd_parts);
131
132 if (h720x_map.virt) {
133 iounmap((void *)h720x_map.virt);
134 h720x_map.virt = 0;
135 }
136}
137
138
139module_init(h720x_mtd_init);
140module_exit(h720x_mtd_cleanup);
141
142MODULE_LICENSE("GPL");
143MODULE_AUTHOR("Thomas Gleixner <tglx@linutronix.de>");
144MODULE_DESCRIPTION("MTD map driver for Hynix evaluation boards");
diff --git a/drivers/mtd/maps/ichxrom.c b/drivers/mtd/maps/ichxrom.c
new file mode 100644
index 000000000000..29d1cc1bb426
--- /dev/null
+++ b/drivers/mtd/maps/ichxrom.c
@@ -0,0 +1,383 @@
1/*
2 * ichxrom.c
3 *
4 * Normal mappings of chips in physical memory
5 * $Id: ichxrom.c,v 1.16 2004/11/28 09:40:39 dwmw2 Exp $
6 */
7
8#include <linux/module.h>
9#include <linux/types.h>
10#include <linux/kernel.h>
11#include <linux/init.h>
12#include <asm/io.h>
13#include <linux/mtd/mtd.h>
14#include <linux/mtd/map.h>
15#include <linux/mtd/cfi.h>
16#include <linux/mtd/flashchip.h>
17#include <linux/config.h>
18#include <linux/pci.h>
19#include <linux/pci_ids.h>
20#include <linux/list.h>
21
22#define xstr(s) str(s)
23#define str(s) #s
24#define MOD_NAME xstr(KBUILD_BASENAME)
25
26#define ADDRESS_NAME_LEN 18
27
28#define ROM_PROBE_STEP_SIZE (64*1024) /* 64KiB */
29
30#define BIOS_CNTL 0x4e
31#define FWH_DEC_EN1 0xE3
32#define FWH_DEC_EN2 0xF0
33#define FWH_SEL1 0xE8
34#define FWH_SEL2 0xEE
35
36struct ichxrom_window {
37 void __iomem* virt;
38 unsigned long phys;
39 unsigned long size;
40 struct list_head maps;
41 struct resource rsrc;
42 struct pci_dev *pdev;
43};
44
45struct ichxrom_map_info {
46 struct list_head list;
47 struct map_info map;
48 struct mtd_info *mtd;
49 struct resource rsrc;
50 char map_name[sizeof(MOD_NAME) + 2 + ADDRESS_NAME_LEN];
51};
52
53static struct ichxrom_window ichxrom_window = {
54 .maps = LIST_HEAD_INIT(ichxrom_window.maps),
55};
56
57static void ichxrom_cleanup(struct ichxrom_window *window)
58{
59 struct ichxrom_map_info *map, *scratch;
60 u16 word;
61
62 /* Disable writes through the rom window */
63 pci_read_config_word(window->pdev, BIOS_CNTL, &word);
64 pci_write_config_word(window->pdev, BIOS_CNTL, word & ~1);
65
66 /* Free all of the mtd devices */
67 list_for_each_entry_safe(map, scratch, &window->maps, list) {
68 if (map->rsrc.parent)
69 release_resource(&map->rsrc);
70 del_mtd_device(map->mtd);
71 map_destroy(map->mtd);
72 list_del(&map->list);
73 kfree(map);
74 }
75 if (window->rsrc.parent)
76 release_resource(&window->rsrc);
77 if (window->virt) {
78 iounmap(window->virt);
79 window->virt = NULL;
80 window->phys = 0;
81 window->size = 0;
82 window->pdev = NULL;
83 }
84}
85
86
87static int __devinit ichxrom_init_one (struct pci_dev *pdev,
88 const struct pci_device_id *ent)
89{
90 static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL };
91 struct ichxrom_window *window = &ichxrom_window;
92 struct ichxrom_map_info *map = NULL;
93 unsigned long map_top;
94 u8 byte;
95 u16 word;
96
97 /* For now I just handle the ichx and I assume there
98 * are not a lot of resources up at the top of the address
99 * space. It is possible to handle other devices in the
100 * top 16MB but it is very painful. Also since
101 * you can only really attach a FWH to an ICHX there
102 * a number of simplifications you can make.
103 *
104 * Also you can page firmware hubs if an 8MB window isn't enough
105 * but don't currently handle that case either.
106 */
107 window->pdev = pdev;
108
109 /* Find a region continuous to the end of the ROM window */
110 window->phys = 0;
111 pci_read_config_byte(pdev, FWH_DEC_EN1, &byte);
112 if (byte == 0xff) {
113 window->phys = 0xffc00000;
114 pci_read_config_byte(pdev, FWH_DEC_EN2, &byte);
115 if ((byte & 0x0f) == 0x0f) {
116 window->phys = 0xff400000;
117 }
118 else if ((byte & 0x0e) == 0x0e) {
119 window->phys = 0xff500000;
120 }
121 else if ((byte & 0x0c) == 0x0c) {
122 window->phys = 0xff600000;
123 }
124 else if ((byte & 0x08) == 0x08) {
125 window->phys = 0xff700000;
126 }
127 }
128 else if ((byte & 0xfe) == 0xfe) {
129 window->phys = 0xffc80000;
130 }
131 else if ((byte & 0xfc) == 0xfc) {
132 window->phys = 0xffd00000;
133 }
134 else if ((byte & 0xf8) == 0xf8) {
135 window->phys = 0xffd80000;
136 }
137 else if ((byte & 0xf0) == 0xf0) {
138 window->phys = 0xffe00000;
139 }
140 else if ((byte & 0xe0) == 0xe0) {
141 window->phys = 0xffe80000;
142 }
143 else if ((byte & 0xc0) == 0xc0) {
144 window->phys = 0xfff00000;
145 }
146 else if ((byte & 0x80) == 0x80) {
147 window->phys = 0xfff80000;
148 }
149
150 if (window->phys == 0) {
151 printk(KERN_ERR MOD_NAME ": Rom window is closed\n");
152 goto out;
153 }
154 window->phys -= 0x400000UL;
155 window->size = (0xffffffffUL - window->phys) + 1UL;
156
157 /* Enable writes through the rom window */
158 pci_read_config_word(pdev, BIOS_CNTL, &word);
159 if (!(word & 1) && (word & (1<<1))) {
160 /* The BIOS will generate an error if I enable
161 * this device, so don't even try.
162 */
163 printk(KERN_ERR MOD_NAME ": firmware access control, I can't enable writes\n");
164 goto out;
165 }
166 pci_write_config_word(pdev, BIOS_CNTL, word | 1);
167
168 /*
169 * Try to reserve the window mem region. If this fails then
170 * it is likely due to the window being "reseved" by the BIOS.
171 */
172 window->rsrc.name = MOD_NAME;
173 window->rsrc.start = window->phys;
174 window->rsrc.end = window->phys + window->size - 1;
175 window->rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
176 if (request_resource(&iomem_resource, &window->rsrc)) {
177 window->rsrc.parent = NULL;
178 printk(KERN_DEBUG MOD_NAME
179 ": %s(): Unable to register resource"
180 " 0x%.08lx-0x%.08lx - kernel bug?\n",
181 __func__,
182 window->rsrc.start, window->rsrc.end);
183 }
184
185 /* Map the firmware hub into my address space. */
186 window->virt = ioremap_nocache(window->phys, window->size);
187 if (!window->virt) {
188 printk(KERN_ERR MOD_NAME ": ioremap(%08lx, %08lx) failed\n",
189 window->phys, window->size);
190 goto out;
191 }
192
193 /* Get the first address to look for an rom chip at */
194 map_top = window->phys;
195 if ((window->phys & 0x3fffff) != 0) {
196 map_top = window->phys + 0x400000;
197 }
198#if 1
199 /* The probe sequence run over the firmware hub lock
200 * registers sets them to 0x7 (no access).
201 * Probe at most the last 4M of the address space.
202 */
203 if (map_top < 0xffc00000) {
204 map_top = 0xffc00000;
205 }
206#endif
207 /* Loop through and look for rom chips */
208 while((map_top - 1) < 0xffffffffUL) {
209 struct cfi_private *cfi;
210 unsigned long offset;
211 int i;
212
213 if (!map) {
214 map = kmalloc(sizeof(*map), GFP_KERNEL);
215 }
216 if (!map) {
217 printk(KERN_ERR MOD_NAME ": kmalloc failed");
218 goto out;
219 }
220 memset(map, 0, sizeof(*map));
221 INIT_LIST_HEAD(&map->list);
222 map->map.name = map->map_name;
223 map->map.phys = map_top;
224 offset = map_top - window->phys;
225 map->map.virt = (void __iomem *)
226 (((unsigned long)(window->virt)) + offset);
227 map->map.size = 0xffffffffUL - map_top + 1UL;
228 /* Set the name of the map to the address I am trying */
229 sprintf(map->map_name, "%s @%08lx",
230 MOD_NAME, map->map.phys);
231
232 /* Firmware hubs only use vpp when being programmed
233 * in a factory setting. So in-place programming
234 * needs to use a different method.
235 */
236 for(map->map.bankwidth = 32; map->map.bankwidth;
237 map->map.bankwidth >>= 1)
238 {
239 char **probe_type;
240 /* Skip bankwidths that are not supported */
241 if (!map_bankwidth_supported(map->map.bankwidth))
242 continue;
243
244 /* Setup the map methods */
245 simple_map_init(&map->map);
246
247 /* Try all of the probe methods */
248 probe_type = rom_probe_types;
249 for(; *probe_type; probe_type++) {
250 map->mtd = do_map_probe(*probe_type, &map->map);
251 if (map->mtd)
252 goto found;
253 }
254 }
255 map_top += ROM_PROBE_STEP_SIZE;
256 continue;
257 found:
258 /* Trim the size if we are larger than the map */
259 if (map->mtd->size > map->map.size) {
260 printk(KERN_WARNING MOD_NAME
261 " rom(%u) larger than window(%lu). fixing...\n",
262 map->mtd->size, map->map.size);
263 map->mtd->size = map->map.size;
264 }
265 if (window->rsrc.parent) {
266 /*
267 * Registering the MTD device in iomem may not be possible
268 * if there is a BIOS "reserved" and BUSY range. If this
269 * fails then continue anyway.
270 */
271 map->rsrc.name = map->map_name;
272 map->rsrc.start = map->map.phys;
273 map->rsrc.end = map->map.phys + map->mtd->size - 1;
274 map->rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
275 if (request_resource(&window->rsrc, &map->rsrc)) {
276 printk(KERN_ERR MOD_NAME
277 ": cannot reserve MTD resource\n");
278 map->rsrc.parent = NULL;
279 }
280 }
281
282 /* Make the whole region visible in the map */
283 map->map.virt = window->virt;
284 map->map.phys = window->phys;
285 cfi = map->map.fldrv_priv;
286 for(i = 0; i < cfi->numchips; i++) {
287 cfi->chips[i].start += offset;
288 }
289
290 /* Now that the mtd devices is complete claim and export it */
291 map->mtd->owner = THIS_MODULE;
292 if (add_mtd_device(map->mtd)) {
293 map_destroy(map->mtd);
294 map->mtd = NULL;
295 goto out;
296 }
297
298
299 /* Calculate the new value of map_top */
300 map_top += map->mtd->size;
301
302 /* File away the map structure */
303 list_add(&map->list, &window->maps);
304 map = NULL;
305 }
306
307 out:
308 /* Free any left over map structures */
309 if (map) {
310 kfree(map);
311 }
312 /* See if I have any map structures */
313 if (list_empty(&window->maps)) {
314 ichxrom_cleanup(window);
315 return -ENODEV;
316 }
317 return 0;
318}
319
320
321static void __devexit ichxrom_remove_one (struct pci_dev *pdev)
322{
323 struct ichxrom_window *window = &ichxrom_window;
324 ichxrom_cleanup(window);
325}
326
327static struct pci_device_id ichxrom_pci_tbl[] __devinitdata = {
328 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0,
329 PCI_ANY_ID, PCI_ANY_ID, },
330 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0,
331 PCI_ANY_ID, PCI_ANY_ID, },
332 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0,
333 PCI_ANY_ID, PCI_ANY_ID, },
334 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0,
335 PCI_ANY_ID, PCI_ANY_ID, },
336 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_1,
337 PCI_ANY_ID, PCI_ANY_ID, },
338 { 0, },
339};
340
341MODULE_DEVICE_TABLE(pci, ichxrom_pci_tbl);
342
343#if 0
344static struct pci_driver ichxrom_driver = {
345 .name = MOD_NAME,
346 .id_table = ichxrom_pci_tbl,
347 .probe = ichxrom_init_one,
348 .remove = ichxrom_remove_one,
349};
350#endif
351
352static int __init init_ichxrom(void)
353{
354 struct pci_dev *pdev;
355 struct pci_device_id *id;
356
357 pdev = NULL;
358 for (id = ichxrom_pci_tbl; id->vendor; id++) {
359 pdev = pci_find_device(id->vendor, id->device, NULL);
360 if (pdev) {
361 break;
362 }
363 }
364 if (pdev) {
365 return ichxrom_init_one(pdev, &ichxrom_pci_tbl[0]);
366 }
367 return -ENXIO;
368#if 0
369 return pci_module_init(&ichxrom_driver);
370#endif
371}
372
373static void __exit cleanup_ichxrom(void)
374{
375 ichxrom_remove_one(ichxrom_window.pdev);
376}
377
378module_init(init_ichxrom);
379module_exit(cleanup_ichxrom);
380
381MODULE_LICENSE("GPL");
382MODULE_AUTHOR("Eric Biederman <ebiederman@lnxi.com>");
383MODULE_DESCRIPTION("MTD map driver for BIOS chips on the ICHX southbridge");
diff --git a/drivers/mtd/maps/impa7.c b/drivers/mtd/maps/impa7.c
new file mode 100644
index 000000000000..cb39172c81d2
--- /dev/null
+++ b/drivers/mtd/maps/impa7.c
@@ -0,0 +1,161 @@
1/*
2 * $Id: impa7.c,v 1.13 2004/11/04 13:24:14 gleixner Exp $
3 *
4 * Handle mapping of the NOR flash on implementa A7 boards
5 *
6 * Copyright 2002 SYSGO Real-Time Solutions GmbH
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/module.h>
14#include <linux/types.h>
15#include <linux/kernel.h>
16#include <linux/init.h>
17#include <asm/io.h>
18#include <linux/mtd/mtd.h>
19#include <linux/mtd/map.h>
20#include <linux/config.h>
21
22#ifdef CONFIG_MTD_PARTITIONS
23#include <linux/mtd/partitions.h>
24#endif
25
26#define WINDOW_ADDR0 0x00000000 /* physical properties of flash */
27#define WINDOW_SIZE0 0x00800000
28#define WINDOW_ADDR1 0x10000000 /* physical properties of flash */
29#define WINDOW_SIZE1 0x00800000
30#define NUM_FLASHBANKS 2
31#define BUSWIDTH 4
32
33/* can be { "cfi_probe", "jedec_probe", "map_rom", NULL } */
34#define PROBETYPES { "jedec_probe", NULL }
35
36#define MSG_PREFIX "impA7:" /* prefix for our printk()'s */
37#define MTDID "impa7-%d" /* for mtdparts= partitioning */
38
39static struct mtd_info *impa7_mtd[NUM_FLASHBANKS];
40
41
42static struct map_info impa7_map[NUM_FLASHBANKS] = {
43 {
44 .name = "impA7 NOR Flash Bank #0",
45 .size = WINDOW_SIZE0,
46 .bankwidth = BUSWIDTH,
47 },
48 {
49 .name = "impA7 NOR Flash Bank #1",
50 .size = WINDOW_SIZE1,
51 .bankwidth = BUSWIDTH,
52 },
53};
54
55#ifdef CONFIG_MTD_PARTITIONS
56
57/*
58 * MTD partitioning stuff
59 */
60static struct mtd_partition static_partitions[] =
61{
62 {
63 .name = "FileSystem",
64 .size = 0x800000,
65 .offset = 0x00000000
66 },
67};
68
69static int mtd_parts_nb[NUM_FLASHBANKS];
70static struct mtd_partition *mtd_parts[NUM_FLASHBANKS];
71
72#endif
73
74static const char *probes[] = { "cmdlinepart", NULL };
75
76int __init init_impa7(void)
77{
78 static const char *rom_probe_types[] = PROBETYPES;
79 const char **type;
80 const char *part_type = 0;
81 int i;
82 static struct { u_long addr; u_long size; } pt[NUM_FLASHBANKS] = {
83 { WINDOW_ADDR0, WINDOW_SIZE0 },
84 { WINDOW_ADDR1, WINDOW_SIZE1 },
85 };
86 int devicesfound = 0;
87
88 for(i=0; i<NUM_FLASHBANKS; i++)
89 {
90 printk(KERN_NOTICE MSG_PREFIX "probing 0x%08lx at 0x%08lx\n",
91 pt[i].size, pt[i].addr);
92
93 impa7_map[i].phys = pt[i].addr;
94 impa7_map[i].virt = ioremap(pt[i].addr, pt[i].size);
95 if (!impa7_map[i].virt) {
96 printk(MSG_PREFIX "failed to ioremap\n");
97 return -EIO;
98 }
99 simple_map_init(&impa7_map[i]);
100
101 impa7_mtd[i] = 0;
102 type = rom_probe_types;
103 for(; !impa7_mtd[i] && *type; type++) {
104 impa7_mtd[i] = do_map_probe(*type, &impa7_map[i]);
105 }
106
107 if (impa7_mtd[i]) {
108 impa7_mtd[i]->owner = THIS_MODULE;
109 devicesfound++;
110#ifdef CONFIG_MTD_PARTITIONS
111 mtd_parts_nb[i] = parse_mtd_partitions(impa7_mtd[i],
112 probes,
113 &mtd_parts[i],
114 0);
115 if (mtd_parts_nb[i] > 0) {
116 part_type = "command line";
117 } else {
118 mtd_parts[i] = static_partitions;
119 mtd_parts_nb[i] = ARRAY_SIZE(static_partitions);
120 part_type = "static";
121 }
122
123 printk(KERN_NOTICE MSG_PREFIX
124 "using %s partition definition\n",
125 part_type);
126 add_mtd_partitions(impa7_mtd[i],
127 mtd_parts[i], mtd_parts_nb[i]);
128#else
129 add_mtd_device(impa7_mtd[i]);
130
131#endif
132 }
133 else
134 iounmap((void *)impa7_map[i].virt);
135 }
136 return devicesfound == 0 ? -ENXIO : 0;
137}
138
139static void __exit cleanup_impa7(void)
140{
141 int i;
142 for (i=0; i<NUM_FLASHBANKS; i++) {
143 if (impa7_mtd[i]) {
144#ifdef CONFIG_MTD_PARTITIONS
145 del_mtd_partitions(impa7_mtd[i]);
146#else
147 del_mtd_device(impa7_mtd[i]);
148#endif
149 map_destroy(impa7_mtd[i]);
150 iounmap((void *)impa7_map[i].virt);
151 impa7_map[i].virt = 0;
152 }
153 }
154}
155
156module_init(init_impa7);
157module_exit(cleanup_impa7);
158
159MODULE_LICENSE("GPL");
160MODULE_AUTHOR("Pavel Bartusek <pba@sysgo.de>");
161MODULE_DESCRIPTION("MTD map driver for implementa impA7");
diff --git a/drivers/mtd/maps/integrator-flash.c b/drivers/mtd/maps/integrator-flash.c
new file mode 100644
index 000000000000..e39a98a0171c
--- /dev/null
+++ b/drivers/mtd/maps/integrator-flash.c
@@ -0,0 +1,217 @@
1/*======================================================================
2
3 drivers/mtd/maps/integrator-flash.c: ARM Integrator flash map driver
4
5 Copyright (C) 2000 ARM Limited
6 Copyright (C) 2003 Deep Blue Solutions Ltd.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
22 This is access code for flashes using ARM's flash partitioning
23 standards.
24
25 $Id: integrator-flash.c,v 1.18 2004/11/01 13:26:15 rmk Exp $
26
27======================================================================*/
28
29#include <linux/config.h>
30#include <linux/module.h>
31#include <linux/types.h>
32#include <linux/kernel.h>
33#include <linux/slab.h>
34#include <linux/ioport.h>
35#include <linux/device.h>
36#include <linux/init.h>
37
38#include <linux/mtd/mtd.h>
39#include <linux/mtd/map.h>
40#include <linux/mtd/partitions.h>
41
42#include <asm/mach/flash.h>
43#include <asm/hardware.h>
44#include <asm/io.h>
45#include <asm/system.h>
46
47#ifdef CONFIG_ARCH_P720T
48#define FLASH_BASE (0x04000000)
49#define FLASH_SIZE (64*1024*1024)
50#endif
51
52struct armflash_info {
53 struct flash_platform_data *plat;
54 struct resource *res;
55 struct mtd_partition *parts;
56 struct mtd_info *mtd;
57 struct map_info map;
58};
59
60static void armflash_set_vpp(struct map_info *map, int on)
61{
62 struct armflash_info *info = container_of(map, struct armflash_info, map);
63
64 if (info->plat && info->plat->set_vpp)
65 info->plat->set_vpp(on);
66}
67
68static const char *probes[] = { "cmdlinepart", "RedBoot", "afs", NULL };
69
70static int armflash_probe(struct device *_dev)
71{
72 struct platform_device *dev = to_platform_device(_dev);
73 struct flash_platform_data *plat = dev->dev.platform_data;
74 struct resource *res = dev->resource;
75 unsigned int size = res->end - res->start + 1;
76 struct armflash_info *info;
77 int err;
78 void __iomem *base;
79
80 info = kmalloc(sizeof(struct armflash_info), GFP_KERNEL);
81 if (!info) {
82 err = -ENOMEM;
83 goto out;
84 }
85
86 memset(info, 0, sizeof(struct armflash_info));
87
88 info->plat = plat;
89 if (plat && plat->init) {
90 err = plat->init();
91 if (err)
92 goto no_resource;
93 }
94
95 info->res = request_mem_region(res->start, size, "armflash");
96 if (!info->res) {
97 err = -EBUSY;
98 goto no_resource;
99 }
100
101 base = ioremap(res->start, size);
102 if (!base) {
103 err = -ENOMEM;
104 goto no_mem;
105 }
106
107 /*
108 * look for CFI based flash parts fitted to this board
109 */
110 info->map.size = size;
111 info->map.bankwidth = plat->width;
112 info->map.phys = res->start;
113 info->map.virt = base;
114 info->map.name = dev->dev.bus_id;
115 info->map.set_vpp = armflash_set_vpp;
116
117 simple_map_init(&info->map);
118
119 /*
120 * Also, the CFI layer automatically works out what size
121 * of chips we have, and does the necessary identification
122 * for us automatically.
123 */
124 info->mtd = do_map_probe(plat->map_name, &info->map);
125 if (!info->mtd) {
126 err = -ENXIO;
127 goto no_device;
128 }
129
130 info->mtd->owner = THIS_MODULE;
131
132 err = parse_mtd_partitions(info->mtd, probes, &info->parts, 0);
133 if (err > 0) {
134 err = add_mtd_partitions(info->mtd, info->parts, err);
135 if (err)
136 printk(KERN_ERR
137 "mtd partition registration failed: %d\n", err);
138 }
139
140 if (err == 0)
141 dev_set_drvdata(&dev->dev, info);
142
143 /*
144 * If we got an error, free all resources.
145 */
146 if (err < 0) {
147 if (info->mtd) {
148 del_mtd_partitions(info->mtd);
149 map_destroy(info->mtd);
150 }
151 if (info->parts)
152 kfree(info->parts);
153
154 no_device:
155 iounmap(base);
156 no_mem:
157 release_mem_region(res->start, size);
158 no_resource:
159 if (plat && plat->exit)
160 plat->exit();
161 kfree(info);
162 }
163 out:
164 return err;
165}
166
167static int armflash_remove(struct device *_dev)
168{
169 struct platform_device *dev = to_platform_device(_dev);
170 struct armflash_info *info = dev_get_drvdata(&dev->dev);
171
172 dev_set_drvdata(&dev->dev, NULL);
173
174 if (info) {
175 if (info->mtd) {
176 del_mtd_partitions(info->mtd);
177 map_destroy(info->mtd);
178 }
179 if (info->parts)
180 kfree(info->parts);
181
182 iounmap(info->map.virt);
183 release_resource(info->res);
184 kfree(info->res);
185
186 if (info->plat && info->plat->exit)
187 info->plat->exit();
188
189 kfree(info);
190 }
191
192 return 0;
193}
194
195static struct device_driver armflash_driver = {
196 .name = "armflash",
197 .bus = &platform_bus_type,
198 .probe = armflash_probe,
199 .remove = armflash_remove,
200};
201
202static int __init armflash_init(void)
203{
204 return driver_register(&armflash_driver);
205}
206
207static void __exit armflash_exit(void)
208{
209 driver_unregister(&armflash_driver);
210}
211
212module_init(armflash_init);
213module_exit(armflash_exit);
214
215MODULE_AUTHOR("ARM Ltd");
216MODULE_DESCRIPTION("ARM Integrator CFI map driver");
217MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/maps/ipaq-flash.c b/drivers/mtd/maps/ipaq-flash.c
new file mode 100644
index 000000000000..712401810841
--- /dev/null
+++ b/drivers/mtd/maps/ipaq-flash.c
@@ -0,0 +1,464 @@
1/*
2 * Flash memory access on iPAQ Handhelds (either SA1100 or PXA250 based)
3 *
4 * (C) 2000 Nicolas Pitre <nico@cam.org>
5 * (C) 2002 Hewlett-Packard Company <jamey.hicks@hp.com>
6 * (C) 2003 Christian Pellegrin <chri@ascensit.com>, <chri@infis.univ.ts.it>: concatenation of multiple flashes
7 *
8 * $Id: ipaq-flash.c,v 1.3 2004/11/04 13:24:15 gleixner Exp $
9 */
10
11#include <linux/config.h>
12#include <linux/module.h>
13#include <linux/types.h>
14#include <linux/kernel.h>
15#include <linux/spinlock.h>
16#include <linux/init.h>
17#include <linux/slab.h>
18#include <asm/page.h>
19#include <asm/mach-types.h>
20#include <asm/system.h>
21#include <asm/errno.h>
22
23#include <linux/mtd/mtd.h>
24#include <linux/mtd/map.h>
25#include <linux/mtd/partitions.h>
26#ifdef CONFIG_MTD_CONCAT
27#include <linux/mtd/concat.h>
28#endif
29
30#include <asm/hardware.h>
31#include <asm/arch-sa1100/h3600.h>
32#include <asm/io.h>
33
34
35#ifndef CONFIG_IPAQ_HANDHELD
36#error This is for iPAQ Handhelds only
37#endif
38#ifdef CONFIG_SA1100_JORNADA56X
39
40static void jornada56x_set_vpp(struct map_info *map, int vpp)
41{
42 if (vpp)
43 GPSR = GPIO_GPIO26;
44 else
45 GPCR = GPIO_GPIO26;
46 GPDR |= GPIO_GPIO26;
47}
48
49#endif
50
51#ifdef CONFIG_SA1100_JORNADA720
52
53static void jornada720_set_vpp(struct map_info *map, int vpp)
54{
55 if (vpp)
56 PPSR |= 0x80;
57 else
58 PPSR &= ~0x80;
59 PPDR |= 0x80;
60}
61
62#endif
63
64#define MAX_IPAQ_CS 2 /* Number of CS we are going to test */
65
66#define IPAQ_MAP_INIT(X) \
67 { \
68 name: "IPAQ flash " X, \
69 }
70
71
72static struct map_info ipaq_map[MAX_IPAQ_CS] = {
73 IPAQ_MAP_INIT("bank 1"),
74 IPAQ_MAP_INIT("bank 2")
75};
76
77static struct mtd_info *my_sub_mtd[MAX_IPAQ_CS] = {
78 NULL,
79 NULL
80};
81
82/*
83 * Here are partition information for all known IPAQ-based devices.
84 * See include/linux/mtd/partitions.h for definition of the mtd_partition
85 * structure.
86 *
87 * The *_max_flash_size is the maximum possible mapped flash size which
88 * is not necessarily the actual flash size. It must be no more than
89 * the value specified in the "struct map_desc *_io_desc" mapping
90 * definition for the corresponding machine.
91 *
92 * Please keep these in alphabetical order, and formatted as per existing
93 * entries. Thanks.
94 */
95
96#ifdef CONFIG_IPAQ_HANDHELD
97static unsigned long h3xxx_max_flash_size = 0x04000000;
98static struct mtd_partition h3xxx_partitions[] = {
99 {
100 name: "H3XXX boot firmware",
101#ifndef CONFIG_LAB
102 size: 0x00040000,
103#else
104 size: 0x00080000,
105#endif
106 offset: 0,
107#ifndef CONFIG_LAB
108 mask_flags: MTD_WRITEABLE, /* force read-only */
109#endif
110 },
111 {
112 name: "H3XXX root jffs2",
113#ifndef CONFIG_LAB
114 size: 0x2000000 - 2*0x40000, /* Warning, this is fixed later */
115 offset: 0x00040000,
116#else
117 size: 0x2000000 - 0x40000 - 0x80000, /* Warning, this is fixed later */
118 offset: 0x00080000,
119#endif
120 },
121 {
122 name: "asset",
123 size: 0x40000,
124 offset: 0x2000000 - 0x40000, /* Warning, this is fixed later */
125 mask_flags: MTD_WRITEABLE, /* force read-only */
126 }
127};
128
129#ifndef CONFIG_MTD_CONCAT
130static struct mtd_partition h3xxx_partitions_bank2[] = {
131 /* this is used only on 2 CS machines when concat is not present */
132 {
133 name: "second H3XXX root jffs2",
134 size: 0x1000000 - 0x40000, /* Warning, this is fixed later */
135 offset: 0x00000000,
136 },
137 {
138 name: "second asset",
139 size: 0x40000,
140 offset: 0x1000000 - 0x40000, /* Warning, this is fixed later */
141 mask_flags: MTD_WRITEABLE, /* force read-only */
142 }
143};
144#endif
145
146static DEFINE_SPINLOCK(ipaq_vpp_lock);
147
148static void h3xxx_set_vpp(struct map_info *map, int vpp)
149{
150 static int nest = 0;
151
152 spin_lock(&ipaq_vpp_lock);
153 if (vpp)
154 nest++;
155 else
156 nest--;
157 if (nest)
158 assign_h3600_egpio(IPAQ_EGPIO_VPP_ON, 1);
159 else
160 assign_h3600_egpio(IPAQ_EGPIO_VPP_ON, 0);
161 spin_unlock(&ipaq_vpp_lock);
162}
163
164#endif
165
166#if defined(CONFIG_SA1100_JORNADA56X) || defined(CONFIG_SA1100_JORNADA720)
167static unsigned long jornada_max_flash_size = 0x02000000;
168static struct mtd_partition jornada_partitions[] = {
169 {
170 name: "Jornada boot firmware",
171 size: 0x00040000,
172 offset: 0,
173 mask_flags: MTD_WRITEABLE, /* force read-only */
174 }, {
175 name: "Jornada root jffs2",
176 size: MTDPART_SIZ_FULL,
177 offset: 0x00040000,
178 }
179};
180#endif
181
182
183static struct mtd_partition *parsed_parts;
184static struct mtd_info *mymtd;
185
186static unsigned long cs_phys[] = {
187#ifdef CONFIG_ARCH_SA1100
188 SA1100_CS0_PHYS,
189 SA1100_CS1_PHYS,
190 SA1100_CS2_PHYS,
191 SA1100_CS3_PHYS,
192 SA1100_CS4_PHYS,
193 SA1100_CS5_PHYS,
194#else
195 PXA_CS0_PHYS,
196 PXA_CS1_PHYS,
197 PXA_CS2_PHYS,
198 PXA_CS3_PHYS,
199 PXA_CS4_PHYS,
200 PXA_CS5_PHYS,
201#endif
202};
203
204static const char *part_probes[] = { "cmdlinepart", "RedBoot", NULL };
205
206static int __init h1900_special_case(void);
207
208int __init ipaq_mtd_init(void)
209{
210 struct mtd_partition *parts = NULL;
211 int nb_parts = 0;
212 int parsed_nr_parts = 0;
213 const char *part_type;
214 int i; /* used when we have >1 flash chips */
215 unsigned long tot_flashsize = 0; /* used when we have >1 flash chips */
216
217 /* Default flash bankwidth */
218 // ipaq_map.bankwidth = (MSC0 & MSC_RBW) ? 2 : 4;
219
220 if (machine_is_h1900())
221 {
222 /* For our intents, the h1900 is not a real iPAQ, so we special-case it. */
223 return h1900_special_case();
224 }
225
226 if (machine_is_h3100() || machine_is_h1900())
227 for(i=0; i<MAX_IPAQ_CS; i++)
228 ipaq_map[i].bankwidth = 2;
229 else
230 for(i=0; i<MAX_IPAQ_CS; i++)
231 ipaq_map[i].bankwidth = 4;
232
233 /*
234 * Static partition definition selection
235 */
236 part_type = "static";
237
238 simple_map_init(&ipaq_map[0]);
239 simple_map_init(&ipaq_map[1]);
240
241#ifdef CONFIG_IPAQ_HANDHELD
242 if (machine_is_ipaq()) {
243 parts = h3xxx_partitions;
244 nb_parts = ARRAY_SIZE(h3xxx_partitions);
245 for(i=0; i<MAX_IPAQ_CS; i++) {
246 ipaq_map[i].size = h3xxx_max_flash_size;
247 ipaq_map[i].set_vpp = h3xxx_set_vpp;
248 ipaq_map[i].phys = cs_phys[i];
249 ipaq_map[i].virt = __ioremap(cs_phys[i], 0x04000000, 0, 1);
250 if (machine_is_h3100 () || machine_is_h1900())
251 ipaq_map[i].bankwidth = 2;
252 }
253 if (machine_is_h3600()) {
254 /* No asset partition here */
255 h3xxx_partitions[1].size += 0x40000;
256 nb_parts--;
257 }
258 }
259#endif
260#ifdef CONFIG_ARCH_H5400
261 if (machine_is_h5400()) {
262 ipaq_map[0].size = 0x02000000;
263 ipaq_map[1].size = 0x02000000;
264 ipaq_map[1].phys = 0x02000000;
265 ipaq_map[1].virt = ipaq_map[0].virt + 0x02000000;
266 }
267#endif
268#ifdef CONFIG_ARCH_H1900
269 if (machine_is_h1900()) {
270 ipaq_map[0].size = 0x00400000;
271 ipaq_map[1].size = 0x02000000;
272 ipaq_map[1].phys = 0x00080000;
273 ipaq_map[1].virt = ipaq_map[0].virt + 0x00080000;
274 }
275#endif
276
277#ifdef CONFIG_SA1100_JORNADA56X
278 if (machine_is_jornada56x()) {
279 parts = jornada_partitions;
280 nb_parts = ARRAY_SIZE(jornada_partitions);
281 ipaq_map[0].size = jornada_max_flash_size;
282 ipaq_map[0].set_vpp = jornada56x_set_vpp;
283 ipaq_map[0].virt = (__u32)__ioremap(0x0, 0x04000000, 0, 1);
284 }
285#endif
286#ifdef CONFIG_SA1100_JORNADA720
287 if (machine_is_jornada720()) {
288 parts = jornada_partitions;
289 nb_parts = ARRAY_SIZE(jornada_partitions);
290 ipaq_map[0].size = jornada_max_flash_size;
291 ipaq_map[0].set_vpp = jornada720_set_vpp;
292 }
293#endif
294
295
296 if (machine_is_ipaq()) { /* for iPAQs only */
297 for(i=0; i<MAX_IPAQ_CS; i++) {
298 printk(KERN_NOTICE "iPAQ flash: probing %d-bit flash bus, window=%lx with CFI.\n", ipaq_map[i].bankwidth*8, ipaq_map[i].virt);
299 my_sub_mtd[i] = do_map_probe("cfi_probe", &ipaq_map[i]);
300 if (!my_sub_mtd[i]) {
301 printk(KERN_NOTICE "iPAQ flash: probing %d-bit flash bus, window=%lx with JEDEC.\n", ipaq_map[i].bankwidth*8, ipaq_map[i].virt);
302 my_sub_mtd[i] = do_map_probe("jedec_probe", &ipaq_map[i]);
303 }
304 if (!my_sub_mtd[i]) {
305 printk(KERN_NOTICE "iPAQ flash: failed to find flash.\n");
306 if (i)
307 break;
308 else
309 return -ENXIO;
310 } else
311 printk(KERN_NOTICE "iPAQ flash: found %d bytes\n", my_sub_mtd[i]->size);
312
313 /* do we really need this debugging? --joshua 20030703 */
314 // printk("my_sub_mtd[%d]=%p\n", i, my_sub_mtd[i]);
315 my_sub_mtd[i]->owner = THIS_MODULE;
316 tot_flashsize += my_sub_mtd[i]->size;
317 }
318#ifdef CONFIG_MTD_CONCAT
319 /* fix the asset location */
320# ifdef CONFIG_LAB
321 h3xxx_partitions[1].size = tot_flashsize - 0x40000 - 0x80000 /* extra big boot block */;
322# else
323 h3xxx_partitions[1].size = tot_flashsize - 2 * 0x40000;
324# endif
325 h3xxx_partitions[2].offset = tot_flashsize - 0x40000;
326 /* and concat the devices */
327 mymtd = mtd_concat_create(&my_sub_mtd[0], i,
328 "ipaq");
329 if (!mymtd) {
330 printk("Cannot create iPAQ concat device\n");
331 return -ENXIO;
332 }
333#else
334 mymtd = my_sub_mtd[0];
335
336 /*
337 *In the very near future, command line partition parsing
338 * will use the device name as 'mtd-id' instead of a value
339 * passed to the parse_cmdline_partitions() routine. Since
340 * the bootldr says 'ipaq', make sure it continues to work.
341 */
342 mymtd->name = "ipaq";
343
344 if ((machine_is_h3600())) {
345# ifdef CONFIG_LAB
346 h3xxx_partitions[1].size = my_sub_mtd[0]->size - 0x80000;
347# else
348 h3xxx_partitions[1].size = my_sub_mtd[0]->size - 0x40000;
349# endif
350 nb_parts = 2;
351 } else {
352# ifdef CONFIG_LAB
353 h3xxx_partitions[1].size = my_sub_mtd[0]->size - 0x40000 - 0x80000; /* extra big boot block */
354# else
355 h3xxx_partitions[1].size = my_sub_mtd[0]->size - 2*0x40000;
356# endif
357 h3xxx_partitions[2].offset = my_sub_mtd[0]->size - 0x40000;
358 }
359
360 if (my_sub_mtd[1]) {
361# ifdef CONFIG_LAB
362 h3xxx_partitions_bank2[0].size = my_sub_mtd[1]->size - 0x80000;
363# else
364 h3xxx_partitions_bank2[0].size = my_sub_mtd[1]->size - 0x40000;
365# endif
366 h3xxx_partitions_bank2[1].offset = my_sub_mtd[1]->size - 0x40000;
367 }
368#endif
369 }
370 else {
371 /*
372 * Now let's probe for the actual flash. Do it here since
373 * specific machine settings might have been set above.
374 */
375 printk(KERN_NOTICE "IPAQ flash: probing %d-bit flash bus, window=%lx\n", ipaq_map[0].bankwidth*8, ipaq_map[0].virt);
376 mymtd = do_map_probe("cfi_probe", &ipaq_map[0]);
377 if (!mymtd)
378 return -ENXIO;
379 mymtd->owner = THIS_MODULE;
380 }
381
382
383 /*
384 * Dynamic partition selection stuff (might override the static ones)
385 */
386
387 i = parse_mtd_partitions(mymtd, part_probes, &parsed_parts, 0);
388
389 if (i > 0) {
390 nb_parts = parsed_nr_parts = i;
391 parts = parsed_parts;
392 part_type = "dynamic";
393 }
394
395 if (!parts) {
396 printk(KERN_NOTICE "IPAQ flash: no partition info available, registering whole flash at once\n");
397 add_mtd_device(mymtd);
398#ifndef CONFIG_MTD_CONCAT
399 if (my_sub_mtd[1])
400 add_mtd_device(my_sub_mtd[1]);
401#endif
402 } else {
403 printk(KERN_NOTICE "Using %s partition definition\n", part_type);
404 add_mtd_partitions(mymtd, parts, nb_parts);
405#ifndef CONFIG_MTD_CONCAT
406 if (my_sub_mtd[1])
407 add_mtd_partitions(my_sub_mtd[1], h3xxx_partitions_bank2, ARRAY_SIZE(h3xxx_partitions_bank2));
408#endif
409 }
410
411 return 0;
412}
413
414static void __exit ipaq_mtd_cleanup(void)
415{
416 int i;
417
418 if (mymtd) {
419 del_mtd_partitions(mymtd);
420#ifndef CONFIG_MTD_CONCAT
421 if (my_sub_mtd[1])
422 del_mtd_partitions(my_sub_mtd[1]);
423#endif
424 map_destroy(mymtd);
425#ifdef CONFIG_MTD_CONCAT
426 for(i=0; i<MAX_IPAQ_CS; i++)
427#else
428 for(i=1; i<MAX_IPAQ_CS; i++)
429#endif
430 {
431 if (my_sub_mtd[i])
432 map_destroy(my_sub_mtd[i]);
433 }
434 if (parsed_parts)
435 kfree(parsed_parts);
436 }
437}
438
439static int __init h1900_special_case(void)
440{
441 /* The iPAQ h1900 is a special case - it has weird ROM. */
442 simple_map_init(&ipaq_map[0]);
443 ipaq_map[0].size = 0x80000;
444 ipaq_map[0].set_vpp = h3xxx_set_vpp;
445 ipaq_map[0].phys = 0x0;
446 ipaq_map[0].virt = __ioremap(0x0, 0x04000000, 0, 1);
447 ipaq_map[0].bankwidth = 2;
448
449 printk(KERN_NOTICE "iPAQ flash: probing %d-bit flash bus, window=%lx with JEDEC.\n", ipaq_map[0].bankwidth*8, ipaq_map[0].virt);
450 mymtd = do_map_probe("jedec_probe", &ipaq_map[0]);
451 if (!mymtd)
452 return -ENODEV;
453 add_mtd_device(mymtd);
454 printk(KERN_NOTICE "iPAQ flash: registered h1910 flash\n");
455
456 return 0;
457}
458
459module_init(ipaq_mtd_init);
460module_exit(ipaq_mtd_cleanup);
461
462MODULE_AUTHOR("Jamey Hicks");
463MODULE_DESCRIPTION("IPAQ CFI map driver");
464MODULE_LICENSE("MIT");
diff --git a/drivers/mtd/maps/iq80310.c b/drivers/mtd/maps/iq80310.c
new file mode 100644
index 000000000000..558d014e7acc
--- /dev/null
+++ b/drivers/mtd/maps/iq80310.c
@@ -0,0 +1,119 @@
1/*
2 * $Id: iq80310.c,v 1.20 2004/11/04 13:24:15 gleixner Exp $
3 *
4 * Mapping for the Intel XScale IQ80310 evaluation board
5 *
6 * Author: Nicolas Pitre
7 * Copyright: (C) 2001 MontaVista Software Inc.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
14#include <linux/module.h>
15#include <linux/types.h>
16#include <linux/kernel.h>
17#include <linux/init.h>
18#include <linux/slab.h>
19#include <asm/io.h>
20#include <linux/mtd/mtd.h>
21#include <linux/mtd/map.h>
22#include <linux/mtd/partitions.h>
23
24
25#define WINDOW_ADDR 0
26#define WINDOW_SIZE 8*1024*1024
27#define BUSWIDTH 1
28
29static struct mtd_info *mymtd;
30
31static struct map_info iq80310_map = {
32 .name = "IQ80310 flash",
33 .size = WINDOW_SIZE,
34 .bankwidth = BUSWIDTH,
35 .phys = WINDOW_ADDR
36};
37
38static struct mtd_partition iq80310_partitions[4] = {
39 {
40 .name = "Firmware",
41 .size = 0x00080000,
42 .offset = 0,
43 .mask_flags = MTD_WRITEABLE /* force read-only */
44 },{
45 .name = "Kernel",
46 .size = 0x000a0000,
47 .offset = 0x00080000,
48 },{
49 .name = "Filesystem",
50 .size = 0x00600000,
51 .offset = 0x00120000
52 },{
53 .name = "RedBoot",
54 .size = 0x000e0000,
55 .offset = 0x00720000,
56 .mask_flags = MTD_WRITEABLE
57 }
58};
59
60static struct mtd_info *mymtd;
61static struct mtd_partition *parsed_parts;
62static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
63
64static int __init init_iq80310(void)
65{
66 struct mtd_partition *parts;
67 int nb_parts = 0;
68 int parsed_nr_parts = 0;
69 int ret;
70
71 iq80310_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE);
72 if (!iq80310_map.virt) {
73 printk("Failed to ioremap\n");
74 return -EIO;
75 }
76 simple_map_init(&iq80310_map);
77
78 mymtd = do_map_probe("cfi_probe", &iq80310_map);
79 if (!mymtd) {
80 iounmap((void *)iq80310_map.virt);
81 return -ENXIO;
82 }
83 mymtd->owner = THIS_MODULE;
84
85 ret = parse_mtd_partitions(mymtd, probes, &parsed_parts, 0);
86
87 if (ret > 0)
88 parsed_nr_parts = ret;
89
90 if (parsed_nr_parts > 0) {
91 parts = parsed_parts;
92 nb_parts = parsed_nr_parts;
93 } else {
94 parts = iq80310_partitions;
95 nb_parts = ARRAY_SIZE(iq80310_partitions);
96 }
97 add_mtd_partitions(mymtd, parts, nb_parts);
98 return 0;
99}
100
101static void __exit cleanup_iq80310(void)
102{
103 if (mymtd) {
104 del_mtd_partitions(mymtd);
105 map_destroy(mymtd);
106 if (parsed_parts)
107 kfree(parsed_parts);
108 }
109 if (iq80310_map.virt)
110 iounmap((void *)iq80310_map.virt);
111}
112
113module_init(init_iq80310);
114module_exit(cleanup_iq80310);
115
116
117MODULE_LICENSE("GPL");
118MODULE_AUTHOR("Nicolas Pitre <nico@cam.org>");
119MODULE_DESCRIPTION("MTD map driver for Intel XScale IQ80310 evaluation board");
diff --git a/drivers/mtd/maps/ixp2000.c b/drivers/mtd/maps/ixp2000.c
new file mode 100644
index 000000000000..c5b5f447e34b
--- /dev/null
+++ b/drivers/mtd/maps/ixp2000.c
@@ -0,0 +1,280 @@
1/*
2 * $Id: ixp2000.c,v 1.5 2004/11/16 17:15:48 dsaxena Exp $
3 *
4 * drivers/mtd/maps/ixp2000.c
5 *
6 * Mapping for the Intel XScale IXP2000 based systems
7 *
8 * Copyright (C) 2002 Intel Corp.
9 * Copyright (C) 2003-2004 MontaVista Software, Inc.
10 *
11 * Original Author: Naeem M Afzal <naeem.m.afzal@intel.com>
12 * Maintainer: Deepak Saxena <dsaxena@plexity.net>
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License version 2 as
16 * published by the Free Software Foundation.
17 *
18 */
19
20#include <linux/module.h>
21#include <linux/types.h>
22#include <linux/init.h>
23#include <linux/kernel.h>
24#include <linux/string.h>
25#include <linux/mtd/mtd.h>
26#include <linux/mtd/map.h>
27#include <linux/mtd/partitions.h>
28#include <linux/ioport.h>
29#include <linux/device.h>
30
31#include <asm/io.h>
32#include <asm/hardware.h>
33#include <asm/mach-types.h>
34#include <asm/mach/flash.h>
35
36#include <linux/reboot.h>
37
38struct ixp2000_flash_info {
39 struct mtd_info *mtd;
40 struct map_info map;
41 struct mtd_partition *partitions;
42 struct resource *res;
43 int nr_banks;
44};
45
46static inline unsigned long flash_bank_setup(struct map_info *map, unsigned long ofs)
47{
48 unsigned long (*set_bank)(unsigned long) =
49 (unsigned long(*)(unsigned long))map->map_priv_2;
50
51 return (set_bank ? set_bank(ofs) : ofs);
52}
53
54#ifdef __ARMEB__
55/*
56 * Rev A0 and A1 of IXP2400 silicon have a broken addressing unit which
57 * causes the lower address bits to be XORed with 0x11 on 8 bit accesses
58 * and XORed with 0x10 on 16 bit accesses. See the spec update, erratum 44.
59 */
60static int erratum44_workaround = 0;
61
62static inline unsigned long address_fix8_write(unsigned long addr)
63{
64 if (erratum44_workaround) {
65 return (addr ^ 3);
66 }
67 return addr;
68}
69#else
70
71#define address_fix8_write(x) (x)
72#endif
73
74static map_word ixp2000_flash_read8(struct map_info *map, unsigned long ofs)
75{
76 map_word val;
77
78 val.x[0] = *((u8 *)(map->map_priv_1 + flash_bank_setup(map, ofs)));
79 return val;
80}
81
82/*
83 * We can't use the standard memcpy due to the broken SlowPort
84 * address translation on rev A0 and A1 silicon and the fact that
85 * we have banked flash.
86 */
87static void ixp2000_flash_copy_from(struct map_info *map, void *to,
88 unsigned long from, ssize_t len)
89{
90 from = flash_bank_setup(map, from);
91 while(len--)
92 *(__u8 *) to++ = *(__u8 *)(map->map_priv_1 + from++);
93}
94
95static void ixp2000_flash_write8(struct map_info *map, map_word d, unsigned long ofs)
96{
97 *(__u8 *) (address_fix8_write(map->map_priv_1 +
98 flash_bank_setup(map, ofs))) = d.x[0];
99}
100
101static void ixp2000_flash_copy_to(struct map_info *map, unsigned long to,
102 const void *from, ssize_t len)
103{
104 to = flash_bank_setup(map, to);
105 while(len--) {
106 unsigned long tmp = address_fix8_write(map->map_priv_1 + to++);
107 *(__u8 *)(tmp) = *(__u8 *)(from++);
108 }
109}
110
111
112static int ixp2000_flash_remove(struct device *_dev)
113{
114 struct platform_device *dev = to_platform_device(_dev);
115 struct flash_platform_data *plat = dev->dev.platform_data;
116 struct ixp2000_flash_info *info = dev_get_drvdata(&dev->dev);
117
118 dev_set_drvdata(&dev->dev, NULL);
119
120 if(!info)
121 return 0;
122
123 if (info->mtd) {
124 del_mtd_partitions(info->mtd);
125 map_destroy(info->mtd);
126 }
127 if (info->map.map_priv_1)
128 iounmap((void *) info->map.map_priv_1);
129
130 if (info->partitions) {
131 kfree(info->partitions); }
132
133 if (info->res) {
134 release_resource(info->res);
135 kfree(info->res);
136 }
137
138 if (plat->exit)
139 plat->exit();
140
141 return 0;
142}
143
144
145static int ixp2000_flash_probe(struct device *_dev)
146{
147 static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
148 struct platform_device *dev = to_platform_device(_dev);
149 struct ixp2000_flash_data *ixp_data = dev->dev.platform_data;
150 struct flash_platform_data *plat;
151 struct ixp2000_flash_info *info;
152 unsigned long window_size;
153 int err = -1;
154
155 if (!ixp_data)
156 return -ENODEV;
157
158 plat = ixp_data->platform_data;
159 if (!plat)
160 return -ENODEV;
161
162 window_size = dev->resource->end - dev->resource->start + 1;
163 dev_info(_dev, "Probe of IXP2000 flash(%d banks x %dMiB)\n",
164 ixp_data->nr_banks, ((u32)window_size >> 20));
165
166 if (plat->width != 1) {
167 dev_err(_dev, "IXP2000 MTD map only supports 8-bit mode, asking for %d\n",
168 plat->width * 8);
169 return -EIO;
170 }
171
172 info = kmalloc(sizeof(struct ixp2000_flash_info), GFP_KERNEL);
173 if(!info) {
174 err = -ENOMEM;
175 goto Error;
176 }
177 memzero(info, sizeof(struct ixp2000_flash_info));
178
179 dev_set_drvdata(&dev->dev, info);
180
181 /*
182 * Tell the MTD layer we're not 1:1 mapped so that it does
183 * not attempt to do a direct access on us.
184 */
185 info->map.phys = NO_XIP;
186
187 info->nr_banks = ixp_data->nr_banks;
188 info->map.size = ixp_data->nr_banks * window_size;
189 info->map.bankwidth = 1;
190
191 /*
192 * map_priv_2 is used to store a ptr to to the bank_setup routine
193 */
194 info->map.map_priv_2 = (void __iomem *) ixp_data->bank_setup;
195
196 info->map.name = dev->dev.bus_id;
197 info->map.read = ixp2000_flash_read8;
198 info->map.write = ixp2000_flash_write8;
199 info->map.copy_from = ixp2000_flash_copy_from;
200 info->map.copy_to = ixp2000_flash_copy_to;
201
202 info->res = request_mem_region(dev->resource->start,
203 dev->resource->end - dev->resource->start + 1,
204 dev->dev.bus_id);
205 if (!info->res) {
206 dev_err(_dev, "Could not reserve memory region\n");
207 err = -ENOMEM;
208 goto Error;
209 }
210
211 info->map.map_priv_1 = ioremap(dev->resource->start,
212 dev->resource->end - dev->resource->start + 1);
213 if (!info->map.map_priv_1) {
214 dev_err(_dev, "Failed to ioremap flash region\n");
215 err = -EIO;
216 goto Error;
217 }
218
219 /*
220 * Setup read mode for FLASH
221 */
222 *IXP2000_SLOWPORT_FRM = 1;
223
224#if defined(__ARMEB__)
225 /*
226 * Enable erratum 44 workaround for NPUs with broken slowport
227 */
228
229 erratum44_workaround = ixp2000_has_broken_slowport();
230 dev_info(_dev, "Erratum 44 workaround %s\n",
231 erratum44_workaround ? "enabled" : "disabled");
232#endif
233
234 info->mtd = do_map_probe(plat->map_name, &info->map);
235 if (!info->mtd) {
236 dev_err(_dev, "map_probe failed\n");
237 err = -ENXIO;
238 goto Error;
239 }
240 info->mtd->owner = THIS_MODULE;
241
242 err = parse_mtd_partitions(info->mtd, probes, &info->partitions, 0);
243 if (err > 0) {
244 err = add_mtd_partitions(info->mtd, info->partitions, err);
245 if(err)
246 dev_err(_dev, "Could not parse partitions\n");
247 }
248
249 if (err)
250 goto Error;
251
252 return 0;
253
254Error:
255 ixp2000_flash_remove(_dev);
256 return err;
257}
258
259static struct device_driver ixp2000_flash_driver = {
260 .name = "IXP2000-Flash",
261 .bus = &platform_bus_type,
262 .probe = &ixp2000_flash_probe,
263 .remove = &ixp2000_flash_remove
264};
265
266static int __init ixp2000_flash_init(void)
267{
268 return driver_register(&ixp2000_flash_driver);
269}
270
271static void __exit ixp2000_flash_exit(void)
272{
273 driver_unregister(&ixp2000_flash_driver);
274}
275
276module_init(ixp2000_flash_init);
277module_exit(ixp2000_flash_exit);
278MODULE_LICENSE("GPL");
279MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net>");
280
diff --git a/drivers/mtd/maps/ixp4xx.c b/drivers/mtd/maps/ixp4xx.c
new file mode 100644
index 000000000000..5afe660aa2c4
--- /dev/null
+++ b/drivers/mtd/maps/ixp4xx.c
@@ -0,0 +1,259 @@
1/*
2 * $Id: ixp4xx.c,v 1.7 2004/11/04 13:24:15 gleixner Exp $
3 *
4 * drivers/mtd/maps/ixp4xx.c
5 *
6 * MTD Map file for IXP4XX based systems. Please do not make per-board
7 * changes in here. If your board needs special setup, do it in your
8 * platform level code in arch/arm/mach-ixp4xx/board-setup.c
9 *
10 * Original Author: Intel Corporation
11 * Maintainer: Deepak Saxena <dsaxena@mvista.com>
12 *
13 * Copyright (C) 2002 Intel Corporation
14 * Copyright (C) 2003-2004 MontaVista Software, Inc.
15 *
16 */
17
18#include <linux/module.h>
19#include <linux/types.h>
20#include <linux/init.h>
21#include <linux/kernel.h>
22#include <linux/string.h>
23#include <linux/mtd/mtd.h>
24#include <linux/mtd/map.h>
25#include <linux/mtd/partitions.h>
26#include <linux/ioport.h>
27#include <linux/device.h>
28#include <asm/io.h>
29#include <asm/mach-types.h>
30#include <asm/mach/flash.h>
31
32#include <linux/reboot.h>
33
34#ifndef __ARMEB__
35#define BYTE0(h) ((h) & 0xFF)
36#define BYTE1(h) (((h) >> 8) & 0xFF)
37#else
38#define BYTE0(h) (((h) >> 8) & 0xFF)
39#define BYTE1(h) ((h) & 0xFF)
40#endif
41
42static map_word ixp4xx_read16(struct map_info *map, unsigned long ofs)
43{
44 map_word val;
45 val.x[0] = *(__u16 *) (map->map_priv_1 + ofs);
46 return val;
47}
48
49/*
50 * The IXP4xx expansion bus only allows 16-bit wide acceses
51 * when attached to a 16-bit wide device (such as the 28F128J3A),
52 * so we can't just memcpy_fromio().
53 */
54static void ixp4xx_copy_from(struct map_info *map, void *to,
55 unsigned long from, ssize_t len)
56{
57 int i;
58 u8 *dest = (u8 *) to;
59 u16 *src = (u16 *) (map->map_priv_1 + from);
60 u16 data;
61
62 for (i = 0; i < (len / 2); i++) {
63 data = src[i];
64 dest[i * 2] = BYTE0(data);
65 dest[i * 2 + 1] = BYTE1(data);
66 }
67
68 if (len & 1)
69 dest[len - 1] = BYTE0(src[i]);
70}
71
72/*
73 * Unaligned writes are ignored, causing the 8-bit
74 * probe to fail and proceed to the 16-bit probe (which succeeds).
75 */
76static void ixp4xx_probe_write16(struct map_info *map, map_word d, unsigned long adr)
77{
78 if (!(adr & 1))
79 *(__u16 *) (map->map_priv_1 + adr) = d.x[0];
80}
81
82/*
83 * Fast write16 function without the probing check above
84 */
85static void ixp4xx_write16(struct map_info *map, map_word d, unsigned long adr)
86{
87 *(__u16 *) (map->map_priv_1 + adr) = d.x[0];
88}
89
90struct ixp4xx_flash_info {
91 struct mtd_info *mtd;
92 struct map_info map;
93 struct mtd_partition *partitions;
94 struct resource *res;
95};
96
97static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
98
99static int ixp4xx_flash_remove(struct device *_dev)
100{
101 struct platform_device *dev = to_platform_device(_dev);
102 struct flash_platform_data *plat = dev->dev.platform_data;
103 struct ixp4xx_flash_info *info = dev_get_drvdata(&dev->dev);
104 map_word d;
105
106 dev_set_drvdata(&dev->dev, NULL);
107
108 if(!info)
109 return 0;
110
111 /*
112 * This is required for a soft reboot to work.
113 */
114 d.x[0] = 0xff;
115 ixp4xx_write16(&info->map, d, 0x55 * 0x2);
116
117 if (info->mtd) {
118 del_mtd_partitions(info->mtd);
119 map_destroy(info->mtd);
120 }
121 if (info->map.map_priv_1)
122 iounmap((void *) info->map.map_priv_1);
123
124 if (info->partitions)
125 kfree(info->partitions);
126
127 if (info->res) {
128 release_resource(info->res);
129 kfree(info->res);
130 }
131
132 if (plat->exit)
133 plat->exit();
134
135 /* Disable flash write */
136 *IXP4XX_EXP_CS0 &= ~IXP4XX_FLASH_WRITABLE;
137
138 return 0;
139}
140
141static int ixp4xx_flash_probe(struct device *_dev)
142{
143 struct platform_device *dev = to_platform_device(_dev);
144 struct flash_platform_data *plat = dev->dev.platform_data;
145 struct ixp4xx_flash_info *info;
146 int err = -1;
147
148 if (!plat)
149 return -ENODEV;
150
151 if (plat->init) {
152 err = plat->init();
153 if (err)
154 return err;
155 }
156
157 info = kmalloc(sizeof(struct ixp4xx_flash_info), GFP_KERNEL);
158 if(!info) {
159 err = -ENOMEM;
160 goto Error;
161 }
162 memzero(info, sizeof(struct ixp4xx_flash_info));
163
164 dev_set_drvdata(&dev->dev, info);
165
166 /*
167 * Enable flash write
168 * TODO: Move this out to board specific code
169 */
170 *IXP4XX_EXP_CS0 |= IXP4XX_FLASH_WRITABLE;
171
172 /*
173 * Tell the MTD layer we're not 1:1 mapped so that it does
174 * not attempt to do a direct access on us.
175 */
176 info->map.phys = NO_XIP;
177 info->map.size = dev->resource->end - dev->resource->start + 1;
178
179 /*
180 * We only support 16-bit accesses for now. If and when
181 * any board use 8-bit access, we'll fixup the driver to
182 * handle that.
183 */
184 info->map.bankwidth = 2;
185 info->map.name = dev->dev.bus_id;
186 info->map.read = ixp4xx_read16,
187 info->map.write = ixp4xx_probe_write16,
188 info->map.copy_from = ixp4xx_copy_from,
189
190 info->res = request_mem_region(dev->resource->start,
191 dev->resource->end - dev->resource->start + 1,
192 "IXP4XXFlash");
193 if (!info->res) {
194 printk(KERN_ERR "IXP4XXFlash: Could not reserve memory region\n");
195 err = -ENOMEM;
196 goto Error;
197 }
198
199 info->map.map_priv_1 = ioremap(dev->resource->start,
200 dev->resource->end - dev->resource->start + 1);
201 if (!info->map.map_priv_1) {
202 printk(KERN_ERR "IXP4XXFlash: Failed to ioremap region\n");
203 err = -EIO;
204 goto Error;
205 }
206
207 info->mtd = do_map_probe(plat->map_name, &info->map);
208 if (!info->mtd) {
209 printk(KERN_ERR "IXP4XXFlash: map_probe failed\n");
210 err = -ENXIO;
211 goto Error;
212 }
213 info->mtd->owner = THIS_MODULE;
214
215 /* Use the fast version */
216 info->map.write = ixp4xx_write16,
217
218 err = parse_mtd_partitions(info->mtd, probes, &info->partitions, 0);
219 if (err > 0) {
220 err = add_mtd_partitions(info->mtd, info->partitions, err);
221 if(err)
222 printk(KERN_ERR "Could not parse partitions\n");
223 }
224
225 if (err)
226 goto Error;
227
228 return 0;
229
230Error:
231 ixp4xx_flash_remove(_dev);
232 return err;
233}
234
235static struct device_driver ixp4xx_flash_driver = {
236 .name = "IXP4XX-Flash",
237 .bus = &platform_bus_type,
238 .probe = ixp4xx_flash_probe,
239 .remove = ixp4xx_flash_remove,
240};
241
242static int __init ixp4xx_flash_init(void)
243{
244 return driver_register(&ixp4xx_flash_driver);
245}
246
247static void __exit ixp4xx_flash_exit(void)
248{
249 driver_unregister(&ixp4xx_flash_driver);
250}
251
252
253module_init(ixp4xx_flash_init);
254module_exit(ixp4xx_flash_exit);
255
256MODULE_LICENSE("GPL");
257MODULE_DESCRIPTION("MTD map driver for Intel IXP4xx systems")
258MODULE_AUTHOR("Deepak Saxena");
259
diff --git a/drivers/mtd/maps/l440gx.c b/drivers/mtd/maps/l440gx.c
new file mode 100644
index 000000000000..b08668212ab7
--- /dev/null
+++ b/drivers/mtd/maps/l440gx.c
@@ -0,0 +1,157 @@
1/*
2 * $Id: l440gx.c,v 1.17 2004/11/28 09:40:39 dwmw2 Exp $
3 *
4 * BIOS Flash chip on Intel 440GX board.
5 *
6 * Bugs this currently does not work under linuxBIOS.
7 */
8
9#include <linux/module.h>
10#include <linux/pci.h>
11#include <linux/kernel.h>
12#include <linux/init.h>
13#include <asm/io.h>
14#include <linux/mtd/mtd.h>
15#include <linux/mtd/map.h>
16#include <linux/config.h>
17
18#define PIIXE_IOBASE_RESOURCE 11
19
20#define WINDOW_ADDR 0xfff00000
21#define WINDOW_SIZE 0x00100000
22#define BUSWIDTH 1
23
24static u32 iobase;
25#define IOBASE iobase
26#define TRIBUF_PORT (IOBASE+0x37)
27#define VPP_PORT (IOBASE+0x28)
28
29static struct mtd_info *mymtd;
30
31
32/* Is this really the vpp port? */
33static void l440gx_set_vpp(struct map_info *map, int vpp)
34{
35 unsigned long l;
36
37 l = inl(VPP_PORT);
38 if (vpp) {
39 l |= 1;
40 } else {
41 l &= ~1;
42 }
43 outl(l, VPP_PORT);
44}
45
46static struct map_info l440gx_map = {
47 .name = "L440GX BIOS",
48 .size = WINDOW_SIZE,
49 .bankwidth = BUSWIDTH,
50 .phys = WINDOW_ADDR,
51#if 0
52 /* FIXME verify that this is the
53 * appripriate code for vpp enable/disable
54 */
55 .set_vpp = l440gx_set_vpp
56#endif
57};
58
59static int __init init_l440gx(void)
60{
61 struct pci_dev *dev, *pm_dev;
62 struct resource *pm_iobase;
63 __u16 word;
64
65 dev = pci_find_device(PCI_VENDOR_ID_INTEL,
66 PCI_DEVICE_ID_INTEL_82371AB_0, NULL);
67
68 pm_dev = pci_find_device(PCI_VENDOR_ID_INTEL,
69 PCI_DEVICE_ID_INTEL_82371AB_3, NULL);
70
71 if (!dev || !pm_dev) {
72 printk(KERN_NOTICE "L440GX flash mapping: failed to find PIIX4 ISA bridge, cannot continue\n");
73 return -ENODEV;
74 }
75
76 l440gx_map.virt = ioremap_nocache(WINDOW_ADDR, WINDOW_SIZE);
77
78 if (!l440gx_map.virt) {
79 printk(KERN_WARNING "Failed to ioremap L440GX flash region\n");
80 return -ENOMEM;
81 }
82 simple_map_init(&l440gx_map);
83 printk(KERN_NOTICE "window_addr = 0x%08lx\n", (unsigned long)l440gx_map.virt);
84
85 /* Setup the pm iobase resource
86 * This code should move into some kind of generic bridge
87 * driver but for the moment I'm content with getting the
88 * allocation correct.
89 */
90 pm_iobase = &pm_dev->resource[PIIXE_IOBASE_RESOURCE];
91 if (!(pm_iobase->flags & IORESOURCE_IO)) {
92 pm_iobase->name = "pm iobase";
93 pm_iobase->start = 0;
94 pm_iobase->end = 63;
95 pm_iobase->flags = IORESOURCE_IO;
96
97 /* Put the current value in the resource */
98 pci_read_config_dword(pm_dev, 0x40, &iobase);
99 iobase &= ~1;
100 pm_iobase->start += iobase & ~1;
101 pm_iobase->end += iobase & ~1;
102
103 /* Allocate the resource region */
104 if (pci_assign_resource(pm_dev, PIIXE_IOBASE_RESOURCE) != 0) {
105 printk(KERN_WARNING "Could not allocate pm iobase resource\n");
106 iounmap(l440gx_map.virt);
107 return -ENXIO;
108 }
109 }
110 /* Set the iobase */
111 iobase = pm_iobase->start;
112 pci_write_config_dword(pm_dev, 0x40, iobase | 1);
113
114
115 /* Set XBCS# */
116 pci_read_config_word(dev, 0x4e, &word);
117 word |= 0x4;
118 pci_write_config_word(dev, 0x4e, word);
119
120 /* Supply write voltage to the chip */
121 l440gx_set_vpp(&l440gx_map, 1);
122
123 /* Enable the gate on the WE line */
124 outb(inb(TRIBUF_PORT) & ~1, TRIBUF_PORT);
125
126 printk(KERN_NOTICE "Enabled WE line to L440GX BIOS flash chip.\n");
127
128 mymtd = do_map_probe("jedec_probe", &l440gx_map);
129 if (!mymtd) {
130 printk(KERN_NOTICE "JEDEC probe on BIOS chip failed. Using ROM\n");
131 mymtd = do_map_probe("map_rom", &l440gx_map);
132 }
133 if (mymtd) {
134 mymtd->owner = THIS_MODULE;
135
136 add_mtd_device(mymtd);
137 return 0;
138 }
139
140 iounmap(l440gx_map.virt);
141 return -ENXIO;
142}
143
144static void __exit cleanup_l440gx(void)
145{
146 del_mtd_device(mymtd);
147 map_destroy(mymtd);
148
149 iounmap(l440gx_map.virt);
150}
151
152module_init(init_l440gx);
153module_exit(cleanup_l440gx);
154
155MODULE_LICENSE("GPL");
156MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
157MODULE_DESCRIPTION("MTD map driver for BIOS chips on Intel L440GX motherboards");
diff --git a/drivers/mtd/maps/lasat.c b/drivers/mtd/maps/lasat.c
new file mode 100644
index 000000000000..c658d4045ef2
--- /dev/null
+++ b/drivers/mtd/maps/lasat.c
@@ -0,0 +1,102 @@
1/*
2 * Flash device on Lasat 100 and 200 boards
3 *
4 * (C) 2002 Brian Murphy <brian@murphy.dk>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License version
8 * 2 as published by the Free Software Foundation.
9 *
10 * $Id: lasat.c,v 1.9 2004/11/04 13:24:15 gleixner Exp $
11 *
12 */
13
14#include <linux/module.h>
15#include <linux/types.h>
16#include <linux/kernel.h>
17#include <linux/init.h>
18#include <asm/io.h>
19#include <linux/mtd/mtd.h>
20#include <linux/mtd/map.h>
21#include <linux/mtd/partitions.h>
22#include <linux/config.h>
23#include <asm/lasat/lasat.h>
24
25static struct mtd_info *lasat_mtd;
26
27static struct mtd_partition partition_info[LASAT_MTD_LAST];
28static char *lasat_mtd_partnames[] = {"Bootloader", "Service", "Normal", "Filesystem", "Config"};
29
30static void lasat_set_vpp(struct map_info *map, int vpp)
31{
32 if (vpp)
33 *lasat_misc->flash_wp_reg |= 1 << lasat_misc->flash_wp_bit;
34 else
35 *lasat_misc->flash_wp_reg &= ~(1 << lasat_misc->flash_wp_bit);
36}
37
38static struct map_info lasat_map = {
39 .name = "LASAT flash",
40 .bankwidth = 4,
41 .set_vpp = lasat_set_vpp
42};
43
44static int __init init_lasat(void)
45{
46 int i;
47 /* since we use AMD chips and set_vpp is not implimented
48 * for these (yet) we still have to permanently enable flash write */
49 printk(KERN_NOTICE "Unprotecting flash\n");
50 ENABLE_VPP((&lasat_map));
51
52 lasat_map.phys = lasat_flash_partition_start(LASAT_MTD_BOOTLOADER);
53 lasat_map.virt = ioremap_nocache(
54 lasat_map.phys, lasat_board_info.li_flash_size);
55 lasat_map.size = lasat_board_info.li_flash_size;
56
57 simple_map_init(&lasat_map);
58
59 for (i=0; i < LASAT_MTD_LAST; i++)
60 partition_info[i].name = lasat_mtd_partnames[i];
61
62 lasat_mtd = do_map_probe("cfi_probe", &lasat_map);
63
64 if (!lasat_mtd)
65 lasat_mtd = do_map_probe("jedec_probe", &lasat_map);
66
67 if (lasat_mtd) {
68 u32 size, offset = 0;
69
70 lasat_mtd->owner = THIS_MODULE;
71
72 for (i=0; i < LASAT_MTD_LAST; i++) {
73 size = lasat_flash_partition_size(i);
74 partition_info[i].size = size;
75 partition_info[i].offset = offset;
76 offset += size;
77 }
78
79 add_mtd_partitions( lasat_mtd, partition_info, LASAT_MTD_LAST );
80 return 0;
81 }
82
83 return -ENXIO;
84}
85
86static void __exit cleanup_lasat(void)
87{
88 if (lasat_mtd) {
89 del_mtd_partitions(lasat_mtd);
90 map_destroy(lasat_mtd);
91 }
92 if (lasat_map.virt) {
93 lasat_map.virt = 0;
94 }
95}
96
97module_init(init_lasat);
98module_exit(cleanup_lasat);
99
100MODULE_LICENSE("GPL");
101MODULE_AUTHOR("Brian Murphy <brian@murphy.dk>");
102MODULE_DESCRIPTION("Lasat Safepipe/Masquerade MTD map driver");
diff --git a/drivers/mtd/maps/lubbock-flash.c b/drivers/mtd/maps/lubbock-flash.c
new file mode 100644
index 000000000000..1298de475c9a
--- /dev/null
+++ b/drivers/mtd/maps/lubbock-flash.c
@@ -0,0 +1,168 @@
1/*
2 * $Id: lubbock-flash.c,v 1.19 2004/11/04 13:24:15 gleixner Exp $
3 *
4 * Map driver for the Lubbock developer platform.
5 *
6 * Author: Nicolas Pitre
7 * Copyright: (C) 2001 MontaVista Software Inc.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
14#include <linux/module.h>
15#include <linux/types.h>
16#include <linux/kernel.h>
17#include <linux/init.h>
18#include <linux/dma-mapping.h>
19#include <linux/mtd/mtd.h>
20#include <linux/mtd/map.h>
21#include <linux/mtd/partitions.h>
22#include <asm/io.h>
23#include <asm/hardware.h>
24#include <asm/arch/pxa-regs.h>
25#include <asm/arch/lubbock.h>
26
27
28#define ROM_ADDR 0x00000000
29#define FLASH_ADDR 0x04000000
30
31#define WINDOW_SIZE 64*1024*1024
32
33static void lubbock_map_inval_cache(struct map_info *map, unsigned long from, ssize_t len)
34{
35 consistent_sync((char *)map->cached + from, len, DMA_FROM_DEVICE);
36}
37
38static struct map_info lubbock_maps[2] = { {
39 .size = WINDOW_SIZE,
40 .phys = 0x00000000,
41 .inval_cache = lubbock_map_inval_cache,
42}, {
43 .size = WINDOW_SIZE,
44 .phys = 0x04000000,
45 .inval_cache = lubbock_map_inval_cache,
46} };
47
48static struct mtd_partition lubbock_partitions[] = {
49 {
50 .name = "Bootloader",
51 .size = 0x00040000,
52 .offset = 0,
53 .mask_flags = MTD_WRITEABLE /* force read-only */
54 },{
55 .name = "Kernel",
56 .size = 0x00100000,
57 .offset = 0x00040000,
58 },{
59 .name = "Filesystem",
60 .size = MTDPART_SIZ_FULL,
61 .offset = 0x00140000
62 }
63};
64
65static struct mtd_info *mymtds[2];
66static struct mtd_partition *parsed_parts[2];
67static int nr_parsed_parts[2];
68
69static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
70
71static int __init init_lubbock(void)
72{
73 int flashboot = (LUB_CONF_SWITCHES & 1);
74 int ret = 0, i;
75
76 lubbock_maps[0].bankwidth = lubbock_maps[1].bankwidth =
77 (BOOT_DEF & 1) ? 2 : 4;
78
79 /* Compensate for the nROMBT switch which swaps the flash banks */
80 printk(KERN_NOTICE "Lubbock configured to boot from %s (bank %d)\n",
81 flashboot?"Flash":"ROM", flashboot);
82
83 lubbock_maps[flashboot^1].name = "Lubbock Application Flash";
84 lubbock_maps[flashboot].name = "Lubbock Boot ROM";
85
86 for (i = 0; i < 2; i++) {
87 lubbock_maps[i].virt = ioremap(lubbock_maps[i].phys, WINDOW_SIZE);
88 if (!lubbock_maps[i].virt) {
89 printk(KERN_WARNING "Failed to ioremap %s\n", lubbock_maps[i].name);
90 if (!ret)
91 ret = -ENOMEM;
92 continue;
93 }
94 lubbock_maps[i].cached = ioremap_cached(lubbock_maps[i].phys, WINDOW_SIZE);
95 if (!lubbock_maps[i].cached)
96 printk(KERN_WARNING "Failed to ioremap cached %s\n", lubbock_maps[i].name);
97 simple_map_init(&lubbock_maps[i]);
98
99 printk(KERN_NOTICE "Probing %s at physical address 0x%08lx (%d-bit bankwidth)\n",
100 lubbock_maps[i].name, lubbock_maps[i].phys,
101 lubbock_maps[i].bankwidth * 8);
102
103 mymtds[i] = do_map_probe("cfi_probe", &lubbock_maps[i]);
104
105 if (!mymtds[i]) {
106 iounmap((void *)lubbock_maps[i].virt);
107 if (lubbock_maps[i].cached)
108 iounmap(lubbock_maps[i].cached);
109 if (!ret)
110 ret = -EIO;
111 continue;
112 }
113 mymtds[i]->owner = THIS_MODULE;
114
115 ret = parse_mtd_partitions(mymtds[i], probes,
116 &parsed_parts[i], 0);
117
118 if (ret > 0)
119 nr_parsed_parts[i] = ret;
120 }
121
122 if (!mymtds[0] && !mymtds[1])
123 return ret;
124
125 for (i = 0; i < 2; i++) {
126 if (!mymtds[i]) {
127 printk(KERN_WARNING "%s is absent. Skipping\n", lubbock_maps[i].name);
128 } else if (nr_parsed_parts[i]) {
129 add_mtd_partitions(mymtds[i], parsed_parts[i], nr_parsed_parts[i]);
130 } else if (!i) {
131 printk("Using static partitions on %s\n", lubbock_maps[i].name);
132 add_mtd_partitions(mymtds[i], lubbock_partitions, ARRAY_SIZE(lubbock_partitions));
133 } else {
134 printk("Registering %s as whole device\n", lubbock_maps[i].name);
135 add_mtd_device(mymtds[i]);
136 }
137 }
138 return 0;
139}
140
141static void __exit cleanup_lubbock(void)
142{
143 int i;
144 for (i = 0; i < 2; i++) {
145 if (!mymtds[i])
146 continue;
147
148 if (nr_parsed_parts[i] || !i)
149 del_mtd_partitions(mymtds[i]);
150 else
151 del_mtd_device(mymtds[i]);
152
153 map_destroy(mymtds[i]);
154 iounmap((void *)lubbock_maps[i].virt);
155 if (lubbock_maps[i].cached)
156 iounmap(lubbock_maps[i].cached);
157
158 if (parsed_parts[i])
159 kfree(parsed_parts[i]);
160 }
161}
162
163module_init(init_lubbock);
164module_exit(cleanup_lubbock);
165
166MODULE_LICENSE("GPL");
167MODULE_AUTHOR("Nicolas Pitre <nico@cam.org>");
168MODULE_DESCRIPTION("MTD map driver for Intel Lubbock");
diff --git a/drivers/mtd/maps/map_funcs.c b/drivers/mtd/maps/map_funcs.c
new file mode 100644
index 000000000000..38f6a7af53f8
--- /dev/null
+++ b/drivers/mtd/maps/map_funcs.c
@@ -0,0 +1,44 @@
1/*
2 * $Id: map_funcs.c,v 1.9 2004/07/13 22:33:15 dwmw2 Exp $
3 *
4 * Out-of-line map I/O functions for simple maps when CONFIG_COMPLEX_MAPPINGS
5 * is enabled.
6 */
7
8#include <linux/kernel.h>
9#include <linux/module.h>
10
11#include <linux/mtd/map.h>
12
13static map_word simple_map_read(struct map_info *map, unsigned long ofs)
14{
15 return inline_map_read(map, ofs);
16}
17
18static void simple_map_write(struct map_info *map, const map_word datum, unsigned long ofs)
19{
20 inline_map_write(map, datum, ofs);
21}
22
23static void simple_map_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
24{
25 inline_map_copy_from(map, to, from, len);
26}
27
28static void simple_map_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
29{
30 inline_map_copy_to(map, to, from, len);
31}
32
33void simple_map_init(struct map_info *map)
34{
35 BUG_ON(!map_bankwidth_supported(map->bankwidth));
36
37 map->read = simple_map_read;
38 map->write = simple_map_write;
39 map->copy_from = simple_map_copy_from;
40 map->copy_to = simple_map_copy_to;
41}
42
43EXPORT_SYMBOL(simple_map_init);
44MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/maps/mbx860.c b/drivers/mtd/maps/mbx860.c
new file mode 100644
index 000000000000..c5c6901a4763
--- /dev/null
+++ b/drivers/mtd/maps/mbx860.c
@@ -0,0 +1,100 @@
1/*
2 * $Id: mbx860.c,v 1.8 2004/11/04 13:24:15 gleixner Exp $
3 *
4 * Handle mapping of the flash on MBX860 boards
5 *
6 * Author: Anton Todorov
7 * Copyright: (C) 2001 Emness Technology
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 *
13 */
14
15#include <linux/module.h>
16#include <linux/types.h>
17#include <linux/kernel.h>
18#include <linux/init.h>
19#include <asm/io.h>
20#include <linux/mtd/mtd.h>
21#include <linux/mtd/map.h>
22#include <linux/mtd/partitions.h>
23
24
25#define WINDOW_ADDR 0xfe000000
26#define WINDOW_SIZE 0x00200000
27
28/* Flash / Partition sizing */
29#define MAX_SIZE_KiB 8192
30#define BOOT_PARTITION_SIZE_KiB 512
31#define KERNEL_PARTITION_SIZE_KiB 5632
32#define APP_PARTITION_SIZE_KiB 2048
33
34#define NUM_PARTITIONS 3
35
36/* partition_info gives details on the logical partitions that the split the
37 * single flash device into. If the size if zero we use up to the end of the
38 * device. */
39static struct mtd_partition partition_info[]={
40 { .name = "MBX flash BOOT partition",
41 .offset = 0,
42 .size = BOOT_PARTITION_SIZE_KiB*1024 },
43 { .name = "MBX flash DATA partition",
44 .offset = BOOT_PARTITION_SIZE_KiB*1024,
45 .size = (KERNEL_PARTITION_SIZE_KiB)*1024 },
46 { .name = "MBX flash APPLICATION partition",
47 .offset = (BOOT_PARTITION_SIZE_KiB+KERNEL_PARTITION_SIZE_KiB)*1024 }
48};
49
50
51static struct mtd_info *mymtd;
52
53struct map_info mbx_map = {
54 .name = "MBX flash",
55 .size = WINDOW_SIZE,
56 .phys = WINDOW_ADDR,
57 .bankwidth = 4,
58};
59
60int __init init_mbx(void)
61{
62 printk(KERN_NOTICE "Motorola MBX flash device: 0x%x at 0x%x\n", WINDOW_SIZE*4, WINDOW_ADDR);
63 mbx_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE * 4);
64
65 if (!mbx_map.virt) {
66 printk("Failed to ioremap\n");
67 return -EIO;
68 }
69 simple_map_init(&mbx_map);
70
71 mymtd = do_map_probe("jedec_probe", &mbx_map);
72 if (mymtd) {
73 mymtd->owner = THIS_MODULE;
74 add_mtd_device(mymtd);
75 add_mtd_partitions(mymtd, partition_info, NUM_PARTITIONS);
76 return 0;
77 }
78
79 iounmap((void *)mbx_map.virt);
80 return -ENXIO;
81}
82
83static void __exit cleanup_mbx(void)
84{
85 if (mymtd) {
86 del_mtd_device(mymtd);
87 map_destroy(mymtd);
88 }
89 if (mbx_map.virt) {
90 iounmap((void *)mbx_map.virt);
91 mbx_map.virt = 0;
92 }
93}
94
95module_init(init_mbx);
96module_exit(cleanup_mbx);
97
98MODULE_AUTHOR("Anton Todorov <a.todorov@emness.com>");
99MODULE_DESCRIPTION("MTD map driver for Motorola MBX860 board");
100MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/maps/mpc1211.c b/drivers/mtd/maps/mpc1211.c
new file mode 100644
index 000000000000..4685e8e13460
--- /dev/null
+++ b/drivers/mtd/maps/mpc1211.c
@@ -0,0 +1,81 @@
1/*
2 * Flash on MPC-1211
3 *
4 * $Id: mpc1211.c,v 1.4 2004/09/16 23:27:13 gleixner Exp $
5 *
6 * (C) 2002 Interface, Saito.K & Jeanne
7 *
8 * GPL'd
9 */
10
11#include <linux/module.h>
12#include <linux/types.h>
13#include <linux/kernel.h>
14#include <asm/io.h>
15#include <linux/mtd/mtd.h>
16#include <linux/mtd/map.h>
17#include <linux/mtd/partitions.h>
18#include <linux/config.h>
19
20static struct mtd_info *flash_mtd;
21static struct mtd_partition *parsed_parts;
22
23struct map_info mpc1211_flash_map = {
24 .name = "MPC-1211 FLASH",
25 .size = 0x80000,
26 .bankwidth = 1,
27};
28
29static struct mtd_partition mpc1211_partitions[] = {
30 {
31 .name = "IPL & ETH-BOOT",
32 .offset = 0x00000000,
33 .size = 0x10000,
34 },
35 {
36 .name = "Flash FS",
37 .offset = 0x00010000,
38 .size = MTDPART_SIZ_FULL,
39 }
40};
41
42static int __init init_mpc1211_maps(void)
43{
44 int nr_parts;
45
46 mpc1211_flash_map.phys = 0;
47 mpc1211_flash_map.virt = (void __iomem *)P2SEGADDR(0);
48
49 simple_map_init(&mpc1211_flash_map);
50
51 printk(KERN_NOTICE "Probing for flash chips at 0x00000000:\n");
52 flash_mtd = do_map_probe("jedec_probe", &mpc1211_flash_map);
53 if (!flash_mtd) {
54 printk(KERN_NOTICE "Flash chips not detected at either possible location.\n");
55 return -ENXIO;
56 }
57 printk(KERN_NOTICE "MPC-1211: Flash at 0x%08lx\n", mpc1211_flash_map.virt & 0x1fffffff);
58 flash_mtd->module = THIS_MODULE;
59
60 parsed_parts = mpc1211_partitions;
61 nr_parts = ARRAY_SIZE(mpc1211_partitions);
62
63 add_mtd_partitions(flash_mtd, parsed_parts, nr_parts);
64 return 0;
65}
66
67static void __exit cleanup_mpc1211_maps(void)
68{
69 if (parsed_parts)
70 del_mtd_partitions(flash_mtd);
71 else
72 del_mtd_device(flash_mtd);
73 map_destroy(flash_mtd);
74}
75
76module_init(init_mpc1211_maps);
77module_exit(cleanup_mpc1211_maps);
78
79MODULE_LICENSE("GPL");
80MODULE_AUTHOR("Saito.K & Jeanne <ksaito@interface.co.jp>");
81MODULE_DESCRIPTION("MTD map driver for MPC-1211 boards. Interface");
diff --git a/drivers/mtd/maps/netsc520.c b/drivers/mtd/maps/netsc520.c
new file mode 100644
index 000000000000..ab7e6358d281
--- /dev/null
+++ b/drivers/mtd/maps/netsc520.c
@@ -0,0 +1,140 @@
1/* netsc520.c -- MTD map driver for AMD NetSc520 Demonstration Board
2 *
3 * Copyright (C) 2001 Mark Langsdorf (mark.langsdorf@amd.com)
4 * based on sc520cdp.c by Sysgo Real-Time Solutions GmbH
5 *
6 * $Id: netsc520.c,v 1.13 2004/11/28 09:40:40 dwmw2 Exp $
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
21 *
22 * The NetSc520 is a demonstration board for the Elan Sc520 processor available
23 * from AMD. It has a single back of 16 megs of 32-bit Flash ROM and another
24 * 16 megs of SDRAM.
25 */
26
27#include <linux/module.h>
28#include <linux/types.h>
29#include <linux/kernel.h>
30#include <linux/init.h>
31#include <asm/io.h>
32#include <linux/mtd/mtd.h>
33#include <linux/mtd/map.h>
34#include <linux/mtd/partitions.h>
35
36
37/*
38** The single, 16 megabyte flash bank is divided into four virtual
39** partitions. The first partition is 768 KiB and is intended to
40** store the kernel image loaded by the bootstrap loader. The second
41** partition is 256 KiB and holds the BIOS image. The third
42** partition is 14.5 MiB and is intended for the flash file system
43** image. The last partition is 512 KiB and contains another copy
44** of the BIOS image and the reset vector.
45**
46** Only the third partition should be mounted. The first partition
47** should not be mounted, but it can erased and written to using the
48** MTD character routines. The second and fourth partitions should
49** not be touched - it is possible to corrupt the BIOS image by
50** mounting these partitions, and potentially the board will not be
51** recoverable afterwards.
52*/
53
54/* partition_info gives details on the logical partitions that the split the
55 * single flash device into. If the size if zero we use up to the end of the
56 * device. */
57static struct mtd_partition partition_info[]={
58 {
59 .name = "NetSc520 boot kernel",
60 .offset = 0,
61 .size = 0xc0000
62 },
63 {
64 .name = "NetSc520 Low BIOS",
65 .offset = 0xc0000,
66 .size = 0x40000
67 },
68 {
69 .name = "NetSc520 file system",
70 .offset = 0x100000,
71 .size = 0xe80000
72 },
73 {
74 .name = "NetSc520 High BIOS",
75 .offset = 0xf80000,
76 .size = 0x80000
77 },
78};
79#define NUM_PARTITIONS (sizeof(partition_info)/sizeof(partition_info[0]))
80
81#define WINDOW_SIZE 0x00100000
82#define WINDOW_ADDR 0x00200000
83
84static struct map_info netsc520_map = {
85 .name = "netsc520 Flash Bank",
86 .size = WINDOW_SIZE,
87 .bankwidth = 4,
88 .phys = WINDOW_ADDR,
89};
90
91#define NUM_FLASH_BANKS (sizeof(netsc520_map)/sizeof(struct map_info))
92
93static struct mtd_info *mymtd;
94
95static int __init init_netsc520(void)
96{
97 printk(KERN_NOTICE "NetSc520 flash device: 0x%lx at 0x%lx\n", netsc520_map.size, netsc520_map.phys);
98 netsc520_map.virt = ioremap_nocache(netsc520_map.phys, netsc520_map.size);
99
100 if (!netsc520_map.virt) {
101 printk("Failed to ioremap_nocache\n");
102 return -EIO;
103 }
104
105 simple_map_init(&netsc520_map);
106
107 mymtd = do_map_probe("cfi_probe", &netsc520_map);
108 if(!mymtd)
109 mymtd = do_map_probe("map_ram", &netsc520_map);
110 if(!mymtd)
111 mymtd = do_map_probe("map_rom", &netsc520_map);
112
113 if (!mymtd) {
114 iounmap(netsc520_map.virt);
115 return -ENXIO;
116 }
117
118 mymtd->owner = THIS_MODULE;
119 add_mtd_partitions( mymtd, partition_info, NUM_PARTITIONS );
120 return 0;
121}
122
123static void __exit cleanup_netsc520(void)
124{
125 if (mymtd) {
126 del_mtd_partitions(mymtd);
127 map_destroy(mymtd);
128 }
129 if (netsc520_map.virt) {
130 iounmap(netsc520_map.virt);
131 netsc520_map.virt = NULL;
132 }
133}
134
135module_init(init_netsc520);
136module_exit(cleanup_netsc520);
137
138MODULE_LICENSE("GPL");
139MODULE_AUTHOR("Mark Langsdorf <mark.langsdorf@amd.com>");
140MODULE_DESCRIPTION("MTD map driver for AMD NetSc520 Demonstration Board");
diff --git a/drivers/mtd/maps/nettel.c b/drivers/mtd/maps/nettel.c
new file mode 100644
index 000000000000..61be5a4148c9
--- /dev/null
+++ b/drivers/mtd/maps/nettel.c
@@ -0,0 +1,496 @@
1/****************************************************************************/
2
3/*
4 * nettel.c -- mappings for NETtel/SecureEdge/SnapGear (x86) boards.
5 *
6 * (C) Copyright 2000-2001, Greg Ungerer (gerg@snapgear.com)
7 * (C) Copyright 2001-2002, SnapGear (www.snapgear.com)
8 *
9 * $Id: nettel.c,v 1.10 2005/01/05 17:11:29 dwmw2 Exp $
10 */
11
12/****************************************************************************/
13
14#include <linux/module.h>
15#include <linux/init.h>
16#include <linux/types.h>
17#include <linux/kernel.h>
18#include <linux/mtd/mtd.h>
19#include <linux/mtd/map.h>
20#include <linux/mtd/partitions.h>
21#include <linux/mtd/cfi.h>
22#include <linux/reboot.h>
23#include <asm/io.h>
24
25/****************************************************************************/
26
27#define INTEL_BUSWIDTH 1
28#define AMD_WINDOW_MAXSIZE 0x00200000
29#define AMD_BUSWIDTH 1
30
31/*
32 * PAR masks and shifts, assuming 64K pages.
33 */
34#define SC520_PAR_ADDR_MASK 0x00003fff
35#define SC520_PAR_ADDR_SHIFT 16
36#define SC520_PAR_TO_ADDR(par) \
37 (((par)&SC520_PAR_ADDR_MASK) << SC520_PAR_ADDR_SHIFT)
38
39#define SC520_PAR_SIZE_MASK 0x01ffc000
40#define SC520_PAR_SIZE_SHIFT 2
41#define SC520_PAR_TO_SIZE(par) \
42 ((((par)&SC520_PAR_SIZE_MASK) << SC520_PAR_SIZE_SHIFT) + (64*1024))
43
44#define SC520_PAR(cs, addr, size) \
45 ((cs) | \
46 ((((size)-(64*1024)) >> SC520_PAR_SIZE_SHIFT) & SC520_PAR_SIZE_MASK) | \
47 (((addr) >> SC520_PAR_ADDR_SHIFT) & SC520_PAR_ADDR_MASK))
48
49#define SC520_PAR_BOOTCS 0x8a000000
50#define SC520_PAR_ROMCS1 0xaa000000
51#define SC520_PAR_ROMCS2 0xca000000 /* Cache disabled, 64K page */
52
53static void *nettel_mmcrp = NULL;
54
55#ifdef CONFIG_MTD_CFI_INTELEXT
56static struct mtd_info *intel_mtd;
57#endif
58static struct mtd_info *amd_mtd;
59
60/****************************************************************************/
61
62/****************************************************************************/
63
64#ifdef CONFIG_MTD_CFI_INTELEXT
65static struct map_info nettel_intel_map = {
66 .name = "SnapGear Intel",
67 .size = 0,
68 .bankwidth = INTEL_BUSWIDTH,
69};
70
71static struct mtd_partition nettel_intel_partitions[] = {
72 {
73 .name = "SnapGear kernel",
74 .offset = 0,
75 .size = 0x000e0000
76 },
77 {
78 .name = "SnapGear filesystem",
79 .offset = 0x00100000,
80 },
81 {
82 .name = "SnapGear config",
83 .offset = 0x000e0000,
84 .size = 0x00020000
85 },
86 {
87 .name = "SnapGear Intel",
88 .offset = 0
89 },
90 {
91 .name = "SnapGear BIOS Config",
92 .offset = 0x007e0000,
93 .size = 0x00020000
94 },
95 {
96 .name = "SnapGear BIOS",
97 .offset = 0x007e0000,
98 .size = 0x00020000
99 },
100};
101#endif
102
103static struct map_info nettel_amd_map = {
104 .name = "SnapGear AMD",
105 .size = AMD_WINDOW_MAXSIZE,
106 .bankwidth = AMD_BUSWIDTH,
107};
108
109static struct mtd_partition nettel_amd_partitions[] = {
110 {
111 .name = "SnapGear BIOS config",
112 .offset = 0x000e0000,
113 .size = 0x00010000
114 },
115 {
116 .name = "SnapGear BIOS",
117 .offset = 0x000f0000,
118 .size = 0x00010000
119 },
120 {
121 .name = "SnapGear AMD",
122 .offset = 0
123 },
124 {
125 .name = "SnapGear high BIOS",
126 .offset = 0x001f0000,
127 .size = 0x00010000
128 }
129};
130
131#define NUM_AMD_PARTITIONS \
132 (sizeof(nettel_amd_partitions)/sizeof(nettel_amd_partitions[0]))
133
134/****************************************************************************/
135
136#ifdef CONFIG_MTD_CFI_INTELEXT
137
138/*
139 * Set the Intel flash back to read mode since some old boot
140 * loaders don't.
141 */
142static int nettel_reboot_notifier(struct notifier_block *nb, unsigned long val, void *v)
143{
144 struct cfi_private *cfi = nettel_intel_map.fldrv_priv;
145 unsigned long b;
146
147 /* Make sure all FLASH chips are put back into read mode */
148 for (b = 0; (b < nettel_intel_partitions[3].size); b += 0x100000) {
149 cfi_send_gen_cmd(0xff, 0x55, b, &nettel_intel_map, cfi,
150 cfi->device_type, NULL);
151 }
152 return(NOTIFY_OK);
153}
154
155static struct notifier_block nettel_notifier_block = {
156 nettel_reboot_notifier, NULL, 0
157};
158
159/*
160 * Erase the configuration file system.
161 * Used to support the software reset button.
162 */
163static void nettel_erasecallback(struct erase_info *done)
164{
165 wait_queue_head_t *wait_q = (wait_queue_head_t *)done->priv;
166 wake_up(wait_q);
167}
168
169static struct erase_info nettel_erase;
170
171int nettel_eraseconfig(void)
172{
173 struct mtd_info *mtd;
174 DECLARE_WAITQUEUE(wait, current);
175 wait_queue_head_t wait_q;
176 int ret;
177
178 init_waitqueue_head(&wait_q);
179 mtd = get_mtd_device(NULL, 2);
180 if (mtd) {
181 nettel_erase.mtd = mtd;
182 nettel_erase.callback = nettel_erasecallback;
183 nettel_erase.callback = NULL;
184 nettel_erase.addr = 0;
185 nettel_erase.len = mtd->size;
186 nettel_erase.priv = (u_long) &wait_q;
187 nettel_erase.priv = 0;
188
189 set_current_state(TASK_INTERRUPTIBLE);
190 add_wait_queue(&wait_q, &wait);
191
192 ret = MTD_ERASE(mtd, &nettel_erase);
193 if (ret) {
194 set_current_state(TASK_RUNNING);
195 remove_wait_queue(&wait_q, &wait);
196 put_mtd_device(mtd);
197 return(ret);
198 }
199
200 schedule(); /* Wait for erase to finish. */
201 remove_wait_queue(&wait_q, &wait);
202
203 put_mtd_device(mtd);
204 }
205
206 return(0);
207}
208
209#else
210
211int nettel_eraseconfig(void)
212{
213 return(0);
214}
215
216#endif
217
218/****************************************************************************/
219
220int __init nettel_init(void)
221{
222 volatile unsigned long *amdpar;
223 unsigned long amdaddr, maxsize;
224 int num_amd_partitions=0;
225#ifdef CONFIG_MTD_CFI_INTELEXT
226 volatile unsigned long *intel0par, *intel1par;
227 unsigned long orig_bootcspar, orig_romcs1par;
228 unsigned long intel0addr, intel0size;
229 unsigned long intel1addr, intel1size;
230 int intelboot, intel0cs, intel1cs;
231 int num_intel_partitions;
232#endif
233 int rc = 0;
234
235 nettel_mmcrp = (void *) ioremap_nocache(0xfffef000, 4096);
236 if (nettel_mmcrp == NULL) {
237 printk("SNAPGEAR: failed to disable MMCR cache??\n");
238 return(-EIO);
239 }
240
241 /* Set CPU clock to be 33.000MHz */
242 *((unsigned char *) (nettel_mmcrp + 0xc64)) = 0x01;
243
244 amdpar = (volatile unsigned long *) (nettel_mmcrp + 0xc4);
245
246#ifdef CONFIG_MTD_CFI_INTELEXT
247 intelboot = 0;
248 intel0cs = SC520_PAR_ROMCS1;
249 intel0par = (volatile unsigned long *) (nettel_mmcrp + 0xc0);
250 intel1cs = SC520_PAR_ROMCS2;
251 intel1par = (volatile unsigned long *) (nettel_mmcrp + 0xbc);
252
253 /*
254 * Save the CS settings then ensure ROMCS1 and ROMCS2 are off,
255 * otherwise they might clash with where we try to map BOOTCS.
256 */
257 orig_bootcspar = *amdpar;
258 orig_romcs1par = *intel0par;
259 *intel0par = 0;
260 *intel1par = 0;
261#endif
262
263 /*
264 * The first thing to do is determine if we have a separate
265 * boot FLASH device. Typically this is a small (1 to 2MB)
266 * AMD FLASH part. It seems that device size is about the
267 * only way to tell if this is the case...
268 */
269 amdaddr = 0x20000000;
270 maxsize = AMD_WINDOW_MAXSIZE;
271
272 *amdpar = SC520_PAR(SC520_PAR_BOOTCS, amdaddr, maxsize);
273 __asm__ ("wbinvd");
274
275 nettel_amd_map.phys = amdaddr;
276 nettel_amd_map.virt = ioremap_nocache(amdaddr, maxsize);
277 if (!nettel_amd_map.virt) {
278 printk("SNAPGEAR: failed to ioremap() BOOTCS\n");
279 return(-EIO);
280 }
281 simple_map_init(&nettel_amd_map);
282
283 if ((amd_mtd = do_map_probe("jedec_probe", &nettel_amd_map))) {
284 printk(KERN_NOTICE "SNAPGEAR: AMD flash device size = %dK\n",
285 amd_mtd->size>>10);
286
287 amd_mtd->owner = THIS_MODULE;
288
289 /* The high BIOS partition is only present for 2MB units */
290 num_amd_partitions = NUM_AMD_PARTITIONS;
291 if (amd_mtd->size < AMD_WINDOW_MAXSIZE)
292 num_amd_partitions--;
293 /* Don't add the partition until after the primary INTEL's */
294
295#ifdef CONFIG_MTD_CFI_INTELEXT
296 /*
297 * Map the Intel flash into memory after the AMD
298 * It has to start on a multiple of maxsize.
299 */
300 maxsize = SC520_PAR_TO_SIZE(orig_romcs1par);
301 if (maxsize < (32 * 1024 * 1024))
302 maxsize = (32 * 1024 * 1024);
303 intel0addr = amdaddr + maxsize;
304#endif
305 } else {
306#ifdef CONFIG_MTD_CFI_INTELEXT
307 /* INTEL boot FLASH */
308 intelboot++;
309
310 if (!orig_romcs1par) {
311 intel0cs = SC520_PAR_BOOTCS;
312 intel0par = (volatile unsigned long *)
313 (nettel_mmcrp + 0xc4);
314 intel1cs = SC520_PAR_ROMCS1;
315 intel1par = (volatile unsigned long *)
316 (nettel_mmcrp + 0xc0);
317
318 intel0addr = SC520_PAR_TO_ADDR(orig_bootcspar);
319 maxsize = SC520_PAR_TO_SIZE(orig_bootcspar);
320 } else {
321 /* Kernel base is on ROMCS1, not BOOTCS */
322 intel0cs = SC520_PAR_ROMCS1;
323 intel0par = (volatile unsigned long *)
324 (nettel_mmcrp + 0xc0);
325 intel1cs = SC520_PAR_BOOTCS;
326 intel1par = (volatile unsigned long *)
327 (nettel_mmcrp + 0xc4);
328
329 intel0addr = SC520_PAR_TO_ADDR(orig_romcs1par);
330 maxsize = SC520_PAR_TO_SIZE(orig_romcs1par);
331 }
332
333 /* Destroy useless AMD MTD mapping */
334 amd_mtd = NULL;
335 iounmap(nettel_amd_map.virt);
336 nettel_amd_map.virt = NULL;
337#else
338 /* Only AMD flash supported */
339 return(-ENXIO);
340#endif
341 }
342
343#ifdef CONFIG_MTD_CFI_INTELEXT
344 /*
345 * We have determined the INTEL FLASH configuration, so lets
346 * go ahead and probe for them now.
347 */
348
349 /* Set PAR to the maximum size */
350 if (maxsize < (32 * 1024 * 1024))
351 maxsize = (32 * 1024 * 1024);
352 *intel0par = SC520_PAR(intel0cs, intel0addr, maxsize);
353
354 /* Turn other PAR off so the first probe doesn't find it */
355 *intel1par = 0;
356
357 /* Probe for the the size of the first Intel flash */
358 nettel_intel_map.size = maxsize;
359 nettel_intel_map.phys = intel0addr;
360 nettel_intel_map.virt = ioremap_nocache(intel0addr, maxsize);
361 if (!nettel_intel_map.virt) {
362 printk("SNAPGEAR: failed to ioremap() ROMCS1\n");
363 return(-EIO);
364 }
365 simple_map_init(&nettel_intel_map);
366
367 intel_mtd = do_map_probe("cfi_probe", &nettel_intel_map);
368 if (!intel_mtd) {
369 iounmap(nettel_intel_map.virt);
370 return(-ENXIO);
371 }
372
373 /* Set PAR to the detected size */
374 intel0size = intel_mtd->size;
375 *intel0par = SC520_PAR(intel0cs, intel0addr, intel0size);
376
377 /*
378 * Map second Intel FLASH right after first. Set its size to the
379 * same maxsize used for the first Intel FLASH.
380 */
381 intel1addr = intel0addr + intel0size;
382 *intel1par = SC520_PAR(intel1cs, intel1addr, maxsize);
383 __asm__ ("wbinvd");
384
385 maxsize += intel0size;
386
387 /* Delete the old map and probe again to do both chips */
388 map_destroy(intel_mtd);
389 intel_mtd = NULL;
390 iounmap(nettel_intel_map.virt);
391
392 nettel_intel_map.size = maxsize;
393 nettel_intel_map.virt = ioremap_nocache(intel0addr, maxsize);
394 if (!nettel_intel_map.virt) {
395 printk("SNAPGEAR: failed to ioremap() ROMCS1/2\n");
396 return(-EIO);
397 }
398
399 intel_mtd = do_map_probe("cfi_probe", &nettel_intel_map);
400 if (! intel_mtd) {
401 iounmap((void *) nettel_intel_map.virt);
402 return(-ENXIO);
403 }
404
405 intel1size = intel_mtd->size - intel0size;
406 if (intel1size > 0) {
407 *intel1par = SC520_PAR(intel1cs, intel1addr, intel1size);
408 __asm__ ("wbinvd");
409 } else {
410 *intel1par = 0;
411 }
412
413 printk(KERN_NOTICE "SNAPGEAR: Intel flash device size = %dK\n",
414 (intel_mtd->size >> 10));
415
416 intel_mtd->owner = THIS_MODULE;
417
418#ifndef CONFIG_BLK_DEV_INITRD
419 ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, 1);
420#endif
421
422 num_intel_partitions = sizeof(nettel_intel_partitions) /
423 sizeof(nettel_intel_partitions[0]);
424
425 if (intelboot) {
426 /*
427 * Adjust offset and size of last boot partition.
428 * Must allow for BIOS region at end of FLASH.
429 */
430 nettel_intel_partitions[1].size = (intel0size + intel1size) -
431 (1024*1024 + intel_mtd->erasesize);
432 nettel_intel_partitions[3].size = intel0size + intel1size;
433 nettel_intel_partitions[4].offset =
434 (intel0size + intel1size) - intel_mtd->erasesize;
435 nettel_intel_partitions[4].size = intel_mtd->erasesize;
436 nettel_intel_partitions[5].offset =
437 nettel_intel_partitions[4].offset;
438 nettel_intel_partitions[5].size =
439 nettel_intel_partitions[4].size;
440 } else {
441 /* No BIOS regions when AMD boot */
442 num_intel_partitions -= 2;
443 }
444 rc = add_mtd_partitions(intel_mtd, nettel_intel_partitions,
445 num_intel_partitions);
446#endif
447
448 if (amd_mtd) {
449 rc = add_mtd_partitions(amd_mtd, nettel_amd_partitions,
450 num_amd_partitions);
451 }
452
453#ifdef CONFIG_MTD_CFI_INTELEXT
454 register_reboot_notifier(&nettel_notifier_block);
455#endif
456
457 return(rc);
458}
459
460/****************************************************************************/
461
462void __exit nettel_cleanup(void)
463{
464#ifdef CONFIG_MTD_CFI_INTELEXT
465 unregister_reboot_notifier(&nettel_notifier_block);
466#endif
467 if (amd_mtd) {
468 del_mtd_partitions(amd_mtd);
469 map_destroy(amd_mtd);
470 }
471 if (nettel_amd_map.virt) {
472 iounmap(nettel_amd_map.virt);
473 nettel_amd_map.virt = NULL;
474 }
475#ifdef CONFIG_MTD_CFI_INTELEXT
476 if (intel_mtd) {
477 del_mtd_partitions(intel_mtd);
478 map_destroy(intel_mtd);
479 }
480 if (nettel_intel_map.virt) {
481 iounmap(nettel_intel_map.virt);
482 nettel_intel_map.virt = 0;
483 }
484#endif
485}
486
487/****************************************************************************/
488
489module_init(nettel_init);
490module_exit(nettel_cleanup);
491
492MODULE_LICENSE("GPL");
493MODULE_AUTHOR("Greg Ungerer <gerg@snapgear.com>");
494MODULE_DESCRIPTION("SnapGear/SecureEdge FLASH support");
495
496/****************************************************************************/
diff --git a/drivers/mtd/maps/ocelot.c b/drivers/mtd/maps/ocelot.c
new file mode 100644
index 000000000000..82c3070678c5
--- /dev/null
+++ b/drivers/mtd/maps/ocelot.c
@@ -0,0 +1,175 @@
1/*
2 * $Id: ocelot.c,v 1.16 2005/01/05 18:05:13 dwmw2 Exp $
3 *
4 * Flash on Momenco Ocelot
5 */
6
7#include <linux/module.h>
8#include <linux/types.h>
9#include <linux/kernel.h>
10#include <linux/init.h>
11#include <asm/io.h>
12#include <linux/mtd/mtd.h>
13#include <linux/mtd/map.h>
14#include <linux/mtd/partitions.h>
15
16#define OCELOT_PLD 0x2c000000
17#define FLASH_WINDOW_ADDR 0x2fc00000
18#define FLASH_WINDOW_SIZE 0x00080000
19#define FLASH_BUSWIDTH 1
20#define NVRAM_WINDOW_ADDR 0x2c800000
21#define NVRAM_WINDOW_SIZE 0x00007FF0
22#define NVRAM_BUSWIDTH 1
23
24static unsigned int cacheflush = 0;
25
26static struct mtd_info *flash_mtd;
27static struct mtd_info *nvram_mtd;
28
29static void ocelot_ram_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf)
30{
31 struct map_info *map = mtd->priv;
32 size_t done = 0;
33
34 /* If we use memcpy, it does word-wide writes. Even though we told the
35 GT64120A that it's an 8-bit wide region, word-wide writes don't work.
36 We end up just writing the first byte of the four to all four bytes.
37 So we have this loop instead */
38 *retlen = len;
39 while(len) {
40 __raw_writeb(*(unsigned char *) from, map->virt + to);
41 from++;
42 to++;
43 len--;
44 }
45}
46
47static struct mtd_partition *parsed_parts;
48
49struct map_info ocelot_flash_map = {
50 .name = "Ocelot boot flash",
51 .size = FLASH_WINDOW_SIZE,
52 .bankwidth = FLASH_BUSWIDTH,
53 .phys = FLASH_WINDOW_ADDR,
54};
55
56struct map_info ocelot_nvram_map = {
57 .name = "Ocelot NVRAM",
58 .size = NVRAM_WINDOW_SIZE,
59 .bankwidth = NVRAM_BUSWIDTH,
60 .phys = NVRAM_WINDOW_ADDR,
61};
62
63static const char *probes[] = { "RedBoot", NULL };
64
65static int __init init_ocelot_maps(void)
66{
67 void *pld;
68 int nr_parts;
69 unsigned char brd_status;
70
71 printk(KERN_INFO "Momenco Ocelot MTD mappings: Flash 0x%x at 0x%x, NVRAM 0x%x at 0x%x\n",
72 FLASH_WINDOW_SIZE, FLASH_WINDOW_ADDR, NVRAM_WINDOW_SIZE, NVRAM_WINDOW_ADDR);
73
74 /* First check whether the flash jumper is present */
75 pld = ioremap(OCELOT_PLD, 0x10);
76 if (!pld) {
77 printk(KERN_NOTICE "Failed to ioremap Ocelot PLD\n");
78 return -EIO;
79 }
80 brd_status = readb(pld+4);
81 iounmap(pld);
82
83 /* Now ioremap the NVRAM space */
84 ocelot_nvram_map.virt = ioremap_nocache(NVRAM_WINDOW_ADDR, NVRAM_WINDOW_SIZE);
85 if (!ocelot_nvram_map.virt) {
86 printk(KERN_NOTICE "Failed to ioremap Ocelot NVRAM space\n");
87 return -EIO;
88 }
89
90 simple_map_init(&ocelot_nvram_map);
91
92 /* And do the RAM probe on it to get an MTD device */
93 nvram_mtd = do_map_probe("map_ram", &ocelot_nvram_map);
94 if (!nvram_mtd) {
95 printk("NVRAM probe failed\n");
96 goto fail_1;
97 }
98 nvram_mtd->owner = THIS_MODULE;
99 nvram_mtd->erasesize = 16;
100 /* Override the write() method */
101 nvram_mtd->write = ocelot_ram_write;
102
103 /* Now map the flash space */
104 ocelot_flash_map.virt = ioremap_nocache(FLASH_WINDOW_ADDR, FLASH_WINDOW_SIZE);
105 if (!ocelot_flash_map.virt) {
106 printk(KERN_NOTICE "Failed to ioremap Ocelot flash space\n");
107 goto fail_2;
108 }
109 /* Now the cached version */
110 ocelot_flash_map.cached = (unsigned long)__ioremap(FLASH_WINDOW_ADDR, FLASH_WINDOW_SIZE, 0);
111
112 simple_map_init(&ocelot_flash_map);
113
114 /* Only probe for flash if the write jumper is present */
115 if (brd_status & 0x40) {
116 flash_mtd = do_map_probe("jedec", &ocelot_flash_map);
117 } else {
118 printk(KERN_NOTICE "Ocelot flash write jumper not present. Treating as ROM\n");
119 }
120 /* If that failed or the jumper's absent, pretend it's ROM */
121 if (!flash_mtd) {
122 flash_mtd = do_map_probe("map_rom", &ocelot_flash_map);
123 /* If we're treating it as ROM, set the erase size */
124 if (flash_mtd)
125 flash_mtd->erasesize = 0x10000;
126 }
127 if (!flash_mtd)
128 goto fail3;
129
130 add_mtd_device(nvram_mtd);
131
132 flash_mtd->owner = THIS_MODULE;
133 nr_parts = parse_mtd_partitions(flash_mtd, probes, &parsed_parts, 0);
134
135 if (nr_parts > 0)
136 add_mtd_partitions(flash_mtd, parsed_parts, nr_parts);
137 else
138 add_mtd_device(flash_mtd);
139
140 return 0;
141
142 fail3:
143 iounmap((void *)ocelot_flash_map.virt);
144 if (ocelot_flash_map.cached)
145 iounmap((void *)ocelot_flash_map.cached);
146 fail_2:
147 map_destroy(nvram_mtd);
148 fail_1:
149 iounmap((void *)ocelot_nvram_map.virt);
150
151 return -ENXIO;
152}
153
154static void __exit cleanup_ocelot_maps(void)
155{
156 del_mtd_device(nvram_mtd);
157 map_destroy(nvram_mtd);
158 iounmap((void *)ocelot_nvram_map.virt);
159
160 if (parsed_parts)
161 del_mtd_partitions(flash_mtd);
162 else
163 del_mtd_device(flash_mtd);
164 map_destroy(flash_mtd);
165 iounmap((void *)ocelot_flash_map.virt);
166 if (ocelot_flash_map.cached)
167 iounmap((void *)ocelot_flash_map.cached);
168}
169
170module_init(init_ocelot_maps);
171module_exit(cleanup_ocelot_maps);
172
173MODULE_LICENSE("GPL");
174MODULE_AUTHOR("Red Hat, Inc. - David Woodhouse <dwmw2@cambridge.redhat.com>");
175MODULE_DESCRIPTION("MTD map driver for Momenco Ocelot board");
diff --git a/drivers/mtd/maps/ocotea.c b/drivers/mtd/maps/ocotea.c
new file mode 100644
index 000000000000..6e559bc14636
--- /dev/null
+++ b/drivers/mtd/maps/ocotea.c
@@ -0,0 +1,154 @@
1/*
2 * Mapping for Ocotea user flash
3 *
4 * Matt Porter <mporter@kernel.crashing.org>
5 *
6 * Copyright 2002-2004 MontaVista Software Inc.
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 */
13
14#include <linux/module.h>
15#include <linux/types.h>
16#include <linux/kernel.h>
17#include <linux/init.h>
18#include <linux/mtd/mtd.h>
19#include <linux/mtd/map.h>
20#include <linux/mtd/partitions.h>
21#include <linux/config.h>
22#include <linux/version.h>
23#include <asm/io.h>
24#include <asm/ibm44x.h>
25#include <platforms/4xx/ocotea.h>
26
27static struct mtd_info *flash;
28
29static struct map_info ocotea_small_map = {
30 .name = "Ocotea small flash",
31 .size = OCOTEA_SMALL_FLASH_SIZE,
32 .buswidth = 1,
33};
34
35static struct map_info ocotea_large_map = {
36 .name = "Ocotea large flash",
37 .size = OCOTEA_LARGE_FLASH_SIZE,
38 .buswidth = 1,
39};
40
41static struct mtd_partition ocotea_small_partitions[] = {
42 {
43 .name = "pibs",
44 .offset = 0x0,
45 .size = 0x100000,
46 }
47};
48
49static struct mtd_partition ocotea_large_partitions[] = {
50 {
51 .name = "fs",
52 .offset = 0,
53 .size = 0x300000,
54 },
55 {
56 .name = "firmware",
57 .offset = 0x300000,
58 .size = 0x100000,
59 }
60};
61
62#define NB_OF(x) (sizeof(x)/sizeof(x[0]))
63
64int __init init_ocotea(void)
65{
66 u8 fpga0_reg;
67 u8 *fpga0_adr;
68 unsigned long long small_flash_base, large_flash_base;
69
70 fpga0_adr = ioremap64(OCOTEA_FPGA_ADDR, 16);
71 if (!fpga0_adr)
72 return -ENOMEM;
73
74 fpga0_reg = readb((unsigned long)fpga0_adr);
75 iounmap(fpga0_adr);
76
77 if (OCOTEA_BOOT_LARGE_FLASH(fpga0_reg)) {
78 small_flash_base = OCOTEA_SMALL_FLASH_HIGH;
79 large_flash_base = OCOTEA_LARGE_FLASH_LOW;
80 }
81 else {
82 small_flash_base = OCOTEA_SMALL_FLASH_LOW;
83 large_flash_base = OCOTEA_LARGE_FLASH_HIGH;
84 }
85
86 ocotea_small_map.phys = small_flash_base;
87 ocotea_small_map.virt = ioremap64(small_flash_base,
88 ocotea_small_map.size);
89
90 if (!ocotea_small_map.virt) {
91 printk("Failed to ioremap flash\n");
92 return -EIO;
93 }
94
95 simple_map_init(&ocotea_small_map);
96
97 flash = do_map_probe("map_rom", &ocotea_small_map);
98 if (flash) {
99 flash->owner = THIS_MODULE;
100 add_mtd_partitions(flash, ocotea_small_partitions,
101 NB_OF(ocotea_small_partitions));
102 } else {
103 printk("map probe failed for flash\n");
104 return -ENXIO;
105 }
106
107 ocotea_large_map.phys = large_flash_base;
108 ocotea_large_map.virt = ioremap64(large_flash_base,
109 ocotea_large_map.size);
110
111 if (!ocotea_large_map.virt) {
112 printk("Failed to ioremap flash\n");
113 return -EIO;
114 }
115
116 simple_map_init(&ocotea_large_map);
117
118 flash = do_map_probe("cfi_probe", &ocotea_large_map);
119 if (flash) {
120 flash->owner = THIS_MODULE;
121 add_mtd_partitions(flash, ocotea_large_partitions,
122 NB_OF(ocotea_large_partitions));
123 } else {
124 printk("map probe failed for flash\n");
125 return -ENXIO;
126 }
127
128 return 0;
129}
130
131static void __exit cleanup_ocotea(void)
132{
133 if (flash) {
134 del_mtd_partitions(flash);
135 map_destroy(flash);
136 }
137
138 if (ocotea_small_map.virt) {
139 iounmap((void *)ocotea_small_map.virt);
140 ocotea_small_map.virt = 0;
141 }
142
143 if (ocotea_large_map.virt) {
144 iounmap((void *)ocotea_large_map.virt);
145 ocotea_large_map.virt = 0;
146 }
147}
148
149module_init(init_ocotea);
150module_exit(cleanup_ocotea);
151
152MODULE_LICENSE("GPL");
153MODULE_AUTHOR("Matt Porter <mporter@kernel.crashing.org>");
154MODULE_DESCRIPTION("MTD map and partitions for IBM 440GX Ocotea boards");
diff --git a/drivers/mtd/maps/octagon-5066.c b/drivers/mtd/maps/octagon-5066.c
new file mode 100644
index 000000000000..e5ff83de420e
--- /dev/null
+++ b/drivers/mtd/maps/octagon-5066.c
@@ -0,0 +1,248 @@
1// $Id: octagon-5066.c,v 1.26 2004/07/12 22:38:29 dwmw2 Exp $
2/* ######################################################################
3
4 Octagon 5066 MTD Driver.
5
6 The Octagon 5066 is a SBC based on AMD's 586-WB running at 133 MHZ. It
7 comes with a builtin AMD 29F016 flash chip and a socketed EEPROM that
8 is replacable by flash. Both units are mapped through a multiplexer
9 into a 32k memory window at 0xe8000. The control register for the
10 multiplexing unit is located at IO 0x208 with a bit map of
11 0-5 Page Selection in 32k increments
12 6-7 Device selection:
13 00 SSD off
14 01 SSD 0 (Socket)
15 10 SSD 1 (Flash chip)
16 11 undefined
17
18 On each SSD, the first 128k is reserved for use by the bios
19 (actually it IS the bios..) This only matters if you are booting off the
20 flash, you must not put a file system starting there.
21
22 The driver tries to do a detection algorithm to guess what sort of devices
23 are plugged into the sockets.
24
25 ##################################################################### */
26
27#include <linux/module.h>
28#include <linux/slab.h>
29#include <linux/ioport.h>
30#include <linux/init.h>
31#include <asm/io.h>
32
33#include <linux/mtd/map.h>
34#include <linux/mtd/mtd.h>
35
36#define WINDOW_START 0xe8000
37#define WINDOW_LENGTH 0x8000
38#define WINDOW_SHIFT 27
39#define WINDOW_MASK 0x7FFF
40#define PAGE_IO 0x208
41
42static volatile char page_n_dev = 0;
43static unsigned long iomapadr;
44static DEFINE_SPINLOCK(oct5066_spin);
45
46/*
47 * We use map_priv_1 to identify which device we are.
48 */
49
50static void __oct5066_page(struct map_info *map, __u8 byte)
51{
52 outb(byte,PAGE_IO);
53 page_n_dev = byte;
54}
55
56static inline void oct5066_page(struct map_info *map, unsigned long ofs)
57{
58 __u8 byte = map->map_priv_1 | (ofs >> WINDOW_SHIFT);
59
60 if (page_n_dev != byte)
61 __oct5066_page(map, byte);
62}
63
64
65static map_word oct5066_read8(struct map_info *map, unsigned long ofs)
66{
67 map_word ret;
68 spin_lock(&oct5066_spin);
69 oct5066_page(map, ofs);
70 ret.x[0] = readb(iomapadr + (ofs & WINDOW_MASK));
71 spin_unlock(&oct5066_spin);
72 return ret;
73}
74
75static void oct5066_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
76{
77 while(len) {
78 unsigned long thislen = len;
79 if (len > (WINDOW_LENGTH - (from & WINDOW_MASK)))
80 thislen = WINDOW_LENGTH-(from & WINDOW_MASK);
81
82 spin_lock(&oct5066_spin);
83 oct5066_page(map, from);
84 memcpy_fromio(to, iomapadr + from, thislen);
85 spin_unlock(&oct5066_spin);
86 to += thislen;
87 from += thislen;
88 len -= thislen;
89 }
90}
91
92static void oct5066_write8(struct map_info *map, map_word d, unsigned long adr)
93{
94 spin_lock(&oct5066_spin);
95 oct5066_page(map, adr);
96 writeb(d.x[0], iomapadr + (adr & WINDOW_MASK));
97 spin_unlock(&oct5066_spin);
98}
99
100static void oct5066_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
101{
102 while(len) {
103 unsigned long thislen = len;
104 if (len > (WINDOW_LENGTH - (to & WINDOW_MASK)))
105 thislen = WINDOW_LENGTH-(to & WINDOW_MASK);
106
107 spin_lock(&oct5066_spin);
108 oct5066_page(map, to);
109 memcpy_toio(iomapadr + to, from, thislen);
110 spin_unlock(&oct5066_spin);
111 to += thislen;
112 from += thislen;
113 len -= thislen;
114 }
115}
116
117static struct map_info oct5066_map[2] = {
118 {
119 .name = "Octagon 5066 Socket",
120 .phys = NO_XIP,
121 .size = 512 * 1024,
122 .bankwidth = 1,
123 .read = oct5066_read8,
124 .copy_from = oct5066_copy_from,
125 .write = oct5066_write8,
126 .copy_to = oct5066_copy_to,
127 .map_priv_1 = 1<<6
128 },
129 {
130 .name = "Octagon 5066 Internal Flash",
131 .phys = NO_XIP,
132 .size = 2 * 1024 * 1024,
133 .bankwidth = 1,
134 .read = oct5066_read8,
135 .copy_from = oct5066_copy_from,
136 .write = oct5066_write8,
137 .copy_to = oct5066_copy_to,
138 .map_priv_1 = 2<<6
139 }
140};
141
142static struct mtd_info *oct5066_mtd[2] = {NULL, NULL};
143
144// OctProbe - Sense if this is an octagon card
145// ---------------------------------------------------------------------
146/* Perform a simple validity test, we map the window select SSD0 and
147 change pages while monitoring the window. A change in the window,
148 controlled by the PAGE_IO port is a functioning 5066 board. This will
149 fail if the thing in the socket is set to a uniform value. */
150static int __init OctProbe(void)
151{
152 unsigned int Base = (1 << 6);
153 unsigned long I;
154 unsigned long Values[10];
155 for (I = 0; I != 20; I++)
156 {
157 outb(Base + (I%10),PAGE_IO);
158 if (I < 10)
159 {
160 // Record the value and check for uniqueness
161 Values[I%10] = readl(iomapadr);
162 if (I > 0 && Values[I%10] == Values[0])
163 return -EAGAIN;
164 }
165 else
166 {
167 // Make sure we get the same values on the second pass
168 if (Values[I%10] != readl(iomapadr))
169 return -EAGAIN;
170 }
171 }
172 return 0;
173}
174
175void cleanup_oct5066(void)
176{
177 int i;
178 for (i=0; i<2; i++) {
179 if (oct5066_mtd[i]) {
180 del_mtd_device(oct5066_mtd[i]);
181 map_destroy(oct5066_mtd[i]);
182 }
183 }
184 iounmap((void *)iomapadr);
185 release_region(PAGE_IO, 1);
186}
187
188int __init init_oct5066(void)
189{
190 int i;
191 int ret = 0;
192
193 // Do an autoprobe sequence
194 if (!request_region(PAGE_IO,1,"Octagon SSD")) {
195 printk(KERN_NOTICE "5066: Page Register in Use\n");
196 return -EAGAIN;
197 }
198 iomapadr = (unsigned long)ioremap(WINDOW_START, WINDOW_LENGTH);
199 if (!iomapadr) {
200 printk(KERN_NOTICE "Failed to ioremap memory region\n");
201 ret = -EIO;
202 goto out_rel;
203 }
204 if (OctProbe() != 0) {
205 printk(KERN_NOTICE "5066: Octagon Probe Failed, is this an Octagon 5066 SBC?\n");
206 iounmap((void *)iomapadr);
207 ret = -EAGAIN;
208 goto out_unmap;
209 }
210
211 // Print out our little header..
212 printk("Octagon 5066 SSD IO:0x%x MEM:0x%x-0x%x\n",PAGE_IO,WINDOW_START,
213 WINDOW_START+WINDOW_LENGTH);
214
215 for (i=0; i<2; i++) {
216 oct5066_mtd[i] = do_map_probe("cfi_probe", &oct5066_map[i]);
217 if (!oct5066_mtd[i])
218 oct5066_mtd[i] = do_map_probe("jedec", &oct5066_map[i]);
219 if (!oct5066_mtd[i])
220 oct5066_mtd[i] = do_map_probe("map_ram", &oct5066_map[i]);
221 if (!oct5066_mtd[i])
222 oct5066_mtd[i] = do_map_probe("map_rom", &oct5066_map[i]);
223 if (oct5066_mtd[i]) {
224 oct5066_mtd[i]->owner = THIS_MODULE;
225 add_mtd_device(oct5066_mtd[i]);
226 }
227 }
228
229 if (!oct5066_mtd[0] && !oct5066_mtd[1]) {
230 cleanup_oct5066();
231 return -ENXIO;
232 }
233
234 return 0;
235
236 out_unmap:
237 iounmap((void *)iomapadr);
238 out_rel:
239 release_region(PAGE_IO, 1);
240 return ret;
241}
242
243module_init(init_oct5066);
244module_exit(cleanup_oct5066);
245
246MODULE_LICENSE("GPL");
247MODULE_AUTHOR("Jason Gunthorpe <jgg@deltatee.com>, David Woodhouse <dwmw2@infradead.org>");
248MODULE_DESCRIPTION("MTD map driver for Octagon 5066 Single Board Computer");
diff --git a/drivers/mtd/maps/omap-toto-flash.c b/drivers/mtd/maps/omap-toto-flash.c
new file mode 100644
index 000000000000..496109071cb1
--- /dev/null
+++ b/drivers/mtd/maps/omap-toto-flash.c
@@ -0,0 +1,137 @@
1/*
2 * NOR Flash memory access on TI Toto board
3 *
4 * jzhang@ti.com (C) 2003 Texas Instruments.
5 *
6 * (C) 2002 MontVista Software, Inc.
7 *
8 * $Id: omap-toto-flash.c,v 1.3 2004/09/16 23:27:13 gleixner Exp $
9 */
10
11#include <linux/config.h>
12#include <linux/module.h>
13#include <linux/types.h>
14#include <linux/kernel.h>
15
16#include <linux/errno.h>
17#include <linux/init.h>
18
19#include <linux/mtd/mtd.h>
20#include <linux/mtd/map.h>
21#include <linux/mtd/partitions.h>
22
23#include <asm/hardware.h>
24#include <asm/io.h>
25
26
27#ifndef CONFIG_ARCH_OMAP
28#error This is for OMAP architecture only
29#endif
30
31//these lines need be moved to a hardware header file
32#define OMAP_TOTO_FLASH_BASE 0xd8000000
33#define OMAP_TOTO_FLASH_SIZE 0x80000
34
35static struct map_info omap_toto_map_flash = {
36 .name = "OMAP Toto flash",
37 .bankwidth = 2,
38 .virt = (void __iomem *)OMAP_TOTO_FLASH_BASE,
39};
40
41
42static struct mtd_partition toto_flash_partitions[] = {
43 {
44 .name = "BootLoader",
45 .size = 0x00040000, /* hopefully u-boot will stay 128k + 128*/
46 .offset = 0,
47 .mask_flags = MTD_WRITEABLE, /* force read-only */
48 }, {
49 .name = "ReservedSpace",
50 .size = 0x00030000,
51 .offset = MTDPART_OFS_APPEND,
52 //mask_flags: MTD_WRITEABLE, /* force read-only */
53 }, {
54 .name = "EnvArea", /* bottom 64KiB for env vars */
55 .size = MTDPART_SIZ_FULL,
56 .offset = MTDPART_OFS_APPEND,
57 }
58};
59
60static struct mtd_partition *parsed_parts;
61
62static struct mtd_info *flash_mtd;
63
64static int __init init_flash (void)
65{
66
67 struct mtd_partition *parts;
68 int nb_parts = 0;
69 int parsed_nr_parts = 0;
70 const char *part_type;
71
72 /*
73 * Static partition definition selection
74 */
75 part_type = "static";
76
77 parts = toto_flash_partitions;
78 nb_parts = ARRAY_SIZE(toto_flash_partitions);
79 omap_toto_map_flash.size = OMAP_TOTO_FLASH_SIZE;
80 omap_toto_map_flash.phys = virt_to_phys(OMAP_TOTO_FLASH_BASE);
81
82 simple_map_init(&omap_toto_map_flash);
83 /*
84 * Now let's probe for the actual flash. Do it here since
85 * specific machine settings might have been set above.
86 */
87 printk(KERN_NOTICE "OMAP toto flash: probing %d-bit flash bus\n",
88 omap_toto_map_flash.bankwidth*8);
89 flash_mtd = do_map_probe("jedec_probe", &omap_toto_map_flash);
90 if (!flash_mtd)
91 return -ENXIO;
92
93 if (parsed_nr_parts > 0) {
94 parts = parsed_parts;
95 nb_parts = parsed_nr_parts;
96 }
97
98 if (nb_parts == 0) {
99 printk(KERN_NOTICE "OMAP toto flash: no partition info available,"
100 "registering whole flash at once\n");
101 if (add_mtd_device(flash_mtd)){
102 return -ENXIO;
103 }
104 } else {
105 printk(KERN_NOTICE "Using %s partition definition\n",
106 part_type);
107 return add_mtd_partitions(flash_mtd, parts, nb_parts);
108 }
109 return 0;
110}
111
112int __init omap_toto_mtd_init(void)
113{
114 int status;
115
116 if (status = init_flash()) {
117 printk(KERN_ERR "OMAP Toto Flash: unable to init map for toto flash\n");
118 }
119 return status;
120}
121
122static void __exit omap_toto_mtd_cleanup(void)
123{
124 if (flash_mtd) {
125 del_mtd_partitions(flash_mtd);
126 map_destroy(flash_mtd);
127 if (parsed_parts)
128 kfree(parsed_parts);
129 }
130}
131
132module_init(omap_toto_mtd_init);
133module_exit(omap_toto_mtd_cleanup);
134
135MODULE_AUTHOR("Jian Zhang");
136MODULE_DESCRIPTION("OMAP Toto board map driver");
137MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/maps/pb1550-flash.c b/drivers/mtd/maps/pb1550-flash.c
new file mode 100644
index 000000000000..1424726a219e
--- /dev/null
+++ b/drivers/mtd/maps/pb1550-flash.c
@@ -0,0 +1,203 @@
1/*
2 * Flash memory access on Alchemy Pb1550 board
3 *
4 * $Id: pb1550-flash.c,v 1.6 2004/11/04 13:24:15 gleixner Exp $
5 *
6 * (C) 2004 Embedded Edge, LLC, based on pb1550-flash.c:
7 * (C) 2003 Pete Popov <ppopov@pacbell.net>
8 *
9 */
10
11#include <linux/config.h>
12#include <linux/init.h>
13#include <linux/module.h>
14#include <linux/types.h>
15#include <linux/kernel.h>
16
17#include <linux/mtd/mtd.h>
18#include <linux/mtd/map.h>
19#include <linux/mtd/partitions.h>
20
21#include <asm/io.h>
22#include <asm/au1000.h>
23#include <asm/pb1550.h>
24
25#ifdef DEBUG_RW
26#define DBG(x...) printk(x)
27#else
28#define DBG(x...)
29#endif
30
31static unsigned long window_addr;
32static unsigned long window_size;
33
34
35static struct map_info pb1550_map = {
36 .name = "Pb1550 flash",
37};
38
39static unsigned char flash_bankwidth = 4;
40
41/*
42 * Support only 64MB NOR Flash parts
43 */
44
45#ifdef PB1550_BOTH_BANKS
46/* both banks will be used. Combine the first bank and the first
47 * part of the second bank together into a single jffs/jffs2
48 * partition.
49 */
50static struct mtd_partition pb1550_partitions[] = {
51 /* assume boot[2:0]:swap is '0000' or '1000', which translates to:
52 * 1C00 0000 1FFF FFFF CE0 64MB Boot NOR Flash
53 * 1800 0000 1BFF FFFF CE0 64MB Param NOR Flash
54 */
55 {
56 .name = "User FS",
57 .size = (0x1FC00000 - 0x18000000),
58 .offset = 0x0000000
59 },{
60 .name = "yamon",
61 .size = 0x0100000,
62 .offset = MTDPART_OFS_APPEND,
63 .mask_flags = MTD_WRITEABLE
64 },{
65 .name = "raw kernel",
66 .size = (0x300000 - 0x40000), /* last 256KB is yamon env */
67 .offset = MTDPART_OFS_APPEND,
68 }
69};
70#elif defined(PB1550_BOOT_ONLY)
71static struct mtd_partition pb1550_partitions[] = {
72 /* assume boot[2:0]:swap is '0000' or '1000', which translates to:
73 * 1C00 0000 1FFF FFFF CE0 64MB Boot NOR Flash
74 */
75 {
76 .name = "User FS",
77 .size = 0x03c00000,
78 .offset = 0x0000000
79 },{
80 .name = "yamon",
81 .size = 0x0100000,
82 .offset = MTDPART_OFS_APPEND,
83 .mask_flags = MTD_WRITEABLE
84 },{
85 .name = "raw kernel",
86 .size = (0x300000-0x40000), /* last 256KB is yamon env */
87 .offset = MTDPART_OFS_APPEND,
88 }
89};
90#elif defined(PB1550_USER_ONLY)
91static struct mtd_partition pb1550_partitions[] = {
92 /* assume boot[2:0]:swap is '0000' or '1000', which translates to:
93 * 1800 0000 1BFF FFFF CE0 64MB Param NOR Flash
94 */
95 {
96 .name = "User FS",
97 .size = (0x4000000 - 0x200000), /* reserve 2MB for raw kernel */
98 .offset = 0x0000000
99 },{
100 .name = "raw kernel",
101 .size = MTDPART_SIZ_FULL,
102 .offset = MTDPART_OFS_APPEND,
103 }
104};
105#else
106#error MTD_PB1550 define combo error /* should never happen */
107#endif
108
109#define NB_OF(x) (sizeof(x)/sizeof(x[0]))
110
111static struct mtd_info *mymtd;
112
113/*
114 * Probe the flash density and setup window address and size
115 * based on user CONFIG options. There are times when we don't
116 * want the MTD driver to be probing the boot or user flash,
117 * so having the option to enable only one bank is important.
118 */
119int setup_flash_params(void)
120{
121 u16 boot_swapboot;
122 boot_swapboot = (au_readl(MEM_STSTAT) & (0x7<<1)) |
123 ((bcsr->status >> 6) & 0x1);
124 printk("Pb1550 MTD: boot:swap %d\n", boot_swapboot);
125
126 switch (boot_swapboot) {
127 case 0: /* 512Mbit devices, both enabled */
128 case 1:
129 case 8:
130 case 9:
131#if defined(PB1550_BOTH_BANKS)
132 window_addr = 0x18000000;
133 window_size = 0x8000000;
134#elif defined(PB1550_BOOT_ONLY)
135 window_addr = 0x1C000000;
136 window_size = 0x4000000;
137#else /* USER ONLY */
138 window_addr = 0x1E000000;
139 window_size = 0x4000000;
140#endif
141 break;
142 case 0xC:
143 case 0xD:
144 case 0xE:
145 case 0xF:
146 /* 64 MB Boot NOR Flash is disabled */
147 /* and the start address is moved to 0x0C00000 */
148 window_addr = 0x0C000000;
149 window_size = 0x4000000;
150 default:
151 printk("Pb1550 MTD: unsupported boot:swap setting\n");
152 return 1;
153 }
154 return 0;
155}
156
157int __init pb1550_mtd_init(void)
158{
159 struct mtd_partition *parts;
160 int nb_parts = 0;
161
162 /* Default flash bankwidth */
163 pb1550_map.bankwidth = flash_bankwidth;
164
165 if (setup_flash_params())
166 return -ENXIO;
167
168 /*
169 * Static partition definition selection
170 */
171 parts = pb1550_partitions;
172 nb_parts = NB_OF(pb1550_partitions);
173 pb1550_map.size = window_size;
174
175 /*
176 * Now let's probe for the actual flash. Do it here since
177 * specific machine settings might have been set above.
178 */
179 printk(KERN_NOTICE "Pb1550 flash: probing %d-bit flash bus\n",
180 pb1550_map.bankwidth*8);
181 pb1550_map.virt = ioremap(window_addr, window_size);
182 mymtd = do_map_probe("cfi_probe", &pb1550_map);
183 if (!mymtd) return -ENXIO;
184 mymtd->owner = THIS_MODULE;
185
186 add_mtd_partitions(mymtd, parts, nb_parts);
187 return 0;
188}
189
190static void __exit pb1550_mtd_cleanup(void)
191{
192 if (mymtd) {
193 del_mtd_partitions(mymtd);
194 map_destroy(mymtd);
195 }
196}
197
198module_init(pb1550_mtd_init);
199module_exit(pb1550_mtd_cleanup);
200
201MODULE_AUTHOR("Embedded Edge, LLC");
202MODULE_DESCRIPTION("Pb1550 mtd map driver");
203MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/maps/pb1xxx-flash.c b/drivers/mtd/maps/pb1xxx-flash.c
new file mode 100644
index 000000000000..06e731540552
--- /dev/null
+++ b/drivers/mtd/maps/pb1xxx-flash.c
@@ -0,0 +1,178 @@
1/*
2 * Flash memory access on Alchemy Pb1xxx boards
3 *
4 * (C) 2001 Pete Popov <ppopov@mvista.com>
5 *
6 * $Id: pb1xxx-flash.c,v 1.14 2004/11/04 13:24:15 gleixner Exp $
7 */
8
9#include <linux/config.h>
10#include <linux/module.h>
11#include <linux/types.h>
12#include <linux/init.h>
13#include <linux/kernel.h>
14
15#include <linux/mtd/mtd.h>
16#include <linux/mtd/map.h>
17#include <linux/mtd/partitions.h>
18
19#include <asm/io.h>
20
21#ifdef DEBUG_RW
22#define DBG(x...) printk(x)
23#else
24#define DBG(x...)
25#endif
26
27#ifdef CONFIG_MIPS_PB1000
28
29#define WINDOW_ADDR 0x1F800000
30#define WINDOW_SIZE 0x800000
31
32static struct mtd_partition pb1xxx_partitions[] = {
33 {
34 .name = "yamon env",
35 .size = 0x00020000,
36 .offset = 0,
37 .mask_flags = MTD_WRITEABLE},
38 {
39 .name = "User FS",
40 .size = 0x003e0000,
41 .offset = 0x20000,},
42 {
43 .name = "boot code",
44 .size = 0x100000,
45 .offset = 0x400000,
46 .mask_flags = MTD_WRITEABLE},
47 {
48 .name = "raw/kernel",
49 .size = 0x300000,
50 .offset = 0x500000}
51};
52
53#elif defined(CONFIG_MIPS_PB1500) || defined(CONFIG_MIPS_PB1100)
54
55#if defined(CONFIG_MTD_PB1500_BOOT) && defined(CONFIG_MTD_PB1500_USER)
56/* both 32MB banks will be used. Combine the first 32MB bank and the
57 * first 28MB of the second bank together into a single jffs/jffs2
58 * partition.
59 */
60#define WINDOW_ADDR 0x1C000000
61#define WINDOW_SIZE 0x4000000
62static struct mtd_partition pb1xxx_partitions[] = {
63 {
64 .name = "User FS",
65 .size = 0x3c00000,
66 .offset = 0x0000000
67 },{
68 .name = "yamon",
69 .size = 0x0100000,
70 .offset = 0x3c00000,
71 .mask_flags = MTD_WRITEABLE
72 },{
73 .name = "raw kernel",
74 .size = 0x02c0000,
75 .offset = 0x3d00000
76 }
77};
78#elif defined(CONFIG_MTD_PB1500_BOOT) && !defined(CONFIG_MTD_PB1500_USER)
79#define WINDOW_ADDR 0x1E000000
80#define WINDOW_SIZE 0x2000000
81static struct mtd_partition pb1xxx_partitions[] = {
82 {
83 .name = "User FS",
84 .size = 0x1c00000,
85 .offset = 0x0000000
86 },{
87 .name = "yamon",
88 .size = 0x0100000,
89 .offset = 0x1c00000,
90 .mask_flags = MTD_WRITEABLE
91 },{
92 .name = "raw kernel",
93 .size = 0x02c0000,
94 .offset = 0x1d00000
95 }
96};
97#elif !defined(CONFIG_MTD_PB1500_BOOT) && defined(CONFIG_MTD_PB1500_USER)
98#define WINDOW_ADDR 0x1C000000
99#define WINDOW_SIZE 0x2000000
100static struct mtd_partition pb1xxx_partitions[] = {
101 {
102 .name = "User FS",
103 .size = 0x1e00000,
104 .offset = 0x0000000
105 },{
106 .name = "raw kernel",
107 .size = 0x0200000,
108 .offset = 0x1e00000,
109 }
110};
111#else
112#error MTD_PB1500 define combo error /* should never happen */
113#endif
114#else
115#error Unsupported board
116#endif
117
118#define NAME "Pb1x00 Linux Flash"
119#define PADDR WINDOW_ADDR
120#define BUSWIDTH 4
121#define SIZE WINDOW_SIZE
122#define PARTITIONS 4
123
124static struct map_info pb1xxx_mtd_map = {
125 .name = NAME,
126 .size = SIZE,
127 .bankwidth = BUSWIDTH,
128 .phys = PADDR,
129};
130
131static struct mtd_info *pb1xxx_mtd;
132
133int __init pb1xxx_mtd_init(void)
134{
135 struct mtd_partition *parts;
136 int nb_parts = 0;
137 char *part_type;
138
139 /*
140 * Static partition definition selection
141 */
142 part_type = "static";
143 parts = pb1xxx_partitions;
144 nb_parts = ARRAY_SIZE(pb1xxx_partitions);
145
146 /*
147 * Now let's probe for the actual flash. Do it here since
148 * specific machine settings might have been set above.
149 */
150 printk(KERN_NOTICE "Pb1xxx flash: probing %d-bit flash bus\n",
151 BUSWIDTH*8);
152 pb1xxx_mtd_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE);
153
154 simple_map_init(&pb1xxx_mtd_map);
155
156 pb1xxx_mtd = do_map_probe("cfi_probe", &pb1xxx_mtd_map);
157 if (!pb1xxx_mtd) return -ENXIO;
158 pb1xxx_mtd->owner = THIS_MODULE;
159
160 add_mtd_partitions(pb1xxx_mtd, parts, nb_parts);
161 return 0;
162}
163
164static void __exit pb1xxx_mtd_cleanup(void)
165{
166 if (pb1xxx_mtd) {
167 del_mtd_partitions(pb1xxx_mtd);
168 map_destroy(pb1xxx_mtd);
169 iounmap((void *) pb1xxx_mtd_map.virt);
170 }
171}
172
173module_init(pb1xxx_mtd_init);
174module_exit(pb1xxx_mtd_cleanup);
175
176MODULE_AUTHOR("Pete Popov");
177MODULE_DESCRIPTION("Pb1xxx CFI map driver");
178MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/maps/pci.c b/drivers/mtd/maps/pci.c
new file mode 100644
index 000000000000..08b60bdc5381
--- /dev/null
+++ b/drivers/mtd/maps/pci.c
@@ -0,0 +1,388 @@
1/*
2 * linux/drivers/mtd/maps/pci.c
3 *
4 * Copyright (C) 2001 Russell King, All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * $Id: pci.c,v 1.9 2004/11/28 09:40:40 dwmw2 Exp $
11 *
12 * Generic PCI memory map driver. We support the following boards:
13 * - Intel IQ80310 ATU.
14 * - Intel EBSA285 (blank rom programming mode). Tested working 27/09/2001
15 */
16#include <linux/module.h>
17#include <linux/kernel.h>
18#include <linux/pci.h>
19#include <linux/init.h>
20
21#include <linux/mtd/mtd.h>
22#include <linux/mtd/map.h>
23#include <linux/mtd/partitions.h>
24
25struct map_pci_info;
26
27struct mtd_pci_info {
28 int (*init)(struct pci_dev *dev, struct map_pci_info *map);
29 void (*exit)(struct pci_dev *dev, struct map_pci_info *map);
30 unsigned long (*translate)(struct map_pci_info *map, unsigned long ofs);
31 const char *map_name;
32};
33
34struct map_pci_info {
35 struct map_info map;
36 void __iomem *base;
37 void (*exit)(struct pci_dev *dev, struct map_pci_info *map);
38 unsigned long (*translate)(struct map_pci_info *map, unsigned long ofs);
39 struct pci_dev *dev;
40};
41
42static map_word mtd_pci_read8(struct map_info *_map, unsigned long ofs)
43{
44 struct map_pci_info *map = (struct map_pci_info *)_map;
45 map_word val;
46 val.x[0]= readb(map->base + map->translate(map, ofs));
47// printk("read8 : %08lx => %02x\n", ofs, val.x[0]);
48 return val;
49}
50
51#if 0
52static map_word mtd_pci_read16(struct map_info *_map, unsigned long ofs)
53{
54 struct map_pci_info *map = (struct map_pci_info *)_map;
55 map_word val;
56 val.x[0] = readw(map->base + map->translate(map, ofs));
57// printk("read16: %08lx => %04x\n", ofs, val.x[0]);
58 return val;
59}
60#endif
61static map_word mtd_pci_read32(struct map_info *_map, unsigned long ofs)
62{
63 struct map_pci_info *map = (struct map_pci_info *)_map;
64 map_word val;
65 val.x[0] = readl(map->base + map->translate(map, ofs));
66// printk("read32: %08lx => %08x\n", ofs, val.x[0]);
67 return val;
68}
69
70static void mtd_pci_copyfrom(struct map_info *_map, void *to, unsigned long from, ssize_t len)
71{
72 struct map_pci_info *map = (struct map_pci_info *)_map;
73 memcpy_fromio(to, map->base + map->translate(map, from), len);
74}
75
76static void mtd_pci_write8(struct map_info *_map, map_word val, unsigned long ofs)
77{
78 struct map_pci_info *map = (struct map_pci_info *)_map;
79// printk("write8 : %08lx <= %02x\n", ofs, val.x[0]);
80 writeb(val.x[0], map->base + map->translate(map, ofs));
81}
82
83#if 0
84static void mtd_pci_write16(struct map_info *_map, map_word val, unsigned long ofs)
85{
86 struct map_pci_info *map = (struct map_pci_info *)_map;
87// printk("write16: %08lx <= %04x\n", ofs, val.x[0]);
88 writew(val.x[0], map->base + map->translate(map, ofs));
89}
90#endif
91static void mtd_pci_write32(struct map_info *_map, map_word val, unsigned long ofs)
92{
93 struct map_pci_info *map = (struct map_pci_info *)_map;
94// printk("write32: %08lx <= %08x\n", ofs, val.x[0]);
95 writel(val.x[0], map->base + map->translate(map, ofs));
96}
97
98static void mtd_pci_copyto(struct map_info *_map, unsigned long to, const void *from, ssize_t len)
99{
100 struct map_pci_info *map = (struct map_pci_info *)_map;
101 memcpy_toio(map->base + map->translate(map, to), from, len);
102}
103
104static struct map_info mtd_pci_map = {
105 .phys = NO_XIP,
106 .copy_from = mtd_pci_copyfrom,
107 .copy_to = mtd_pci_copyto,
108};
109
110/*
111 * Intel IOP80310 Flash driver
112 */
113
114static int
115intel_iq80310_init(struct pci_dev *dev, struct map_pci_info *map)
116{
117 u32 win_base;
118
119 map->map.bankwidth = 1;
120 map->map.read = mtd_pci_read8,
121 map->map.write = mtd_pci_write8,
122
123 map->map.size = 0x00800000;
124 map->base = ioremap_nocache(pci_resource_start(dev, 0),
125 pci_resource_len(dev, 0));
126
127 if (!map->base)
128 return -ENOMEM;
129
130 /*
131 * We want to base the memory window at Xscale
132 * bus address 0, not 0x1000.
133 */
134 pci_read_config_dword(dev, 0x44, &win_base);
135 pci_write_config_dword(dev, 0x44, 0);
136
137 map->map.map_priv_2 = win_base;
138
139 return 0;
140}
141
142static void
143intel_iq80310_exit(struct pci_dev *dev, struct map_pci_info *map)
144{
145 if (map->base)
146 iounmap(map->base);
147 pci_write_config_dword(dev, 0x44, map->map.map_priv_2);
148}
149
150static unsigned long
151intel_iq80310_translate(struct map_pci_info *map, unsigned long ofs)
152{
153 unsigned long page_addr = ofs & 0x00400000;
154
155 /*
156 * This mundges the flash location so we avoid
157 * the first 80 bytes (they appear to read nonsense).
158 */
159 if (page_addr) {
160 writel(0x00000008, map->base + 0x1558);
161 writel(0x00000000, map->base + 0x1550);
162 } else {
163 writel(0x00000007, map->base + 0x1558);
164 writel(0x00800000, map->base + 0x1550);
165 ofs += 0x00800000;
166 }
167
168 return ofs;
169}
170
171static struct mtd_pci_info intel_iq80310_info = {
172 .init = intel_iq80310_init,
173 .exit = intel_iq80310_exit,
174 .translate = intel_iq80310_translate,
175 .map_name = "cfi_probe",
176};
177
178/*
179 * Intel DC21285 driver
180 */
181
182static int
183intel_dc21285_init(struct pci_dev *dev, struct map_pci_info *map)
184{
185 unsigned long base, len;
186
187 base = pci_resource_start(dev, PCI_ROM_RESOURCE);
188 len = pci_resource_len(dev, PCI_ROM_RESOURCE);
189
190 if (!len || !base) {
191 /*
192 * No ROM resource
193 */
194 base = pci_resource_start(dev, 2);
195 len = pci_resource_len(dev, 2);
196
197 /*
198 * We need to re-allocate PCI BAR2 address range to the
199 * PCI ROM BAR, and disable PCI BAR2.
200 */
201 } else {
202 /*
203 * Hmm, if an address was allocated to the ROM resource, but
204 * not enabled, should we be allocating a new resource for it
205 * or simply enabling it?
206 */
207 if (!(pci_resource_flags(dev, PCI_ROM_RESOURCE) &
208 IORESOURCE_ROM_ENABLE)) {
209 u32 val;
210 pci_resource_flags(dev, PCI_ROM_RESOURCE) |= IORESOURCE_ROM_ENABLE;
211 pci_read_config_dword(dev, PCI_ROM_ADDRESS, &val);
212 val |= PCI_ROM_ADDRESS_ENABLE;
213 pci_write_config_dword(dev, PCI_ROM_ADDRESS, val);
214 printk("%s: enabling expansion ROM\n", pci_name(dev));
215 }
216 }
217
218 if (!len || !base)
219 return -ENXIO;
220
221 map->map.bankwidth = 4;
222 map->map.read = mtd_pci_read32,
223 map->map.write = mtd_pci_write32,
224 map->map.size = len;
225 map->base = ioremap_nocache(base, len);
226
227 if (!map->base)
228 return -ENOMEM;
229
230 return 0;
231}
232
233static void
234intel_dc21285_exit(struct pci_dev *dev, struct map_pci_info *map)
235{
236 u32 val;
237
238 if (map->base)
239 iounmap(map->base);
240
241 /*
242 * We need to undo the PCI BAR2/PCI ROM BAR address alteration.
243 */
244 pci_resource_flags(dev, PCI_ROM_RESOURCE) &= ~IORESOURCE_ROM_ENABLE;
245 pci_read_config_dword(dev, PCI_ROM_ADDRESS, &val);
246 val &= ~PCI_ROM_ADDRESS_ENABLE;
247 pci_write_config_dword(dev, PCI_ROM_ADDRESS, val);
248}
249
250static unsigned long
251intel_dc21285_translate(struct map_pci_info *map, unsigned long ofs)
252{
253 return ofs & 0x00ffffc0 ? ofs : (ofs ^ (1 << 5));
254}
255
256static struct mtd_pci_info intel_dc21285_info = {
257 .init = intel_dc21285_init,
258 .exit = intel_dc21285_exit,
259 .translate = intel_dc21285_translate,
260 .map_name = "jedec_probe",
261};
262
263/*
264 * PCI device ID table
265 */
266
267static struct pci_device_id mtd_pci_ids[] = {
268 {
269 .vendor = PCI_VENDOR_ID_INTEL,
270 .device = 0x530d,
271 .subvendor = PCI_ANY_ID,
272 .subdevice = PCI_ANY_ID,
273 .class = PCI_CLASS_MEMORY_OTHER << 8,
274 .class_mask = 0xffff00,
275 .driver_data = (unsigned long)&intel_iq80310_info,
276 },
277 {
278 .vendor = PCI_VENDOR_ID_DEC,
279 .device = PCI_DEVICE_ID_DEC_21285,
280 .subvendor = 0, /* DC21285 defaults to 0 on reset */
281 .subdevice = 0, /* DC21285 defaults to 0 on reset */
282 .driver_data = (unsigned long)&intel_dc21285_info,
283 },
284 { 0, }
285};
286
287/*
288 * Generic code follows.
289 */
290
291static int __devinit
292mtd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
293{
294 struct mtd_pci_info *info = (struct mtd_pci_info *)id->driver_data;
295 struct map_pci_info *map = NULL;
296 struct mtd_info *mtd = NULL;
297 int err;
298
299 err = pci_enable_device(dev);
300 if (err)
301 goto out;
302
303 err = pci_request_regions(dev, "pci mtd");
304 if (err)
305 goto out;
306
307 map = kmalloc(sizeof(*map), GFP_KERNEL);
308 err = -ENOMEM;
309 if (!map)
310 goto release;
311
312 map->map = mtd_pci_map;
313 map->map.name = pci_name(dev);
314 map->dev = dev;
315 map->exit = info->exit;
316 map->translate = info->translate;
317
318 err = info->init(dev, map);
319 if (err)
320 goto release;
321
322 /* tsk - do_map_probe should take const char * */
323 mtd = do_map_probe((char *)info->map_name, &map->map);
324 err = -ENODEV;
325 if (!mtd)
326 goto release;
327
328 mtd->owner = THIS_MODULE;
329 add_mtd_device(mtd);
330
331 pci_set_drvdata(dev, mtd);
332
333 return 0;
334
335release:
336 if (mtd)
337 map_destroy(mtd);
338
339 if (map) {
340 map->exit(dev, map);
341 kfree(map);
342 }
343
344 pci_release_regions(dev);
345out:
346 return err;
347}
348
349static void __devexit
350mtd_pci_remove(struct pci_dev *dev)
351{
352 struct mtd_info *mtd = pci_get_drvdata(dev);
353 struct map_pci_info *map = mtd->priv;
354
355 del_mtd_device(mtd);
356 map_destroy(mtd);
357 map->exit(dev, map);
358 kfree(map);
359
360 pci_set_drvdata(dev, NULL);
361 pci_release_regions(dev);
362}
363
364static struct pci_driver mtd_pci_driver = {
365 .name = "MTD PCI",
366 .probe = mtd_pci_probe,
367 .remove = __devexit_p(mtd_pci_remove),
368 .id_table = mtd_pci_ids,
369};
370
371static int __init mtd_pci_maps_init(void)
372{
373 return pci_module_init(&mtd_pci_driver);
374}
375
376static void __exit mtd_pci_maps_exit(void)
377{
378 pci_unregister_driver(&mtd_pci_driver);
379}
380
381module_init(mtd_pci_maps_init);
382module_exit(mtd_pci_maps_exit);
383
384MODULE_LICENSE("GPL");
385MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
386MODULE_DESCRIPTION("Generic PCI map driver");
387MODULE_DEVICE_TABLE(pci, mtd_pci_ids);
388
diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c
new file mode 100644
index 000000000000..e37b4c1976e5
--- /dev/null
+++ b/drivers/mtd/maps/pcmciamtd.c
@@ -0,0 +1,860 @@
1/*
2 * $Id: pcmciamtd.c,v 1.51 2004/07/12 22:38:29 dwmw2 Exp $
3 *
4 * pcmciamtd.c - MTD driver for PCMCIA flash memory cards
5 *
6 * Author: Simon Evans <spse@secret.org.uk>
7 *
8 * Copyright (C) 2002 Simon Evans
9 *
10 * Licence: GPL
11 *
12 */
13
14#include <linux/module.h>
15#include <linux/slab.h>
16#include <linux/timer.h>
17#include <linux/init.h>
18#include <asm/io.h>
19#include <asm/system.h>
20
21#include <pcmcia/version.h>
22#include <pcmcia/cs_types.h>
23#include <pcmcia/cs.h>
24#include <pcmcia/cistpl.h>
25#include <pcmcia/ds.h>
26
27#include <linux/mtd/map.h>
28#include <linux/mtd/mtd.h>
29
30#ifdef CONFIG_MTD_DEBUG
31static int debug = CONFIG_MTD_DEBUG_VERBOSE;
32MODULE_PARM(debug, "i");
33MODULE_PARM_DESC(debug, "Set Debug Level 0=quiet, 5=noisy");
34#undef DEBUG
35#define DEBUG(n, format, arg...) \
36 if (n <= debug) { \
37 printk(KERN_DEBUG __FILE__ ":%s(): " format "\n", __FUNCTION__ , ## arg); \
38 }
39
40#else
41#undef DEBUG
42#define DEBUG(n, arg...)
43static const int debug = 0;
44#endif
45
46#define err(format, arg...) printk(KERN_ERR "pcmciamtd: " format "\n" , ## arg)
47#define info(format, arg...) printk(KERN_INFO "pcmciamtd: " format "\n" , ## arg)
48#define warn(format, arg...) printk(KERN_WARNING "pcmciamtd: " format "\n" , ## arg)
49
50
51#define DRIVER_DESC "PCMCIA Flash memory card driver"
52#define DRIVER_VERSION "$Revision: 1.51 $"
53
54/* Size of the PCMCIA address space: 26 bits = 64 MB */
55#define MAX_PCMCIA_ADDR 0x4000000
56
57struct pcmciamtd_dev {
58 dev_link_t link; /* PCMCIA link */
59 dev_node_t node; /* device node */
60 caddr_t win_base; /* ioremapped address of PCMCIA window */
61 unsigned int win_size; /* size of window */
62 unsigned int offset; /* offset into card the window currently points at */
63 struct map_info pcmcia_map;
64 struct mtd_info *mtd_info;
65 int vpp;
66 char mtd_name[sizeof(struct cistpl_vers_1_t)];
67};
68
69
70static dev_info_t dev_info = "pcmciamtd";
71static dev_link_t *dev_list;
72
73/* Module parameters */
74
75/* 2 = do 16-bit transfers, 1 = do 8-bit transfers */
76static int bankwidth = 2;
77
78/* Speed of memory accesses, in ns */
79static int mem_speed;
80
81/* Force the size of an SRAM card */
82static int force_size;
83
84/* Force Vpp */
85static int vpp;
86
87/* Set Vpp */
88static int setvpp;
89
90/* Force card to be treated as FLASH, ROM or RAM */
91static int mem_type;
92
93MODULE_LICENSE("GPL");
94MODULE_AUTHOR("Simon Evans <spse@secret.org.uk>");
95MODULE_DESCRIPTION(DRIVER_DESC);
96MODULE_PARM(bankwidth, "i");
97MODULE_PARM_DESC(bankwidth, "Set bankwidth (1=8 bit, 2=16 bit, default=2)");
98MODULE_PARM(mem_speed, "i");
99MODULE_PARM_DESC(mem_speed, "Set memory access speed in ns");
100MODULE_PARM(force_size, "i");
101MODULE_PARM_DESC(force_size, "Force size of card in MiB (1-64)");
102MODULE_PARM(setvpp, "i");
103MODULE_PARM_DESC(setvpp, "Set Vpp (0=Never, 1=On writes, 2=Always on, default=0)");
104MODULE_PARM(vpp, "i");
105MODULE_PARM_DESC(vpp, "Vpp value in 1/10ths eg 33=3.3V 120=12V (Dangerous)");
106MODULE_PARM(mem_type, "i");
107MODULE_PARM_DESC(mem_type, "Set Memory type (0=Flash, 1=RAM, 2=ROM, default=0)");
108
109
110/* read/write{8,16} copy_{from,to} routines with window remapping to access whole card */
111static caddr_t remap_window(struct map_info *map, unsigned long to)
112{
113 struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1;
114 window_handle_t win = (window_handle_t)map->map_priv_2;
115 memreq_t mrq;
116 int ret;
117
118 if(!(dev->link.state & DEV_PRESENT)) {
119 DEBUG(1, "device removed state = 0x%4.4X", dev->link.state);
120 return 0;
121 }
122
123 mrq.CardOffset = to & ~(dev->win_size-1);
124 if(mrq.CardOffset != dev->offset) {
125 DEBUG(2, "Remapping window from 0x%8.8x to 0x%8.8x",
126 dev->offset, mrq.CardOffset);
127 mrq.Page = 0;
128 if( (ret = pcmcia_map_mem_page(win, &mrq)) != CS_SUCCESS) {
129 cs_error(dev->link.handle, MapMemPage, ret);
130 return NULL;
131 }
132 dev->offset = mrq.CardOffset;
133 }
134 return dev->win_base + (to & (dev->win_size-1));
135}
136
137
138static map_word pcmcia_read8_remap(struct map_info *map, unsigned long ofs)
139{
140 caddr_t addr;
141 map_word d = {{0}};
142
143 addr = remap_window(map, ofs);
144 if(!addr)
145 return d;
146
147 d.x[0] = readb(addr);
148 DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%02x", ofs, addr, d.x[0]);
149 return d;
150}
151
152
153static map_word pcmcia_read16_remap(struct map_info *map, unsigned long ofs)
154{
155 caddr_t addr;
156 map_word d = {{0}};
157
158 addr = remap_window(map, ofs);
159 if(!addr)
160 return d;
161
162 d.x[0] = readw(addr);
163 DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%04x", ofs, addr, d.x[0]);
164 return d;
165}
166
167
168static void pcmcia_copy_from_remap(struct map_info *map, void *to, unsigned long from, ssize_t len)
169{
170 struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1;
171 unsigned long win_size = dev->win_size;
172
173 DEBUG(3, "to = %p from = %lu len = %u", to, from, len);
174 while(len) {
175 int toread = win_size - (from & (win_size-1));
176 caddr_t addr;
177
178 if(toread > len)
179 toread = len;
180
181 addr = remap_window(map, from);
182 if(!addr)
183 return;
184
185 DEBUG(4, "memcpy from %p to %p len = %d", addr, to, toread);
186 memcpy_fromio(to, addr, toread);
187 len -= toread;
188 to += toread;
189 from += toread;
190 }
191}
192
193
194static void pcmcia_write8_remap(struct map_info *map, map_word d, unsigned long adr)
195{
196 caddr_t addr = remap_window(map, adr);
197
198 if(!addr)
199 return;
200
201 DEBUG(3, "adr = 0x%08lx (%p) data = 0x%02x", adr, addr, d.x[0]);
202 writeb(d.x[0], addr);
203}
204
205
206static void pcmcia_write16_remap(struct map_info *map, map_word d, unsigned long adr)
207{
208 caddr_t addr = remap_window(map, adr);
209 if(!addr)
210 return;
211
212 DEBUG(3, "adr = 0x%08lx (%p) data = 0x%04x", adr, addr, d.x[0]);
213 writew(d.x[0], addr);
214}
215
216
217static void pcmcia_copy_to_remap(struct map_info *map, unsigned long to, const void *from, ssize_t len)
218{
219 struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1;
220 unsigned long win_size = dev->win_size;
221
222 DEBUG(3, "to = %lu from = %p len = %u", to, from, len);
223 while(len) {
224 int towrite = win_size - (to & (win_size-1));
225 caddr_t addr;
226
227 if(towrite > len)
228 towrite = len;
229
230 addr = remap_window(map, to);
231 if(!addr)
232 return;
233
234 DEBUG(4, "memcpy from %p to %p len = %d", from, addr, towrite);
235 memcpy_toio(addr, from, towrite);
236 len -= towrite;
237 to += towrite;
238 from += towrite;
239 }
240}
241
242
243/* read/write{8,16} copy_{from,to} routines with direct access */
244
245#define DEV_REMOVED(x) (!(*(u_int *)x->map_priv_1 & DEV_PRESENT))
246
247static map_word pcmcia_read8(struct map_info *map, unsigned long ofs)
248{
249 caddr_t win_base = (caddr_t)map->map_priv_2;
250 map_word d = {{0}};
251
252 if(DEV_REMOVED(map))
253 return d;
254
255 d.x[0] = readb(win_base + ofs);
256 DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%02x", ofs, win_base + ofs, d.x[0]);
257 return d;
258}
259
260
261static map_word pcmcia_read16(struct map_info *map, unsigned long ofs)
262{
263 caddr_t win_base = (caddr_t)map->map_priv_2;
264 map_word d = {{0}};
265
266 if(DEV_REMOVED(map))
267 return d;
268
269 d.x[0] = readw(win_base + ofs);
270 DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%04x", ofs, win_base + ofs, d.x[0]);
271 return d;
272}
273
274
275static void pcmcia_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
276{
277 caddr_t win_base = (caddr_t)map->map_priv_2;
278
279 if(DEV_REMOVED(map))
280 return;
281
282 DEBUG(3, "to = %p from = %lu len = %u", to, from, len);
283 memcpy_fromio(to, win_base + from, len);
284}
285
286
287static void pcmcia_write8(struct map_info *map, u8 d, unsigned long adr)
288{
289 caddr_t win_base = (caddr_t)map->map_priv_2;
290
291 if(DEV_REMOVED(map))
292 return;
293
294 DEBUG(3, "adr = 0x%08lx (%p) data = 0x%02x", adr, win_base + adr, d);
295 writeb(d, win_base + adr);
296}
297
298
299static void pcmcia_write16(struct map_info *map, u16 d, unsigned long adr)
300{
301 caddr_t win_base = (caddr_t)map->map_priv_2;
302
303 if(DEV_REMOVED(map))
304 return;
305
306 DEBUG(3, "adr = 0x%08lx (%p) data = 0x%04x", adr, win_base + adr, d);
307 writew(d, win_base + adr);
308}
309
310
311static void pcmcia_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
312{
313 caddr_t win_base = (caddr_t)map->map_priv_2;
314
315 if(DEV_REMOVED(map))
316 return;
317
318 DEBUG(3, "to = %lu from = %p len = %u", to, from, len);
319 memcpy_toio(win_base + to, from, len);
320}
321
322
323static void pcmciamtd_set_vpp(struct map_info *map, int on)
324{
325 struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1;
326 dev_link_t *link = &dev->link;
327 modconf_t mod;
328 int ret;
329
330 mod.Attributes = CONF_VPP1_CHANGE_VALID | CONF_VPP2_CHANGE_VALID;
331 mod.Vcc = 0;
332 mod.Vpp1 = mod.Vpp2 = on ? dev->vpp : 0;
333
334 DEBUG(2, "dev = %p on = %d vpp = %d\n", dev, on, dev->vpp);
335 ret = pcmcia_modify_configuration(link->handle, &mod);
336 if(ret != CS_SUCCESS) {
337 cs_error(link->handle, ModifyConfiguration, ret);
338 }
339}
340
341
342/* After a card is removed, pcmciamtd_release() will unregister the
343 * device, and release the PCMCIA configuration. If the device is
344 * still open, this will be postponed until it is closed.
345 */
346
347static void pcmciamtd_release(dev_link_t *link)
348{
349 struct pcmciamtd_dev *dev = link->priv;
350
351 DEBUG(3, "link = 0x%p", link);
352
353 if (link->win) {
354 if(dev->win_base) {
355 iounmap(dev->win_base);
356 dev->win_base = NULL;
357 }
358 pcmcia_release_window(link->win);
359 }
360 pcmcia_release_configuration(link->handle);
361 link->state &= ~DEV_CONFIG;
362}
363
364
365static void card_settings(struct pcmciamtd_dev *dev, dev_link_t *link, int *new_name)
366{
367 int rc;
368 tuple_t tuple;
369 cisparse_t parse;
370 u_char buf[64];
371
372 tuple.Attributes = 0;
373 tuple.TupleData = (cisdata_t *)buf;
374 tuple.TupleDataMax = sizeof(buf);
375 tuple.TupleOffset = 0;
376 tuple.DesiredTuple = RETURN_FIRST_TUPLE;
377
378 rc = pcmcia_get_first_tuple(link->handle, &tuple);
379 while(rc == CS_SUCCESS) {
380 rc = pcmcia_get_tuple_data(link->handle, &tuple);
381 if(rc != CS_SUCCESS) {
382 cs_error(link->handle, GetTupleData, rc);
383 break;
384 }
385 rc = pcmcia_parse_tuple(link->handle, &tuple, &parse);
386 if(rc != CS_SUCCESS) {
387 cs_error(link->handle, ParseTuple, rc);
388 break;
389 }
390
391 switch(tuple.TupleCode) {
392 case CISTPL_FORMAT: {
393 cistpl_format_t *t = &parse.format;
394 (void)t; /* Shut up, gcc */
395 DEBUG(2, "Format type: %u, Error Detection: %u, offset = %u, length =%u",
396 t->type, t->edc, t->offset, t->length);
397 break;
398
399 }
400
401 case CISTPL_DEVICE: {
402 cistpl_device_t *t = &parse.device;
403 int i;
404 DEBUG(2, "Common memory:");
405 dev->pcmcia_map.size = t->dev[0].size;
406 for(i = 0; i < t->ndev; i++) {
407 DEBUG(2, "Region %d, type = %u", i, t->dev[i].type);
408 DEBUG(2, "Region %d, wp = %u", i, t->dev[i].wp);
409 DEBUG(2, "Region %d, speed = %u ns", i, t->dev[i].speed);
410 DEBUG(2, "Region %d, size = %u bytes", i, t->dev[i].size);
411 }
412 break;
413 }
414
415 case CISTPL_VERS_1: {
416 cistpl_vers_1_t *t = &parse.version_1;
417 int i;
418 if(t->ns) {
419 dev->mtd_name[0] = '\0';
420 for(i = 0; i < t->ns; i++) {
421 if(i)
422 strcat(dev->mtd_name, " ");
423 strcat(dev->mtd_name, t->str+t->ofs[i]);
424 }
425 }
426 DEBUG(2, "Found name: %s", dev->mtd_name);
427 break;
428 }
429
430 case CISTPL_JEDEC_C: {
431 cistpl_jedec_t *t = &parse.jedec;
432 int i;
433 for(i = 0; i < t->nid; i++) {
434 DEBUG(2, "JEDEC: 0x%02x 0x%02x", t->id[i].mfr, t->id[i].info);
435 }
436 break;
437 }
438
439 case CISTPL_DEVICE_GEO: {
440 cistpl_device_geo_t *t = &parse.device_geo;
441 int i;
442 dev->pcmcia_map.bankwidth = t->geo[0].buswidth;
443 for(i = 0; i < t->ngeo; i++) {
444 DEBUG(2, "region: %d bankwidth = %u", i, t->geo[i].buswidth);
445 DEBUG(2, "region: %d erase_block = %u", i, t->geo[i].erase_block);
446 DEBUG(2, "region: %d read_block = %u", i, t->geo[i].read_block);
447 DEBUG(2, "region: %d write_block = %u", i, t->geo[i].write_block);
448 DEBUG(2, "region: %d partition = %u", i, t->geo[i].partition);
449 DEBUG(2, "region: %d interleave = %u", i, t->geo[i].interleave);
450 }
451 break;
452 }
453
454 default:
455 DEBUG(2, "Unknown tuple code %d", tuple.TupleCode);
456 }
457
458 rc = pcmcia_get_next_tuple(link->handle, &tuple);
459 }
460 if(!dev->pcmcia_map.size)
461 dev->pcmcia_map.size = MAX_PCMCIA_ADDR;
462
463 if(!dev->pcmcia_map.bankwidth)
464 dev->pcmcia_map.bankwidth = 2;
465
466 if(force_size) {
467 dev->pcmcia_map.size = force_size << 20;
468 DEBUG(2, "size forced to %dM", force_size);
469 }
470
471 if(bankwidth) {
472 dev->pcmcia_map.bankwidth = bankwidth;
473 DEBUG(2, "bankwidth forced to %d", bankwidth);
474 }
475
476 dev->pcmcia_map.name = dev->mtd_name;
477 if(!dev->mtd_name[0]) {
478 strcpy(dev->mtd_name, "PCMCIA Memory card");
479 *new_name = 1;
480 }
481
482 DEBUG(1, "Device: Size: %lu Width:%d Name: %s",
483 dev->pcmcia_map.size, dev->pcmcia_map.bankwidth << 3, dev->mtd_name);
484}
485
486
487/* pcmciamtd_config() is scheduled to run after a CARD_INSERTION event
488 * is received, to configure the PCMCIA socket, and to make the
489 * MTD device available to the system.
490 */
491
492#define CS_CHECK(fn, ret) \
493do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
494
495static void pcmciamtd_config(dev_link_t *link)
496{
497 struct pcmciamtd_dev *dev = link->priv;
498 struct mtd_info *mtd = NULL;
499 cs_status_t status;
500 win_req_t req;
501 int last_ret = 0, last_fn = 0;
502 int ret;
503 int i;
504 config_info_t t;
505 static char *probes[] = { "jedec_probe", "cfi_probe" };
506 cisinfo_t cisinfo;
507 int new_name = 0;
508
509 DEBUG(3, "link=0x%p", link);
510
511 /* Configure card */
512 link->state |= DEV_CONFIG;
513
514 DEBUG(2, "Validating CIS");
515 ret = pcmcia_validate_cis(link->handle, &cisinfo);
516 if(ret != CS_SUCCESS) {
517 cs_error(link->handle, GetTupleData, ret);
518 } else {
519 DEBUG(2, "ValidateCIS found %d chains", cisinfo.Chains);
520 }
521
522 card_settings(dev, link, &new_name);
523
524 dev->pcmcia_map.phys = NO_XIP;
525 dev->pcmcia_map.copy_from = pcmcia_copy_from_remap;
526 dev->pcmcia_map.copy_to = pcmcia_copy_to_remap;
527 if (dev->pcmcia_map.bankwidth == 1) {
528 dev->pcmcia_map.read = pcmcia_read8_remap;
529 dev->pcmcia_map.write = pcmcia_write8_remap;
530 } else {
531 dev->pcmcia_map.read = pcmcia_read16_remap;
532 dev->pcmcia_map.write = pcmcia_write16_remap;
533 }
534 if(setvpp == 1)
535 dev->pcmcia_map.set_vpp = pcmciamtd_set_vpp;
536
537 /* Request a memory window for PCMCIA. Some architeures can map windows upto the maximum
538 that PCMCIA can support (64MiB) - this is ideal and we aim for a window the size of the
539 whole card - otherwise we try smaller windows until we succeed */
540
541 req.Attributes = WIN_MEMORY_TYPE_CM | WIN_ENABLE;
542 req.Attributes |= (dev->pcmcia_map.bankwidth == 1) ? WIN_DATA_WIDTH_8 : WIN_DATA_WIDTH_16;
543 req.Base = 0;
544 req.AccessSpeed = mem_speed;
545 link->win = (window_handle_t)link->handle;
546 req.Size = (force_size) ? force_size << 20 : MAX_PCMCIA_ADDR;
547 dev->win_size = 0;
548
549 do {
550 int ret;
551 DEBUG(2, "requesting window with size = %dKiB memspeed = %d",
552 req.Size >> 10, req.AccessSpeed);
553 ret = pcmcia_request_window(&link->handle, &req, &link->win);
554 DEBUG(2, "ret = %d dev->win_size = %d", ret, dev->win_size);
555 if(ret) {
556 req.Size >>= 1;
557 } else {
558 DEBUG(2, "Got window of size %dKiB", req.Size >> 10);
559 dev->win_size = req.Size;
560 break;
561 }
562 } while(req.Size >= 0x1000);
563
564 DEBUG(2, "dev->win_size = %d", dev->win_size);
565
566 if(!dev->win_size) {
567 err("Cant allocate memory window");
568 pcmciamtd_release(link);
569 return;
570 }
571 DEBUG(1, "Allocated a window of %dKiB", dev->win_size >> 10);
572
573 /* Get write protect status */
574 CS_CHECK(GetStatus, pcmcia_get_status(link->handle, &status));
575 DEBUG(2, "status value: 0x%x window handle = 0x%8.8lx",
576 status.CardState, (unsigned long)link->win);
577 dev->win_base = ioremap(req.Base, req.Size);
578 if(!dev->win_base) {
579 err("ioremap(%lu, %u) failed", req.Base, req.Size);
580 pcmciamtd_release(link);
581 return;
582 }
583 DEBUG(1, "mapped window dev = %p req.base = 0x%lx base = %p size = 0x%x",
584 dev, req.Base, dev->win_base, req.Size);
585
586 dev->offset = 0;
587 dev->pcmcia_map.map_priv_1 = (unsigned long)dev;
588 dev->pcmcia_map.map_priv_2 = (unsigned long)link->win;
589
590 DEBUG(2, "Getting configuration");
591 CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link->handle, &t));
592 DEBUG(2, "Vcc = %d Vpp1 = %d Vpp2 = %d", t.Vcc, t.Vpp1, t.Vpp2);
593 dev->vpp = (vpp) ? vpp : t.Vpp1;
594 link->conf.Attributes = 0;
595 link->conf.Vcc = t.Vcc;
596 if(setvpp == 2) {
597 link->conf.Vpp1 = dev->vpp;
598 link->conf.Vpp2 = dev->vpp;
599 } else {
600 link->conf.Vpp1 = 0;
601 link->conf.Vpp2 = 0;
602 }
603
604 link->conf.IntType = INT_MEMORY;
605 link->conf.ConfigBase = t.ConfigBase;
606 link->conf.Status = t.Status;
607 link->conf.Pin = t.Pin;
608 link->conf.Copy = t.Copy;
609 link->conf.ExtStatus = t.ExtStatus;
610 link->conf.ConfigIndex = 0;
611 link->conf.Present = t.Present;
612 DEBUG(2, "Setting Configuration");
613 ret = pcmcia_request_configuration(link->handle, &link->conf);
614 if(ret != CS_SUCCESS) {
615 cs_error(link->handle, RequestConfiguration, ret);
616 }
617
618 if(mem_type == 1) {
619 mtd = do_map_probe("map_ram", &dev->pcmcia_map);
620 } else if(mem_type == 2) {
621 mtd = do_map_probe("map_rom", &dev->pcmcia_map);
622 } else {
623 for(i = 0; i < sizeof(probes) / sizeof(char *); i++) {
624 DEBUG(1, "Trying %s", probes[i]);
625 mtd = do_map_probe(probes[i], &dev->pcmcia_map);
626 if(mtd)
627 break;
628
629 DEBUG(1, "FAILED: %s", probes[i]);
630 }
631 }
632
633 if(!mtd) {
634 DEBUG(1, "Cant find an MTD");
635 pcmciamtd_release(link);
636 return;
637 }
638
639 dev->mtd_info = mtd;
640 mtd->owner = THIS_MODULE;
641
642 if(new_name) {
643 int size = 0;
644 char unit = ' ';
645 /* Since we are using a default name, make it better by adding in the
646 size */
647 if(mtd->size < 1048576) { /* <1MiB in size, show size in KiB */
648 size = mtd->size >> 10;
649 unit = 'K';
650 } else {
651 size = mtd->size >> 20;
652 unit = 'M';
653 }
654 snprintf(dev->mtd_name, sizeof(dev->mtd_name), "%d%ciB %s", size, unit, "PCMCIA Memory card");
655 }
656
657 /* If the memory found is fits completely into the mapped PCMCIA window,
658 use the faster non-remapping read/write functions */
659 if(mtd->size <= dev->win_size) {
660 DEBUG(1, "Using non remapping memory functions");
661 dev->pcmcia_map.map_priv_1 = (unsigned long)&(dev->link.state);
662 dev->pcmcia_map.map_priv_2 = (unsigned long)dev->win_base;
663 if (dev->pcmcia_map.bankwidth == 1) {
664 dev->pcmcia_map.read = pcmcia_read8;
665 dev->pcmcia_map.write = pcmcia_write8;
666 } else {
667 dev->pcmcia_map.read = pcmcia_read16;
668 dev->pcmcia_map.write = pcmcia_write16;
669 }
670 dev->pcmcia_map.copy_from = pcmcia_copy_from;
671 dev->pcmcia_map.copy_to = pcmcia_copy_to;
672 }
673
674 if(add_mtd_device(mtd)) {
675 map_destroy(mtd);
676 dev->mtd_info = NULL;
677 err("Couldnt register MTD device");
678 pcmciamtd_release(link);
679 return;
680 }
681 snprintf(dev->node.dev_name, sizeof(dev->node.dev_name), "mtd%d", mtd->index);
682 info("mtd%d: %s", mtd->index, mtd->name);
683 link->state &= ~DEV_CONFIG_PENDING;
684 link->dev = &dev->node;
685 return;
686
687 cs_failed:
688 cs_error(link->handle, last_fn, last_ret);
689 err("CS Error, exiting");
690 pcmciamtd_release(link);
691 return;
692}
693
694
695/* The card status event handler. Mostly, this schedules other
696 * stuff to run after an event is received. A CARD_REMOVAL event
697 * also sets some flags to discourage the driver from trying
698 * to talk to the card any more.
699 */
700
701static int pcmciamtd_event(event_t event, int priority,
702 event_callback_args_t *args)
703{
704 dev_link_t *link = args->client_data;
705
706 DEBUG(1, "event=0x%06x", event);
707 switch (event) {
708 case CS_EVENT_CARD_REMOVAL:
709 DEBUG(2, "EVENT_CARD_REMOVAL");
710 link->state &= ~DEV_PRESENT;
711 if (link->state & DEV_CONFIG) {
712 struct pcmciamtd_dev *dev = link->priv;
713 if(dev->mtd_info) {
714 del_mtd_device(dev->mtd_info);
715 info("mtd%d: Removed", dev->mtd_info->index);
716 }
717 pcmciamtd_release(link);
718 }
719 break;
720 case CS_EVENT_CARD_INSERTION:
721 DEBUG(2, "EVENT_CARD_INSERTION");
722 link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
723 pcmciamtd_config(link);
724 break;
725 case CS_EVENT_PM_SUSPEND:
726 DEBUG(2, "EVENT_PM_SUSPEND");
727 link->state |= DEV_SUSPEND;
728 /* Fall through... */
729 case CS_EVENT_RESET_PHYSICAL:
730 DEBUG(2, "EVENT_RESET_PHYSICAL");
731 /* get_lock(link); */
732 break;
733 case CS_EVENT_PM_RESUME:
734 DEBUG(2, "EVENT_PM_RESUME");
735 link->state &= ~DEV_SUSPEND;
736 /* Fall through... */
737 case CS_EVENT_CARD_RESET:
738 DEBUG(2, "EVENT_CARD_RESET");
739 /* free_lock(link); */
740 break;
741 default:
742 DEBUG(2, "Unknown event %d", event);
743 }
744 return 0;
745}
746
747
748/* This deletes a driver "instance". The device is de-registered
749 * with Card Services. If it has been released, all local data
750 * structures are freed. Otherwise, the structures will be freed
751 * when the device is released.
752 */
753
754static void pcmciamtd_detach(dev_link_t *link)
755{
756 DEBUG(3, "link=0x%p", link);
757
758 if(link->state & DEV_CONFIG) {
759 pcmciamtd_release(link);
760 }
761
762 if (link->handle) {
763 int ret;
764 DEBUG(2, "Deregistering with card services");
765 ret = pcmcia_deregister_client(link->handle);
766 if (ret != CS_SUCCESS)
767 cs_error(link->handle, DeregisterClient, ret);
768 }
769
770 link->state |= DEV_STALE_LINK;
771}
772
773
774/* pcmciamtd_attach() creates an "instance" of the driver, allocating
775 * local data structures for one device. The device is registered
776 * with Card Services.
777 */
778
779static dev_link_t *pcmciamtd_attach(void)
780{
781 struct pcmciamtd_dev *dev;
782 dev_link_t *link;
783 client_reg_t client_reg;
784 int ret;
785
786 /* Create new memory card device */
787 dev = kmalloc(sizeof(*dev), GFP_KERNEL);
788 if (!dev) return NULL;
789 DEBUG(1, "dev=0x%p", dev);
790
791 memset(dev, 0, sizeof(*dev));
792 link = &dev->link;
793 link->priv = dev;
794
795 link->conf.Attributes = 0;
796 link->conf.IntType = INT_MEMORY;
797
798 link->next = dev_list;
799 dev_list = link;
800
801 /* Register with Card Services */
802 client_reg.dev_info = &dev_info;
803 client_reg.EventMask =
804 CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
805 CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
806 CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
807 client_reg.event_handler = &pcmciamtd_event;
808 client_reg.Version = 0x0210;
809 client_reg.event_callback_args.client_data = link;
810 DEBUG(2, "Calling RegisterClient");
811 ret = pcmcia_register_client(&link->handle, &client_reg);
812 if (ret != 0) {
813 cs_error(link->handle, RegisterClient, ret);
814 pcmciamtd_detach(link);
815 return NULL;
816 }
817 DEBUG(2, "link = %p", link);
818 return link;
819}
820
821
822static struct pcmcia_driver pcmciamtd_driver = {
823 .drv = {
824 .name = "pcmciamtd"
825 },
826 .attach = pcmciamtd_attach,
827 .detach = pcmciamtd_detach,
828 .owner = THIS_MODULE
829};
830
831
832static int __init init_pcmciamtd(void)
833{
834 info(DRIVER_DESC " " DRIVER_VERSION);
835
836 if(bankwidth && bankwidth != 1 && bankwidth != 2) {
837 info("bad bankwidth (%d), using default", bankwidth);
838 bankwidth = 2;
839 }
840 if(force_size && (force_size < 1 || force_size > 64)) {
841 info("bad force_size (%d), using default", force_size);
842 force_size = 0;
843 }
844 if(mem_type && mem_type != 1 && mem_type != 2) {
845 info("bad mem_type (%d), using default", mem_type);
846 mem_type = 0;
847 }
848 return pcmcia_register_driver(&pcmciamtd_driver);
849}
850
851
852static void __exit exit_pcmciamtd(void)
853{
854 DEBUG(1, DRIVER_DESC " unloading");
855 pcmcia_unregister_driver(&pcmciamtd_driver);
856 BUG_ON(dev_list != NULL);
857}
858
859module_init(init_pcmciamtd);
860module_exit(exit_pcmciamtd);
diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c
new file mode 100644
index 000000000000..b853670bfb81
--- /dev/null
+++ b/drivers/mtd/maps/physmap.c
@@ -0,0 +1,125 @@
1/*
2 * $Id: physmap.c,v 1.37 2004/11/28 09:40:40 dwmw2 Exp $
3 *
4 * Normal mappings of chips in physical memory
5 *
6 * Copyright (C) 2003 MontaVista Software Inc.
7 * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
8 *
9 * 031022 - [jsun] add run-time configure and partition setup
10 */
11
12#include <linux/module.h>
13#include <linux/types.h>
14#include <linux/kernel.h>
15#include <linux/init.h>
16#include <linux/slab.h>
17#include <asm/io.h>
18#include <linux/mtd/mtd.h>
19#include <linux/mtd/map.h>
20#include <linux/config.h>
21#include <linux/mtd/partitions.h>
22
23static struct mtd_info *mymtd;
24
25struct map_info physmap_map = {
26 .name = "phys_mapped_flash",
27 .phys = CONFIG_MTD_PHYSMAP_START,
28 .size = CONFIG_MTD_PHYSMAP_LEN,
29 .bankwidth = CONFIG_MTD_PHYSMAP_BANKWIDTH,
30};
31
32#ifdef CONFIG_MTD_PARTITIONS
33static struct mtd_partition *mtd_parts;
34static int mtd_parts_nb;
35
36static int num_physmap_partitions;
37static struct mtd_partition *physmap_partitions;
38
39static const char *part_probes[] __initdata = {"cmdlinepart", "RedBoot", NULL};
40
41void physmap_set_partitions(struct mtd_partition *parts, int num_parts)
42{
43 physmap_partitions=parts;
44 num_physmap_partitions=num_parts;
45}
46#endif /* CONFIG_MTD_PARTITIONS */
47
48static int __init init_physmap(void)
49{
50 static const char *rom_probe_types[] = { "cfi_probe", "jedec_probe", "map_rom", NULL };
51 const char **type;
52
53 printk(KERN_NOTICE "physmap flash device: %lx at %lx\n", physmap_map.size, physmap_map.phys);
54 physmap_map.virt = ioremap(physmap_map.phys, physmap_map.size);
55
56 if (!physmap_map.virt) {
57 printk("Failed to ioremap\n");
58 return -EIO;
59 }
60
61 simple_map_init(&physmap_map);
62
63 mymtd = NULL;
64 type = rom_probe_types;
65 for(; !mymtd && *type; type++) {
66 mymtd = do_map_probe(*type, &physmap_map);
67 }
68 if (mymtd) {
69 mymtd->owner = THIS_MODULE;
70
71#ifdef CONFIG_MTD_PARTITIONS
72 mtd_parts_nb = parse_mtd_partitions(mymtd, part_probes,
73 &mtd_parts, 0);
74
75 if (mtd_parts_nb > 0)
76 {
77 add_mtd_partitions (mymtd, mtd_parts, mtd_parts_nb);
78 return 0;
79 }
80
81 if (num_physmap_partitions != 0)
82 {
83 printk(KERN_NOTICE
84 "Using physmap partition definition\n");
85 add_mtd_partitions (mymtd, physmap_partitions, num_physmap_partitions);
86 return 0;
87 }
88
89#endif
90 add_mtd_device(mymtd);
91
92 return 0;
93 }
94
95 iounmap(physmap_map.virt);
96 return -ENXIO;
97}
98
99static void __exit cleanup_physmap(void)
100{
101#ifdef CONFIG_MTD_PARTITIONS
102 if (mtd_parts_nb) {
103 del_mtd_partitions(mymtd);
104 kfree(mtd_parts);
105 } else if (num_physmap_partitions) {
106 del_mtd_partitions(mymtd);
107 } else {
108 del_mtd_device(mymtd);
109 }
110#else
111 del_mtd_device(mymtd);
112#endif
113 map_destroy(mymtd);
114
115 iounmap(physmap_map.virt);
116 physmap_map.virt = NULL;
117}
118
119module_init(init_physmap);
120module_exit(cleanup_physmap);
121
122
123MODULE_LICENSE("GPL");
124MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
125MODULE_DESCRIPTION("Generic configurable MTD map driver");
diff --git a/drivers/mtd/maps/pnc2000.c b/drivers/mtd/maps/pnc2000.c
new file mode 100644
index 000000000000..a0f43dad8985
--- /dev/null
+++ b/drivers/mtd/maps/pnc2000.c
@@ -0,0 +1,93 @@
1/*
2 * pnc2000.c - mapper for Photron PNC-2000 board.
3 *
4 * Copyright (C) 2000 Crossnet Co. <info@crossnet.co.jp>
5 *
6 * This code is GPL
7 *
8 * $Id: pnc2000.c,v 1.17 2004/11/16 18:29:02 dwmw2 Exp $
9 */
10
11#include <linux/module.h>
12#include <linux/types.h>
13#include <linux/kernel.h>
14#include <linux/init.h>
15
16#include <linux/mtd/mtd.h>
17#include <linux/mtd/map.h>
18#include <linux/mtd/partitions.h>
19
20
21#define WINDOW_ADDR 0xbf000000
22#define WINDOW_SIZE 0x00400000
23
24/*
25 * MAP DRIVER STUFF
26 */
27
28
29static struct map_info pnc_map = {
30 .name = "PNC-2000",
31 .size = WINDOW_SIZE,
32 .bankwidth = 4,
33 .phys = 0xFFFFFFFF,
34 .virt = (void __iomem *)WINDOW_ADDR,
35};
36
37
38/*
39 * MTD 'PARTITIONING' STUFF
40 */
41static struct mtd_partition pnc_partitions[3] = {
42 {
43 .name = "PNC-2000 boot firmware",
44 .size = 0x20000,
45 .offset = 0
46 },
47 {
48 .name = "PNC-2000 kernel",
49 .size = 0x1a0000,
50 .offset = 0x20000
51 },
52 {
53 .name = "PNC-2000 filesystem",
54 .size = 0x240000,
55 .offset = 0x1c0000
56 }
57};
58
59/*
60 * This is the master MTD device for which all the others are just
61 * auto-relocating aliases.
62 */
63static struct mtd_info *mymtd;
64
65static int __init init_pnc2000(void)
66{
67 printk(KERN_NOTICE "Photron PNC-2000 flash mapping: %x at %x\n", WINDOW_SIZE, WINDOW_ADDR);
68
69 simple_map_init(&pnc_map);
70
71 mymtd = do_map_probe("cfi_probe", &pnc_map);
72 if (mymtd) {
73 mymtd->owner = THIS_MODULE;
74 return add_mtd_partitions(mymtd, pnc_partitions, 3);
75 }
76
77 return -ENXIO;
78}
79
80static void __exit cleanup_pnc2000(void)
81{
82 if (mymtd) {
83 del_mtd_partitions(mymtd);
84 map_destroy(mymtd);
85 }
86}
87
88module_init(init_pnc2000);
89module_exit(cleanup_pnc2000);
90
91MODULE_LICENSE("GPL");
92MODULE_AUTHOR("Crossnet Co. <info@crossnet.co.jp>");
93MODULE_DESCRIPTION("MTD map driver for Photron PNC-2000 board");
diff --git a/drivers/mtd/maps/redwood.c b/drivers/mtd/maps/redwood.c
new file mode 100644
index 000000000000..edd01ee4f90b
--- /dev/null
+++ b/drivers/mtd/maps/redwood.c
@@ -0,0 +1,169 @@
1/*
2 * $Id: redwood.c,v 1.10 2004/11/04 13:24:15 gleixner Exp $
3 *
4 * drivers/mtd/maps/redwood.c
5 *
6 * FLASH map for the IBM Redwood 4/5/6 boards.
7 *
8 * Author: MontaVista Software, Inc. <source@mvista.com>
9 *
10 * 2001-2003 (c) MontaVista, Software, Inc. This file is licensed under
11 * the terms of the GNU General Public License version 2. This program
12 * is licensed "as is" without any warranty of any kind, whether express
13 * or implied.
14 */
15
16#include <linux/config.h>
17#include <linux/module.h>
18#include <linux/types.h>
19#include <linux/kernel.h>
20#include <linux/init.h>
21
22#include <linux/mtd/mtd.h>
23#include <linux/mtd/map.h>
24#include <linux/mtd/partitions.h>
25
26#include <asm/io.h>
27
28#if !defined (CONFIG_REDWOOD_6)
29
30#define WINDOW_ADDR 0xffc00000
31#define WINDOW_SIZE 0x00400000
32
33#define RW_PART0_OF 0
34#define RW_PART0_SZ 0x10000
35#define RW_PART1_OF RW_PART0_SZ
36#define RW_PART1_SZ 0x200000 - 0x10000
37#define RW_PART2_OF 0x200000
38#define RW_PART2_SZ 0x10000
39#define RW_PART3_OF 0x210000
40#define RW_PART3_SZ 0x200000 - (0x10000 + 0x20000)
41#define RW_PART4_OF 0x3e0000
42#define RW_PART4_SZ 0x20000
43
44static struct mtd_partition redwood_flash_partitions[] = {
45 {
46 .name = "Redwood OpenBIOS Vital Product Data",
47 .offset = RW_PART0_OF,
48 .size = RW_PART0_SZ,
49 .mask_flags = MTD_WRITEABLE /* force read-only */
50 },
51 {
52 .name = "Redwood kernel",
53 .offset = RW_PART1_OF,
54 .size = RW_PART1_SZ
55 },
56 {
57 .name = "Redwood OpenBIOS non-volatile storage",
58 .offset = RW_PART2_OF,
59 .size = RW_PART2_SZ,
60 .mask_flags = MTD_WRITEABLE /* force read-only */
61 },
62 {
63 .name = "Redwood filesystem",
64 .offset = RW_PART3_OF,
65 .size = RW_PART3_SZ
66 },
67 {
68 .name = "Redwood OpenBIOS",
69 .offset = RW_PART4_OF,
70 .size = RW_PART4_SZ,
71 .mask_flags = MTD_WRITEABLE /* force read-only */
72 }
73};
74
75#else /* CONFIG_REDWOOD_6 */
76/* FIXME: the window is bigger - armin */
77#define WINDOW_ADDR 0xff800000
78#define WINDOW_SIZE 0x00800000
79
80#define RW_PART0_OF 0
81#define RW_PART0_SZ 0x400000 /* 4 MiB data */
82#define RW_PART1_OF RW_PART0_OF + RW_PART0_SZ
83#define RW_PART1_SZ 0x10000 /* 64K VPD */
84#define RW_PART2_OF RW_PART1_OF + RW_PART1_SZ
85#define RW_PART2_SZ 0x400000 - (0x10000 + 0x20000)
86#define RW_PART3_OF RW_PART2_OF + RW_PART2_SZ
87#define RW_PART3_SZ 0x20000
88
89static struct mtd_partition redwood_flash_partitions[] = {
90 {
91 .name = "Redwood filesystem",
92 .offset = RW_PART0_OF,
93 .size = RW_PART0_SZ
94 },
95 {
96 .name = "Redwood OpenBIOS Vital Product Data",
97 .offset = RW_PART1_OF,
98 .size = RW_PART1_SZ,
99 .mask_flags = MTD_WRITEABLE /* force read-only */
100 },
101 {
102 .name = "Redwood kernel",
103 .offset = RW_PART2_OF,
104 .size = RW_PART2_SZ
105 },
106 {
107 .name = "Redwood OpenBIOS",
108 .offset = RW_PART3_OF,
109 .size = RW_PART3_SZ,
110 .mask_flags = MTD_WRITEABLE /* force read-only */
111 }
112};
113
114#endif /* CONFIG_REDWOOD_6 */
115
116struct map_info redwood_flash_map = {
117 .name = "IBM Redwood",
118 .size = WINDOW_SIZE,
119 .bankwidth = 2,
120 .phys = WINDOW_ADDR,
121};
122
123
124#define NUM_REDWOOD_FLASH_PARTITIONS \
125 (sizeof(redwood_flash_partitions)/sizeof(redwood_flash_partitions[0]))
126
127static struct mtd_info *redwood_mtd;
128
129int __init init_redwood_flash(void)
130{
131 printk(KERN_NOTICE "redwood: flash mapping: %x at %x\n",
132 WINDOW_SIZE, WINDOW_ADDR);
133
134 redwood_flash_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE);
135
136 if (!redwood_flash_map.virt) {
137 printk("init_redwood_flash: failed to ioremap\n");
138 return -EIO;
139 }
140 simple_map_init(&redwood_flash_map);
141
142 redwood_mtd = do_map_probe("cfi_probe",&redwood_flash_map);
143
144 if (redwood_mtd) {
145 redwood_mtd->owner = THIS_MODULE;
146 return add_mtd_partitions(redwood_mtd,
147 redwood_flash_partitions,
148 NUM_REDWOOD_FLASH_PARTITIONS);
149 }
150
151 return -ENXIO;
152}
153
154static void __exit cleanup_redwood_flash(void)
155{
156 if (redwood_mtd) {
157 del_mtd_partitions(redwood_mtd);
158 /* moved iounmap after map_destroy - armin */
159 map_destroy(redwood_mtd);
160 iounmap((void *)redwood_flash_map.virt);
161 }
162}
163
164module_init(init_redwood_flash);
165module_exit(cleanup_redwood_flash);
166
167MODULE_LICENSE("GPL");
168MODULE_AUTHOR("MontaVista Software <source@mvista.com>");
169MODULE_DESCRIPTION("MTD map driver for the IBM Redwood reference boards");
diff --git a/drivers/mtd/maps/rpxlite.c b/drivers/mtd/maps/rpxlite.c
new file mode 100644
index 000000000000..809a0c8e7aaf
--- /dev/null
+++ b/drivers/mtd/maps/rpxlite.c
@@ -0,0 +1,66 @@
1/*
2 * $Id: rpxlite.c,v 1.22 2004/11/04 13:24:15 gleixner Exp $
3 *
4 * Handle mapping of the flash on the RPX Lite and CLLF boards
5 */
6
7#include <linux/module.h>
8#include <linux/types.h>
9#include <linux/kernel.h>
10#include <linux/init.h>
11#include <asm/io.h>
12#include <linux/mtd/mtd.h>
13#include <linux/mtd/map.h>
14
15
16#define WINDOW_ADDR 0xfe000000
17#define WINDOW_SIZE 0x800000
18
19static struct mtd_info *mymtd;
20
21static struct map_info rpxlite_map = {
22 .name = "RPX",
23 .size = WINDOW_SIZE,
24 .bankwidth = 4,
25 .phys = WINDOW_ADDR,
26};
27
28int __init init_rpxlite(void)
29{
30 printk(KERN_NOTICE "RPX Lite or CLLF flash device: %x at %x\n", WINDOW_SIZE*4, WINDOW_ADDR);
31 rpxlite_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE * 4);
32
33 if (!rpxlite_map.virt) {
34 printk("Failed to ioremap\n");
35 return -EIO;
36 }
37 simple_map_init(&rpxlite_map);
38 mymtd = do_map_probe("cfi_probe", &rpxlite_map);
39 if (mymtd) {
40 mymtd->owner = THIS_MODULE;
41 add_mtd_device(mymtd);
42 return 0;
43 }
44
45 iounmap((void *)rpxlite_map.virt);
46 return -ENXIO;
47}
48
49static void __exit cleanup_rpxlite(void)
50{
51 if (mymtd) {
52 del_mtd_device(mymtd);
53 map_destroy(mymtd);
54 }
55 if (rpxlite_map.virt) {
56 iounmap((void *)rpxlite_map.virt);
57 rpxlite_map.virt = 0;
58 }
59}
60
61module_init(init_rpxlite);
62module_exit(cleanup_rpxlite);
63
64MODULE_LICENSE("GPL");
65MODULE_AUTHOR("Arnold Christensen <AKC@pel.dk>");
66MODULE_DESCRIPTION("MTD map driver for RPX Lite and CLLF boards");
diff --git a/drivers/mtd/maps/sa1100-flash.c b/drivers/mtd/maps/sa1100-flash.c
new file mode 100644
index 000000000000..0a6f861c4cd6
--- /dev/null
+++ b/drivers/mtd/maps/sa1100-flash.c
@@ -0,0 +1,453 @@
1/*
2 * Flash memory access on SA11x0 based devices
3 *
4 * (C) 2000 Nicolas Pitre <nico@cam.org>
5 *
6 * $Id: sa1100-flash.c,v 1.47 2004/11/01 13:44:36 rmk Exp $
7 */
8#include <linux/config.h>
9#include <linux/module.h>
10#include <linux/types.h>
11#include <linux/ioport.h>
12#include <linux/kernel.h>
13#include <linux/init.h>
14#include <linux/errno.h>
15#include <linux/slab.h>
16#include <linux/device.h>
17#include <linux/err.h>
18
19#include <linux/mtd/mtd.h>
20#include <linux/mtd/map.h>
21#include <linux/mtd/partitions.h>
22#include <linux/mtd/concat.h>
23
24#include <asm/mach-types.h>
25#include <asm/io.h>
26#include <asm/sizes.h>
27#include <asm/mach/flash.h>
28
29#if 0
30/*
31 * This is here for documentation purposes only - until these people
32 * submit their machine types. It will be gone January 2005.
33 */
34static struct mtd_partition consus_partitions[] = {
35 {
36 .name = "Consus boot firmware",
37 .offset = 0,
38 .size = 0x00040000,
39 .mask_flags = MTD_WRITABLE, /* force read-only */
40 }, {
41 .name = "Consus kernel",
42 .offset = 0x00040000,
43 .size = 0x00100000,
44 .mask_flags = 0,
45 }, {
46 .name = "Consus disk",
47 .offset = 0x00140000,
48 /* The rest (up to 16M) for jffs. We could put 0 and
49 make it find the size automatically, but right now
50 i have 32 megs. jffs will use all 32 megs if given
51 the chance, and this leads to horrible problems
52 when you try to re-flash the image because blob
53 won't erase the whole partition. */
54 .size = 0x01000000 - 0x00140000,
55 .mask_flags = 0,
56 }, {
57 /* this disk is a secondary disk, which can be used as
58 needed, for simplicity, make it the size of the other
59 consus partition, although realistically it could be
60 the remainder of the disk (depending on the file
61 system used) */
62 .name = "Consus disk2",
63 .offset = 0x01000000,
64 .size = 0x01000000 - 0x00140000,
65 .mask_flags = 0,
66 }
67};
68
69/* Frodo has 2 x 16M 28F128J3A flash chips in bank 0: */
70static struct mtd_partition frodo_partitions[] =
71{
72 {
73 .name = "bootloader",
74 .size = 0x00040000,
75 .offset = 0x00000000,
76 .mask_flags = MTD_WRITEABLE
77 }, {
78 .name = "bootloader params",
79 .size = 0x00040000,
80 .offset = MTDPART_OFS_APPEND,
81 .mask_flags = MTD_WRITEABLE
82 }, {
83 .name = "kernel",
84 .size = 0x00100000,
85 .offset = MTDPART_OFS_APPEND,
86 .mask_flags = MTD_WRITEABLE
87 }, {
88 .name = "ramdisk",
89 .size = 0x00400000,
90 .offset = MTDPART_OFS_APPEND,
91 .mask_flags = MTD_WRITEABLE
92 }, {
93 .name = "file system",
94 .size = MTDPART_SIZ_FULL,
95 .offset = MTDPART_OFS_APPEND
96 }
97};
98
99static struct mtd_partition jornada56x_partitions[] = {
100 {
101 .name = "bootldr",
102 .size = 0x00040000,
103 .offset = 0,
104 .mask_flags = MTD_WRITEABLE,
105 }, {
106 .name = "rootfs",
107 .size = MTDPART_SIZ_FULL,
108 .offset = MTDPART_OFS_APPEND,
109 }
110};
111
112static void jornada56x_set_vpp(int vpp)
113{
114 if (vpp)
115 GPSR = GPIO_GPIO26;
116 else
117 GPCR = GPIO_GPIO26;
118 GPDR |= GPIO_GPIO26;
119}
120
121/*
122 * Machine Phys Size set_vpp
123 * Consus : SA1100_CS0_PHYS SZ_32M
124 * Frodo : SA1100_CS0_PHYS SZ_32M
125 * Jornada56x: SA1100_CS0_PHYS SZ_32M jornada56x_set_vpp
126 */
127#endif
128
129struct sa_subdev_info {
130 char name[16];
131 struct map_info map;
132 struct mtd_info *mtd;
133 struct flash_platform_data *data;
134};
135
136struct sa_info {
137 struct mtd_partition *parts;
138 struct mtd_info *mtd;
139 int num_subdev;
140 struct sa_subdev_info subdev[0];
141};
142
143static void sa1100_set_vpp(struct map_info *map, int on)
144{
145 struct sa_subdev_info *subdev = container_of(map, struct sa_subdev_info, map);
146 subdev->data->set_vpp(on);
147}
148
149static void sa1100_destroy_subdev(struct sa_subdev_info *subdev)
150{
151 if (subdev->mtd)
152 map_destroy(subdev->mtd);
153 if (subdev->map.virt)
154 iounmap(subdev->map.virt);
155 release_mem_region(subdev->map.phys, subdev->map.size);
156}
157
158static int sa1100_probe_subdev(struct sa_subdev_info *subdev, struct resource *res)
159{
160 unsigned long phys;
161 unsigned int size;
162 int ret;
163
164 phys = res->start;
165 size = res->end - phys + 1;
166
167 /*
168 * Retrieve the bankwidth from the MSC registers.
169 * We currently only implement CS0 and CS1 here.
170 */
171 switch (phys) {
172 default:
173 printk(KERN_WARNING "SA1100 flash: unknown base address "
174 "0x%08lx, assuming CS0\n", phys);
175
176 case SA1100_CS0_PHYS:
177 subdev->map.bankwidth = (MSC0 & MSC_RBW) ? 2 : 4;
178 break;
179
180 case SA1100_CS1_PHYS:
181 subdev->map.bankwidth = ((MSC0 >> 16) & MSC_RBW) ? 2 : 4;
182 break;
183 }
184
185 if (!request_mem_region(phys, size, subdev->name)) {
186 ret = -EBUSY;
187 goto out;
188 }
189
190 if (subdev->data->set_vpp)
191 subdev->map.set_vpp = sa1100_set_vpp;
192
193 subdev->map.phys = phys;
194 subdev->map.size = size;
195 subdev->map.virt = ioremap(phys, size);
196 if (!subdev->map.virt) {
197 ret = -ENOMEM;
198 goto err;
199 }
200
201 simple_map_init(&subdev->map);
202
203 /*
204 * Now let's probe for the actual flash. Do it here since
205 * specific machine settings might have been set above.
206 */
207 subdev->mtd = do_map_probe(subdev->data->map_name, &subdev->map);
208 if (subdev->mtd == NULL) {
209 ret = -ENXIO;
210 goto err;
211 }
212 subdev->mtd->owner = THIS_MODULE;
213
214 printk(KERN_INFO "SA1100 flash: CFI device at 0x%08lx, %dMiB, "
215 "%d-bit\n", phys, subdev->mtd->size >> 20,
216 subdev->map.bankwidth * 8);
217
218 return 0;
219
220 err:
221 sa1100_destroy_subdev(subdev);
222 out:
223 return ret;
224}
225
226static void sa1100_destroy(struct sa_info *info)
227{
228 int i;
229
230 if (info->mtd) {
231 del_mtd_partitions(info->mtd);
232
233#ifdef CONFIG_MTD_CONCAT
234 if (info->mtd != info->subdev[0].mtd)
235 mtd_concat_destroy(info->mtd);
236#endif
237 }
238
239 if (info->parts)
240 kfree(info->parts);
241
242 for (i = info->num_subdev - 1; i >= 0; i--)
243 sa1100_destroy_subdev(&info->subdev[i]);
244 kfree(info);
245}
246
247static struct sa_info *__init
248sa1100_setup_mtd(struct platform_device *pdev, struct flash_platform_data *flash)
249{
250 struct sa_info *info;
251 int nr, size, i, ret = 0;
252
253 /*
254 * Count number of devices.
255 */
256 for (nr = 0; ; nr++)
257 if (!platform_get_resource(pdev, IORESOURCE_MEM, nr))
258 break;
259
260 if (nr == 0) {
261 ret = -ENODEV;
262 goto out;
263 }
264
265 size = sizeof(struct sa_info) + sizeof(struct sa_subdev_info) * nr;
266
267 /*
268 * Allocate the map_info structs in one go.
269 */
270 info = kmalloc(size, GFP_KERNEL);
271 if (!info) {
272 ret = -ENOMEM;
273 goto out;
274 }
275
276 memset(info, 0, size);
277
278 /*
279 * Claim and then map the memory regions.
280 */
281 for (i = 0; i < nr; i++) {
282 struct sa_subdev_info *subdev = &info->subdev[i];
283 struct resource *res;
284
285 res = platform_get_resource(pdev, IORESOURCE_MEM, i);
286 if (!res)
287 break;
288
289 subdev->map.name = subdev->name;
290 sprintf(subdev->name, "sa1100-%d", i);
291 subdev->data = flash;
292
293 ret = sa1100_probe_subdev(subdev, res);
294 if (ret)
295 break;
296 }
297
298 info->num_subdev = i;
299
300 /*
301 * ENXIO is special. It means we didn't find a chip when we probed.
302 */
303 if (ret != 0 && !(ret == -ENXIO && info->num_subdev > 0))
304 goto err;
305
306 /*
307 * If we found one device, don't bother with concat support. If
308 * we found multiple devices, use concat if we have it available,
309 * otherwise fail. Either way, it'll be called "sa1100".
310 */
311 if (info->num_subdev == 1) {
312 strcpy(info->subdev[0].name, "sa1100");
313 info->mtd = info->subdev[0].mtd;
314 ret = 0;
315 } else if (info->num_subdev > 1) {
316#ifdef CONFIG_MTD_CONCAT
317 struct mtd_info *cdev[nr];
318 /*
319 * We detected multiple devices. Concatenate them together.
320 */
321 for (i = 0; i < info->num_subdev; i++)
322 cdev[i] = info->subdev[i].mtd;
323
324 info->mtd = mtd_concat_create(cdev, info->num_subdev,
325 "sa1100");
326 if (info->mtd == NULL)
327 ret = -ENXIO;
328#else
329 printk(KERN_ERR "SA1100 flash: multiple devices "
330 "found but MTD concat support disabled.\n");
331 ret = -ENXIO;
332#endif
333 }
334
335 if (ret == 0)
336 return info;
337
338 err:
339 sa1100_destroy(info);
340 out:
341 return ERR_PTR(ret);
342}
343
344static const char *part_probes[] = { "cmdlinepart", "RedBoot", NULL };
345
346static int __init sa1100_mtd_probe(struct device *dev)
347{
348 struct platform_device *pdev = to_platform_device(dev);
349 struct flash_platform_data *flash = pdev->dev.platform_data;
350 struct mtd_partition *parts;
351 const char *part_type = NULL;
352 struct sa_info *info;
353 int err, nr_parts = 0;
354
355 if (!flash)
356 return -ENODEV;
357
358 info = sa1100_setup_mtd(pdev, flash);
359 if (IS_ERR(info)) {
360 err = PTR_ERR(info);
361 goto out;
362 }
363
364 /*
365 * Partition selection stuff.
366 */
367#ifdef CONFIG_MTD_PARTITIONS
368 nr_parts = parse_mtd_partitions(info->mtd, part_probes, &parts, 0);
369 if (nr_parts > 0) {
370 info->parts = parts;
371 part_type = "dynamic";
372 } else
373#endif
374 {
375 parts = flash->parts;
376 nr_parts = flash->nr_parts;
377 part_type = "static";
378 }
379
380 if (nr_parts == 0) {
381 printk(KERN_NOTICE "SA1100 flash: no partition info "
382 "available, registering whole flash\n");
383 add_mtd_device(info->mtd);
384 } else {
385 printk(KERN_NOTICE "SA1100 flash: using %s partition "
386 "definition\n", part_type);
387 add_mtd_partitions(info->mtd, parts, nr_parts);
388 }
389
390 dev_set_drvdata(dev, info);
391 err = 0;
392
393 out:
394 return err;
395}
396
397static int __exit sa1100_mtd_remove(struct device *dev)
398{
399 struct sa_info *info = dev_get_drvdata(dev);
400 dev_set_drvdata(dev, NULL);
401 sa1100_destroy(info);
402 return 0;
403}
404
405#ifdef CONFIG_PM
406static int sa1100_mtd_suspend(struct device *dev, u32 state, u32 level)
407{
408 struct sa_info *info = dev_get_drvdata(dev);
409 int ret = 0;
410
411 if (info && level == SUSPEND_SAVE_STATE)
412 ret = info->mtd->suspend(info->mtd);
413
414 return ret;
415}
416
417static int sa1100_mtd_resume(struct device *dev, u32 level)
418{
419 struct sa_info *info = dev_get_drvdata(dev);
420 if (info && level == RESUME_RESTORE_STATE)
421 info->mtd->resume(info->mtd);
422 return 0;
423}
424#else
425#define sa1100_mtd_suspend NULL
426#define sa1100_mtd_resume NULL
427#endif
428
429static struct device_driver sa1100_mtd_driver = {
430 .name = "flash",
431 .bus = &platform_bus_type,
432 .probe = sa1100_mtd_probe,
433 .remove = __exit_p(sa1100_mtd_remove),
434 .suspend = sa1100_mtd_suspend,
435 .resume = sa1100_mtd_resume,
436};
437
438static int __init sa1100_mtd_init(void)
439{
440 return driver_register(&sa1100_mtd_driver);
441}
442
443static void __exit sa1100_mtd_exit(void)
444{
445 driver_unregister(&sa1100_mtd_driver);
446}
447
448module_init(sa1100_mtd_init);
449module_exit(sa1100_mtd_exit);
450
451MODULE_AUTHOR("Nicolas Pitre");
452MODULE_DESCRIPTION("SA1100 CFI map driver");
453MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/maps/sbc8240.c b/drivers/mtd/maps/sbc8240.c
new file mode 100644
index 000000000000..da684d3384e9
--- /dev/null
+++ b/drivers/mtd/maps/sbc8240.c
@@ -0,0 +1,247 @@
1/*
2 * Handle mapping of the flash memory access routines on the SBC8240 board.
3 *
4 * Carolyn Smith, Tektronix, Inc.
5 *
6 * This code is GPLed
7 *
8 * $Id: sbc8240.c,v 1.4 2004/07/12 22:38:29 dwmw2 Exp $
9 *
10 */
11
12/*
13 * The SBC8240 has 2 flash banks.
14 * Bank 0 is a 512 KiB AMD AM29F040B; 8 x 64 KiB sectors.
15 * It contains the U-Boot code (7 sectors) and the environment (1 sector).
16 * Bank 1 is 4 x 1 MiB AMD AM29LV800BT; 15 x 64 KiB sectors, 1 x 32 KiB sector,
17 * 2 x 8 KiB sectors, 1 x 16 KiB sectors.
18 * Both parts are JEDEC compatible.
19 */
20
21#include <linux/config.h>
22#include <linux/module.h>
23#include <linux/types.h>
24#include <linux/kernel.h>
25#include <asm/io.h>
26
27#include <linux/mtd/mtd.h>
28#include <linux/mtd/map.h>
29#include <linux/mtd/cfi.h>
30
31#ifdef CONFIG_MTD_PARTITIONS
32#include <linux/mtd/partitions.h>
33#endif
34
35#define DEBUG
36
37#ifdef DEBUG
38# define debugk(fmt,args...) printk(fmt ,##args)
39#else
40# define debugk(fmt,args...)
41#endif
42
43
44#define WINDOW_ADDR0 0xFFF00000 /* 512 KiB */
45#define WINDOW_SIZE0 0x00080000
46#define BUSWIDTH0 1
47
48#define WINDOW_ADDR1 0xFF000000 /* 4 MiB */
49#define WINDOW_SIZE1 0x00400000
50#define BUSWIDTH1 8
51
52#define MSG_PREFIX "sbc8240:" /* prefix for our printk()'s */
53#define MTDID "sbc8240-%d" /* for mtdparts= partitioning */
54
55
56static struct map_info sbc8240_map[2] = {
57 {
58 .name = "sbc8240 Flash Bank #0",
59 .size = WINDOW_SIZE0,
60 .bankwidth = BUSWIDTH0,
61 },
62 {
63 .name = "sbc8240 Flash Bank #1",
64 .size = WINDOW_SIZE1,
65 .bankwidth = BUSWIDTH1,
66 }
67};
68
69#define NUM_FLASH_BANKS (sizeof(sbc8240_map) / sizeof(struct map_info))
70
71/*
72 * The following defines the partition layout of SBC8240 boards.
73 *
74 * See include/linux/mtd/partitions.h for definition of the
75 * mtd_partition structure.
76 *
77 * The *_max_flash_size is the maximum possible mapped flash size
78 * which is not necessarily the actual flash size. It must correspond
79 * to the value specified in the mapping definition defined by the
80 * "struct map_desc *_io_desc" for the corresponding machine.
81 */
82
83#ifdef CONFIG_MTD_PARTITIONS
84
85static struct mtd_partition sbc8240_uboot_partitions [] = {
86 /* Bank 0 */
87 {
88 .name = "U-boot", /* U-Boot Firmware */
89 .offset = 0,
90 .size = 0x00070000, /* 7 x 64 KiB sectors */
91 .mask_flags = MTD_WRITEABLE, /* force read-only */
92 },
93 {
94 .name = "environment", /* U-Boot environment */
95 .offset = 0x00070000,
96 .size = 0x00010000, /* 1 x 64 KiB sector */
97 },
98};
99
100static struct mtd_partition sbc8240_fs_partitions [] = {
101 {
102 .name = "jffs", /* JFFS filesystem */
103 .offset = 0,
104 .size = 0x003C0000, /* 4 * 15 * 64KiB */
105 },
106 {
107 .name = "tmp32",
108 .offset = 0x003C0000,
109 .size = 0x00020000, /* 4 * 32KiB */
110 },
111 {
112 .name = "tmp8a",
113 .offset = 0x003E0000,
114 .size = 0x00008000, /* 4 * 8KiB */
115 },
116 {
117 .name = "tmp8b",
118 .offset = 0x003E8000,
119 .size = 0x00008000, /* 4 * 8KiB */
120 },
121 {
122 .name = "tmp16",
123 .offset = 0x003F0000,
124 .size = 0x00010000, /* 4 * 16KiB */
125 }
126};
127
128#define NB_OF(x) (sizeof (x) / sizeof (x[0]))
129
130/* trivial struct to describe partition information */
131struct mtd_part_def
132{
133 int nums;
134 unsigned char *type;
135 struct mtd_partition* mtd_part;
136};
137
138static struct mtd_info *sbc8240_mtd[NUM_FLASH_BANKS];
139static struct mtd_part_def sbc8240_part_banks[NUM_FLASH_BANKS];
140
141
142#endif /* CONFIG_MTD_PARTITIONS */
143
144
145int __init init_sbc8240_mtd (void)
146{
147 static struct _cjs {
148 u_long addr;
149 u_long size;
150 } pt[NUM_FLASH_BANKS] = {
151 {
152 .addr = WINDOW_ADDR0,
153 .size = WINDOW_SIZE0
154 },
155 {
156 .addr = WINDOW_ADDR1,
157 .size = WINDOW_SIZE1
158 },
159 };
160
161 int devicesfound = 0;
162 int i;
163
164 for (i = 0; i < NUM_FLASH_BANKS; i++) {
165 printk (KERN_NOTICE MSG_PREFIX
166 "Probing 0x%08lx at 0x%08lx\n", pt[i].size, pt[i].addr);
167
168 sbc8240_map[i].map_priv_1 =
169 (unsigned long) ioremap (pt[i].addr, pt[i].size);
170 if (!sbc8240_map[i].map_priv_1) {
171 printk (MSG_PREFIX "failed to ioremap\n");
172 return -EIO;
173 }
174 simple_map_init(&sbc8240_mtd[i]);
175
176 sbc8240_mtd[i] = do_map_probe("jedec_probe", &sbc8240_map[i]);
177
178 if (sbc8240_mtd[i]) {
179 sbc8240_mtd[i]->module = THIS_MODULE;
180 devicesfound++;
181 }
182 }
183
184 if (!devicesfound) {
185 printk(KERN_NOTICE MSG_PREFIX
186 "No suppported flash chips found!\n");
187 return -ENXIO;
188 }
189
190#ifdef CONFIG_MTD_PARTITIONS
191 sbc8240_part_banks[0].mtd_part = sbc8240_uboot_partitions;
192 sbc8240_part_banks[0].type = "static image";
193 sbc8240_part_banks[0].nums = NB_OF(sbc8240_uboot_partitions);
194 sbc8240_part_banks[1].mtd_part = sbc8240_fs_partitions;
195 sbc8240_part_banks[1].type = "static file system";
196 sbc8240_part_banks[1].nums = NB_OF(sbc8240_fs_partitions);
197
198 for (i = 0; i < NUM_FLASH_BANKS; i++) {
199
200 if (!sbc8240_mtd[i]) continue;
201 if (sbc8240_part_banks[i].nums == 0) {
202 printk (KERN_NOTICE MSG_PREFIX
203 "No partition info available, registering whole device\n");
204 add_mtd_device(sbc8240_mtd[i]);
205 } else {
206 printk (KERN_NOTICE MSG_PREFIX
207 "Using %s partition definition\n", sbc8240_part_banks[i].mtd_part->name);
208 add_mtd_partitions (sbc8240_mtd[i],
209 sbc8240_part_banks[i].mtd_part,
210 sbc8240_part_banks[i].nums);
211 }
212 }
213#else
214 printk(KERN_NOTICE MSG_PREFIX
215 "Registering %d flash banks at once\n", devicesfound);
216
217 for (i = 0; i < devicesfound; i++) {
218 add_mtd_device(sbc8240_mtd[i]);
219 }
220#endif /* CONFIG_MTD_PARTITIONS */
221
222 return devicesfound == 0 ? -ENXIO : 0;
223}
224
225static void __exit cleanup_sbc8240_mtd (void)
226{
227 int i;
228
229 for (i = 0; i < NUM_FLASH_BANKS; i++) {
230 if (sbc8240_mtd[i]) {
231 del_mtd_device (sbc8240_mtd[i]);
232 map_destroy (sbc8240_mtd[i]);
233 }
234 if (sbc8240_map[i].map_priv_1) {
235 iounmap ((void *) sbc8240_map[i].map_priv_1);
236 sbc8240_map[i].map_priv_1 = 0;
237 }
238 }
239}
240
241module_init (init_sbc8240_mtd);
242module_exit (cleanup_sbc8240_mtd);
243
244MODULE_LICENSE ("GPL");
245MODULE_AUTHOR ("Carolyn Smith <carolyn.smith@tektronix.com>");
246MODULE_DESCRIPTION ("MTD map driver for SBC8240 boards");
247
diff --git a/drivers/mtd/maps/sbc_gxx.c b/drivers/mtd/maps/sbc_gxx.c
new file mode 100644
index 000000000000..65add28bde14
--- /dev/null
+++ b/drivers/mtd/maps/sbc_gxx.c
@@ -0,0 +1,239 @@
1/* sbc_gxx.c -- MTD map driver for Arcom Control Systems SBC-MediaGX,
2 SBC-GXm and SBC-GX1 series boards.
3
4 Copyright (C) 2001 Arcom Control System Ltd
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19
20 $Id: sbc_gxx.c,v 1.33 2004/11/28 09:40:40 dwmw2 Exp $
21
22The SBC-MediaGX / SBC-GXx has up to 16 MiB of
23Intel StrataFlash (28F320/28F640) in x8 mode.
24
25This driver uses the CFI probe and Intel Extended Command Set drivers.
26
27The flash is accessed as follows:
28
29 16 KiB memory window at 0xdc000-0xdffff
30
31 Two IO address locations for paging
32
33 0x258
34 bit 0-7: address bit 14-21
35 0x259
36 bit 0-1: address bit 22-23
37 bit 7: 0 - reset/powered down
38 1 - device enabled
39
40The single flash device is divided into 3 partition which appear as
41separate MTD devices.
42
4325/04/2001 AJL (Arcom) Modified signon strings and partition sizes
44 (to support bzImages up to 638KiB-ish)
45*/
46
47// Includes
48
49#include <linux/module.h>
50#include <linux/slab.h>
51#include <linux/ioport.h>
52#include <linux/init.h>
53#include <asm/io.h>
54
55#include <linux/mtd/mtd.h>
56#include <linux/mtd/map.h>
57#include <linux/mtd/partitions.h>
58
59// Defines
60
61// - Hardware specific
62
63#define WINDOW_START 0xdc000
64
65/* Number of bits in offset. */
66#define WINDOW_SHIFT 14
67#define WINDOW_LENGTH (1 << WINDOW_SHIFT)
68
69/* The bits for the offset into the window. */
70#define WINDOW_MASK (WINDOW_LENGTH-1)
71#define PAGE_IO 0x258
72#define PAGE_IO_SIZE 2
73
74/* bit 7 of 0x259 must be 1 to enable device. */
75#define DEVICE_ENABLE 0x8000
76
77// - Flash / Partition sizing
78
79#define MAX_SIZE_KiB 16384
80#define BOOT_PARTITION_SIZE_KiB 768
81#define DATA_PARTITION_SIZE_KiB 1280
82#define APP_PARTITION_SIZE_KiB 6144
83
84// Globals
85
86static volatile int page_in_window = -1; // Current page in window.
87static void __iomem *iomapadr;
88static DEFINE_SPINLOCK(sbc_gxx_spin);
89
90/* partition_info gives details on the logical partitions that the split the
91 * single flash device into. If the size if zero we use up to the end of the
92 * device. */
93static struct mtd_partition partition_info[]={
94 { .name = "SBC-GXx flash boot partition",
95 .offset = 0,
96 .size = BOOT_PARTITION_SIZE_KiB*1024 },
97 { .name = "SBC-GXx flash data partition",
98 .offset = BOOT_PARTITION_SIZE_KiB*1024,
99 .size = (DATA_PARTITION_SIZE_KiB)*1024 },
100 { .name = "SBC-GXx flash application partition",
101 .offset = (BOOT_PARTITION_SIZE_KiB+DATA_PARTITION_SIZE_KiB)*1024 }
102};
103
104#define NUM_PARTITIONS 3
105
106static inline void sbc_gxx_page(struct map_info *map, unsigned long ofs)
107{
108 unsigned long page = ofs >> WINDOW_SHIFT;
109
110 if( page!=page_in_window ) {
111 outw( page | DEVICE_ENABLE, PAGE_IO );
112 page_in_window = page;
113 }
114}
115
116
117static map_word sbc_gxx_read8(struct map_info *map, unsigned long ofs)
118{
119 map_word ret;
120 spin_lock(&sbc_gxx_spin);
121 sbc_gxx_page(map, ofs);
122 ret.x[0] = readb(iomapadr + (ofs & WINDOW_MASK));
123 spin_unlock(&sbc_gxx_spin);
124 return ret;
125}
126
127static void sbc_gxx_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
128{
129 while(len) {
130 unsigned long thislen = len;
131 if (len > (WINDOW_LENGTH - (from & WINDOW_MASK)))
132 thislen = WINDOW_LENGTH-(from & WINDOW_MASK);
133
134 spin_lock(&sbc_gxx_spin);
135 sbc_gxx_page(map, from);
136 memcpy_fromio(to, iomapadr + (from & WINDOW_MASK), thislen);
137 spin_unlock(&sbc_gxx_spin);
138 to += thislen;
139 from += thislen;
140 len -= thislen;
141 }
142}
143
144static void sbc_gxx_write8(struct map_info *map, map_word d, unsigned long adr)
145{
146 spin_lock(&sbc_gxx_spin);
147 sbc_gxx_page(map, adr);
148 writeb(d.x[0], iomapadr + (adr & WINDOW_MASK));
149 spin_unlock(&sbc_gxx_spin);
150}
151
152static void sbc_gxx_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
153{
154 while(len) {
155 unsigned long thislen = len;
156 if (len > (WINDOW_LENGTH - (to & WINDOW_MASK)))
157 thislen = WINDOW_LENGTH-(to & WINDOW_MASK);
158
159 spin_lock(&sbc_gxx_spin);
160 sbc_gxx_page(map, to);
161 memcpy_toio(iomapadr + (to & WINDOW_MASK), from, thislen);
162 spin_unlock(&sbc_gxx_spin);
163 to += thislen;
164 from += thislen;
165 len -= thislen;
166 }
167}
168
169static struct map_info sbc_gxx_map = {
170 .name = "SBC-GXx flash",
171 .phys = NO_XIP,
172 .size = MAX_SIZE_KiB*1024, /* this must be set to a maximum possible amount
173 of flash so the cfi probe routines find all
174 the chips */
175 .bankwidth = 1,
176 .read = sbc_gxx_read8,
177 .copy_from = sbc_gxx_copy_from,
178 .write = sbc_gxx_write8,
179 .copy_to = sbc_gxx_copy_to
180};
181
182/* MTD device for all of the flash. */
183static struct mtd_info *all_mtd;
184
185static void cleanup_sbc_gxx(void)
186{
187 if( all_mtd ) {
188 del_mtd_partitions( all_mtd );
189 map_destroy( all_mtd );
190 }
191
192 iounmap(iomapadr);
193 release_region(PAGE_IO,PAGE_IO_SIZE);
194}
195
196static int __init init_sbc_gxx(void)
197{
198 iomapadr = ioremap(WINDOW_START, WINDOW_LENGTH);
199 if (!iomapadr) {
200 printk( KERN_ERR"%s: failed to ioremap memory region\n",
201 sbc_gxx_map.name );
202 return -EIO;
203 }
204
205 if (!request_region( PAGE_IO, PAGE_IO_SIZE, "SBC-GXx flash")) {
206 printk( KERN_ERR"%s: IO ports 0x%x-0x%x in use\n",
207 sbc_gxx_map.name,
208 PAGE_IO, PAGE_IO+PAGE_IO_SIZE-1 );
209 iounmap(iomapadr);
210 return -EAGAIN;
211 }
212
213
214 printk( KERN_INFO"%s: IO:0x%x-0x%x MEM:0x%x-0x%x\n",
215 sbc_gxx_map.name,
216 PAGE_IO, PAGE_IO+PAGE_IO_SIZE-1,
217 WINDOW_START, WINDOW_START+WINDOW_LENGTH-1 );
218
219 /* Probe for chip. */
220 all_mtd = do_map_probe( "cfi_probe", &sbc_gxx_map );
221 if( !all_mtd ) {
222 cleanup_sbc_gxx();
223 return -ENXIO;
224 }
225
226 all_mtd->owner = THIS_MODULE;
227
228 /* Create MTD devices for each partition. */
229 add_mtd_partitions(all_mtd, partition_info, NUM_PARTITIONS );
230
231 return 0;
232}
233
234module_init(init_sbc_gxx);
235module_exit(cleanup_sbc_gxx);
236
237MODULE_LICENSE("GPL");
238MODULE_AUTHOR("Arcom Control Systems Ltd.");
239MODULE_DESCRIPTION("MTD map driver for SBC-GXm and SBC-GX1 series boards");
diff --git a/drivers/mtd/maps/sc520cdp.c b/drivers/mtd/maps/sc520cdp.c
new file mode 100644
index 000000000000..a06ed21e7ed1
--- /dev/null
+++ b/drivers/mtd/maps/sc520cdp.c
@@ -0,0 +1,304 @@
1/* sc520cdp.c -- MTD map driver for AMD SC520 Customer Development Platform
2 *
3 * Copyright (C) 2001 Sysgo Real-Time Solutions GmbH
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
18 *
19 * $Id: sc520cdp.c,v 1.21 2004/12/13 10:27:08 dedekind Exp $
20 *
21 *
22 * The SC520CDP is an evaluation board for the Elan SC520 processor available
23 * from AMD. It has two banks of 32-bit Flash ROM, each 8 Megabytes in size,
24 * and up to 512 KiB of 8-bit DIL Flash ROM.
25 * For details see http://www.amd.com/products/epd/desiging/evalboards/18.elansc520/520_cdp_brief/index.html
26 */
27
28#include <linux/config.h>
29#include <linux/module.h>
30#include <linux/types.h>
31#include <linux/kernel.h>
32#include <linux/init.h>
33#include <asm/io.h>
34#include <linux/mtd/mtd.h>
35#include <linux/mtd/map.h>
36#include <linux/mtd/concat.h>
37
38/*
39** The Embedded Systems BIOS decodes the first FLASH starting at
40** 0x8400000. This is a *terrible* place for it because accessing
41** the flash at this location causes the A22 address line to be high
42** (that's what 0x8400000 binary's ought to be). But this is the highest
43** order address line on the raw flash devices themselves!!
44** This causes the top HALF of the flash to be accessed first. Beyond
45** the physical limits of the flash, the flash chip aliases over (to
46** 0x880000 which causes the bottom half to be accessed. This splits the
47** flash into two and inverts it! If you then try to access this from another
48** program that does NOT do this insanity, then you *will* access the
49** first half of the flash, but not find what you expect there. That
50** stuff is in the *second* half! Similarly, the address used by the
51** BIOS for the second FLASH bank is also quite a bad choice.
52** If REPROGRAM_PAR is defined below (the default), then this driver will
53** choose more useful addresses for the FLASH banks by reprogramming the
54** responsible PARxx registers in the SC520's MMCR region. This will
55** cause the settings to be incompatible with the BIOS's settings, which
56** shouldn't be a problem since you are running Linux, (i.e. the BIOS is
57** not much use anyway). However, if you need to be compatible with
58** the BIOS for some reason, just undefine REPROGRAM_PAR.
59*/
60#define REPROGRAM_PAR
61
62
63
64#ifdef REPROGRAM_PAR
65
66/* These are the addresses we want.. */
67#define WINDOW_ADDR_0 0x08800000
68#define WINDOW_ADDR_1 0x09000000
69#define WINDOW_ADDR_2 0x09800000
70
71/* .. and these are the addresses the BIOS gives us */
72#define WINDOW_ADDR_0_BIOS 0x08400000
73#define WINDOW_ADDR_1_BIOS 0x08c00000
74#define WINDOW_ADDR_2_BIOS 0x09400000
75
76#else
77
78#define WINDOW_ADDR_0 0x08400000
79#define WINDOW_ADDR_1 0x08C00000
80#define WINDOW_ADDR_2 0x09400000
81
82#endif
83
84#define WINDOW_SIZE_0 0x00800000
85#define WINDOW_SIZE_1 0x00800000
86#define WINDOW_SIZE_2 0x00080000
87
88
89static struct map_info sc520cdp_map[] = {
90 {
91 .name = "SC520CDP Flash Bank #0",
92 .size = WINDOW_SIZE_0,
93 .bankwidth = 4,
94 .phys = WINDOW_ADDR_0
95 },
96 {
97 .name = "SC520CDP Flash Bank #1",
98 .size = WINDOW_SIZE_1,
99 .bankwidth = 4,
100 .phys = WINDOW_ADDR_1
101 },
102 {
103 .name = "SC520CDP DIL Flash",
104 .size = WINDOW_SIZE_2,
105 .bankwidth = 1,
106 .phys = WINDOW_ADDR_2
107 },
108};
109
110#define NUM_FLASH_BANKS (sizeof(sc520cdp_map)/sizeof(struct map_info))
111
112static struct mtd_info *mymtd[NUM_FLASH_BANKS];
113static struct mtd_info *merged_mtd;
114
115#ifdef REPROGRAM_PAR
116
117/*
118** The SC520 MMCR (memory mapped control register) region resides
119** at 0xFFFEF000. The 16 Programmable Address Region (PAR) registers
120** are at offset 0x88 in the MMCR:
121*/
122#define SC520_MMCR_BASE 0xFFFEF000
123#define SC520_MMCR_EXTENT 0x1000
124#define SC520_PAR(x) ((0x88/sizeof(unsigned long)) + (x))
125#define NUM_SC520_PAR 16 /* total number of PAR registers */
126
127/*
128** The highest three bits in a PAR register determine what target
129** device is controlled by this PAR. Here, only ROMCS? and BOOTCS
130** devices are of interest.
131*/
132#define SC520_PAR_BOOTCS (0x4<<29)
133#define SC520_PAR_ROMCS0 (0x5<<29)
134#define SC520_PAR_ROMCS1 (0x6<<29)
135#define SC520_PAR_TRGDEV (0x7<<29)
136
137/*
138** Bits 28 thru 26 determine some attributes for the
139** region controlled by the PAR. (We only use non-cacheable)
140*/
141#define SC520_PAR_WRPROT (1<<26) /* write protected */
142#define SC520_PAR_NOCACHE (1<<27) /* non-cacheable */
143#define SC520_PAR_NOEXEC (1<<28) /* code execution denied */
144
145
146/*
147** Bit 25 determines the granularity: 4K or 64K
148*/
149#define SC520_PAR_PG_SIZ4 (0<<25)
150#define SC520_PAR_PG_SIZ64 (1<<25)
151
152/*
153** Build a value to be written into a PAR register.
154** We only need ROM entries, 64K page size:
155*/
156#define SC520_PAR_ENTRY(trgdev, address, size) \
157 ((trgdev) | SC520_PAR_NOCACHE | SC520_PAR_PG_SIZ64 | \
158 (address) >> 16 | (((size) >> 16) - 1) << 14)
159
160struct sc520_par_table
161{
162 unsigned long trgdev;
163 unsigned long new_par;
164 unsigned long default_address;
165};
166
167static struct sc520_par_table par_table[NUM_FLASH_BANKS] =
168{
169 { /* Flash Bank #0: selected by ROMCS0 */
170 SC520_PAR_ROMCS0,
171 SC520_PAR_ENTRY(SC520_PAR_ROMCS0, WINDOW_ADDR_0, WINDOW_SIZE_0),
172 WINDOW_ADDR_0_BIOS
173 },
174 { /* Flash Bank #1: selected by ROMCS1 */
175 SC520_PAR_ROMCS1,
176 SC520_PAR_ENTRY(SC520_PAR_ROMCS1, WINDOW_ADDR_1, WINDOW_SIZE_1),
177 WINDOW_ADDR_1_BIOS
178 },
179 { /* DIL (BIOS) Flash: selected by BOOTCS */
180 SC520_PAR_BOOTCS,
181 SC520_PAR_ENTRY(SC520_PAR_BOOTCS, WINDOW_ADDR_2, WINDOW_SIZE_2),
182 WINDOW_ADDR_2_BIOS
183 }
184};
185
186
187static void sc520cdp_setup_par(void)
188{
189 volatile unsigned long __iomem *mmcr;
190 unsigned long mmcr_val;
191 int i, j;
192
193 /* map in SC520's MMCR area */
194 mmcr = ioremap_nocache(SC520_MMCR_BASE, SC520_MMCR_EXTENT);
195 if(!mmcr) { /* ioremap_nocache failed: skip the PAR reprogramming */
196 /* force physical address fields to BIOS defaults: */
197 for(i = 0; i < NUM_FLASH_BANKS; i++)
198 sc520cdp_map[i].phys = par_table[i].default_address;
199 return;
200 }
201
202 /*
203 ** Find the PARxx registers that are reponsible for activating
204 ** ROMCS0, ROMCS1 and BOOTCS. Reprogram each of these with a
205 ** new value from the table.
206 */
207 for(i = 0; i < NUM_FLASH_BANKS; i++) { /* for each par_table entry */
208 for(j = 0; j < NUM_SC520_PAR; j++) { /* for each PAR register */
209 mmcr_val = mmcr[SC520_PAR(j)];
210 /* if target device field matches, reprogram the PAR */
211 if((mmcr_val & SC520_PAR_TRGDEV) == par_table[i].trgdev)
212 {
213 mmcr[SC520_PAR(j)] = par_table[i].new_par;
214 break;
215 }
216 }
217 if(j == NUM_SC520_PAR)
218 { /* no matching PAR found: try default BIOS address */
219 printk(KERN_NOTICE "Could not find PAR responsible for %s\n",
220 sc520cdp_map[i].name);
221 printk(KERN_NOTICE "Trying default address 0x%lx\n",
222 par_table[i].default_address);
223 sc520cdp_map[i].phys = par_table[i].default_address;
224 }
225 }
226 iounmap(mmcr);
227}
228#endif
229
230
231static int __init init_sc520cdp(void)
232{
233 int i, devices_found = 0;
234
235#ifdef REPROGRAM_PAR
236 /* reprogram PAR registers so flash appears at the desired addresses */
237 sc520cdp_setup_par();
238#endif
239
240 for (i = 0; i < NUM_FLASH_BANKS; i++) {
241 printk(KERN_NOTICE "SC520 CDP flash device: 0x%lx at 0x%lx\n",
242 sc520cdp_map[i].size, sc520cdp_map[i].phys);
243
244 sc520cdp_map[i].virt = ioremap_nocache(sc520cdp_map[i].phys, sc520cdp_map[i].size);
245
246 if (!sc520cdp_map[i].virt) {
247 printk("Failed to ioremap_nocache\n");
248 return -EIO;
249 }
250
251 simple_map_init(&sc520cdp_map[i]);
252
253 mymtd[i] = do_map_probe("cfi_probe", &sc520cdp_map[i]);
254 if(!mymtd[i])
255 mymtd[i] = do_map_probe("jedec_probe", &sc520cdp_map[i]);
256 if(!mymtd[i])
257 mymtd[i] = do_map_probe("map_rom", &sc520cdp_map[i]);
258
259 if (mymtd[i]) {
260 mymtd[i]->owner = THIS_MODULE;
261 ++devices_found;
262 }
263 else {
264 iounmap(sc520cdp_map[i].virt);
265 }
266 }
267 if(devices_found >= 2) {
268 /* Combine the two flash banks into a single MTD device & register it: */
269 merged_mtd = mtd_concat_create(mymtd, 2, "SC520CDP Flash Banks #0 and #1");
270 if(merged_mtd)
271 add_mtd_device(merged_mtd);
272 }
273 if(devices_found == 3) /* register the third (DIL-Flash) device */
274 add_mtd_device(mymtd[2]);
275 return(devices_found ? 0 : -ENXIO);
276}
277
278static void __exit cleanup_sc520cdp(void)
279{
280 int i;
281
282 if (merged_mtd) {
283 del_mtd_device(merged_mtd);
284 mtd_concat_destroy(merged_mtd);
285 }
286 if (mymtd[2])
287 del_mtd_device(mymtd[2]);
288
289 for (i = 0; i < NUM_FLASH_BANKS; i++) {
290 if (mymtd[i])
291 map_destroy(mymtd[i]);
292 if (sc520cdp_map[i].virt) {
293 iounmap(sc520cdp_map[i].virt);
294 sc520cdp_map[i].virt = NULL;
295 }
296 }
297}
298
299module_init(init_sc520cdp);
300module_exit(cleanup_sc520cdp);
301
302MODULE_LICENSE("GPL");
303MODULE_AUTHOR("Sysgo Real-Time Solutions GmbH");
304MODULE_DESCRIPTION("MTD map driver for AMD SC520 Customer Development Platform");
diff --git a/drivers/mtd/maps/scb2_flash.c b/drivers/mtd/maps/scb2_flash.c
new file mode 100644
index 000000000000..5bb3b600e5d0
--- /dev/null
+++ b/drivers/mtd/maps/scb2_flash.c
@@ -0,0 +1,256 @@
1/*
2 * MTD map driver for BIOS Flash on Intel SCB2 boards
3 * $Id: scb2_flash.c,v 1.11 2004/11/28 09:40:40 dwmw2 Exp $
4 * Copyright (C) 2002 Sun Microsystems, Inc.
5 * Tim Hockin <thockin@sun.com>
6 *
7 * A few notes on this MTD map:
8 *
9 * This was developed with a small number of SCB2 boards to test on.
10 * Hopefully, Intel has not introducted too many unaccounted variables in the
11 * making of this board.
12 *
13 * The BIOS marks its own memory region as 'reserved' in the e820 map. We
14 * try to request it here, but if it fails, we carry on anyway.
15 *
16 * This is how the chip is attached, so said the schematic:
17 * * a 4 MiB (32 Mib) 16 bit chip
18 * * a 1 MiB memory region
19 * * A20 and A21 pulled up
20 * * D8-D15 ignored
21 * What this means is that, while we are addressing bytes linearly, we are
22 * really addressing words, and discarding the other byte. This means that
23 * the chip MUST BE at least 2 MiB. This also means that every block is
24 * actually half as big as the chip reports. It also means that accesses of
25 * logical address 0 hit higher-address sections of the chip, not physical 0.
26 * One can only hope that these 4MiB x16 chips were a lot cheaper than 1MiB x8
27 * chips.
28 *
29 * This driver assumes the chip is not write-protected by an external signal.
30 * As of the this writing, that is true, but may change, just to spite me.
31 *
32 * The actual BIOS layout has been mostly reverse engineered. Intel BIOS
33 * updates for this board include 10 related (*.bio - &.bi9) binary files and
34 * another separate (*.bbo) binary file. The 10 files are 64k of data + a
35 * small header. If the headers are stripped off, the 10 64k files can be
36 * concatenated into a 640k image. This is your BIOS image, proper. The
37 * separate .bbo file also has a small header. It is the 'Boot Block'
38 * recovery BIOS. Once the header is stripped, no further prep is needed.
39 * As best I can tell, the BIOS is arranged as such:
40 * offset 0x00000 to 0x4ffff (320k): unknown - SCSI BIOS, etc?
41 * offset 0x50000 to 0xeffff (640k): BIOS proper
42 * offset 0xf0000 ty 0xfffff (64k): Boot Block region
43 *
44 * Intel's BIOS update program flashes the BIOS and Boot Block in separate
45 * steps. Probably a wise thing to do.
46 */
47
48#include <linux/module.h>
49#include <linux/types.h>
50#include <linux/kernel.h>
51#include <linux/init.h>
52#include <asm/io.h>
53#include <linux/mtd/mtd.h>
54#include <linux/mtd/map.h>
55#include <linux/mtd/cfi.h>
56#include <linux/config.h>
57#include <linux/pci.h>
58#include <linux/pci_ids.h>
59
60#define MODNAME "scb2_flash"
61#define SCB2_ADDR 0xfff00000
62#define SCB2_WINDOW 0x00100000
63
64
65static void __iomem *scb2_ioaddr;
66static struct mtd_info *scb2_mtd;
67static struct map_info scb2_map = {
68 .name = "SCB2 BIOS Flash",
69 .size = 0,
70 .bankwidth = 1,
71};
72static int region_fail;
73
74static int __devinit
75scb2_fixup_mtd(struct mtd_info *mtd)
76{
77 int i;
78 int done = 0;
79 struct map_info *map = mtd->priv;
80 struct cfi_private *cfi = map->fldrv_priv;
81
82 /* barf if this doesn't look right */
83 if (cfi->cfiq->InterfaceDesc != 1) {
84 printk(KERN_ERR MODNAME ": unsupported InterfaceDesc: %#x\n",
85 cfi->cfiq->InterfaceDesc);
86 return -1;
87 }
88
89 /* I wasn't here. I didn't see. dwmw2. */
90
91 /* the chip is sometimes bigger than the map - what a waste */
92 mtd->size = map->size;
93
94 /*
95 * We only REALLY get half the chip, due to the way it is
96 * wired up - D8-D15 are tossed away. We read linear bytes,
97 * but in reality we are getting 1/2 of each 16-bit read,
98 * which LOOKS linear to us. Because CFI code accounts for
99 * things like lock/unlock/erase by eraseregions, we need to
100 * fudge them to reflect this. Erases go like this:
101 * * send an erase to an address
102 * * the chip samples the address and erases the block
103 * * add the block erasesize to the address and repeat
104 * -- the problem is that addresses are 16-bit addressable
105 * -- we end up erasing every-other block
106 */
107 mtd->erasesize /= 2;
108 for (i = 0; i < mtd->numeraseregions; i++) {
109 struct mtd_erase_region_info *region = &mtd->eraseregions[i];
110 region->erasesize /= 2;
111 }
112
113 /*
114 * If the chip is bigger than the map, it is wired with the high
115 * address lines pulled up. This makes us access the top portion of
116 * the chip, so all our erase-region info is wrong. Start cutting from
117 * the bottom.
118 */
119 for (i = 0; !done && i < mtd->numeraseregions; i++) {
120 struct mtd_erase_region_info *region = &mtd->eraseregions[i];
121
122 if (region->numblocks * region->erasesize > mtd->size) {
123 region->numblocks = (mtd->size / region->erasesize);
124 done = 1;
125 } else {
126 region->numblocks = 0;
127 }
128 region->offset = 0;
129 }
130
131 return 0;
132}
133
134/* CSB5's 'Function Control Register' has bits for decoding @ >= 0xffc00000 */
135#define CSB5_FCR 0x41
136#define CSB5_FCR_DECODE_ALL 0x0e
137static int __devinit
138scb2_flash_probe(struct pci_dev *dev, const struct pci_device_id *ent)
139{
140 u8 reg;
141
142 /* enable decoding of the flash region in the south bridge */
143 pci_read_config_byte(dev, CSB5_FCR, &reg);
144 pci_write_config_byte(dev, CSB5_FCR, reg | CSB5_FCR_DECODE_ALL);
145
146 if (!request_mem_region(SCB2_ADDR, SCB2_WINDOW, scb2_map.name)) {
147 /*
148 * The BIOS seems to mark the flash region as 'reserved'
149 * in the e820 map. Warn and go about our business.
150 */
151 printk(KERN_WARNING MODNAME
152 ": warning - can't reserve rom window, continuing\n");
153 region_fail = 1;
154 }
155
156 /* remap the IO window (w/o caching) */
157 scb2_ioaddr = ioremap_nocache(SCB2_ADDR, SCB2_WINDOW);
158 if (!scb2_ioaddr) {
159 printk(KERN_ERR MODNAME ": Failed to ioremap window!\n");
160 if (!region_fail)
161 release_mem_region(SCB2_ADDR, SCB2_WINDOW);
162 return -ENOMEM;
163 }
164
165 scb2_map.phys = SCB2_ADDR;
166 scb2_map.virt = scb2_ioaddr;
167 scb2_map.size = SCB2_WINDOW;
168
169 simple_map_init(&scb2_map);
170
171 /* try to find a chip */
172 scb2_mtd = do_map_probe("cfi_probe", &scb2_map);
173
174 if (!scb2_mtd) {
175 printk(KERN_ERR MODNAME ": flash probe failed!\n");
176 iounmap(scb2_ioaddr);
177 if (!region_fail)
178 release_mem_region(SCB2_ADDR, SCB2_WINDOW);
179 return -ENODEV;
180 }
181
182 scb2_mtd->owner = THIS_MODULE;
183 if (scb2_fixup_mtd(scb2_mtd) < 0) {
184 del_mtd_device(scb2_mtd);
185 map_destroy(scb2_mtd);
186 iounmap(scb2_ioaddr);
187 if (!region_fail)
188 release_mem_region(SCB2_ADDR, SCB2_WINDOW);
189 return -ENODEV;
190 }
191
192 printk(KERN_NOTICE MODNAME ": chip size 0x%x at offset 0x%x\n",
193 scb2_mtd->size, SCB2_WINDOW - scb2_mtd->size);
194
195 add_mtd_device(scb2_mtd);
196
197 return 0;
198}
199
200static void __devexit
201scb2_flash_remove(struct pci_dev *dev)
202{
203 if (!scb2_mtd)
204 return;
205
206 /* disable flash writes */
207 if (scb2_mtd->lock)
208 scb2_mtd->lock(scb2_mtd, 0, scb2_mtd->size);
209
210 del_mtd_device(scb2_mtd);
211 map_destroy(scb2_mtd);
212
213 iounmap(scb2_ioaddr);
214 scb2_ioaddr = NULL;
215
216 if (!region_fail)
217 release_mem_region(SCB2_ADDR, SCB2_WINDOW);
218 pci_set_drvdata(dev, NULL);
219}
220
221static struct pci_device_id scb2_flash_pci_ids[] = {
222 {
223 .vendor = PCI_VENDOR_ID_SERVERWORKS,
224 .device = PCI_DEVICE_ID_SERVERWORKS_CSB5,
225 .subvendor = PCI_ANY_ID,
226 .subdevice = PCI_ANY_ID
227 },
228 { 0, }
229};
230
231static struct pci_driver scb2_flash_driver = {
232 .name = "Intel SCB2 BIOS Flash",
233 .id_table = scb2_flash_pci_ids,
234 .probe = scb2_flash_probe,
235 .remove = __devexit_p(scb2_flash_remove),
236};
237
238static int __init
239scb2_flash_init(void)
240{
241 return pci_module_init(&scb2_flash_driver);
242}
243
244static void __exit
245scb2_flash_exit(void)
246{
247 pci_unregister_driver(&scb2_flash_driver);
248}
249
250module_init(scb2_flash_init);
251module_exit(scb2_flash_exit);
252
253MODULE_LICENSE("GPL");
254MODULE_AUTHOR("Tim Hockin <thockin@sun.com>");
255MODULE_DESCRIPTION("MTD map driver for Intel SCB2 BIOS Flash");
256MODULE_DEVICE_TABLE(pci, scb2_flash_pci_ids);
diff --git a/drivers/mtd/maps/scx200_docflash.c b/drivers/mtd/maps/scx200_docflash.c
new file mode 100644
index 000000000000..0ece3786d6ea
--- /dev/null
+++ b/drivers/mtd/maps/scx200_docflash.c
@@ -0,0 +1,233 @@
1/* linux/drivers/mtd/maps/scx200_docflash.c
2
3 Copyright (c) 2001,2002 Christer Weinigel <wingel@nano-system.com>
4
5 $Id: scx200_docflash.c,v 1.10 2004/11/28 09:40:40 dwmw2 Exp $
6
7 National Semiconductor SCx200 flash mapped with DOCCS
8*/
9
10#include <linux/module.h>
11#include <linux/config.h>
12#include <linux/types.h>
13#include <linux/kernel.h>
14#include <linux/init.h>
15#include <asm/io.h>
16#include <linux/mtd/mtd.h>
17#include <linux/mtd/map.h>
18#include <linux/mtd/partitions.h>
19
20#include <linux/pci.h>
21#include <linux/scx200.h>
22
23#define NAME "scx200_docflash"
24
25MODULE_AUTHOR("Christer Weinigel <wingel@hack.org>");
26MODULE_DESCRIPTION("NatSemi SCx200 DOCCS Flash Driver");
27MODULE_LICENSE("GPL");
28
29static int probe = 0; /* Don't autoprobe */
30static unsigned size = 0x1000000; /* 16 MiB the whole ISA address space */
31static unsigned width = 8; /* Default to 8 bits wide */
32static char *flashtype = "cfi_probe";
33
34module_param(probe, int, 0);
35MODULE_PARM_DESC(probe, "Probe for a BIOS mapping");
36module_param(size, int, 0);
37MODULE_PARM_DESC(size, "Size of the flash mapping");
38module_param(width, int, 0);
39MODULE_PARM_DESC(width, "Data width of the flash mapping (8/16)");
40module_param(flashtype, charp, 0);
41MODULE_PARM_DESC(flashtype, "Type of MTD probe to do");
42
43static struct resource docmem = {
44 .flags = IORESOURCE_MEM,
45 .name = "NatSemi SCx200 DOCCS Flash",
46};
47
48static struct mtd_info *mymtd;
49
50#ifdef CONFIG_MTD_PARTITIONS
51static struct mtd_partition partition_info[] = {
52 {
53 .name = "DOCCS Boot kernel",
54 .offset = 0,
55 .size = 0xc0000
56 },
57 {
58 .name = "DOCCS Low BIOS",
59 .offset = 0xc0000,
60 .size = 0x40000
61 },
62 {
63 .name = "DOCCS File system",
64 .offset = 0x100000,
65 .size = ~0 /* calculate from flash size */
66 },
67 {
68 .name = "DOCCS High BIOS",
69 .offset = ~0, /* calculate from flash size */
70 .size = 0x80000
71 },
72};
73#define NUM_PARTITIONS (sizeof(partition_info)/sizeof(partition_info[0]))
74#endif
75
76
77static struct map_info scx200_docflash_map = {
78 .name = "NatSemi SCx200 DOCCS Flash",
79};
80
81static int __init init_scx200_docflash(void)
82{
83 unsigned u;
84 unsigned base;
85 unsigned ctrl;
86 unsigned pmr;
87 struct pci_dev *bridge;
88
89 printk(KERN_DEBUG NAME ": NatSemi SCx200 DOCCS Flash Driver\n");
90
91 if ((bridge = pci_find_device(PCI_VENDOR_ID_NS,
92 PCI_DEVICE_ID_NS_SCx200_BRIDGE,
93 NULL)) == NULL)
94 return -ENODEV;
95
96 /* check that we have found the configuration block */
97 if (!scx200_cb_present())
98 return -ENODEV;
99
100 if (probe) {
101 /* Try to use the present flash mapping if any */
102 pci_read_config_dword(bridge, SCx200_DOCCS_BASE, &base);
103 pci_read_config_dword(bridge, SCx200_DOCCS_CTRL, &ctrl);
104 pmr = inl(scx200_cb_base + SCx200_PMR);
105
106 if (base == 0
107 || (ctrl & 0x07000000) != 0x07000000
108 || (ctrl & 0x0007ffff) == 0)
109 return -ENODEV;
110
111 size = ((ctrl&0x1fff)<<13) + (1<<13);
112
113 for (u = size; u > 1; u >>= 1)
114 ;
115 if (u != 1)
116 return -ENODEV;
117
118 if (pmr & (1<<6))
119 width = 16;
120 else
121 width = 8;
122
123 docmem.start = base;
124 docmem.end = base + size;
125
126 if (request_resource(&iomem_resource, &docmem)) {
127 printk(KERN_ERR NAME ": unable to allocate memory for flash mapping\n");
128 return -ENOMEM;
129 }
130 } else {
131 for (u = size; u > 1; u >>= 1)
132 ;
133 if (u != 1) {
134 printk(KERN_ERR NAME ": invalid size for flash mapping\n");
135 return -EINVAL;
136 }
137
138 if (width != 8 && width != 16) {
139 printk(KERN_ERR NAME ": invalid bus width for flash mapping\n");
140 return -EINVAL;
141 }
142
143 if (allocate_resource(&iomem_resource, &docmem,
144 size,
145 0xc0000000, 0xffffffff,
146 size, NULL, NULL)) {
147 printk(KERN_ERR NAME ": unable to allocate memory for flash mapping\n");
148 return -ENOMEM;
149 }
150
151 ctrl = 0x07000000 | ((size-1) >> 13);
152
153 printk(KERN_INFO "DOCCS BASE=0x%08lx, CTRL=0x%08lx\n", (long)docmem.start, (long)ctrl);
154
155 pci_write_config_dword(bridge, SCx200_DOCCS_BASE, docmem.start);
156 pci_write_config_dword(bridge, SCx200_DOCCS_CTRL, ctrl);
157 pmr = inl(scx200_cb_base + SCx200_PMR);
158
159 if (width == 8) {
160 pmr &= ~(1<<6);
161 } else {
162 pmr |= (1<<6);
163 }
164 outl(pmr, scx200_cb_base + SCx200_PMR);
165 }
166
167 printk(KERN_INFO NAME ": DOCCS mapped at 0x%lx-0x%lx, width %d\n",
168 docmem.start, docmem.end, width);
169
170 scx200_docflash_map.size = size;
171 if (width == 8)
172 scx200_docflash_map.bankwidth = 1;
173 else
174 scx200_docflash_map.bankwidth = 2;
175
176 simple_map_init(&scx200_docflash_map);
177
178 scx200_docflash_map.phys = docmem.start;
179 scx200_docflash_map.virt = ioremap(docmem.start, scx200_docflash_map.size);
180 if (!scx200_docflash_map.virt) {
181 printk(KERN_ERR NAME ": failed to ioremap the flash\n");
182 release_resource(&docmem);
183 return -EIO;
184 }
185
186 mymtd = do_map_probe(flashtype, &scx200_docflash_map);
187 if (!mymtd) {
188 printk(KERN_ERR NAME ": unable to detect flash\n");
189 iounmap(scx200_docflash_map.virt);
190 release_resource(&docmem);
191 return -ENXIO;
192 }
193
194 if (size < mymtd->size)
195 printk(KERN_WARNING NAME ": warning, flash mapping is smaller than flash size\n");
196
197 mymtd->owner = THIS_MODULE;
198
199#ifdef CONFIG_MTD_PARTITIONS
200 partition_info[3].offset = mymtd->size-partition_info[3].size;
201 partition_info[2].size = partition_info[3].offset-partition_info[2].offset;
202 add_mtd_partitions(mymtd, partition_info, NUM_PARTITIONS);
203#else
204 add_mtd_device(mymtd);
205#endif
206 return 0;
207}
208
209static void __exit cleanup_scx200_docflash(void)
210{
211 if (mymtd) {
212#ifdef CONFIG_MTD_PARTITIONS
213 del_mtd_partitions(mymtd);
214#else
215 del_mtd_device(mymtd);
216#endif
217 map_destroy(mymtd);
218 }
219 if (scx200_docflash_map.virt) {
220 iounmap(scx200_docflash_map.virt);
221 release_resource(&docmem);
222 }
223}
224
225module_init(init_scx200_docflash);
226module_exit(cleanup_scx200_docflash);
227
228/*
229 Local variables:
230 compile-command: "make -k -C ../../.. SUBDIRS=drivers/mtd/maps modules"
231 c-basic-offset: 8
232 End:
233*/
diff --git a/drivers/mtd/maps/sharpsl-flash.c b/drivers/mtd/maps/sharpsl-flash.c
new file mode 100644
index 000000000000..b3b39cb7c608
--- /dev/null
+++ b/drivers/mtd/maps/sharpsl-flash.c
@@ -0,0 +1,101 @@
1/*
2 * sharpsl-flash.c
3 *
4 * Copyright (C) 2001 Lineo Japan, Inc.
5 * Copyright (C) 2002 SHARP
6 *
7 * $Id: sharpsl-flash.c,v 1.2 2004/11/24 20:38:06 rpurdie Exp $
8 *
9 * based on rpxlite.c,v 1.15 2001/10/02 15:05:14 dwmw2 Exp
10 * Handle mapping of the flash on the RPX Lite and CLLF boards
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 */
23
24#include <linux/module.h>
25#include <linux/types.h>
26#include <linux/kernel.h>
27#include <asm/io.h>
28#include <linux/mtd/mtd.h>
29#include <linux/mtd/map.h>
30#include <linux/mtd/partitions.h>
31
32#define WINDOW_ADDR 0x00000000
33#define WINDOW_SIZE 0x01000000
34#define BANK_WIDTH 2
35
36static struct mtd_info *mymtd;
37
38struct map_info sharpsl_map = {
39 .name = "sharpsl-flash",
40 .size = WINDOW_SIZE,
41 .bankwidth = BANK_WIDTH,
42 .phys = WINDOW_ADDR
43};
44
45static struct mtd_partition sharpsl_partitions[1] = {
46 {
47 name: "Filesystem",
48 size: 0x006d0000,
49 offset: 0x00120000
50 }
51};
52
53#define NB_OF(x) (sizeof(x)/sizeof(x[0]))
54
55int __init init_sharpsl(void)
56{
57 struct mtd_partition *parts;
58 int nb_parts = 0;
59 char *part_type = "static";
60
61 printk(KERN_NOTICE "Sharp SL series flash device: %x at %x\n", WINDOW_SIZE, WINDOW_ADDR);
62 sharpsl_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE);
63 if (!sharpsl_map.virt) {
64 printk("Failed to ioremap\n");
65 return -EIO;
66 }
67 mymtd = do_map_probe("map_rom", &sharpsl_map);
68 if (!mymtd) {
69 iounmap(sharpsl_map.virt);
70 return -ENXIO;
71 }
72
73 mymtd->owner = THIS_MODULE;
74
75 parts = sharpsl_partitions;
76 nb_parts = NB_OF(sharpsl_partitions);
77
78 printk(KERN_NOTICE "Using %s partision definition\n", part_type);
79 add_mtd_partitions(mymtd, parts, nb_parts);
80
81 return 0;
82}
83
84static void __exit cleanup_sharpsl(void)
85{
86 if (mymtd) {
87 del_mtd_partitions(mymtd);
88 map_destroy(mymtd);
89 }
90 if (sharpsl_map.virt) {
91 iounmap(sharpsl_map.virt);
92 sharpsl_map.virt = 0;
93 }
94}
95
96module_init(init_sharpsl);
97module_exit(cleanup_sharpsl);
98
99MODULE_LICENSE("GPL");
100MODULE_AUTHOR("SHARP (Original: Arnold Christensen <AKC@pel.dk>)");
101MODULE_DESCRIPTION("MTD map driver for SHARP SL series");
diff --git a/drivers/mtd/maps/solutionengine.c b/drivers/mtd/maps/solutionengine.c
new file mode 100644
index 000000000000..8ce5d897645c
--- /dev/null
+++ b/drivers/mtd/maps/solutionengine.c
@@ -0,0 +1,137 @@
1/*
2 * $Id: solutionengine.c,v 1.14 2004/09/16 23:27:14 gleixner Exp $
3 *
4 * Flash and EPROM on Hitachi Solution Engine and similar boards.
5 *
6 * (C) 2001 Red Hat, Inc.
7 *
8 * GPL'd
9 */
10
11#include <linux/module.h>
12#include <linux/types.h>
13#include <linux/kernel.h>
14#include <linux/init.h>
15#include <asm/io.h>
16#include <linux/mtd/mtd.h>
17#include <linux/mtd/map.h>
18#include <linux/mtd/partitions.h>
19#include <linux/config.h>
20#include <linux/errno.h>
21
22static struct mtd_info *flash_mtd;
23static struct mtd_info *eprom_mtd;
24
25static struct mtd_partition *parsed_parts;
26
27struct map_info soleng_eprom_map = {
28 .name = "Solution Engine EPROM",
29 .size = 0x400000,
30 .bankwidth = 4,
31};
32
33struct map_info soleng_flash_map = {
34 .name = "Solution Engine FLASH",
35 .size = 0x400000,
36 .bankwidth = 4,
37};
38
39static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
40
41#ifdef CONFIG_MTD_SUPERH_RESERVE
42static struct mtd_partition superh_se_partitions[] = {
43 /* Reserved for boot code, read-only */
44 {
45 .name = "flash_boot",
46 .offset = 0x00000000,
47 .size = CONFIG_MTD_SUPERH_RESERVE,
48 .mask_flags = MTD_WRITEABLE,
49 },
50 /* All else is writable (e.g. JFFS) */
51 {
52 .name = "Flash FS",
53 .offset = MTDPART_OFS_NXTBLK,
54 .size = MTDPART_SIZ_FULL,
55 }
56};
57#endif /* CONFIG_MTD_SUPERH_RESERVE */
58
59static int __init init_soleng_maps(void)
60{
61 int nr_parts = 0;
62
63 /* First probe at offset 0 */
64 soleng_flash_map.phys = 0;
65 soleng_flash_map.virt = (void __iomem *)P2SEGADDR(0);
66 soleng_eprom_map.phys = 0x01000000;
67 soleng_eprom_map.virt = (void __iomem *)P1SEGADDR(0x01000000);
68 simple_map_init(&soleng_eprom_map);
69 simple_map_init(&soleng_flash_map);
70
71 printk(KERN_NOTICE "Probing for flash chips at 0x00000000:\n");
72 flash_mtd = do_map_probe("cfi_probe", &soleng_flash_map);
73 if (!flash_mtd) {
74 /* Not there. Try swapping */
75 printk(KERN_NOTICE "Probing for flash chips at 0x01000000:\n");
76 soleng_flash_map.phys = 0x01000000;
77 soleng_flash_map.virt = P2SEGADDR(0x01000000);
78 soleng_eprom_map.phys = 0;
79 soleng_eprom_map.virt = P1SEGADDR(0);
80 flash_mtd = do_map_probe("cfi_probe", &soleng_flash_map);
81 if (!flash_mtd) {
82 /* Eep. */
83 printk(KERN_NOTICE "Flash chips not detected at either possible location.\n");
84 return -ENXIO;
85 }
86 }
87 printk(KERN_NOTICE "Solution Engine: Flash at 0x%08lx, EPROM at 0x%08lx\n",
88 soleng_flash_map.phys & 0x1fffffff,
89 soleng_eprom_map.phys & 0x1fffffff);
90 flash_mtd->owner = THIS_MODULE;
91
92 eprom_mtd = do_map_probe("map_rom", &soleng_eprom_map);
93 if (eprom_mtd) {
94 eprom_mtd->owner = THIS_MODULE;
95 add_mtd_device(eprom_mtd);
96 }
97
98 nr_parts = parse_mtd_partitions(flash_mtd, probes, &parsed_parts, 0);
99
100#ifdef CONFIG_MTD_SUPERH_RESERVE
101 if (nr_parts <= 0) {
102 printk(KERN_NOTICE "Using configured partition at 0x%08x.\n",
103 CONFIG_MTD_SUPERH_RESERVE);
104 parsed_parts = superh_se_partitions;
105 nr_parts = sizeof(superh_se_partitions)/sizeof(*parsed_parts);
106 }
107#endif /* CONFIG_MTD_SUPERH_RESERVE */
108
109 if (nr_parts > 0)
110 add_mtd_partitions(flash_mtd, parsed_parts, nr_parts);
111 else
112 add_mtd_device(flash_mtd);
113
114 return 0;
115}
116
117static void __exit cleanup_soleng_maps(void)
118{
119 if (eprom_mtd) {
120 del_mtd_device(eprom_mtd);
121 map_destroy(eprom_mtd);
122 }
123
124 if (parsed_parts)
125 del_mtd_partitions(flash_mtd);
126 else
127 del_mtd_device(flash_mtd);
128 map_destroy(flash_mtd);
129}
130
131module_init(init_soleng_maps);
132module_exit(cleanup_soleng_maps);
133
134MODULE_LICENSE("GPL");
135MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
136MODULE_DESCRIPTION("MTD map driver for Hitachi SolutionEngine (and similar) boards");
137
diff --git a/drivers/mtd/maps/sun_uflash.c b/drivers/mtd/maps/sun_uflash.c
new file mode 100644
index 000000000000..29091d10030a
--- /dev/null
+++ b/drivers/mtd/maps/sun_uflash.c
@@ -0,0 +1,177 @@
1/* $Id: sun_uflash.c,v 1.11 2004/11/04 13:24:15 gleixner Exp $
2 *
3 * sun_uflash - Driver implementation for user-programmable flash
4 * present on many Sun Microsystems SME boardsets.
5 *
6 * This driver does NOT provide access to the OBP-flash for
7 * safety reasons-- use <linux>/drivers/sbus/char/flash.c instead.
8 *
9 * Copyright (c) 2001 Eric Brower (ebrower@usa.net)
10 *
11 */
12
13#include <linux/kernel.h>
14#include <linux/module.h>
15#include <linux/fs.h>
16#include <linux/errno.h>
17#include <linux/init.h>
18#include <linux/ioport.h>
19#include <asm/ebus.h>
20#include <asm/oplib.h>
21#include <asm/uaccess.h>
22#include <asm/io.h>
23
24#include <linux/mtd/mtd.h>
25#include <linux/mtd/map.h>
26
27#define UFLASH_OBPNAME "flashprom"
28#define UFLASH_DEVNAME "userflash"
29
30#define UFLASH_WINDOW_SIZE 0x200000
31#define UFLASH_BUSWIDTH 1 /* EBus is 8-bit */
32
33MODULE_AUTHOR
34 ("Eric Brower <ebrower@usa.net>");
35MODULE_DESCRIPTION
36 ("User-programmable flash device on Sun Microsystems boardsets");
37MODULE_SUPPORTED_DEVICE
38 ("userflash");
39MODULE_LICENSE
40 ("GPL");
41
42static LIST_HEAD(device_list);
43struct uflash_dev {
44 char * name; /* device name */
45 struct map_info map; /* mtd map info */
46 struct mtd_info * mtd; /* mtd info */
47 struct list_head list;
48};
49
50
51struct map_info uflash_map_templ = {
52 .name = "SUNW,???-????",
53 .size = UFLASH_WINDOW_SIZE,
54 .bankwidth = UFLASH_BUSWIDTH,
55};
56
57int uflash_devinit(struct linux_ebus_device* edev)
58{
59 int iTmp, nregs;
60 struct linux_prom_registers regs[2];
61 struct uflash_dev *pdev;
62
63 iTmp = prom_getproperty(
64 edev->prom_node, "reg", (void *)regs, sizeof(regs));
65 if ((iTmp % sizeof(regs[0])) != 0) {
66 printk("%s: Strange reg property size %d\n",
67 UFLASH_DEVNAME, iTmp);
68 return -ENODEV;
69 }
70
71 nregs = iTmp / sizeof(regs[0]);
72
73 if (nregs != 1) {
74 /* Non-CFI userflash device-- once I find one we
75 * can work on supporting it.
76 */
77 printk("%s: unsupported device at 0x%lx (%d regs): " \
78 "email ebrower@usa.net\n",
79 UFLASH_DEVNAME, edev->resource[0].start, nregs);
80 return -ENODEV;
81 }
82
83 if(0 == (pdev = kmalloc(sizeof(struct uflash_dev), GFP_KERNEL))) {
84 printk("%s: unable to kmalloc new device\n", UFLASH_DEVNAME);
85 return(-ENOMEM);
86 }
87
88 /* copy defaults and tweak parameters */
89 memcpy(&pdev->map, &uflash_map_templ, sizeof(uflash_map_templ));
90 pdev->map.size = regs[0].reg_size;
91
92 iTmp = prom_getproplen(edev->prom_node, "model");
93 pdev->name = kmalloc(iTmp, GFP_KERNEL);
94 prom_getstring(edev->prom_node, "model", pdev->name, iTmp);
95 if(0 != pdev->name && 0 < strlen(pdev->name)) {
96 pdev->map.name = pdev->name;
97 }
98 pdev->map.phys = edev->resource[0].start;
99 pdev->map.virt = ioremap_nocache(edev->resource[0].start, pdev->map.size);
100 if(0 == pdev->map.virt) {
101 printk("%s: failed to map device\n", __FUNCTION__);
102 kfree(pdev->name);
103 kfree(pdev);
104 return(-1);
105 }
106
107 simple_map_init(&pdev->map);
108
109 /* MTD registration */
110 pdev->mtd = do_map_probe("cfi_probe", &pdev->map);
111 if(0 == pdev->mtd) {
112 iounmap(pdev->map.virt);
113 kfree(pdev->name);
114 kfree(pdev);
115 return(-ENXIO);
116 }
117
118 list_add(&pdev->list, &device_list);
119
120 pdev->mtd->owner = THIS_MODULE;
121
122 add_mtd_device(pdev->mtd);
123 return(0);
124}
125
126static int __init uflash_init(void)
127{
128 struct linux_ebus *ebus = NULL;
129 struct linux_ebus_device *edev = NULL;
130
131 for_each_ebus(ebus) {
132 for_each_ebusdev(edev, ebus) {
133 if (!strcmp(edev->prom_name, UFLASH_OBPNAME)) {
134 if(0 > prom_getproplen(edev->prom_node, "user")) {
135 DEBUG(2, "%s: ignoring device at 0x%lx\n",
136 UFLASH_DEVNAME, edev->resource[0].start);
137 } else {
138 uflash_devinit(edev);
139 }
140 }
141 }
142 }
143
144 if(list_empty(&device_list)) {
145 printk("%s: unable to locate device\n", UFLASH_DEVNAME);
146 return -ENODEV;
147 }
148 return(0);
149}
150
151static void __exit uflash_cleanup(void)
152{
153 struct list_head *udevlist;
154 struct uflash_dev *udev;
155
156 list_for_each(udevlist, &device_list) {
157 udev = list_entry(udevlist, struct uflash_dev, list);
158 DEBUG(2, "%s: removing device %s\n",
159 UFLASH_DEVNAME, udev->name);
160
161 if(0 != udev->mtd) {
162 del_mtd_device(udev->mtd);
163 map_destroy(udev->mtd);
164 }
165 if(0 != udev->map.virt) {
166 iounmap(udev->map.virt);
167 udev->map.virt = NULL;
168 }
169 if(0 != udev->name) {
170 kfree(udev->name);
171 }
172 kfree(udev);
173 }
174}
175
176module_init(uflash_init);
177module_exit(uflash_cleanup);
diff --git a/drivers/mtd/maps/tqm8xxl.c b/drivers/mtd/maps/tqm8xxl.c
new file mode 100644
index 000000000000..995e9991cb8d
--- /dev/null
+++ b/drivers/mtd/maps/tqm8xxl.c
@@ -0,0 +1,263 @@
1/*
2 * Handle mapping of the flash memory access routines
3 * on TQM8xxL based devices.
4 *
5 * $Id: tqm8xxl.c,v 1.13 2004/10/20 22:21:53 dwmw2 Exp $
6 *
7 * based on rpxlite.c
8 *
9 * Copyright(C) 2001 Kirk Lee <kirk@hpc.ee.ntu.edu.tw>
10 *
11 * This code is GPLed
12 *
13 */
14
15/*
16 * According to TQM8xxL hardware manual, TQM8xxL series have
17 * following flash memory organisations:
18 * | capacity | | chip type | | bank0 | | bank1 |
19 * 2MiB 512Kx16 2MiB 0
20 * 4MiB 1Mx16 4MiB 0
21 * 8MiB 1Mx16 4MiB 4MiB
22 * Thus, we choose CONFIG_MTD_CFI_I2 & CONFIG_MTD_CFI_B4 at
23 * kernel configuration.
24 */
25#include <linux/config.h>
26#include <linux/module.h>
27#include <linux/types.h>
28#include <linux/kernel.h>
29#include <linux/init.h>
30#include <asm/io.h>
31
32#include <linux/mtd/mtd.h>
33#include <linux/mtd/map.h>
34#include <linux/mtd/partitions.h>
35
36#define FLASH_ADDR 0x40000000
37#define FLASH_SIZE 0x00800000
38#define FLASH_BANK_MAX 4
39
40// trivial struct to describe partition information
41struct mtd_part_def
42{
43 int nums;
44 unsigned char *type;
45 struct mtd_partition* mtd_part;
46};
47
48//static struct mtd_info *mymtd;
49static struct mtd_info* mtd_banks[FLASH_BANK_MAX];
50static struct map_info* map_banks[FLASH_BANK_MAX];
51static struct mtd_part_def part_banks[FLASH_BANK_MAX];
52static unsigned long num_banks;
53static void __iomem *start_scan_addr;
54
55/*
56 * Here are partition information for all known TQM8xxL series devices.
57 * See include/linux/mtd/partitions.h for definition of the mtd_partition
58 * structure.
59 *
60 * The *_max_flash_size is the maximum possible mapped flash size which
61 * is not necessarily the actual flash size. It must correspond to the
62 * value specified in the mapping definition defined by the
63 * "struct map_desc *_io_desc" for the corresponding machine.
64 */
65
66#ifdef CONFIG_MTD_PARTITIONS
67/* Currently, TQM8xxL has upto 8MiB flash */
68static unsigned long tqm8xxl_max_flash_size = 0x00800000;
69
70/* partition definition for first flash bank
71 * (cf. "drivers/char/flash_config.c")
72 */
73static struct mtd_partition tqm8xxl_partitions[] = {
74 {
75 .name = "ppcboot",
76 .offset = 0x00000000,
77 .size = 0x00020000, /* 128KB */
78 .mask_flags = MTD_WRITEABLE, /* force read-only */
79 },
80 {
81 .name = "kernel", /* default kernel image */
82 .offset = 0x00020000,
83 .size = 0x000e0000,
84 .mask_flags = MTD_WRITEABLE, /* force read-only */
85 },
86 {
87 .name = "user",
88 .offset = 0x00100000,
89 .size = 0x00100000,
90 },
91 {
92 .name = "initrd",
93 .offset = 0x00200000,
94 .size = 0x00200000,
95 }
96};
97/* partition definition for second flash bank */
98static struct mtd_partition tqm8xxl_fs_partitions[] = {
99 {
100 .name = "cramfs",
101 .offset = 0x00000000,
102 .size = 0x00200000,
103 },
104 {
105 .name = "jffs",
106 .offset = 0x00200000,
107 .size = 0x00200000,
108 //.size = MTDPART_SIZ_FULL,
109 }
110};
111#endif
112
113int __init init_tqm_mtd(void)
114{
115 int idx = 0, ret = 0;
116 unsigned long flash_addr, flash_size, mtd_size = 0;
117 /* pointer to TQM8xxL board info data */
118 bd_t *bd = (bd_t *)__res;
119
120 flash_addr = bd->bi_flashstart;
121 flash_size = bd->bi_flashsize;
122
123 //request maximum flash size address space
124 start_scan_addr = ioremap(flash_addr, flash_size);
125 if (!start_scan_addr) {
126 printk(KERN_WARNING "%s:Failed to ioremap address:0x%x\n", __FUNCTION__, flash_addr);
127 return -EIO;
128 }
129
130 for (idx = 0 ; idx < FLASH_BANK_MAX ; idx++) {
131 if(mtd_size >= flash_size)
132 break;
133
134 printk(KERN_INFO "%s: chip probing count %d\n", __FUNCTION__, idx);
135
136 map_banks[idx] = (struct map_info *)kmalloc(sizeof(struct map_info), GFP_KERNEL);
137 if(map_banks[idx] == NULL) {
138 ret = -ENOMEM;
139 /* FIXME: What if some MTD devices were probed already? */
140 goto error_mem;
141 }
142
143 memset((void *)map_banks[idx], 0, sizeof(struct map_info));
144 map_banks[idx]->name = (char *)kmalloc(16, GFP_KERNEL);
145
146 if (!map_banks[idx]->name) {
147 ret = -ENOMEM;
148 /* FIXME: What if some MTD devices were probed already? */
149 goto error_mem;
150 }
151 sprintf(map_banks[idx]->name, "TQM8xxL%d", idx);
152
153 map_banks[idx]->size = flash_size;
154 map_banks[idx]->bankwidth = 4;
155
156 simple_map_init(map_banks[idx]);
157
158 map_banks[idx]->virt = start_scan_addr;
159 map_banks[idx]->phys = flash_addr;
160 /* FIXME: This looks utterly bogus, but I'm trying to
161 preserve the behaviour of the original (shown here)...
162
163 map_banks[idx]->map_priv_1 =
164 start_scan_addr + ((idx > 0) ?
165 (mtd_banks[idx-1] ? mtd_banks[idx-1]->size : 0) : 0);
166 */
167
168 if (idx && mtd_banks[idx-1]) {
169 map_banks[idx]->virt += mtd_banks[idx-1]->size;
170 map_banks[idx]->phys += mtd_banks[idx-1]->size;
171 }
172
173 //start to probe flash chips
174 mtd_banks[idx] = do_map_probe("cfi_probe", map_banks[idx]);
175
176 if (mtd_banks[idx]) {
177 mtd_banks[idx]->owner = THIS_MODULE;
178 mtd_size += mtd_banks[idx]->size;
179 num_banks++;
180
181 printk(KERN_INFO "%s: bank%d, name:%s, size:%dbytes \n", __FUNCTION__, num_banks,
182 mtd_banks[idx]->name, mtd_banks[idx]->size);
183 }
184 }
185
186 /* no supported flash chips found */
187 if (!num_banks) {
188 printk(KERN_NOTICE "TQM8xxL: No support flash chips found!\n");
189 ret = -ENXIO;
190 goto error_mem;
191 }
192
193#ifdef CONFIG_MTD_PARTITIONS
194 /*
195 * Select Static partition definitions
196 */
197 part_banks[0].mtd_part = tqm8xxl_partitions;
198 part_banks[0].type = "Static image";
199 part_banks[0].nums = ARRAY_SIZE(tqm8xxl_partitions);
200
201 part_banks[1].mtd_part = tqm8xxl_fs_partitions;
202 part_banks[1].type = "Static file system";
203 part_banks[1].nums = ARRAY_SIZE(tqm8xxl_fs_partitions);
204
205 for(idx = 0; idx < num_banks ; idx++) {
206 if (part_banks[idx].nums == 0) {
207 printk(KERN_NOTICE "TQM flash%d: no partition info available, registering whole flash at once\n", idx);
208 add_mtd_device(mtd_banks[idx]);
209 } else {
210 printk(KERN_NOTICE "TQM flash%d: Using %s partition definition\n",
211 idx, part_banks[idx].type);
212 add_mtd_partitions(mtd_banks[idx], part_banks[idx].mtd_part,
213 part_banks[idx].nums);
214 }
215 }
216#else
217 printk(KERN_NOTICE "TQM flash: registering %d whole flash banks at once\n", num_banks);
218 for(idx = 0 ; idx < num_banks ; idx++)
219 add_mtd_device(mtd_banks[idx]);
220#endif
221 return 0;
222error_mem:
223 for(idx = 0 ; idx < FLASH_BANK_MAX ; idx++) {
224 if(map_banks[idx] != NULL) {
225 if(map_banks[idx]->name != NULL) {
226 kfree(map_banks[idx]->name);
227 map_banks[idx]->name = NULL;
228 }
229 kfree(map_banks[idx]);
230 map_banks[idx] = NULL;
231 }
232 }
233error:
234 iounmap(start_scan_addr);
235 return ret;
236}
237
238static void __exit cleanup_tqm_mtd(void)
239{
240 unsigned int idx = 0;
241 for(idx = 0 ; idx < num_banks ; idx++) {
242 /* destroy mtd_info previously allocated */
243 if (mtd_banks[idx]) {
244 del_mtd_partitions(mtd_banks[idx]);
245 map_destroy(mtd_banks[idx]);
246 }
247 /* release map_info not used anymore */
248 kfree(map_banks[idx]->name);
249 kfree(map_banks[idx]);
250 }
251
252 if (start_scan_addr) {
253 iounmap(start_scan_addr);
254 start_scan_addr = 0;
255 }
256}
257
258module_init(init_tqm_mtd);
259module_exit(cleanup_tqm_mtd);
260
261MODULE_LICENSE("GPL");
262MODULE_AUTHOR("Kirk Lee <kirk@hpc.ee.ntu.edu.tw>");
263MODULE_DESCRIPTION("MTD map driver for TQM8xxL boards");
diff --git a/drivers/mtd/maps/ts5500_flash.c b/drivers/mtd/maps/ts5500_flash.c
new file mode 100644
index 000000000000..3ebd90f56503
--- /dev/null
+++ b/drivers/mtd/maps/ts5500_flash.c
@@ -0,0 +1,141 @@
1/*
2 * ts5500_flash.c -- MTD map driver for Technology Systems TS-5500 board
3 *
4 * Copyright (C) 2004 Sean Young <sean@mess.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19 *
20 * Note:
21 * - In order for detection to work, jumper 3 must be set.
22 * - Drive A and B use a proprietary FTL from General Software which isn't
23 * supported as of yet so standard drives can't be mounted; you can create
24 * your own (e.g. jffs) file system.
25 * - If you have created your own jffs file system and the bios overwrites
26 * it during boot, try disabling Drive A: and B: in the boot order.
27 *
28 * $Id: ts5500_flash.c,v 1.2 2004/11/28 09:40:40 dwmw2 Exp $
29 */
30
31#include <linux/config.h>
32#include <linux/module.h>
33#include <linux/types.h>
34#include <linux/kernel.h>
35#include <linux/init.h>
36#include <linux/mtd/mtd.h>
37#include <linux/mtd/map.h>
38
39#ifdef CONFIG_MTD_PARTITIONS
40#include <linux/mtd/partitions.h>
41#endif
42
43#define WINDOW_ADDR 0x09400000
44#define WINDOW_SIZE 0x00200000
45
46static struct map_info ts5500_map = {
47 .name = "TS-5500 Flash",
48 .size = WINDOW_SIZE,
49 .bankwidth = 1,
50 .phys = WINDOW_ADDR
51};
52
53#ifdef CONFIG_MTD_PARTITIONS
54static struct mtd_partition ts5500_partitions[] = {
55 {
56 .name = "Drive A",
57 .offset = 0,
58 .size = 0x0e0000
59 },
60 {
61 .name = "BIOS",
62 .offset = 0x0e0000,
63 .size = 0x020000,
64 },
65 {
66 .name = "Drive B",
67 .offset = 0x100000,
68 .size = 0x100000
69 }
70};
71
72#define NUM_PARTITIONS (sizeof(ts5500_partitions)/sizeof(struct mtd_partition))
73
74#endif
75
76static struct mtd_info *mymtd;
77
78static int __init init_ts5500_map(void)
79{
80 int rc = 0;
81
82 ts5500_map.virt = ioremap_nocache(ts5500_map.phys, ts5500_map.size);
83
84 if(!ts5500_map.virt) {
85 printk(KERN_ERR "Failed to ioremap_nocache\n");
86 rc = -EIO;
87 goto err_out_ioremap;
88 }
89
90 simple_map_init(&ts5500_map);
91
92 mymtd = do_map_probe("jedec_probe", &ts5500_map);
93 if(!mymtd)
94 mymtd = do_map_probe("map_rom", &ts5500_map);
95
96 if(!mymtd) {
97 rc = -ENXIO;
98 goto err_out_map;
99 }
100
101 mymtd->owner = THIS_MODULE;
102#ifdef CONFIG_MTD_PARTITIONS
103 add_mtd_partitions(mymtd, ts5500_partitions, NUM_PARTITIONS);
104#else
105 add_mtd_device(mymtd);
106#endif
107
108 return 0;
109
110err_out_map:
111 map_destroy(mymtd);
112err_out_ioremap:
113 iounmap(ts5500_map.virt);
114
115 return rc;
116}
117
118static void __exit cleanup_ts5500_map(void)
119{
120 if (mymtd) {
121#ifdef CONFIG_MTD_PARTITIONS
122 del_mtd_partitions(mymtd);
123#else
124 del_mtd_device(mymtd);
125#endif
126 map_destroy(mymtd);
127 }
128
129 if (ts5500_map.virt) {
130 iounmap(ts5500_map.virt);
131 ts5500_map.virt = NULL;
132 }
133}
134
135module_init(init_ts5500_map);
136module_exit(cleanup_ts5500_map);
137
138MODULE_LICENSE("GPL");
139MODULE_AUTHOR("Sean Young <sean@mess.org>");
140MODULE_DESCRIPTION("MTD map driver for Techology Systems TS-5500 board");
141
diff --git a/drivers/mtd/maps/tsunami_flash.c b/drivers/mtd/maps/tsunami_flash.c
new file mode 100644
index 000000000000..170d71239e5e
--- /dev/null
+++ b/drivers/mtd/maps/tsunami_flash.c
@@ -0,0 +1,108 @@
1/*
2 * tsunami_flash.c
3 *
4 * flash chip on alpha ds10...
5 * $Id: tsunami_flash.c,v 1.9 2004/07/14 09:52:55 dwmw2 Exp $
6 */
7#include <asm/io.h>
8#include <asm/core_tsunami.h>
9#include <linux/init.h>
10#include <linux/mtd/map.h>
11#include <linux/mtd/mtd.h>
12
13#define FLASH_ENABLE_PORT 0x00C00001
14#define FLASH_ENABLE_BYTE 0x01
15#define FLASH_DISABLE_BYTE 0x00
16
17#define MAX_TIG_FLASH_SIZE (12*1024*1024)
18static inline map_word tsunami_flash_read8(struct map_info *map, unsigned long offset)
19{
20 map_word val;
21 val.x[0] = tsunami_tig_readb(offset);
22 return val;
23}
24
25static void tsunami_flash_write8(struct map_info *map, map_word value, unsigned long offset)
26{
27 tsunami_tig_writeb(value.x[0], offset);
28}
29
30static void tsunami_flash_copy_from(
31 struct map_info *map, void *addr, unsigned long offset, ssize_t len)
32{
33 unsigned char *dest;
34 dest = addr;
35 while(len && (offset < MAX_TIG_FLASH_SIZE)) {
36 *dest = tsunami_tig_readb(offset);
37 offset++;
38 dest++;
39 len--;
40 }
41}
42
43static void tsunami_flash_copy_to(
44 struct map_info *map, unsigned long offset,
45 const void *addr, ssize_t len)
46{
47 const unsigned char *src;
48 src = addr;
49 while(len && (offset < MAX_TIG_FLASH_SIZE)) {
50 tsunami_tig_writeb(*src, offset);
51 offset++;
52 src++;
53 len--;
54 }
55}
56
57/*
58 * Deliberately don't provide operations wider than 8 bits. I don't
59 * have then and it scares me to think how you could mess up if
60 * you tried to use them. Buswidth is correctly so I'm safe.
61 */
62static struct map_info tsunami_flash_map = {
63 .name = "flash chip on the Tsunami TIG bus",
64 .size = MAX_TIG_FLASH_SIZE,
65 .phys = NO_XIP;
66 .bankwidth = 1,
67 .read = tsunami_flash_read8,
68 .copy_from = tsunami_flash_copy_from,
69 .write = tsunami_flash_write8,
70 .copy_to = tsunami_flash_copy_to,
71};
72
73static struct mtd_info *tsunami_flash_mtd;
74
75static void __exit cleanup_tsunami_flash(void)
76{
77 struct mtd_info *mtd;
78 mtd = tsunami_flash_mtd;
79 if (mtd) {
80 del_mtd_device(mtd);
81 map_destroy(mtd);
82 }
83 tsunami_flash_mtd = 0;
84}
85
86
87static int __init init_tsunami_flash(void)
88{
89 static const char *rom_probe_types[] = { "cfi_probe", "jedec_probe", "map_rom", NULL };
90 char **type;
91
92 tsunami_tig_writeb(FLASH_ENABLE_BYTE, FLASH_ENABLE_PORT);
93
94 tsunami_flash_mtd = 0;
95 type = rom_probe_types;
96 for(; !tsunami_flash_mtd && *type; type++) {
97 tsunami_flash_mtd = do_map_probe(*type, &tsunami_flash_map);
98 }
99 if (tsunami_flash_mtd) {
100 tsunami_flash_mtd->owner = THIS_MODULE;
101 add_mtd_device(tsunami_flash_mtd);
102 return 0;
103 }
104 return -ENXIO;
105}
106
107module_init(init_tsunami_flash);
108module_exit(cleanup_tsunami_flash);
diff --git a/drivers/mtd/maps/uclinux.c b/drivers/mtd/maps/uclinux.c
new file mode 100644
index 000000000000..811d92e5f5b1
--- /dev/null
+++ b/drivers/mtd/maps/uclinux.c
@@ -0,0 +1,127 @@
1/****************************************************************************/
2
3/*
4 * uclinux.c -- generic memory mapped MTD driver for uclinux
5 *
6 * (C) Copyright 2002, Greg Ungerer (gerg@snapgear.com)
7 *
8 * $Id: uclinux.c,v 1.10 2005/01/05 18:05:13 dwmw2 Exp $
9 */
10
11/****************************************************************************/
12
13#include <linux/config.h>
14#include <linux/module.h>
15#include <linux/types.h>
16#include <linux/init.h>
17#include <linux/kernel.h>
18#include <linux/fs.h>
19#include <linux/major.h>
20#include <linux/root_dev.h>
21#include <linux/mtd/mtd.h>
22#include <linux/mtd/map.h>
23#include <linux/mtd/partitions.h>
24#include <asm/io.h>
25
26/****************************************************************************/
27
28
29/****************************************************************************/
30
31struct map_info uclinux_ram_map = {
32 .name = "RAM",
33};
34
35struct mtd_info *uclinux_ram_mtdinfo;
36
37/****************************************************************************/
38
39struct mtd_partition uclinux_romfs[] = {
40 { .name = "ROMfs" }
41};
42
43#define NUM_PARTITIONS (sizeof(uclinux_romfs) / sizeof(uclinux_romfs[0]))
44
45/****************************************************************************/
46
47int uclinux_point(struct mtd_info *mtd, loff_t from, size_t len,
48 size_t *retlen, u_char **mtdbuf)
49{
50 struct map_info *map = mtd->priv;
51 *mtdbuf = (u_char *) (map->virt + ((int) from));
52 *retlen = len;
53 return(0);
54}
55
56/****************************************************************************/
57
58int __init uclinux_mtd_init(void)
59{
60 struct mtd_info *mtd;
61 struct map_info *mapp;
62 extern char _ebss;
63
64 mapp = &uclinux_ram_map;
65 mapp->phys = (unsigned long) &_ebss;
66 mapp->size = PAGE_ALIGN(*((unsigned long *)((&_ebss) + 8)));
67 mapp->bankwidth = 4;
68
69 printk("uclinux[mtd]: RAM probe address=0x%x size=0x%x\n",
70 (int) mapp->map_priv_2, (int) mapp->size);
71
72 mapp->virt = ioremap_nocache(mapp->phys, mapp->size);
73
74 if (mapp->virt == 0) {
75 printk("uclinux[mtd]: ioremap_nocache() failed\n");
76 return(-EIO);
77 }
78
79 simple_map_init(mapp);
80
81 mtd = do_map_probe("map_ram", mapp);
82 if (!mtd) {
83 printk("uclinux[mtd]: failed to find a mapping?\n");
84 iounmap(mapp->virt);
85 return(-ENXIO);
86 }
87
88 mtd->owner = THIS_MODULE;
89 mtd->point = uclinux_point;
90 mtd->priv = mapp;
91
92 uclinux_ram_mtdinfo = mtd;
93 add_mtd_partitions(mtd, uclinux_romfs, NUM_PARTITIONS);
94
95 printk("uclinux[mtd]: set %s to be root filesystem\n",
96 uclinux_romfs[0].name);
97 ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, 0);
98 put_mtd_device(mtd);
99
100 return(0);
101}
102
103/****************************************************************************/
104
105void __exit uclinux_mtd_cleanup(void)
106{
107 if (uclinux_ram_mtdinfo) {
108 del_mtd_partitions(uclinux_ram_mtdinfo);
109 map_destroy(uclinux_ram_mtdinfo);
110 uclinux_ram_mtdinfo = NULL;
111 }
112 if (uclinux_ram_map.map_priv_1) {
113 iounmap((void *) uclinux_ram_map.virt);
114 uclinux_ram_map.virt = 0;
115 }
116}
117
118/****************************************************************************/
119
120module_init(uclinux_mtd_init);
121module_exit(uclinux_mtd_cleanup);
122
123MODULE_LICENSE("GPL");
124MODULE_AUTHOR("Greg Ungerer <gerg@snapgear.com>");
125MODULE_DESCRIPTION("Generic RAM based MTD for uClinux");
126
127/****************************************************************************/
diff --git a/drivers/mtd/maps/vmax301.c b/drivers/mtd/maps/vmax301.c
new file mode 100644
index 000000000000..c8c74110ed1b
--- /dev/null
+++ b/drivers/mtd/maps/vmax301.c
@@ -0,0 +1,198 @@
1// $Id: vmax301.c,v 1.30 2004/07/12 22:38:29 dwmw2 Exp $
2/* ######################################################################
3
4 Tempustech VMAX SBC301 MTD Driver.
5
6 The VMAx 301 is a SBC based on . It
7 comes with three builtin AMD 29F016B flash chips and a socket for SRAM or
8 more flash. Each unit has it's own 8k mapping into a settable region
9 (0xD8000). There are two 8k mappings for each MTD, the first is always set
10 to the lower 8k of the device the second is paged. Writing a 16 bit page
11 value to anywhere in the first 8k will cause the second 8k to page around.
12
13 To boot the device a bios extension must be installed into the first 8k
14 of flash that is smart enough to copy itself down, page in the rest of
15 itself and begin executing.
16
17 ##################################################################### */
18
19#include <linux/module.h>
20#include <linux/slab.h>
21#include <linux/ioport.h>
22#include <linux/init.h>
23#include <linux/spinlock.h>
24#include <asm/io.h>
25
26#include <linux/mtd/map.h>
27#include <linux/mtd/mtd.h>
28
29
30#define WINDOW_START 0xd8000
31#define WINDOW_LENGTH 0x2000
32#define WINDOW_SHIFT 25
33#define WINDOW_MASK 0x1FFF
34
35/* Actually we could use two spinlocks, but we'd have to have
36 more private space in the struct map_info. We lose a little
37 performance like this, but we'd probably lose more by having
38 the extra indirection from having one of the map->map_priv
39 fields pointing to yet another private struct.
40*/
41static DEFINE_SPINLOCK(vmax301_spin);
42
43static void __vmax301_page(struct map_info *map, unsigned long page)
44{
45 writew(page, map->map_priv_2 - WINDOW_LENGTH);
46 map->map_priv_1 = page;
47}
48
49static inline void vmax301_page(struct map_info *map,
50 unsigned long ofs)
51{
52 unsigned long page = (ofs >> WINDOW_SHIFT);
53 if (map->map_priv_1 != page)
54 __vmax301_page(map, page);
55}
56
57static map_word vmax301_read8(struct map_info *map, unsigned long ofs)
58{
59 map_word ret;
60 spin_lock(&vmax301_spin);
61 vmax301_page(map, ofs);
62 ret.x[0] = readb(map->map_priv_2 + (ofs & WINDOW_MASK));
63 spin_unlock(&vmax301_spin);
64 return ret;
65}
66
67static void vmax301_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
68{
69 while(len) {
70 unsigned long thislen = len;
71 if (len > (WINDOW_LENGTH - (from & WINDOW_MASK)))
72 thislen = WINDOW_LENGTH-(from & WINDOW_MASK);
73 spin_lock(&vmax301_spin);
74 vmax301_page(map, from);
75 memcpy_fromio(to, map->map_priv_2 + from, thislen);
76 spin_unlock(&vmax301_spin);
77 to += thislen;
78 from += thislen;
79 len -= thislen;
80 }
81}
82
83static void vmax301_write8(struct map_info *map, map_word d, unsigned long adr)
84{
85 spin_lock(&vmax301_spin);
86 vmax301_page(map, adr);
87 writeb(d.x[0], map->map_priv_2 + (adr & WINDOW_MASK));
88 spin_unlock(&vmax301_spin);
89}
90
91static void vmax301_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
92{
93 while(len) {
94 unsigned long thislen = len;
95 if (len > (WINDOW_LENGTH - (to & WINDOW_MASK)))
96 thislen = WINDOW_LENGTH-(to & WINDOW_MASK);
97
98 spin_lock(&vmax301_spin);
99 vmax301_page(map, to);
100 memcpy_toio(map->map_priv_2 + to, from, thislen);
101 spin_unlock(&vmax301_spin);
102 to += thislen;
103 from += thislen;
104 len -= thislen;
105 }
106}
107
108static struct map_info vmax_map[2] = {
109 {
110 .name = "VMAX301 Internal Flash",
111 .phys = NO_XIP,
112 .size = 3*2*1024*1024,
113 .bankwidth = 1,
114 .read = vmax301_read8,
115 .copy_from = vmax301_copy_from,
116 .write = vmax301_write8,
117 .copy_to = vmax301_copy_to,
118 .map_priv_1 = WINDOW_START + WINDOW_LENGTH,
119 .map_priv_2 = 0xFFFFFFFF
120 },
121 {
122 .name = "VMAX301 Socket",
123 .phys = NO_XIP,
124 .size = 0,
125 .bankwidth = 1,
126 .read = vmax301_read8,
127 .copy_from = vmax301_copy_from,
128 .write = vmax301_write8,
129 .copy_to = vmax301_copy_to,
130 .map_priv_1 = WINDOW_START + (3*WINDOW_LENGTH),
131 .map_priv_2 = 0xFFFFFFFF
132 }
133};
134
135static struct mtd_info *vmax_mtd[2] = {NULL, NULL};
136
137static void __exit cleanup_vmax301(void)
138{
139 int i;
140
141 for (i=0; i<2; i++) {
142 if (vmax_mtd[i]) {
143 del_mtd_device(vmax_mtd[i]);
144 map_destroy(vmax_mtd[i]);
145 }
146 }
147 iounmap((void *)vmax_map[0].map_priv_1 - WINDOW_START);
148}
149
150int __init init_vmax301(void)
151{
152 int i;
153 unsigned long iomapadr;
154 // Print out our little header..
155 printk("Tempustech VMAX 301 MEM:0x%x-0x%x\n",WINDOW_START,
156 WINDOW_START+4*WINDOW_LENGTH);
157
158 iomapadr = (unsigned long)ioremap(WINDOW_START, WINDOW_LENGTH*4);
159 if (!iomapadr) {
160 printk("Failed to ioremap memory region\n");
161 return -EIO;
162 }
163 /* Put the address in the map's private data area.
164 We store the actual MTD IO address rather than the
165 address of the first half, because it's used more
166 often.
167 */
168 vmax_map[0].map_priv_2 = iomapadr + WINDOW_START;
169 vmax_map[1].map_priv_2 = iomapadr + (3*WINDOW_START);
170
171 for (i=0; i<2; i++) {
172 vmax_mtd[i] = do_map_probe("cfi_probe", &vmax_map[i]);
173 if (!vmax_mtd[i])
174 vmax_mtd[i] = do_map_probe("jedec", &vmax_map[i]);
175 if (!vmax_mtd[i])
176 vmax_mtd[i] = do_map_probe("map_ram", &vmax_map[i]);
177 if (!vmax_mtd[i])
178 vmax_mtd[i] = do_map_probe("map_rom", &vmax_map[i]);
179 if (vmax_mtd[i]) {
180 vmax_mtd[i]->owner = THIS_MODULE;
181 add_mtd_device(vmax_mtd[i]);
182 }
183 }
184
185 if (!vmax_mtd[1] && !vmax_mtd[2]) {
186 iounmap((void *)iomapadr);
187 return -ENXIO;
188 }
189
190 return 0;
191}
192
193module_init(init_vmax301);
194module_exit(cleanup_vmax301);
195
196MODULE_LICENSE("GPL");
197MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
198MODULE_DESCRIPTION("MTD map driver for Tempustech VMAX SBC301 board");
diff --git a/drivers/mtd/maps/walnut.c b/drivers/mtd/maps/walnut.c
new file mode 100644
index 000000000000..d6137b1b5670
--- /dev/null
+++ b/drivers/mtd/maps/walnut.c
@@ -0,0 +1,122 @@
1/*
2 * $Id: walnut.c,v 1.2 2004/12/10 12:07:42 holindho Exp $
3 *
4 * Mapping for Walnut flash
5 * (used ebony.c as a "framework")
6 *
7 * Heikki Lindholm <holindho@infradead.org>
8 *
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
14 */
15
16#include <linux/module.h>
17#include <linux/types.h>
18#include <linux/kernel.h>
19#include <linux/init.h>
20#include <linux/mtd/mtd.h>
21#include <linux/mtd/map.h>
22#include <linux/mtd/partitions.h>
23#include <linux/config.h>
24#include <linux/version.h>
25#include <asm/io.h>
26#include <asm/ibm4xx.h>
27#include <platforms/4xx/walnut.h>
28
29/* these should be in platforms/4xx/walnut.h ? */
30#define WALNUT_FLASH_ONBD_N(x) (x & 0x02)
31#define WALNUT_FLASH_SRAM_SEL(x) (x & 0x01)
32#define WALNUT_FLASH_LOW 0xFFF00000
33#define WALNUT_FLASH_HIGH 0xFFF80000
34#define WALNUT_FLASH_SIZE 0x80000
35
36static struct mtd_info *flash;
37
38static struct map_info walnut_map = {
39 .name = "Walnut flash",
40 .size = WALNUT_FLASH_SIZE,
41 .bankwidth = 1,
42};
43
44/* Actually, OpenBIOS is the last 128 KiB of the flash - better
45 * partitioning could be made */
46static struct mtd_partition walnut_partitions[] = {
47 {
48 .name = "OpenBIOS",
49 .offset = 0x0,
50 .size = WALNUT_FLASH_SIZE,
51 /*.mask_flags = MTD_WRITEABLE, */ /* force read-only */
52 }
53};
54
55int __init init_walnut(void)
56{
57 u8 fpga_brds1;
58 void *fpga_brds1_adr;
59 void *fpga_status_adr;
60 unsigned long flash_base;
61
62 /* this should already be mapped (platform/4xx/walnut.c) */
63 fpga_status_adr = ioremap(WALNUT_FPGA_BASE, 8);
64 if (!fpga_status_adr)
65 return -ENOMEM;
66
67 fpga_brds1_adr = fpga_status_adr+5;
68 fpga_brds1 = readb(fpga_brds1_adr);
69 /* iounmap(fpga_status_adr); */
70
71 if (WALNUT_FLASH_ONBD_N(fpga_brds1)) {
72 printk("The on-board flash is disabled (U79 sw 5)!");
73 return -EIO;
74 }
75 if (WALNUT_FLASH_SRAM_SEL(fpga_brds1))
76 flash_base = WALNUT_FLASH_LOW;
77 else
78 flash_base = WALNUT_FLASH_HIGH;
79
80 walnut_map.phys = flash_base;
81 walnut_map.virt =
82 (void __iomem *)ioremap(flash_base, walnut_map.size);
83
84 if (!walnut_map.virt) {
85 printk("Failed to ioremap flash.\n");
86 return -EIO;
87 }
88
89 simple_map_init(&walnut_map);
90
91 flash = do_map_probe("jedec_probe", &walnut_map);
92 if (flash) {
93 flash->owner = THIS_MODULE;
94 add_mtd_partitions(flash, walnut_partitions,
95 ARRAY_SIZE(walnut_partitions));
96 } else {
97 printk("map probe failed for flash\n");
98 return -ENXIO;
99 }
100
101 return 0;
102}
103
104static void __exit cleanup_walnut(void)
105{
106 if (flash) {
107 del_mtd_partitions(flash);
108 map_destroy(flash);
109 }
110
111 if (walnut_map.virt) {
112 iounmap((void *)walnut_map.virt);
113 walnut_map.virt = 0;
114 }
115}
116
117module_init(init_walnut);
118module_exit(cleanup_walnut);
119
120MODULE_LICENSE("GPL");
121MODULE_AUTHOR("Heikki Lindholm <holindho@infradead.org>");
122MODULE_DESCRIPTION("MTD map and partitions for IBM 405GP Walnut boards");
diff --git a/drivers/mtd/maps/wr_sbc82xx_flash.c b/drivers/mtd/maps/wr_sbc82xx_flash.c
new file mode 100644
index 000000000000..82b887b05707
--- /dev/null
+++ b/drivers/mtd/maps/wr_sbc82xx_flash.c
@@ -0,0 +1,181 @@
1/*
2 * $Id: wr_sbc82xx_flash.c,v 1.7 2004/11/04 13:24:15 gleixner Exp $
3 *
4 * Map for flash chips on Wind River PowerQUICC II SBC82xx board.
5 *
6 * Copyright (C) 2004 Red Hat, Inc.
7 *
8 * Author: David Woodhouse <dwmw2@infradead.org>
9 *
10 */
11
12#include <linux/module.h>
13#include <linux/types.h>
14#include <linux/kernel.h>
15#include <linux/init.h>
16#include <linux/slab.h>
17#include <asm/io.h>
18#include <linux/mtd/mtd.h>
19#include <linux/mtd/map.h>
20#include <linux/config.h>
21#include <linux/mtd/partitions.h>
22
23#include <asm/immap_cpm2.h>
24
25static struct mtd_info *sbcmtd[3];
26static struct mtd_partition *sbcmtd_parts[3];
27
28struct map_info sbc82xx_flash_map[3] = {
29 {.name = "Boot flash"},
30 {.name = "Alternate boot flash"},
31 {.name = "User flash"}
32};
33
34static struct mtd_partition smallflash_parts[] = {
35 {
36 .name = "space",
37 .size = 0x100000,
38 .offset = 0,
39 }, {
40 .name = "bootloader",
41 .size = MTDPART_SIZ_FULL,
42 .offset = MTDPART_OFS_APPEND,
43 }
44};
45
46static struct mtd_partition bigflash_parts[] = {
47 {
48 .name = "bootloader",
49 .size = 0x00100000,
50 .offset = 0,
51 }, {
52 .name = "file system",
53 .size = 0x01f00000,
54 .offset = MTDPART_OFS_APPEND,
55 }, {
56 .name = "boot config",
57 .size = 0x00100000,
58 .offset = MTDPART_OFS_APPEND,
59 }, {
60 .name = "space",
61 .size = 0x01f00000,
62 .offset = MTDPART_OFS_APPEND,
63 }
64};
65
66static const char *part_probes[] __initdata = {"cmdlinepart", "RedBoot", NULL};
67
68#define init_sbc82xx_one_flash(map, br, or) \
69do { \
70 (map).phys = (br & 1) ? (br & 0xffff8000) : 0; \
71 (map).size = (br & 1) ? (~(or & 0xffff8000) + 1) : 0; \
72 switch (br & 0x00001800) { \
73 case 0x00000000: \
74 case 0x00000800: (map).bankwidth = 1; break; \
75 case 0x00001000: (map).bankwidth = 2; break; \
76 case 0x00001800: (map).bankwidth = 4; break; \
77 } \
78} while (0);
79
80int __init init_sbc82xx_flash(void)
81{
82 volatile memctl_cpm2_t *mc = &cpm2_immr->im_memctl;
83 int bigflash;
84 int i;
85
86#ifdef CONFIG_SBC8560
87 mc = ioremap(0xff700000 + 0x5000, sizeof(memctl_cpm2_t));
88#else
89 mc = &cpm2_immr->im_memctl;
90#endif
91
92 bigflash = 1;
93 if ((mc->memc_br0 & 0x00001800) == 0x00001800)
94 bigflash = 0;
95
96 init_sbc82xx_one_flash(sbc82xx_flash_map[0], mc->memc_br0, mc->memc_or0);
97 init_sbc82xx_one_flash(sbc82xx_flash_map[1], mc->memc_br6, mc->memc_or6);
98 init_sbc82xx_one_flash(sbc82xx_flash_map[2], mc->memc_br1, mc->memc_or1);
99
100#ifdef CONFIG_SBC8560
101 iounmap((void *) mc);
102#endif
103
104 for (i=0; i<3; i++) {
105 int8_t flashcs[3] = { 0, 6, 1 };
106 int nr_parts;
107
108 printk(KERN_NOTICE "PowerQUICC II %s (%ld MiB on CS%d",
109 sbc82xx_flash_map[i].name,
110 (sbc82xx_flash_map[i].size >> 20),
111 flashcs[i]);
112 if (!sbc82xx_flash_map[i].phys) {
113 /* We know it can't be at zero. */
114 printk("): disabled by bootloader.\n");
115 continue;
116 }
117 printk(" at %08lx)\n", sbc82xx_flash_map[i].phys);
118
119 sbc82xx_flash_map[i].virt = ioremap(sbc82xx_flash_map[i].phys, sbc82xx_flash_map[i].size);
120
121 if (!sbc82xx_flash_map[i].virt) {
122 printk("Failed to ioremap\n");
123 continue;
124 }
125
126 simple_map_init(&sbc82xx_flash_map[i]);
127
128 sbcmtd[i] = do_map_probe("cfi_probe", &sbc82xx_flash_map[i]);
129
130 if (!sbcmtd[i])
131 continue;
132
133 sbcmtd[i]->owner = THIS_MODULE;
134
135 nr_parts = parse_mtd_partitions(sbcmtd[i], part_probes,
136 &sbcmtd_parts[i], 0);
137 if (nr_parts > 0) {
138 add_mtd_partitions (sbcmtd[i], sbcmtd_parts[i], nr_parts);
139 continue;
140 }
141
142 /* No partitioning detected. Use default */
143 if (i == 2) {
144 add_mtd_device(sbcmtd[i]);
145 } else if (i == bigflash) {
146 add_mtd_partitions (sbcmtd[i], bigflash_parts, ARRAY_SIZE(bigflash_parts));
147 } else {
148 add_mtd_partitions (sbcmtd[i], smallflash_parts, ARRAY_SIZE(smallflash_parts));
149 }
150 }
151 return 0;
152}
153
154static void __exit cleanup_sbc82xx_flash(void)
155{
156 int i;
157
158 for (i=0; i<3; i++) {
159 if (!sbcmtd[i])
160 continue;
161
162 if (i<2 || sbcmtd_parts[i])
163 del_mtd_partitions(sbcmtd[i]);
164 else
165 del_mtd_device(sbcmtd[i]);
166
167 kfree(sbcmtd_parts[i]);
168 map_destroy(sbcmtd[i]);
169
170 iounmap((void *)sbc82xx_flash_map[i].virt);
171 sbc82xx_flash_map[i].virt = 0;
172 }
173}
174
175module_init(init_sbc82xx_flash);
176module_exit(cleanup_sbc82xx_flash);
177
178
179MODULE_LICENSE("GPL");
180MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
181MODULE_DESCRIPTION("Flash map driver for WindRiver PowerQUICC II");