]>
Commit | Line | Data |
---|---|---|
1da177e4 | 1 | /* |
69f34c98 | 2 | * $Id: cstm_mips_ixx.c,v 1.14 2005/11/07 11:14:26 gleixner Exp $ |
1da177e4 LT |
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 | * | |
69f34c98 | 7 | * Basically physmap.c with the addition of partitions and |
1da177e4 LT |
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; | |
69f34c98 | 72 | |
1da177e4 LT |
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; | |
69f34c98 | 88 | |
1da177e4 LT |
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) | |
69f34c98 TG |
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] = | |
1da177e4 LT |
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) */ | |
69f34c98 TG |
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] = | |
1da177e4 | 136 | { |
69f34c98 | 137 | { |
1da177e4 LT |
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] = { | |
69f34c98 | 147 | { |
1da177e4 LT |
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++) { | |
69f34c98 | 168 | printk(KERN_NOTICE "cstm_mips_ixx flash device: 0x%lx at 0x%lx\n", |
1da177e4 LT |
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 | ||
69f34c98 | 238 | *(__u32 *)CC_CONFADDR = offset; |
1da177e4 LT |
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"); |