aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/maps
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/maps')
-rw-r--r--drivers/mtd/maps/Kconfig16
-rw-r--r--drivers/mtd/maps/Makefile1
-rw-r--r--drivers/mtd/maps/dilnetpc.c496
3 files changed, 0 insertions, 513 deletions
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
index 888e6842b698..b6a369a07dbc 100644
--- a/drivers/mtd/maps/Kconfig
+++ b/drivers/mtd/maps/Kconfig
@@ -249,22 +249,6 @@ config MTD_LANTIQ
249 help 249 help
250 Support for NOR flash attached to the Lantiq SoC's External Bus Unit. 250 Support for NOR flash attached to the Lantiq SoC's External Bus Unit.
251 251
252config MTD_DILNETPC
253 tristate "CFI Flash device mapped on DIL/Net PC"
254 depends on X86 && MTD_CFI_INTELEXT && BROKEN
255 help
256 MTD map driver for SSV DIL/Net PC Boards "DNP" and "ADNP".
257 For details, see <http://www.ssv-embedded.de/ssv/pc104/p169.htm>
258 and <http://www.ssv-embedded.de/ssv/pc104/p170.htm>
259
260config MTD_DILNETPC_BOOTSIZE
261 hex "Size of DIL/Net PC flash boot partition"
262 depends on MTD_DILNETPC
263 default "0x80000"
264 help
265 The amount of space taken up by the kernel or Etherboot
266 on the DIL/Net PC flash chips.
267
268config MTD_L440GX 252config MTD_L440GX
269 tristate "BIOS flash chip on Intel L440GX boards" 253 tristate "BIOS flash chip on Intel L440GX boards"
270 depends on X86 && MTD_JEDECPROBE 254 depends on X86 && MTD_JEDECPROBE
diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile
index 0cdc881fe262..7315ed8c9643 100644
--- a/drivers/mtd/maps/Makefile
+++ b/drivers/mtd/maps/Makefile
@@ -9,7 +9,6 @@ endif
9# Chip mappings 9# Chip mappings
10obj-$(CONFIG_MTD_CFI_FLAGADM) += cfi_flagadm.o 10obj-$(CONFIG_MTD_CFI_FLAGADM) += cfi_flagadm.o
11obj-$(CONFIG_MTD_DC21285) += dc21285.o 11obj-$(CONFIG_MTD_DC21285) += dc21285.o
12obj-$(CONFIG_MTD_DILNETPC) += dilnetpc.o
13obj-$(CONFIG_MTD_L440GX) += l440gx.o 12obj-$(CONFIG_MTD_L440GX) += l440gx.o
14obj-$(CONFIG_MTD_AMD76XROM) += amd76xrom.o 13obj-$(CONFIG_MTD_AMD76XROM) += amd76xrom.o
15obj-$(CONFIG_MTD_ESB2ROM) += esb2rom.o 14obj-$(CONFIG_MTD_ESB2ROM) += esb2rom.o
diff --git a/drivers/mtd/maps/dilnetpc.c b/drivers/mtd/maps/dilnetpc.c
deleted file mode 100644
index 3e393f0da823..000000000000
--- a/drivers/mtd/maps/dilnetpc.c
+++ /dev/null
@@ -1,496 +0,0 @@
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 * The DIL/Net PC is a tiny embedded PC board made by SSV Embedded Systems
18 * featuring the AMD Elan SC410 processor. There are two variants of this
19 * board: DNP/1486 and ADNP/1486. The DNP version has 2 megs of flash
20 * ROM (Intel 28F016S3) and 8 megs of DRAM, the ADNP version has 4 megs
21 * flash and 16 megs of RAM.
22 * For details, see http://www.ssv-embedded.de/ssv/pc104/p169.htm
23 * and http://www.ssv-embedded.de/ssv/pc104/p170.htm
24 */
25
26#include <linux/module.h>
27#include <linux/types.h>
28#include <linux/kernel.h>
29#include <linux/init.h>
30#include <linux/string.h>
31
32#include <linux/mtd/mtd.h>
33#include <linux/mtd/map.h>
34#include <linux/mtd/partitions.h>
35#include <linux/mtd/concat.h>
36
37#include <asm/io.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
219 BUG_ON(vpp_counter < 0);
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
241 BUG_ON(vpp_counter < 0);
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 ARRAY_SIZE(partition_info)
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 ARRAY_SIZE(higlvl_partition_info)
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%llx\n",
404 is_dnp ? "DNPC" : "ADNP", dnpc_map.size, (unsigned long long)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 mtd_device_register(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 mtd_device_register(merged_mtd, higlvl_partition_info,
467 NUM_HIGHLVL_PARTITIONS);
468 }
469
470 return 0;
471}
472
473static void __exit cleanup_dnpc(void)
474{
475 if(merged_mtd) {
476 mtd_device_unregister(merged_mtd);
477 mtd_concat_destroy(merged_mtd);
478 }
479
480 if (mymtd) {
481 mtd_device_unregister(mymtd);
482 map_destroy(mymtd);
483 }
484 if (dnpc_map.virt) {
485 iounmap(dnpc_map.virt);
486 dnpc_unmap_flash();
487 dnpc_map.virt = NULL;
488 }
489}
490
491module_init(init_dnpc);
492module_exit(cleanup_dnpc);
493
494MODULE_LICENSE("GPL");
495MODULE_AUTHOR("Sysgo Real-Time Solutions GmbH");
496MODULE_DESCRIPTION("MTD map driver for SSV DIL/NetPC DNP & ADNP");