1/*
2 * Flash on Cirrus CDB89712
3 *
4 * $Id: cdb89712.c,v 1.1.1.1 2008/10/15 03:26:35 james26_jang Exp $
5 */
6
7#include <linux/module.h>
8#include <linux/types.h>
9#include <linux/kernel.h>
10#include <linux/ioport.h>
11#include <asm/io.h>
12#include <asm/arch/hardware.h>
13#include <linux/mtd/mtd.h>
14#include <linux/mtd/map.h>
15#include <linux/mtd/partitions.h>
16
17
18
19__u8 cdb89712_read8(struct map_info *map, unsigned long ofs)
20{
21	return __raw_readb(map->map_priv_1 + ofs);
22}
23
24__u16 cdb89712_read16(struct map_info *map, unsigned long ofs)
25{
26	return __raw_readw(map->map_priv_1 + ofs);
27}
28
29__u32 cdb89712_read32(struct map_info *map, unsigned long ofs)
30{
31	return __raw_readl(map->map_priv_1 + ofs);
32}
33
34void cdb89712_write8(struct map_info *map, __u8 d, unsigned long adr)
35{
36	__raw_writeb(d, map->map_priv_1 + adr);
37	mb();
38}
39
40void cdb89712_write16(struct map_info *map, __u16 d, unsigned long adr)
41{
42	__raw_writew(d, map->map_priv_1 + adr);
43	mb();
44}
45
46void cdb89712_write32(struct map_info *map, __u32 d, unsigned long adr)
47{
48	__raw_writel(d, map->map_priv_1 + adr);
49	mb();
50}
51
52void cdb89712_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
53{
54	// printk ("cdb89712_copy_from: 0x%x@0x%x -> 0x%x\n", len, from, to);
55	memcpy_fromio(to, map->map_priv_1 + from, len);
56}
57
58void cdb89712_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
59{
60	while(len) {
61		__raw_writeb(*(unsigned char *) from, map->map_priv_1 + to);
62		from++;
63		to++;
64		len--;
65	}
66}
67
68
69static struct mtd_info *flash_mtd;
70
71struct map_info cdb89712_flash_map = {
72	name: "flash",
73	size: FLASH_SIZE,
74	buswidth: FLASH_WIDTH,
75	read8: cdb89712_read8,
76	read16: cdb89712_read16,
77	read32: cdb89712_read32,
78	copy_from: cdb89712_copy_from,
79	write8: cdb89712_write8,
80	write16: cdb89712_write16,
81	write32: cdb89712_write32,
82	copy_to: cdb89712_copy_to
83};
84
85struct resource cdb89712_flash_resource = {
86	name:   "Flash",
87	start:  FLASH_START,
88	end:    FLASH_START + FLASH_SIZE - 1,
89	flags:  IORESOURCE_IO | IORESOURCE_BUSY,
90};
91
92static int __init init_cdb89712_flash (void)
93{
94	int err;
95
96	if (request_resource (&ioport_resource, &cdb89712_flash_resource)) {
97		printk(KERN_NOTICE "Failed to reserve Cdb89712 FLASH space\n");
98		err = -EBUSY;
99		goto out;
100	}
101
102	cdb89712_flash_map.map_priv_1 = (unsigned long)ioremap(FLASH_START, FLASH_SIZE);
103	if (!cdb89712_flash_map.map_priv_1) {
104		printk(KERN_NOTICE "Failed to ioremap Cdb89712 FLASH space\n");
105		err = -EIO;
106		goto out_resource;
107	}
108
109	flash_mtd = do_map_probe("cfi_probe", &cdb89712_flash_map);
110	if (!flash_mtd) {
111		flash_mtd = do_map_probe("map_rom", &cdb89712_flash_map);
112		if (flash_mtd)
113			flash_mtd->erasesize = 0x10000;
114	}
115	if (!flash_mtd) {
116		printk("FLASH probe failed\n");
117		err = -ENXIO;
118		goto out_ioremap;
119	}
120
121	flash_mtd->module = THIS_MODULE;
122
123	if (add_mtd_device(flash_mtd)) {
124		printk("FLASH device addition failed\n");
125		err = -ENOMEM;
126		goto out_probe;
127	}
128
129	return 0;
130
131out_probe:
132	map_destroy(flash_mtd);
133	flash_mtd = 0;
134out_ioremap:
135	iounmap((void *)cdb89712_flash_map.map_priv_1);
136out_resource:
137	release_resource (&cdb89712_flash_resource);
138out:
139	return err;
140}
141
142
143
144
145
146static struct mtd_info *sram_mtd;
147
148struct map_info cdb89712_sram_map = {
149	name: "SRAM",
150	size: SRAM_SIZE,
151	buswidth: SRAM_WIDTH,
152	read8: cdb89712_read8,
153	read16: cdb89712_read16,
154	read32: cdb89712_read32,
155	copy_from: cdb89712_copy_from,
156	write8: cdb89712_write8,
157	write16: cdb89712_write16,
158	write32: cdb89712_write32,
159	copy_to: cdb89712_copy_to
160};
161
162struct resource cdb89712_sram_resource = {
163	name:   "SRAM",
164	start:  SRAM_START,
165	end:    SRAM_START + SRAM_SIZE - 1,
166	flags:  IORESOURCE_IO | IORESOURCE_BUSY,
167};
168
169static int __init init_cdb89712_sram (void)
170{
171	int err;
172
173	if (request_resource (&ioport_resource, &cdb89712_sram_resource)) {
174		printk(KERN_NOTICE "Failed to reserve Cdb89712 SRAM space\n");
175		err = -EBUSY;
176		goto out;
177	}
178
179	cdb89712_sram_map.map_priv_1 = (unsigned long)ioremap(SRAM_START, SRAM_SIZE);
180	if (!cdb89712_sram_map.map_priv_1) {
181		printk(KERN_NOTICE "Failed to ioremap Cdb89712 SRAM space\n");
182		err = -EIO;
183		goto out_resource;
184	}
185
186	sram_mtd = do_map_probe("map_ram", &cdb89712_sram_map);
187	if (!sram_mtd) {
188		printk("SRAM probe failed\n");
189		err = -ENXIO;
190		goto out_ioremap;
191	}
192
193	sram_mtd->module = THIS_MODULE;
194	sram_mtd->erasesize = 16;
195
196	if (add_mtd_device(sram_mtd)) {
197		printk("SRAM device addition failed\n");
198		err = -ENOMEM;
199		goto out_probe;
200	}
201
202	return 0;
203
204out_probe:
205	map_destroy(sram_mtd);
206	sram_mtd = 0;
207out_ioremap:
208	iounmap((void *)cdb89712_sram_map.map_priv_1);
209out_resource:
210	release_resource (&cdb89712_sram_resource);
211out:
212	return err;
213}
214
215
216
217
218
219
220
221static struct mtd_info *bootrom_mtd;
222
223struct map_info cdb89712_bootrom_map = {
224	name: "BootROM",
225	size: BOOTROM_SIZE,
226	buswidth: BOOTROM_WIDTH,
227	read8: cdb89712_read8,
228	read16: cdb89712_read16,
229	read32: cdb89712_read32,
230	copy_from: cdb89712_copy_from,
231};
232
233struct resource cdb89712_bootrom_resource = {
234	name:   "BootROM",
235	start:  BOOTROM_START,
236	end:    BOOTROM_START + BOOTROM_SIZE - 1,
237	flags:  IORESOURCE_IO | IORESOURCE_BUSY,
238};
239
240static int __init init_cdb89712_bootrom (void)
241{
242	int err;
243
244	if (request_resource (&ioport_resource, &cdb89712_bootrom_resource)) {
245		printk(KERN_NOTICE "Failed to reserve Cdb89712 BOOTROM space\n");
246		err = -EBUSY;
247		goto out;
248	}
249
250	cdb89712_bootrom_map.map_priv_1 = (unsigned long)ioremap(BOOTROM_START, BOOTROM_SIZE);
251	if (!cdb89712_bootrom_map.map_priv_1) {
252		printk(KERN_NOTICE "Failed to ioremap Cdb89712 BootROM space\n");
253		err = -EIO;
254		goto out_resource;
255	}
256
257	bootrom_mtd = do_map_probe("map_rom", &cdb89712_bootrom_map);
258	if (!bootrom_mtd) {
259		printk("BootROM probe failed\n");
260		err = -ENXIO;
261		goto out_ioremap;
262	}
263
264	bootrom_mtd->module = THIS_MODULE;
265	bootrom_mtd->erasesize = 0x10000;
266
267	if (add_mtd_device(bootrom_mtd)) {
268		printk("BootROM device addition failed\n");
269		err = -ENOMEM;
270		goto out_probe;
271	}
272
273	return 0;
274
275out_probe:
276	map_destroy(bootrom_mtd);
277	bootrom_mtd = 0;
278out_ioremap:
279	iounmap((void *)cdb89712_bootrom_map.map_priv_1);
280out_resource:
281	release_resource (&cdb89712_bootrom_resource);
282out:
283	return err;
284}
285
286
287
288
289
290static int __init init_cdb89712_maps(void)
291{
292
293       	printk(KERN_INFO "Cirrus CDB89712 MTD mappings:\n  Flash 0x%x at 0x%x\n  SRAM 0x%x at 0x%x\n  BootROM 0x%x at 0x%x\n",
294	       FLASH_SIZE, FLASH_START, SRAM_SIZE, SRAM_START, BOOTROM_SIZE, BOOTROM_START);
295
296	init_cdb89712_flash();
297	init_cdb89712_sram();
298	init_cdb89712_bootrom();
299
300	return 0;
301}
302
303
304static void __exit cleanup_cdb89712_maps(void)
305{
306	if (sram_mtd) {
307		del_mtd_device(sram_mtd);
308		map_destroy(sram_mtd);
309		iounmap((void *)cdb89712_sram_map.map_priv_1);
310		release_resource (&cdb89712_sram_resource);
311	}
312
313	if (flash_mtd) {
314		del_mtd_device(flash_mtd);
315		map_destroy(flash_mtd);
316		iounmap((void *)cdb89712_flash_map.map_priv_1);
317		release_resource (&cdb89712_flash_resource);
318	}
319
320	if (bootrom_mtd) {
321		del_mtd_device(bootrom_mtd);
322		map_destroy(bootrom_mtd);
323		iounmap((void *)cdb89712_bootrom_map.map_priv_1);
324		release_resource (&cdb89712_bootrom_resource);
325	}
326}
327
328module_init(init_cdb89712_maps);
329module_exit(cleanup_cdb89712_maps);
330
331MODULE_AUTHOR("Ray L");
332MODULE_DESCRIPTION("ARM CDB89712 map driver");
333MODULE_LICENSE("GPL");
334