diff options
Diffstat (limited to 'drivers/mtd/maps/cstm_mips_ixx.c')
-rw-r--r-- | drivers/mtd/maps/cstm_mips_ixx.c | 270 |
1 files changed, 270 insertions, 0 deletions
diff --git a/drivers/mtd/maps/cstm_mips_ixx.c b/drivers/mtd/maps/cstm_mips_ixx.c new file mode 100644 index 000000000000..ae9252fbf176 --- /dev/null +++ b/drivers/mtd/maps/cstm_mips_ixx.c | |||
@@ -0,0 +1,270 @@ | |||
1 | /* | ||
2 | * $Id: cstm_mips_ixx.c,v 1.12 2004/11/04 13:24:14 gleixner Exp $ | ||
3 | * | ||
4 | * Mapping of a custom board with both AMD CFI and JEDEC flash in partitions. | ||
5 | * Config with both CFI and JEDEC device support. | ||
6 | * | ||
7 | * Basically physmap.c with the addition of partitions and | ||
8 | * an array of mapping info to accomodate more than one flash type per board. | ||
9 | * | ||
10 | * Copyright 2000 MontaVista Software Inc. | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify it | ||
13 | * under the terms of the GNU General Public License as published by the | ||
14 | * Free Software Foundation; either version 2 of the License, or (at your | ||
15 | * option) any later version. | ||
16 | * | ||
17 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
18 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
19 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN | ||
20 | * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
22 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | ||
23 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
24 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
27 | * | ||
28 | * You should have received a copy of the GNU General Public License along | ||
29 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
30 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
31 | */ | ||
32 | |||
33 | #include <linux/module.h> | ||
34 | #include <linux/types.h> | ||
35 | #include <linux/kernel.h> | ||
36 | #include <linux/init.h> | ||
37 | #include <asm/io.h> | ||
38 | #include <linux/mtd/mtd.h> | ||
39 | #include <linux/mtd/map.h> | ||
40 | #include <linux/mtd/partitions.h> | ||
41 | #include <linux/config.h> | ||
42 | #include <linux/delay.h> | ||
43 | |||
44 | #if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) | ||
45 | #define CC_GCR 0xB4013818 | ||
46 | #define CC_GPBCR 0xB401380A | ||
47 | #define CC_GPBDR 0xB4013808 | ||
48 | #define CC_M68K_DEVICE 1 | ||
49 | #define CC_M68K_FUNCTION 6 | ||
50 | #define CC_CONFADDR 0xB8004000 | ||
51 | #define CC_CONFDATA 0xB8004004 | ||
52 | #define CC_FC_FCR 0xB8002004 | ||
53 | #define CC_FC_DCR 0xB8002008 | ||
54 | #define CC_GPACR 0xB4013802 | ||
55 | #define CC_GPAICR 0xB4013804 | ||
56 | #endif /* defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) */ | ||
57 | |||
58 | #if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) | ||
59 | void cstm_mips_ixx_set_vpp(struct map_info *map,int vpp) | ||
60 | { | ||
61 | static DEFINE_SPINLOCK(vpp_lock); | ||
62 | static int vpp_count = 0; | ||
63 | unsigned long flags; | ||
64 | |||
65 | spin_lock_irqsave(&vpp_lock, flags); | ||
66 | |||
67 | if (vpp) { | ||
68 | if (!vpp_count++) { | ||
69 | __u16 data; | ||
70 | __u8 data1; | ||
71 | static u8 first = 1; | ||
72 | |||
73 | // Set GPIO port B pin3 to high | ||
74 | data = *(__u16 *)(CC_GPBCR); | ||
75 | data = (data & 0xff0f) | 0x0040; | ||
76 | *(__u16 *)CC_GPBCR = data; | ||
77 | *(__u8 *)CC_GPBDR = (*(__u8*)CC_GPBDR) | 0x08; | ||
78 | if (first) { | ||
79 | first = 0; | ||
80 | /* need to have this delay for first | ||
81 | enabling vpp after powerup */ | ||
82 | udelay(40); | ||
83 | } | ||
84 | } | ||
85 | } else { | ||
86 | if (!--vpp_count) { | ||
87 | __u16 data; | ||
88 | |||
89 | // Set GPIO port B pin3 to high | ||
90 | data = *(__u16 *)(CC_GPBCR); | ||
91 | data = (data & 0xff3f) | 0x0040; | ||
92 | *(__u16 *)CC_GPBCR = data; | ||
93 | *(__u8 *)CC_GPBDR = (*(__u8*)CC_GPBDR) & 0xf7; | ||
94 | } | ||
95 | } | ||
96 | spin_unlock_irqrestore(&vpp_lock, flags); | ||
97 | } | ||
98 | #endif | ||
99 | |||
100 | /* board and partition description */ | ||
101 | |||
102 | #define MAX_PHYSMAP_PARTITIONS 8 | ||
103 | struct cstm_mips_ixx_info { | ||
104 | char *name; | ||
105 | unsigned long window_addr; | ||
106 | unsigned long window_size; | ||
107 | int bankwidth; | ||
108 | int num_partitions; | ||
109 | }; | ||
110 | |||
111 | #if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) | ||
112 | #define PHYSMAP_NUMBER 1 // number of board desc structs needed, one per contiguous flash type | ||
113 | const struct cstm_mips_ixx_info cstm_mips_ixx_board_desc[PHYSMAP_NUMBER] = | ||
114 | { | ||
115 | { // 28F128J3A in 2x16 configuration | ||
116 | "big flash", // name | ||
117 | 0x08000000, // window_addr | ||
118 | 0x02000000, // window_size | ||
119 | 4, // bankwidth | ||
120 | 1, // num_partitions | ||
121 | } | ||
122 | |||
123 | }; | ||
124 | static struct mtd_partition cstm_mips_ixx_partitions[PHYSMAP_NUMBER][MAX_PHYSMAP_PARTITIONS] = { | ||
125 | { // 28F128J3A in 2x16 configuration | ||
126 | { | ||
127 | .name = "main partition ", | ||
128 | .size = 0x02000000, // 128 x 2 x 128k byte sectors | ||
129 | .offset = 0, | ||
130 | }, | ||
131 | }, | ||
132 | }; | ||
133 | #else /* defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) */ | ||
134 | #define PHYSMAP_NUMBER 1 // number of board desc structs needed, one per contiguous flash type | ||
135 | const struct cstm_mips_ixx_info cstm_mips_ixx_board_desc[PHYSMAP_NUMBER] = | ||
136 | { | ||
137 | { | ||
138 | "MTD flash", // name | ||
139 | CONFIG_MTD_CSTM_MIPS_IXX_START, // window_addr | ||
140 | CONFIG_MTD_CSTM_MIPS_IXX_LEN, // window_size | ||
141 | CONFIG_MTD_CSTM_MIPS_IXX_BUSWIDTH, // bankwidth | ||
142 | 1, // num_partitions | ||
143 | }, | ||
144 | |||
145 | }; | ||
146 | static struct mtd_partition cstm_mips_ixx_partitions[PHYSMAP_NUMBER][MAX_PHYSMAP_PARTITIONS] = { | ||
147 | { | ||
148 | { | ||
149 | .name = "main partition", | ||
150 | .size = CONFIG_MTD_CSTM_MIPS_IXX_LEN, | ||
151 | .offset = 0, | ||
152 | }, | ||
153 | }, | ||
154 | }; | ||
155 | #endif /* defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) */ | ||
156 | |||
157 | struct map_info cstm_mips_ixx_map[PHYSMAP_NUMBER]; | ||
158 | |||
159 | int __init init_cstm_mips_ixx(void) | ||
160 | { | ||
161 | int i; | ||
162 | int jedec; | ||
163 | struct mtd_info *mymtd; | ||
164 | struct mtd_partition *parts; | ||
165 | |||
166 | /* Initialize mapping */ | ||
167 | for (i=0;i<PHYSMAP_NUMBER;i++) { | ||
168 | printk(KERN_NOTICE "cstm_mips_ixx flash device: 0x%lx at 0x%lx\n", | ||
169 | cstm_mips_ixx_board_desc[i].window_size, cstm_mips_ixx_board_desc[i].window_addr); | ||
170 | |||
171 | |||
172 | cstm_mips_ixx_map[i].phys = cstm_mips_ixx_board_desc[i].window_addr; | ||
173 | cstm_mips_ixx_map[i].virt = ioremap(cstm_mips_ixx_board_desc[i].window_addr, cstm_mips_ixx_board_desc[i].window_size); | ||
174 | if (!cstm_mips_ixx_map[i].virt) { | ||
175 | printk(KERN_WARNING "Failed to ioremap\n"); | ||
176 | return -EIO; | ||
177 | } | ||
178 | cstm_mips_ixx_map[i].name = cstm_mips_ixx_board_desc[i].name; | ||
179 | cstm_mips_ixx_map[i].size = cstm_mips_ixx_board_desc[i].window_size; | ||
180 | cstm_mips_ixx_map[i].bankwidth = cstm_mips_ixx_board_desc[i].bankwidth; | ||
181 | #if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) | ||
182 | cstm_mips_ixx_map[i].set_vpp = cstm_mips_ixx_set_vpp; | ||
183 | #endif | ||
184 | simple_map_init(&cstm_mips_ixx_map[i]); | ||
185 | //printk(KERN_NOTICE "cstm_mips_ixx: ioremap is %x\n",(unsigned int)(cstm_mips_ixx_map[i].virt)); | ||
186 | } | ||
187 | |||
188 | #if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) | ||
189 | setup_ITE_IVR_flash(); | ||
190 | #endif /* defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) */ | ||
191 | |||
192 | for (i=0;i<PHYSMAP_NUMBER;i++) { | ||
193 | parts = &cstm_mips_ixx_partitions[i][0]; | ||
194 | jedec = 0; | ||
195 | mymtd = (struct mtd_info *)do_map_probe("cfi_probe", &cstm_mips_ixx_map[i]); | ||
196 | //printk(KERN_NOTICE "phymap %d cfi_probe: mymtd is %x\n",i,(unsigned int)mymtd); | ||
197 | if (!mymtd) { | ||
198 | jedec = 1; | ||
199 | mymtd = (struct mtd_info *)do_map_probe("jedec", &cstm_mips_ixx_map[i]); | ||
200 | printk(KERN_NOTICE "cstm_mips_ixx %d jedec: mymtd is %x\n",i,(unsigned int)mymtd); | ||
201 | } | ||
202 | if (mymtd) { | ||
203 | mymtd->owner = THIS_MODULE; | ||
204 | |||
205 | cstm_mips_ixx_map[i].map_priv_2 = (unsigned long)mymtd; | ||
206 | add_mtd_partitions(mymtd, parts, cstm_mips_ixx_board_desc[i].num_partitions); | ||
207 | } | ||
208 | else | ||
209 | return -ENXIO; | ||
210 | } | ||
211 | return 0; | ||
212 | } | ||
213 | |||
214 | static void __exit cleanup_cstm_mips_ixx(void) | ||
215 | { | ||
216 | int i; | ||
217 | struct mtd_info *mymtd; | ||
218 | |||
219 | for (i=0;i<PHYSMAP_NUMBER;i++) { | ||
220 | mymtd = (struct mtd_info *)cstm_mips_ixx_map[i].map_priv_2; | ||
221 | if (mymtd) { | ||
222 | del_mtd_partitions(mymtd); | ||
223 | map_destroy(mymtd); | ||
224 | } | ||
225 | if (cstm_mips_ixx_map[i].virt) { | ||
226 | iounmap((void *)cstm_mips_ixx_map[i].virt); | ||
227 | cstm_mips_ixx_map[i].virt = 0; | ||
228 | } | ||
229 | } | ||
230 | } | ||
231 | #if defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) | ||
232 | void PCISetULongByOffset(__u32 DevNumber, __u32 FuncNumber, __u32 Offset, __u32 data) | ||
233 | { | ||
234 | __u32 offset; | ||
235 | |||
236 | offset = ( unsigned long )( 0x80000000 | ( DevNumber << 11 ) + ( FuncNumber << 8 ) + Offset) ; | ||
237 | |||
238 | *(__u32 *)CC_CONFADDR = offset; | ||
239 | *(__u32 *)CC_CONFDATA = data; | ||
240 | } | ||
241 | void setup_ITE_IVR_flash() | ||
242 | { | ||
243 | __u32 size, base; | ||
244 | |||
245 | size = 0x0e000000; // 32MiB | ||
246 | base = (0x08000000) >> 8 >>1; // Bug: we must shift one more bit | ||
247 | |||
248 | /* need to set ITE flash to 32 bits instead of default 8 */ | ||
249 | #ifdef CONFIG_MIPS_IVR | ||
250 | *(__u32 *)CC_FC_FCR = 0x55; | ||
251 | *(__u32 *)CC_GPACR = 0xfffc; | ||
252 | #else | ||
253 | *(__u32 *)CC_FC_FCR = 0x77; | ||
254 | #endif | ||
255 | /* turn bursting off */ | ||
256 | *(__u32 *)CC_FC_DCR = 0x0; | ||
257 | |||
258 | /* setup for one chip 4 byte PCI access */ | ||
259 | PCISetULongByOffset(CC_M68K_DEVICE, CC_M68K_FUNCTION, 0x60, size | base); | ||
260 | PCISetULongByOffset(CC_M68K_DEVICE, CC_M68K_FUNCTION, 0x64, 0x02); | ||
261 | } | ||
262 | #endif /* defined(CONFIG_MIPS_ITE8172) || defined(CONFIG_MIPS_IVR) */ | ||
263 | |||
264 | module_init(init_cstm_mips_ixx); | ||
265 | module_exit(cleanup_cstm_mips_ixx); | ||
266 | |||
267 | |||
268 | MODULE_LICENSE("GPL"); | ||
269 | MODULE_AUTHOR("Alice Hennessy <ahennessy@mvista.com>"); | ||
270 | MODULE_DESCRIPTION("MTD map driver for ITE 8172G and Globespan IVR boards"); | ||