1
2
3
4
5
6
7#include <linux/module.h>
8#include <linux/types.h>
9#include <linux/kernel.h>
10#include <asm/io.h>
11#include <linux/mtd/mtd.h>
12#include <linux/mtd/map.h>
13#include <linux/config.h>
14#include <linux/mtd/cfi.h>
15
16#ifdef CONFIG_MTD_PARTITIONS
17#include <linux/mtd/partitions.h>
18#endif
19
20#define WINDOW_ADDR CONFIG_MTD_PHYSMAP_START
21#define WINDOW_SIZE CONFIG_MTD_PHYSMAP_LEN
22#define BUSWIDTH CONFIG_MTD_PHYSMAP_BUSWIDTH
23
24static struct mtd_info *mymtd;
25
26__u8 physmap_read8(struct map_info *map, unsigned long ofs)
27{
28 return __raw_readb(map->map_priv_1 + ofs);
29}
30
31__u16 physmap_read16(struct map_info *map, unsigned long ofs)
32{
33 return __raw_readw(map->map_priv_1 + ofs);
34}
35
36__u32 physmap_read32(struct map_info *map, unsigned long ofs)
37{
38 return __raw_readl(map->map_priv_1 + ofs);
39}
40
41__u64 physmap_read64(struct map_info *map, unsigned long ofs)
42{
43 return __raw_readll(map->map_priv_1 + ofs);
44}
45
46void physmap_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
47{
48 memcpy_fromio(to, map->map_priv_1 + from, len);
49}
50
51void physmap_write8(struct map_info *map, __u8 d, unsigned long adr)
52{
53 __raw_writeb(d, map->map_priv_1 + adr);
54 mb();
55}
56
57void physmap_write16(struct map_info *map, __u16 d, unsigned long adr)
58{
59 __raw_writew(d, map->map_priv_1 + adr);
60 mb();
61}
62
63void physmap_write32(struct map_info *map, __u32 d, unsigned long adr)
64{
65 __raw_writel(d, map->map_priv_1 + adr);
66 mb();
67}
68
69void physmap_write64(struct map_info *map, __u64 d, unsigned long adr)
70{
71 __raw_writell(d, map->map_priv_1 + adr);
72 mb();
73}
74
75void physmap_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
76{
77 memcpy_toio(map->map_priv_1 + to, from, len);
78}
79
80struct map_info physmap_map = {
81 name: "Physically mapped flash",
82 size: WINDOW_SIZE,
83 buswidth: BUSWIDTH,
84 read8: physmap_read8,
85 read16: physmap_read16,
86 read32: physmap_read32,
87 read64: physmap_read64,
88 copy_from: physmap_copy_from,
89 write8: physmap_write8,
90 write16: physmap_write16,
91 write32: physmap_write32,
92 write64: physmap_write64,
93 copy_to: physmap_copy_to
94};
95
96#ifdef CONFIG_MTD_PARTITIONS
97#ifdef CONFIG_MTD_CMDLINE_PARTS
98static struct mtd_partition *mtd_parts = 0;
99static int mtd_parts_nb = 0;
100#else
101static struct mtd_partition physmap_partitions[] = {
102
103#if 0
104 {
105 name: "bootROM",
106 size: 0x80000,
107 offset: 0,
108 mask_flags: MTD_WRITEABLE,
109 }, {
110 name: "zImage",
111 size: 0x100000,
112 offset: MTDPART_OFS_APPEND,
113 mask_flags: MTD_WRITEABLE,
114 }, {
115 name: "ramdisk.gz",
116 size: 0x300000,
117 offset: MTDPART_OFS_APPEND,
118 mask_flags: MTD_WRITEABLE,
119 }, {
120 name: "User FS",
121 size: MTDPART_SIZ_FULL,
122 offset: MTDPART_OFS_APPEND,
123 }
124#endif
125};
126
127#define NUM_PARTITIONS (sizeof(physmap_partitions)/sizeof(struct mtd_partition))
128
129#endif
130#endif
131
132int __init init_physmap(void)
133{
134 static const char *rom_probe_types[] = { "cfi_probe", "jedec_probe", "map_rom", 0 };
135 const char **type;
136
137 printk(KERN_NOTICE "physmap flash device: %x at %x\n", WINDOW_SIZE, WINDOW_ADDR);
138 physmap_map.map_priv_1 = (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE);
139
140 if (!physmap_map.map_priv_1) {
141 printk("Failed to ioremap\n");
142 return -EIO;
143 }
144
145 mymtd = 0;
146 type = rom_probe_types;
147 for(; !mymtd && *type; type++) {
148 mymtd = do_map_probe(*type, &physmap_map);
149 }
150 if (mymtd) {
151 mymtd->module = THIS_MODULE;
152
153 add_mtd_device(mymtd);
154#ifdef CONFIG_MTD_PARTITIONS
155#ifdef CONFIG_MTD_CMDLINE_PARTS
156 mtd_parts_nb = parse_cmdline_partitions(mymtd, &mtd_parts,
157 "phys");
158 if (mtd_parts_nb > 0)
159 {
160 printk(KERN_NOTICE
161 "Using command line partition definition\n");
162 add_mtd_partitions (mymtd, mtd_parts, mtd_parts_nb);
163 }
164#else
165 if (NUM_PARTITIONS != 0)
166 {
167 printk(KERN_NOTICE
168 "Using physmap partition definition\n");
169 add_mtd_partitions (mymtd, physmap_partitions, NUM_PARTITIONS);
170 }
171
172#endif
173#endif
174 return 0;
175 }
176
177 iounmap((void *)physmap_map.map_priv_1);
178 return -ENXIO;
179}
180
181static void __exit cleanup_physmap(void)
182{
183 if (mymtd) {
184 del_mtd_device(mymtd);
185 map_destroy(mymtd);
186 }
187 if (physmap_map.map_priv_1) {
188 iounmap((void *)physmap_map.map_priv_1);
189 physmap_map.map_priv_1 = 0;
190 }
191}
192
193module_init(init_physmap);
194module_exit(cleanup_physmap);
195
196
197MODULE_LICENSE("GPL");
198MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
199MODULE_DESCRIPTION("Generic configurable MTD map driver");
200