1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Handle mapping of the NOR flash on implementa A7 boards |
4 | * |
5 | * Copyright 2002 SYSGO Real-Time Solutions GmbH |
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/partitions.h> |
16 | |
17 | #define WINDOW_ADDR0 0x00000000 /* physical properties of flash */ |
18 | #define WINDOW_SIZE0 0x00800000 |
19 | #define WINDOW_ADDR1 0x10000000 /* physical properties of flash */ |
20 | #define WINDOW_SIZE1 0x00800000 |
21 | #define NUM_FLASHBANKS 2 |
22 | #define BUSWIDTH 4 |
23 | |
24 | #define MSG_PREFIX "impA7:" /* prefix for our printk()'s */ |
25 | #define MTDID "impa7-%d" /* for mtdparts= partitioning */ |
26 | |
27 | static struct mtd_info *impa7_mtd[NUM_FLASHBANKS]; |
28 | |
29 | static const char * const rom_probe_types[] = { "jedec_probe" , NULL }; |
30 | |
31 | static struct map_info impa7_map[NUM_FLASHBANKS] = { |
32 | { |
33 | .name = "impA7 NOR Flash Bank #0" , |
34 | .size = WINDOW_SIZE0, |
35 | .bankwidth = BUSWIDTH, |
36 | }, |
37 | { |
38 | .name = "impA7 NOR Flash Bank #1" , |
39 | .size = WINDOW_SIZE1, |
40 | .bankwidth = BUSWIDTH, |
41 | }, |
42 | }; |
43 | |
44 | /* |
45 | * MTD partitioning stuff |
46 | */ |
47 | static const struct mtd_partition partitions[] = |
48 | { |
49 | { |
50 | .name = "FileSystem" , |
51 | .size = 0x800000, |
52 | .offset = 0x00000000 |
53 | }, |
54 | }; |
55 | |
56 | static int __init init_impa7(void) |
57 | { |
58 | const char * const *type; |
59 | int i; |
60 | static struct { u_long addr; u_long size; } pt[NUM_FLASHBANKS] = { |
61 | { WINDOW_ADDR0, WINDOW_SIZE0 }, |
62 | { WINDOW_ADDR1, WINDOW_SIZE1 }, |
63 | }; |
64 | int devicesfound = 0; |
65 | |
66 | for(i=0; i<NUM_FLASHBANKS; i++) |
67 | { |
68 | printk(KERN_NOTICE MSG_PREFIX "probing 0x%08lx at 0x%08lx\n" , |
69 | pt[i].size, pt[i].addr); |
70 | |
71 | impa7_map[i].phys = pt[i].addr; |
72 | impa7_map[i].virt = ioremap(offset: pt[i].addr, size: pt[i].size); |
73 | if (!impa7_map[i].virt) { |
74 | printk(MSG_PREFIX "failed to ioremap\n" ); |
75 | return -EIO; |
76 | } |
77 | simple_map_init(&impa7_map[i]); |
78 | |
79 | impa7_mtd[i] = NULL; |
80 | type = rom_probe_types; |
81 | for(; !impa7_mtd[i] && *type; type++) { |
82 | impa7_mtd[i] = do_map_probe(name: *type, map: &impa7_map[i]); |
83 | } |
84 | |
85 | if (impa7_mtd[i]) { |
86 | impa7_mtd[i]->owner = THIS_MODULE; |
87 | devicesfound++; |
88 | mtd_device_register(impa7_mtd[i], partitions, |
89 | ARRAY_SIZE(partitions)); |
90 | } else { |
91 | iounmap(addr: (void __iomem *)impa7_map[i].virt); |
92 | } |
93 | } |
94 | return devicesfound == 0 ? -ENXIO : 0; |
95 | } |
96 | |
97 | static void __exit cleanup_impa7(void) |
98 | { |
99 | int i; |
100 | for (i=0; i<NUM_FLASHBANKS; i++) { |
101 | if (impa7_mtd[i]) { |
102 | mtd_device_unregister(master: impa7_mtd[i]); |
103 | map_destroy(mtd: impa7_mtd[i]); |
104 | iounmap(addr: (void __iomem *)impa7_map[i].virt); |
105 | impa7_map[i].virt = NULL; |
106 | } |
107 | } |
108 | } |
109 | |
110 | module_init(init_impa7); |
111 | module_exit(cleanup_impa7); |
112 | |
113 | MODULE_LICENSE("GPL" ); |
114 | MODULE_AUTHOR("Pavel Bartusek <pba@sysgo.de>" ); |
115 | MODULE_DESCRIPTION("MTD map driver for implementa impA7" ); |
116 | |