This commit was manufactured by cvs2svn to create branch 'vserver'.
[linux-2.6.git] / drivers / mtd / maps / wr_sbc82xx_flash.c
1 /*
2  * $Id: wr_sbc82xx_flash.c,v 1.1 2004/06/07 10:21:32 dwmw2 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_8260.h>
24
25 static struct mtd_info *sbcmtd[3];
26 static struct mtd_partition *sbcmtd_parts[3];
27
28 struct map_info sbc82xx_flash_map[3] = {
29         {.name = "Boot flash"},
30         {.name = "Alternate boot flash"},
31         {.name = "User flash"}
32 };
33
34 static 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
46 static struct mtd_partition bigflash_parts[] = {
47         {
48                 .name =         "bootloader",
49                 .size =         0x80000,
50                 .offset =       0,
51         }, {
52                 .name =         "file system",
53                 .size =         MTDPART_SIZ_FULL,
54                 .offset =       MTDPART_OFS_APPEND,
55         }
56 };
57
58 static const char *part_probes[] __initdata = {"cmdlinepart", "RedBoot", NULL};
59
60 int __init init_sbc82xx_flash(void)
61 {
62         volatile  memctl8260_t *mc = &immr->im_memctl;
63         int bigflash;
64         int i;
65
66         /* First, register the boot flash, whichever we're booting from */
67         if ((mc->memc_br0 & 0x00001800) == 0x00001800) {
68                 bigflash = 0;
69         } else if ((mc->memc_br0 & 0x00001800) == 0x00000800) {
70                 bigflash = 1;
71         } else {
72                 printk(KERN_WARNING "Bus Controller register BR0 is %08x. Cannot determine flash configuration\n", mc->memc_br0);
73                 return 1;
74         }
75
76         /* Set parameters for the big flash chip (CS6 or CS0) */
77         sbc82xx_flash_map[bigflash].buswidth = 4;
78         sbc82xx_flash_map[bigflash].size = 0x4000000;
79
80         /* Set parameters for the small flash chip (CS0 or CS6) */
81         sbc82xx_flash_map[!bigflash].buswidth = 1;
82         sbc82xx_flash_map[!bigflash].size = 0x200000;
83
84         /* Set parameters for the user flash chip (CS1) */
85         sbc82xx_flash_map[2].buswidth = 4;
86         sbc82xx_flash_map[2].size = 0x4000000;
87
88         sbc82xx_flash_map[0].phys = mc->memc_br0 & 0xffff8000;
89         sbc82xx_flash_map[1].phys = mc->memc_br6 & 0xffff8000;
90         sbc82xx_flash_map[2].phys = mc->memc_br1 & 0xffff8000;
91
92         for (i=0; i<3; i++) {
93                 int8_t flashcs[3] = { 0, 6, 1 };
94                 int nr_parts;
95
96                 printk(KERN_NOTICE "PowerQUICC II %s (%ld MiB on CS%d",
97                        sbc82xx_flash_map[i].name, sbc82xx_flash_map[i].size >> 20, flashcs[i]);
98                 if (!sbc82xx_flash_map[i].phys) {
99                         /* We know it can't be at zero. */
100                         printk("): disabled by bootloader.\n");
101                         continue;
102                 }
103                 printk(" at %08lx)\n",  sbc82xx_flash_map[i].phys);
104
105                 sbc82xx_flash_map[i].virt = (unsigned long)ioremap(sbc82xx_flash_map[i].phys, sbc82xx_flash_map[i].size);
106
107                 if (!sbc82xx_flash_map[i].virt) {
108                         printk("Failed to ioremap\n");
109                         continue;
110                 }
111
112                 simple_map_init(&sbc82xx_flash_map[i]);
113
114                 sbcmtd[i] = do_map_probe("cfi_probe", &sbc82xx_flash_map[i]);
115
116                 if (!sbcmtd[i])
117                         continue;
118
119                 sbcmtd[i]->owner = THIS_MODULE;
120
121                 nr_parts = parse_mtd_partitions(sbcmtd[i], part_probes,
122                                                 &sbcmtd_parts[i], 0);
123                 if (nr_parts > 0) {
124                         add_mtd_partitions (sbcmtd[i], sbcmtd_parts[i], nr_parts);
125                         continue;
126                 }
127
128                 /* No partitioning detected. Use default */
129                 if (i == 2) {
130                         add_mtd_device(sbcmtd[i]);
131                 } else if (i == bigflash) {
132                         add_mtd_partitions (sbcmtd[i], bigflash_parts, ARRAY_SIZE(bigflash_parts));
133                 } else {
134                         add_mtd_partitions (sbcmtd[i], smallflash_parts, ARRAY_SIZE(smallflash_parts));
135                 }
136         }
137         return 0;
138 }
139
140 static void __exit cleanup_sbc82xx_flash(void)
141 {
142         int i;
143
144         for (i=0; i<3; i++) {
145                 if (!sbcmtd[i])
146                         continue;
147
148                 if (i<2 || sbcmtd_parts[i])
149                         del_mtd_partitions(sbcmtd[i]);
150                 else
151                         del_mtd_device(sbcmtd[i]);
152                         
153                 kfree(sbcmtd_parts[i]);
154                 map_destroy(sbcmtd[i]);
155                 
156                 iounmap((void *)sbc82xx_flash_map[i].virt);
157                 sbc82xx_flash_map[i].virt = 0;
158         }
159 }
160
161 module_init(init_sbc82xx_flash);
162 module_exit(cleanup_sbc82xx_flash);
163
164
165 MODULE_LICENSE("GPL");
166 MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
167 MODULE_DESCRIPTION("Flash map driver for WindRiver PowerQUICC II");