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