Merge master.kernel.org:/pub/scm/linux/kernel/git/tglx/mtd-2.6
[linux-2.6] / drivers / mtd / maps / tqm834x.c
1 /*
2  * drivers/mtd/maps/tqm834x.c
3  *
4  * MTD mapping driver for TQM834x boards
5  *
6  * Copyright 2005 Wolfgang Denk, DENX Software Engineering, <wd@denx.de>.
7  *
8  * This file is licensed under the terms of the GNU General Public License
9  * version 2.  This program is licensed "as is" without any warranty of any
10  * kind, whether express or implied.
11  *
12  */
13
14 #include <linux/config.h>
15 #include <linux/init.h>
16 #include <linux/module.h>
17 #include <linux/types.h>
18 #include <linux/kernel.h>
19 #include <linux/slab.h>
20 #include <asm/io.h>
21 #include <asm/ppcboot.h>
22
23 #include <linux/mtd/mtd.h>
24 #include <linux/mtd/map.h>
25 #include <linux/mtd/partitions.h>
26
27 #define FLASH_BANK_MAX  2
28
29 extern unsigned char __res[];
30
31 /* trivial struct to describe partition information */
32 struct mtd_part_def
33 {
34         int nums;
35         unsigned char *type;
36         struct mtd_partition* mtd_part;
37 };
38
39 static struct mtd_info* mtd_banks[FLASH_BANK_MAX];
40 static struct map_info* map_banks[FLASH_BANK_MAX];
41 static struct mtd_part_def part_banks[FLASH_BANK_MAX];
42
43 static unsigned long num_banks;
44 static unsigned long start_scan_addr;
45
46 #ifdef CONFIG_MTD_PARTITIONS
47 /*
48  * The following defines the partition layout of TQM834x boards.
49  *
50  * See include/linux/mtd/partitions.h for definition of the
51  * mtd_partition structure.
52  *
53  * Assume minimal initial size of 4 MiB per bank, will be updated
54  * later in init_tqm834x_mtd() routine.
55  */
56
57 /* Partition definition for the first flash bank which is always present. */
58 static struct mtd_partition tqm834x_partitions_bank1[] = {
59         {
60                 .name   = "u-boot",             /* u-boot firmware      */
61                 .offset = 0x00000000,
62                 .size   = 0x00040000,           /* 256 KiB              */
63                 /*mask_flags: MTD_WRITEABLE,     * force read-only      */
64         },
65         {
66                 .name   = "env",                /* u-boot environment   */
67                 .offset = 0x00040000,
68                 .size   = 0x00020000,           /* 128 KiB              */
69                 /*mask_flags: MTD_WRITEABLE,     * force read-only      */
70         },
71         {
72                 .name   = "kernel",             /* linux kernel image   */
73                 .offset = 0x00060000,
74                 .size   = 0x00100000,           /* 1 MiB                */
75                 /*mask_flags: MTD_WRITEABLE,     * force read-only      */
76         },
77         {
78                 .name   = "initrd",             /* ramdisk image        */
79                 .offset = 0x00160000,
80                 .size   = 0x00200000,           /* 2 MiB                */
81         },
82         {
83                 .name   = "user",               /* user data            */
84                 .offset = 0x00360000,
85                 .size   = 0x000a0000,           /* remaining space      */
86                 /* NOTE: this parttion size is re-calcated in           */
87                 /* init_tqm834x_mtd() to cover actual remaining space.  */
88         },
89 };
90
91 /* Partition definition for the second flash bank which may be present on some
92  * TQM834x boards.
93  */
94 static struct mtd_partition tqm834x_partitions_bank2[] = {
95         {
96                 .name   = "jffs2",              /* jffs2 filesystem     */
97                 .offset = 0x00000000,
98                 .size   = 0x00400000,           /* whole device         */
99                 /* NOTE: this parttion size is re-calcated in           */
100                 /* init_tqm834x_mtd() to cover actual device size.      */
101         },
102 };
103
104 #endif  /* CONFIG_MTD_PARTITIONS */
105
106 static int __init init_tqm834x_mtd(void)
107 {
108         int idx = 0, ret = 0;
109         unsigned long flash_addr, flash_size, mtd_size = 0;
110
111         /* pointer to TQM834x board info data */
112         bd_t *bd = (bd_t *)__res;
113 #ifdef CONFIG_MTD_CMDLINE_PARTS
114         int n;
115         char mtdid[4];
116         const char *part_probes[] = { "cmdlinepart", NULL };
117 #endif
118
119         flash_addr = bd->bi_flashstart;
120         flash_size = bd->bi_flashsize;
121
122         /* request maximum flash size address space */
123         start_scan_addr = (unsigned long)ioremap(flash_addr, flash_size);
124         if (!start_scan_addr) {
125                 printk("%s: Failed to ioremap address: 0x%lx\n",
126                        __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                 pr_debug("%s: chip probing count %d\n", __FUNCTION__, idx);
135
136                 map_banks[idx] =
137                         (struct map_info *)kmalloc(sizeof(struct map_info),
138                                                    GFP_KERNEL);
139                 if (map_banks[idx] == NULL) {
140                         ret = -ENOMEM;
141                         goto error_mem;
142                 }
143                 memset((void *)map_banks[idx], 0, sizeof(struct map_info));
144                 map_banks[idx]->name = (char *)kmalloc(16, GFP_KERNEL);
145                 if (map_banks[idx]->name == NULL) {
146                         ret = -ENOMEM;
147                         goto error_mem;
148                 }
149                 memset((void *)map_banks[idx]->name, 0, 16);
150
151                 sprintf(map_banks[idx]->name, "TQM834x-%d", idx);
152                 map_banks[idx]->size = flash_size;
153                 map_banks[idx]->bankwidth = 4;
154
155                 simple_map_init(map_banks[idx]);
156
157                 map_banks[idx]->virt = (void __iomem *)
158                         (start_scan_addr + ((idx > 0) ?
159                         (mtd_banks[idx-1] ? mtd_banks[idx-1]->size : 0) : 0));
160                 map_banks[idx]->phys =
161                         flash_addr + ((idx > 0) ?
162                         (mtd_banks[idx-1] ? mtd_banks[idx-1]->size : 0) : 0);
163
164                 /* start to probe flash chips */
165                 mtd_banks[idx] = do_map_probe("cfi_probe", map_banks[idx]);
166                 if (mtd_banks[idx]) {
167                         mtd_banks[idx]->owner = THIS_MODULE;
168                         mtd_size += mtd_banks[idx]->size;
169                         num_banks++;
170                         pr_debug("%s: bank %ld, name: %s, size: %d bytes \n",
171                                  __FUNCTION__, num_banks,
172                                  mtd_banks[idx]->name, mtd_banks[idx]->size);
173                 }
174         }
175
176         /* no supported flash chips found */
177         if (!num_banks) {
178                 printk("TQM834x: No supported flash chips found!\n");
179                 ret = -ENXIO;
180                 goto error_mem;
181         }
182
183 #ifdef CONFIG_MTD_PARTITIONS
184         /*
185          * Select static partition definitions
186          */
187         n = ARRAY_SIZE(tqm834x_partitions_bank1);
188         part_banks[0].mtd_part  = tqm834x_partitions_bank1;
189         part_banks[0].type      = "static image bank1";
190         part_banks[0].nums      = n;
191
192         /* update last partition size to cover actual remaining space */
193         tqm834x_partitions_bank1[n - 1].size =
194                 mtd_banks[0]->size -
195                 tqm834x_partitions_bank1[n - 1].offset;
196
197         /* check if we have second bank? */
198         if (num_banks == 2) {
199                 n = ARRAY_SIZE(tqm834x_partitions_bank2);
200                 part_banks[1].mtd_part  = tqm834x_partitions_bank2;
201                 part_banks[1].type      = "static image bank2";
202                 part_banks[1].nums      = n;
203
204                 /* update last partition size to cover actual remaining space */
205                 tqm834x_partitions_bank2[n - 1].size =
206                         mtd_banks[1]->size -
207                         tqm834x_partitions_bank2[n - 1].offset;
208         }
209
210         for(idx = 0; idx < num_banks ; idx++) {
211 #ifdef CONFIG_MTD_CMDLINE_PARTS
212                 sprintf(mtdid, "%d", idx);
213                 n = parse_mtd_partitions(mtd_banks[idx],
214                                          part_probes,
215                                          &part_banks[idx].mtd_part,
216                                          0);
217                 pr_debug("%s: %d command line partitions on bank %s\n",
218                          __FUNCTION__, n, mtdid);
219                 if (n > 0) {
220                         part_banks[idx].type = "command line";
221                         part_banks[idx].nums = n;
222                 }
223 #endif  /* CONFIG_MTD_CMDLINE_PARTS */
224                 if (part_banks[idx].nums == 0) {
225                         printk(KERN_NOTICE
226                                "TQM834x flash bank %d: no partition info "
227                                "available, registering whole device\n", idx);
228                         add_mtd_device(mtd_banks[idx]);
229                 } else {
230                         printk(KERN_NOTICE
231                                "TQM834x flash bank %d: Using %s partition "
232                                "definition\n", idx, part_banks[idx].type);
233                         add_mtd_partitions(mtd_banks[idx],
234                                            part_banks[idx].mtd_part,
235                                            part_banks[idx].nums);
236                 }
237         }
238 #else   /* ! CONFIG_MTD_PARTITIONS */
239         printk(KERN_NOTICE "TQM834x flash: registering %d flash banks "
240                         "at once\n", num_banks);
241
242         for(idx = 0 ; idx < num_banks ; idx++)
243                 add_mtd_device(mtd_banks[idx]);
244
245 #endif  /* CONFIG_MTD_PARTITIONS */
246
247         return 0;
248 error_mem:
249         for (idx = 0 ; idx < FLASH_BANK_MAX ; idx++) {
250                 if (map_banks[idx] != NULL) {
251                         if (map_banks[idx]->name != NULL) {
252                                 kfree(map_banks[idx]->name);
253                                 map_banks[idx]->name = NULL;
254                         }
255                         kfree(map_banks[idx]);
256                         map_banks[idx] = NULL;
257                 }
258         }
259
260         iounmap((void *)start_scan_addr);
261
262         return ret;
263 }
264
265 static void __exit cleanup_tqm834x_mtd(void)
266 {
267         unsigned int idx = 0;
268         for(idx = 0 ; idx < num_banks ; idx++) {
269                 /* destroy mtd_info previously allocated */
270                 if (mtd_banks[idx]) {
271                         del_mtd_partitions(mtd_banks[idx]);
272                         map_destroy(mtd_banks[idx]);
273                 }
274
275                 /* release map_info not used anymore */
276                 kfree(map_banks[idx]->name);
277                 kfree(map_banks[idx]);
278         }
279
280         if (start_scan_addr) {
281                 iounmap((void *)start_scan_addr);
282                 start_scan_addr = 0;
283         }
284 }
285
286 module_init(init_tqm834x_mtd);
287 module_exit(cleanup_tqm834x_mtd);
288
289 MODULE_LICENSE("GPL");
290 MODULE_AUTHOR("Wolfgang Denk <wd@denx.de>");
291 MODULE_DESCRIPTION("MTD map driver for TQM834x boards");