File: /usr/src/linux/drivers/mtd/maps/ocelot.c
1 /*
2 * $Id: ocelot.c,v 1.4 2001/06/08 15:36:27 dwmw2 Exp $
3 *
4 * Flash on Momenco Ocelot
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/mtd/partitions.h>
14
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
22
23 extern int parse_redboot_partitions(struct mtd_info *master, struct mtd_partition **pparts);
24
25 static unsigned int cacheflush = 0;
26
27 static struct mtd_info *flash_mtd;
28 static struct mtd_info *nvram_mtd;
29
30 __u8 ocelot_read8(struct map_info *map, unsigned long ofs)
31 {
32 return __raw_readb(map->map_priv_1 + ofs);
33 }
34
35 void ocelot_write8(struct map_info *map, __u8 d, unsigned long adr)
36 {
37 cacheflush = 1;
38 __raw_writeb(d, map->map_priv_1 + adr);
39 mb();
40 }
41
42 void ocelot_copy_from_cache(struct map_info *map, void *to, unsigned long from, ssize_t len)
43 {
44 if (cacheflush) {
45 dma_cache_inv(map->map_priv_2, map->size);
46 cacheflush = 0;
47 }
48 memcpy_fromio(to, map->map_priv_1 + from, len);
49 }
50
51 void ocelot_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
52 {
53 memcpy_fromio(to, map->map_priv_1 + from, len);
54 }
55
56 void ocelot_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
57 {
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 */
62 while(len) {
63 __raw_writeb(*(unsigned char *) from, map->map_priv_1 + to);
64 from++;
65 to++;
66 len--;
67 }
68 }
69
70 static struct mtd_partition *parsed_parts;
71
72 struct map_info ocelot_flash_map = {
73 name: "Ocelot boot flash",
74 size: FLASH_WINDOW_SIZE,
75 buswidth: FLASH_BUSWIDTH,
76 read8: ocelot_read8,
77 copy_from: ocelot_copy_from_cache,
78 write8: ocelot_write8,
79 };
80
81 struct map_info ocelot_nvram_map = {
82 name: "Ocelot NVRAM",
83 size: NVRAM_WINDOW_SIZE,
84 buswidth: NVRAM_BUSWIDTH,
85 read8: ocelot_read8,
86 copy_from: ocelot_copy_from,
87 write8: ocelot_write8,
88 copy_to: ocelot_copy_to
89 };
90
91 static int __init init_ocelot_maps(void)
92 {
93 void *pld;
94 int nr_parts;
95 unsigned char brd_status;
96
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);
99
100 /* First check whether the flash jumper is present */
101 pld = ioremap(OCELOT_PLD, 0x10);
102 if (!pld) {
103 printk(KERN_NOTICE "Failed to ioremap Ocelot PLD\n");
104 return -EIO;
105 }
106 brd_status = readb(pld+4);
107 iounmap(pld);
108
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");
113 return -EIO;
114 }
115 // ocelot_nvram_map.map_priv_2 = ocelot_nvram_map.map_priv_1;
116
117 /* And do the RAM probe on it to get an MTD device */
118 nvram_mtd = do_map_probe("ram", &ocelot_nvram_map);
119 if (!nvram_mtd) {
120 printk("NVRAM probe failed\n");
121 goto fail_1;
122 }
123 nvram_mtd->module = THIS_MODULE;
124 nvram_mtd->erasesize = 16;
125
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");
130 goto fail_2;
131 }
132 /* Now the cached version */
133 ocelot_flash_map.map_priv_2 = (unsigned long)__ioremap(FLASH_WINDOW_ADDR, FLASH_WINDOW_SIZE, 0);
134
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;
138 }
139
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);
143 } else {
144 printk(KERN_NOTICE "Ocelot flash write jumper not present. Treating as ROM\n");
145 }
146 /* If that failed or the jumper's absent, pretend it's ROM */
147 if (!flash_mtd) {
148 flash_mtd = do_map_probe("rom", &ocelot_flash_map);
149 /* If we're treating it as ROM, set the erase size */
150 if (flash_mtd)
151 flash_mtd->erasesize = 0x10000;
152 }
153 if (!flash_mtd)
154 goto fail3;
155
156 add_mtd_device(nvram_mtd);
157
158 flash_mtd->module = THIS_MODULE;
159 nr_parts = parse_redboot_partitions(flash_mtd, &parsed_parts);
160
161 if (nr_parts)
162 add_mtd_partitions(flash_mtd, parsed_parts, nr_parts);
163 else
164 add_mtd_device(flash_mtd);
165
166 return 0;
167
168 fail3:
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);
173 fail_2:
174 map_destroy(nvram_mtd);
175 fail_1:
176 iounmap((void *)ocelot_nvram_map.map_priv_1);
177
178 return -ENXIO;
179 }
180
181 static void __exit cleanup_ocelot_maps(void)
182 {
183 del_mtd_device(nvram_mtd);
184 map_destroy(nvram_mtd);
185 iounmap((void *)ocelot_nvram_map.map_priv_1);
186
187 if (parsed_parts)
188 del_mtd_partitions(flash_mtd);
189 else
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);
195 }
196
197 module_init(init_ocelot_maps);
198 module_exit(cleanup_ocelot_maps);
199
200