2 * $Id: ocelot.c,v 1.6 2001/10/02 15:05:14 dwmw2 Exp $
4 * Flash on Momenco Ocelot
7 #include <linux/module.h>
8 #include <linux/types.h>
9 #include <linux/kernel.h>
11 #include <linux/mtd/mtd.h>
12 #include <linux/mtd/map.h>
13 #include <linux/mtd/partitions.h>
15 #define OCELOT_PLD 0x2c000000
16 #define FLASH_WINDOW_ADDR 0x2fc00000
17 #define FLASH_WINDOW_SIZE 0x00080000
18 #define FLASH_BUSWIDTH 1
19 #define NVRAM_WINDOW_ADDR 0x2c800000
20 #define NVRAM_WINDOW_SIZE 0x00007FF0
21 #define NVRAM_BUSWIDTH 1
23 extern int parse_redboot_partitions(struct mtd_info *master, struct mtd_partition **pparts);
25 static unsigned int cacheflush = 0;
27 static struct mtd_info *flash_mtd;
28 static struct mtd_info *nvram_mtd;
30 __u8 ocelot_read8(struct map_info *map, unsigned long ofs)
32 return __raw_readb(map->map_priv_1 + ofs);
35 void ocelot_write8(struct map_info *map, __u8 d, unsigned long adr)
38 __raw_writeb(d, map->map_priv_1 + adr);
42 void ocelot_copy_from_cache(struct map_info *map, void *to, unsigned long from, ssize_t len)
45 dma_cache_inv(map->map_priv_2, map->size);
48 memcpy_fromio(to, map->map_priv_1 + from, len);
51 void ocelot_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
53 memcpy_fromio(to, map->map_priv_1 + from, len);
56 void ocelot_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
58 /* If we use memcpy, it does word-wide writes. Even though we told the
59 GT64120A that it's an 8-bit wide region, word-wide writes don't work.
60 We end up just writing the first byte of the four to all four bytes.
61 So we have this loop instead */
63 __raw_writeb(*(unsigned char *) from, map->map_priv_1 + to);
70 static struct mtd_partition *parsed_parts;
72 struct map_info ocelot_flash_map = {
73 name: "Ocelot boot flash",
74 size: FLASH_WINDOW_SIZE,
75 buswidth: FLASH_BUSWIDTH,
77 copy_from: ocelot_copy_from_cache,
78 write8: ocelot_write8,
81 struct map_info ocelot_nvram_map = {
83 size: NVRAM_WINDOW_SIZE,
84 buswidth: NVRAM_BUSWIDTH,
86 copy_from: ocelot_copy_from,
87 write8: ocelot_write8,
88 copy_to: ocelot_copy_to
91 static int __init init_ocelot_maps(void)
95 unsigned char brd_status;
97 printk(KERN_INFO "Momenco Ocelot MTD mappings: Flash 0x%x at 0x%x, NVRAM 0x%x at 0x%x\n",
98 FLASH_WINDOW_SIZE, FLASH_WINDOW_ADDR, NVRAM_WINDOW_SIZE, NVRAM_WINDOW_ADDR);
100 /* First check whether the flash jumper is present */
101 pld = ioremap(OCELOT_PLD, 0x10);
103 printk(KERN_NOTICE "Failed to ioremap Ocelot PLD\n");
106 brd_status = readb(pld+4);
109 /* Now ioremap the NVRAM space */
110 ocelot_nvram_map.map_priv_1 = (unsigned long)ioremap_nocache(NVRAM_WINDOW_ADDR, NVRAM_WINDOW_SIZE);
111 if (!ocelot_nvram_map.map_priv_1) {
112 printk(KERN_NOTICE "Failed to ioremap Ocelot NVRAM space\n");
115 // ocelot_nvram_map.map_priv_2 = ocelot_nvram_map.map_priv_1;
117 /* And do the RAM probe on it to get an MTD device */
118 nvram_mtd = do_map_probe("map_ram", &ocelot_nvram_map);
120 printk("NVRAM probe failed\n");
123 nvram_mtd->module = THIS_MODULE;
124 nvram_mtd->erasesize = 16;
126 /* Now map the flash space */
127 ocelot_flash_map.map_priv_1 = (unsigned long)ioremap_nocache(FLASH_WINDOW_ADDR, FLASH_WINDOW_SIZE);
128 if (!ocelot_flash_map.map_priv_1) {
129 printk(KERN_NOTICE "Failed to ioremap Ocelot flash space\n");
132 /* Now the cached version */
133 ocelot_flash_map.map_priv_2 = (unsigned long)__ioremap(FLASH_WINDOW_ADDR, FLASH_WINDOW_SIZE, 0);
135 if (!ocelot_flash_map.map_priv_2) {
136 /* Doesn't matter if it failed. Just use the uncached version */
137 ocelot_flash_map.map_priv_2 = ocelot_flash_map.map_priv_1;
140 /* Only probe for flash if the write jumper is present */
141 if (brd_status & 0x40) {
142 flash_mtd = do_map_probe("jedec", &ocelot_flash_map);
144 printk(KERN_NOTICE "Ocelot flash write jumper not present. Treating as ROM\n");
146 /* If that failed or the jumper's absent, pretend it's ROM */
148 flash_mtd = do_map_probe("map_rom", &ocelot_flash_map);
149 /* If we're treating it as ROM, set the erase size */
151 flash_mtd->erasesize = 0x10000;
156 add_mtd_device(nvram_mtd);
158 flash_mtd->module = THIS_MODULE;
159 nr_parts = parse_redboot_partitions(flash_mtd, &parsed_parts);
162 add_mtd_partitions(flash_mtd, parsed_parts, nr_parts);
164 add_mtd_device(flash_mtd);
169 iounmap((void *)ocelot_flash_map.map_priv_1);
170 if (ocelot_flash_map.map_priv_2 &&
171 ocelot_flash_map.map_priv_2 != ocelot_flash_map.map_priv_1)
172 iounmap((void *)ocelot_flash_map.map_priv_2);
174 map_destroy(nvram_mtd);
176 iounmap((void *)ocelot_nvram_map.map_priv_1);
181 static void __exit cleanup_ocelot_maps(void)
183 del_mtd_device(nvram_mtd);
184 map_destroy(nvram_mtd);
185 iounmap((void *)ocelot_nvram_map.map_priv_1);
188 del_mtd_partitions(flash_mtd);
190 del_mtd_device(flash_mtd);
191 map_destroy(flash_mtd);
192 iounmap((void *)ocelot_flash_map.map_priv_1);
193 if (ocelot_flash_map.map_priv_2 != ocelot_flash_map.map_priv_1)
194 iounmap((void *)ocelot_flash_map.map_priv_2);
197 module_init(init_ocelot_maps);
198 module_exit(cleanup_ocelot_maps);
200 MODULE_LICENSE("GPL");
201 MODULE_AUTHOR("Red Hat, Inc. - David Woodhouse <dwmw2@cambridge.redhat.com>");
202 MODULE_DESCRIPTION("MTD map driver for Momenco Ocelot board");