]> rtime.felk.cvut.cz Git - lisovros/linux_canprio.git/blob - drivers/mtd/maps/shark_pmap_of.c
Update Shark 5200 patch to 2.6.36.1
[lisovros/linux_canprio.git] / drivers / mtd / maps / shark_pmap_of.c
1 /*
2  * Flash mappings described by the OF (or flattened) device tree
3  *
4  * Copyright (C) 2006 MontaVista Software Inc.
5  * Author: Vitaly Wool <vwool@ru.mvista.com>
6  *
7  * Revised to handle newer style flash binding by:
8  *   Copyright (C) 2007 David Gibson, IBM Corporation.
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/init.h>
19 #include <linux/device.h>
20 #include <linux/mtd/mtd.h>
21 #include <linux/mtd/map.h>
22 #include <linux/mtd/xip.h>
23 #include <linux/mtd/partitions.h>
24 #include <linux/of.h>
25 #include <linux/of_platform.h>
26 #include <linux/slab.h>
27
28 struct of_flash {
29         struct mtd_info         *mtd;
30         struct map_info         map;
31         struct resource         *res;
32 #ifdef CONFIG_MTD_PARTITIONS
33         struct mtd_partition    *parts;
34 #endif
35 };
36
37 // Support for MPC5200 bank select on Shark board, map_priv_1 - MBAR address
38 void of_shark_mpc5200_set_bank(unsigned long map_priv_1, unsigned long addr)
39 {
40         unsigned long cfg;
41         volatile int i;
42         
43         cfg = (*(unsigned long *)(map_priv_1 + 0x0300)) & ~0xC0;
44         cfg = cfg | ( ( (addr >> 25) & 3) << 6);
45
46         //debug("A:%x:%x ", addr, cfg);
47         *(unsigned long *)(map_priv_1 + 0x0300) = cfg;
48         i = 5; // some small delay
49 }
50
51 static map_word __xipram of_shark_map_read(struct map_info *map, unsigned long ofs)
52 {
53         of_shark_mpc5200_set_bank(map->map_priv_1, ofs);
54         return inline_map_read(map, ofs);
55 }
56
57 static void __xipram of_shark_map_write(struct map_info *map, const map_word datum, unsigned long ofs)
58 {
59         of_shark_mpc5200_set_bank(map->map_priv_1, ofs);
60         inline_map_write(map, datum, ofs);
61 }
62
63 static void __xipram of_shark_map_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
64 {
65         if (map->cached)
66                 memcpy(to, (char *)map->cached + from, len);
67         else
68         {
69                 of_shark_mpc5200_set_bank(map->map_priv_1, from);
70                 if( ((int)from < 0x2000000) && ((int)from + len > 0x2000000) )
71                 {
72                         int iFirstBankLength = 0x2000000 - (int)from;
73                 
74                         memcpy_fromio(to, map->virt + from, iFirstBankLength);
75                 
76                         of_shark_mpc5200_set_bank(map->map_priv_1, from + iFirstBankLength);
77                         memcpy_fromio(to + iFirstBankLength, map->virt + from + iFirstBankLength, len - iFirstBankLength);
78                 }
79                 else
80                         memcpy_fromio(to, map->virt + from, len);
81         }
82 }
83
84 static void __xipram of_shark_map_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
85 {
86         of_shark_mpc5200_set_bank(map->map_priv_1, (unsigned long)from);
87         if( ((int)from < 0x2000000) && ((int)from + len > 0x2000000) )
88         {
89                 int iFirstBankLength = 0x2000000 - (int)from;
90                 memcpy_toio(map->virt + to, from, iFirstBankLength);
91         
92                 of_shark_mpc5200_set_bank(map->map_priv_1, (unsigned long)from + iFirstBankLength);
93                 memcpy_toio(map->virt + to + iFirstBankLength, from + iFirstBankLength, len - iFirstBankLength);
94         }
95         else
96                 memcpy_toio(map->virt + to, from, len);
97 }
98
99 #ifdef CONFIG_MTD_PARTITIONS
100 #define OF_FLASH_PARTS(info)    ((info)->parts)
101
102 static int parse_obsolete_partitions(struct platform_device *dev,
103                                      struct of_flash *info,
104                                      struct device_node *dp)
105 {
106         int i, plen, nr_parts;
107         const struct {
108                 u32 offset, len;
109         } *part;
110         const char *names;
111
112         part = of_get_property(dp, "partitions", &plen);
113         if (!part)
114                 return 0; /* No partitions found */
115
116         dev_warn(&dev->dev, "Device tree uses obsolete partition map binding\n");
117
118         nr_parts = plen / sizeof(part[0]);
119
120         info->parts = kzalloc(nr_parts * sizeof(*info->parts), GFP_KERNEL);
121         if (!info->parts)
122                 return -ENOMEM;
123
124         names = of_get_property(dp, "partition-names", &plen);
125
126         for (i = 0; i < nr_parts; i++) {
127                 info->parts[i].offset = part->offset;
128                 info->parts[i].size   = part->len & ~1;
129                 if (part->len & 1) /* bit 0 set signifies read only partition */
130                         info->parts[i].mask_flags = MTD_WRITEABLE;
131
132                 if (names && (plen > 0)) {
133                         int len = strlen(names) + 1;
134
135                         info->parts[i].name = (char *)names;
136                         plen -= len;
137                         names += len;
138                 } else {
139                         info->parts[i].name = "unnamed";
140                 }
141
142                 part++;
143         }
144
145         return nr_parts;
146 }
147 #else /* MTD_PARTITIONS */
148 #define OF_FLASH_PARTS(info)            (0)
149 #define parse_partitions(info, dev)     (0)
150 #endif /* MTD_PARTITIONS */
151
152 static int of_shark_flash_remove(struct platform_device *dev)
153 {
154         struct of_flash *info;
155
156         info = dev_get_drvdata(&dev->dev);
157         if (!info)
158                 return 0;
159         dev_set_drvdata(&dev->dev, NULL);
160
161         if (info->mtd) {
162                 if (OF_FLASH_PARTS(info)) {
163                         del_mtd_partitions(info->mtd);
164                         kfree(OF_FLASH_PARTS(info));
165                 } else {
166                         del_mtd_device(info->mtd);
167                 }
168                 map_destroy(info->mtd);
169         }
170
171         if (info->map.map_priv_1)
172                 iounmap((void*)info->map.map_priv_1);
173
174         if (info->map.virt)
175                 iounmap(info->map.virt);
176
177         if (info->res) {
178                 release_resource(info->res);
179                 kfree(info->res);
180         }
181
182         return 0;
183 }
184
185 /* Helper function to handle probing of the obsolete "direct-mapped"
186  * compatible binding, which has an extra "probe-type" property
187  * describing the type of flash probe necessary. */
188 static struct mtd_info * __devinit obsolete_probe(struct platform_device *dev,
189                                                   struct map_info *map)
190 {
191         struct device_node *dp = dev->dev.of_node;
192         const char *of_probe;
193         struct mtd_info *mtd;
194         static const char *rom_probe_types[]
195                 = { "cfi_probe", "jedec_probe", "map_rom"};
196         int i;
197
198         dev_warn(&dev->dev, "Device tree uses obsolete \"direct-mapped\" "
199                  "flash binding\n");
200
201         of_probe = of_get_property(dp, "probe-type", NULL);
202         if (!of_probe) {
203                 for (i = 0; i < ARRAY_SIZE(rom_probe_types); i++) {
204                         mtd = do_map_probe(rom_probe_types[i], map);
205                         if (mtd)
206                                 return mtd;
207                 }
208                 return NULL;
209         } else if (strcmp(of_probe, "CFI") == 0) {
210                 return do_map_probe("cfi_probe", map);
211         } else if (strcmp(of_probe, "JEDEC") == 0) {
212                 return do_map_probe("jedec_probe", map);
213         } else {
214                 if (strcmp(of_probe, "ROM") != 0)
215                         dev_warn(&dev->dev, "obsolete_probe: don't know probe "
216                                  "type '%s', mapping as rom\n", of_probe);
217                 return do_map_probe("mtd_rom", map);
218         }
219 }
220
221 static int __devinit of_shark_flash_probe(struct platform_device *dev,
222                                     const struct of_device_id *match)
223 {
224 #ifdef CONFIG_MTD_PARTITIONS
225         static const char *part_probe_types[]
226                 = { "cmdlinepart", "RedBoot", NULL };
227 #endif
228         struct device_node *dp = dev->dev.of_node;
229         struct device_node *np_sys;
230         struct resource res;
231         struct of_flash *info;
232         const char *probe_type = match->data;
233         const u32 *width;
234         int err;
235
236         const struct of_device_id immr_ids[] = {
237                 { .compatible = "fsl,mpc5200-immr", },
238                 { .compatible = "fsl,mpc5200b-immr", },
239                 { .type = "soc", .compatible = "mpc5200", }, /* lite5200 */
240                 { .type = "builtin", .compatible = "mpc5200", }, /* efika */
241                 {}
242         };
243
244         err = -ENXIO;
245         if (of_address_to_resource(dp, 0, &res)) {
246                 dev_err(&dev->dev, "Can't get IO address from device tree\n");
247                 goto err_out;
248         }
249
250         dev_dbg(&dev->dev, "of_flash device: %.8llx-%.8llx\n",
251                 (unsigned long long)res.start, (unsigned long long)res.end);
252
253         err = -ENOMEM;
254         info = kzalloc(sizeof(*info), GFP_KERNEL);
255         if (!info)
256                 goto err_out;
257
258         dev_set_drvdata(&dev->dev, info);
259
260         err = -EBUSY;
261         info->res = request_mem_region(res.start, res.end - res.start + 1,
262                                        dev_name(&dev->dev));
263         if (!info->res)
264                 goto err_out;
265
266         err = -ENXIO;
267         width = of_get_property(dp, "bank-width", NULL);
268         if (!width) {
269                 dev_err(&dev->dev, "Can't get bank width from device tree\n");
270                 goto err_out;
271         }
272
273         info->map.name = dev_name(&dev->dev);
274         info->map.phys = res.start;
275         info->map.size = res.end - res.start + 1;
276         info->map.bankwidth = *width;
277
278         err = -ENOMEM;
279         info->map.virt = ioremap(info->map.phys, info->map.size);
280         if (!info->map.virt) {
281                 dev_err(&dev->dev, "Failed to ioremap() flash region\n");
282                 goto err_out;
283         }
284
285         info->map.read = of_shark_map_read;
286         info->map.write = of_shark_map_write;
287         info->map.copy_from = of_shark_map_copy_from;
288         info->map.copy_to = of_shark_map_copy_to;
289
290         /* map the whole register space */
291         np_sys = of_find_matching_node(NULL, immr_ids);
292         info->map.map_priv_1 = (unsigned long)of_iomap(np_sys, 0);
293         if (!info->map.map_priv_1) {
294                 dev_err(&dev->dev, "of_shark_flash_probe: could not get MBAR address\n");
295                 goto err_out;
296         }
297
298         if (probe_type)
299                 info->mtd = do_map_probe(probe_type, &info->map);
300         else
301                 info->mtd = obsolete_probe(dev, &info->map);
302
303         err = -ENXIO;
304         if (!info->mtd) {
305                 dev_err(&dev->dev, "do_map_probe() failed\n");
306                 goto err_out;
307         }
308         info->mtd->owner = THIS_MODULE;
309         info->mtd->dev.parent = &dev->dev;
310
311 #ifdef CONFIG_MTD_PARTITIONS
312         /* First look for RedBoot table or partitions on the command
313          * line, these take precedence over device tree information */
314         err = parse_mtd_partitions(info->mtd, part_probe_types,
315                                    &info->parts, 0);
316         if (err < 0)
317                 return err;
318
319 #ifdef CONFIG_MTD_OF_PARTS
320         if (err == 0) {
321                 err = of_mtd_parse_partitions(&dev->dev, dp, &info->parts);
322                 if (err < 0)
323                         return err;
324         }
325 #endif
326
327         if (err == 0) {
328                 err = parse_obsolete_partitions(dev, info, dp);
329                 if (err < 0)
330                         return err;
331         }
332
333         if (err > 0)
334                 add_mtd_partitions(info->mtd, info->parts, err);
335         else
336 #endif
337                 add_mtd_device(info->mtd);
338
339         return 0;
340
341 err_out:
342         of_shark_flash_remove(dev);
343         return err;
344 }
345
346 static struct of_device_id of_shark_flash_match[] = {
347         {
348                 .compatible     = "cfi-flash",
349                 .data           = (void *)"cfi_probe",
350         },
351         {
352                 /* FIXME: JEDEC chips can't be safely and reliably
353                  * probed, although the mtd code gets it right in
354                  * practice most of the time.  We should use the
355                  * vendor and device ids specified by the binding to
356                  * bypass the heuristic probe code, but the mtd layer
357                  * provides, at present, no interface for doing so
358                  * :(. */
359                 .compatible     = "jedec-flash",
360                 .data           = (void *)"jedec_probe",
361         },
362         {
363                 .type           = "rom",
364                 .compatible     = "direct-mapped"
365         },
366         { },
367 };
368 MODULE_DEVICE_TABLE(of, of_flash_match);
369
370 static struct of_platform_driver of_shark_flash_driver = {
371         .driver         = {
372                 .name           = "of-flash",
373                 .owner          = THIS_MODULE,
374                 .of_match_table = of_shark_flash_match,
375
376         },
377         .probe          = of_shark_flash_probe,
378         .remove         = of_shark_flash_remove,
379 };
380
381 static int __init of_shark_flash_init(void)
382 {
383         return of_register_platform_driver(&of_shark_flash_driver);
384 }
385
386 static void __exit of_shark_flash_exit(void)
387 {
388         of_unregister_platform_driver(&of_shark_flash_driver);
389 }
390
391 module_init(of_shark_flash_init);
392 module_exit(of_shark_flash_exit);
393
394 MODULE_LICENSE("GPL");
395 MODULE_AUTHOR("Vitaly Wool <vwool@ru.mvista.com>");
396 MODULE_DESCRIPTION("Device tree based MTD map driver");