MOXA linux-2.6.x / linux-2.6.9-uc0 from sdlinux-moxaart.tgz
[linux-2.6.9-moxart.git] / arch / arm / mach-moxacpu / ftpci.c
blobe9aeb89addb7796f04f3ceb06e88611c68595c4f
1 /*
2 History:
3 Date Author Comment
4 11-04-2005 Victor Yu. Create it.
5 */
7 #include <linux/config.h>
8 #include <linux/sched.h>
9 #include <linux/kernel.h>
10 #include <linux/pci.h>
11 #include <linux/ptrace.h>
12 #include <linux/slab.h>
13 #include <linux/ioport.h>
14 #include <linux/interrupt.h>
15 #include <linux/spinlock.h>
16 #include <linux/init.h>
17 #include <asm/hardware.h>
18 #include <asm/irq.h>
19 #include <asm/system.h>
20 #include <asm/mach/pci.h>
21 #include <asm/sizes.h>
22 #include <asm/arch/cpe/cpe.h>
23 #include <asm/arch/cpe_int.h>
24 #include <asm/arch/ftpci.h>
25 #include <asm/mach-types.h>
27 //#define LOCAL_READ_WRITE_LOCK_IRQ 1
28 #define FTPCI_IRQ_STATUS_ADDR 0x4c
30 //#define DEBUG_FTPCI 1
31 #ifdef DEBUG_FTPCI
32 #define dbg_printk(x...) printk(x)
33 #else
34 #define dbg_printk(x...)
35 #endif
37 #define CONFIG_CMD(bus, device_fn, where) (0x80000000 | (bus << 16) | (device_fn << 8) | (where & ~3) )
38 static spinlock_t ftpci_lock;
39 static unsigned int pci_config_addr;
40 static unsigned int pci_config_data;
41 int ftpci_probed=1;
43 static int ftpci_read_config_byte(struct pci_bus *bus, unsigned int devfn, int where, u8 *val)
45 unsigned long flags;
46 u32 v;
47 unsigned int shift;
49 spin_lock_irqsave(&ftpci_lock, flags);
50 *(volatile unsigned int *)pci_config_addr=CONFIG_CMD(bus->number,devfn,where);
51 v=*(volatile unsigned int *)pci_config_data;
52 spin_unlock_irqrestore(&ftpci_lock, flags);
53 shift = (where&0x3)*8;
54 *val = (v>>shift)&0xff;
55 return PCIBIOS_SUCCESSFUL;
58 static int ftpci_read_config_word(struct pci_bus *bus, unsigned int devfn, int where, u16 *val)
60 unsigned long flags;
61 u32 v;
62 unsigned int shift;
64 spin_lock_irqsave(&ftpci_lock, flags);
65 *(volatile unsigned int *)pci_config_addr=CONFIG_CMD(bus->number,devfn,where);
66 v=*(volatile unsigned int *)pci_config_data;
67 spin_unlock_irqrestore(&ftpci_lock, flags);
68 shift = (where&0x3)*8;
69 *val = (v>>shift)&0xffff;
70 return PCIBIOS_SUCCESSFUL;
73 static void ftpci_local_read_config_word(int where, u16 *val)
75 #ifdef LOCAL_READ_WRITE_LOCK_IRQ // mask by Victor Yu. 05-15-2006
76 unsigned long flags;
77 #endif
78 u32 v;
79 unsigned int shift;
81 #ifdef LOCAL_READ_WRITE_LOCK_IRQ // mask by Victor Yu. 05-15-2006
82 spin_lock_irqsave(&ftpci_lock, flags);
83 #else
84 spin_lock(&ftpci_lock);
85 #endif
86 *(volatile unsigned int *)pci_config_addr=CONFIG_CMD(0,0,where);
87 v=*(volatile unsigned int *)pci_config_data;
88 #ifdef LOCAL_READ_WRITE_LOCK_IRQ // mask by Victor Yu. 05-15-2006
89 spin_unlock_irqrestore(&ftpci_lock, flags);
90 #else
91 spin_unlock(&ftpci_lock);
92 #endif
93 shift = (where&0x3)*8;
94 *val = (v>>shift)&0xffff;
97 static int ftpci_read_config_dword(struct pci_bus *bus, unsigned int devfn, int where, u32 *val)
99 unsigned long flags;
100 u32 v;
102 spin_lock_irqsave(&ftpci_lock, flags);
103 *(volatile unsigned int *)pci_config_addr=CONFIG_CMD(bus->number,devfn,where);
104 v=*(volatile unsigned int *)pci_config_data;
105 spin_unlock_irqrestore(&ftpci_lock, flags);
106 *val = v;
107 return PCIBIOS_SUCCESSFUL;
110 static void ftpci_local_read_config_dword(int where, u32 *val)
112 #ifdef LOCAL_READ_WRITE_LOCK_IRQ // mask by Victor Yu. 05-15-2006
113 unsigned long flags;
114 #endif
115 u32 v;
117 #ifdef LOCAL_READ_WRITE_LOCK_IRQ // mask by Victor Yu. 05-15-2006
118 spin_lock_irqsave(&ftpci_lock, flags);
119 #else
120 spin_lock(&ftpci_lock);
121 #endif
122 *(volatile unsigned int *)pci_config_addr=CONFIG_CMD(0,0,where);
123 v=*(volatile unsigned int *)pci_config_data;
124 #ifdef LOCAL_READ_WRITE_LOCK_IRQ // mask by Victor Yu. 05-15-2006
125 spin_unlock_irqrestore(&ftpci_lock, flags);
126 #else
127 spin_unlock(&ftpci_lock);
128 #endif
129 *val = v;
132 static int ftpci_write_config_byte(struct pci_bus *bus, unsigned int devfn, int where, u8 val)
134 u32 org_val;
135 unsigned long flags;
136 unsigned int shift;
138 shift = (where&0x3)*8;
139 spin_lock_irqsave(&ftpci_lock, flags);
140 *(volatile unsigned int *)pci_config_addr=CONFIG_CMD(bus->number,devfn,where);
141 org_val=*(volatile unsigned int *)pci_config_data;
142 org_val=(org_val&~(0xff<<shift))|((u32)val<<shift);
143 *(volatile unsigned int *)pci_config_data=org_val;
144 spin_unlock_irqrestore(&ftpci_lock, flags);
145 return PCIBIOS_SUCCESSFUL;
148 static int ftpci_write_config_word(struct pci_bus *bus, unsigned int devfn, int where, u16 val)
150 u32 org_val;
151 unsigned long flags;
152 unsigned int shift;
154 shift = (where&0x3)*8;
155 spin_lock_irqsave(&ftpci_lock, flags);
156 *(volatile unsigned int *)pci_config_addr=CONFIG_CMD(bus->number, devfn, where);
157 org_val=*(volatile unsigned int *)pci_config_data;
158 org_val=(org_val&~(0xffff<<shift))|((u32)val<<shift);
159 *(volatile unsigned int *)pci_config_data=org_val;
160 spin_unlock_irqrestore(&ftpci_lock, flags);
161 return PCIBIOS_SUCCESSFUL;
164 static void ftpci_local_write_config_word(int where, u16 val)
166 u32 org_val;
167 #ifdef LOCAL_READ_WRITE_LOCK_IRQ // mask by Victor Yu. 05-15-2006
168 unsigned long flags;
169 #endif
170 unsigned int shift;
172 shift = (where&0x3)*8;
173 #ifdef LOCAL_READ_WRITE_LOCK_IRQ // mask by Victor Yu. 05-15-2006
174 spin_lock_irqsave(&ftpci_lock, flags);
175 #else
176 spin_lock(&ftpci_lock);
177 #endif
178 *(volatile unsigned int *)pci_config_addr=CONFIG_CMD(0, 0, where);
179 org_val=*(volatile unsigned int *)pci_config_data;
180 org_val=(org_val&~(0xffff<<shift))|((u32)val<<shift);
181 *(volatile unsigned int *)pci_config_data=org_val;
182 #ifdef LOCAL_READ_WRITE_LOCK_IRQ // mask by Victor Yu. 05-15-2006
183 spin_unlock_irqrestore(&ftpci_lock, flags);
184 #else
185 spin_unlock(&ftpci_lock);
186 #endif
189 static int ftpci_write_config_dword(struct pci_bus *bus, unsigned int devfn, int where, u32 val)
191 unsigned long flags;
192 spin_lock_irqsave(&ftpci_lock, flags);
193 *(volatile unsigned int *)pci_config_addr=CONFIG_CMD(bus->number, devfn, where);
194 *(volatile unsigned int *)pci_config_data=val;
195 spin_unlock_irqrestore(&ftpci_lock, flags);
196 return PCIBIOS_SUCCESSFUL;
199 static void ftpci_local_write_config_dword(int where, u32 val)
201 #ifdef LOCAL_READ_WRITE_LOCK_IRQ // mask by Victor Yu. 05-15-2006
202 unsigned long flags;
203 spin_lock_irqsave(&ftpci_lock, flags);
204 #else
205 spin_lock(&ftpci_lock);
206 #endif
207 *(volatile unsigned int *)pci_config_addr=CONFIG_CMD(0, 0, where);
208 *(volatile unsigned int *)pci_config_data=val;
209 #ifdef LOCAL_READ_WRITE_LOCK_IRQ // mask by Victor Yu. 05-15-2006
210 spin_unlock_irqrestore(&ftpci_lock, flags);
211 #else
212 spin_unlock(&ftpci_lock);
213 #endif
216 static int ftpci_read_config(struct pci_bus *bus, unsigned int devfn, int where,
217 int size, u32 *val)
219 int r;
221 switch (size) {
222 case 1:
223 r = ftpci_read_config_byte(bus,devfn,where,(u8*)val);
224 break;
225 case 2:
226 r = ftpci_read_config_word(bus,devfn,where,(u16*)val);
227 break;
228 default:
229 r = ftpci_read_config_dword(bus,devfn,where,val);
230 break;
233 return r;
236 static int ftpci_write_config(struct pci_bus *bus, unsigned int devfn, int where,
237 int size, u32 val)
239 int r;
241 switch (size) {
242 case 1:
243 r = ftpci_write_config_byte(bus, devfn, where, (u8)val);
244 break;
245 case 2:
246 r = ftpci_write_config_word(bus, devfn, where, (u16)val);
247 break;
248 case 4:
249 r = ftpci_write_config_dword(bus, devfn, where, val);
250 break;
251 default:
252 printk( "Invalid size for ftpci_write()\n" );
253 r = PCIBIOS_FUNC_NOT_SUPPORTED; // Luke Lee 03/23/2005 ins 1
256 return r;
259 static struct pci_ops ftpci_ops = {
260 .read = ftpci_read_config,
261 .write = ftpci_write_config,
264 /* You need to write the physical address to PCI mapping for bridge */
265 /* You need to modify the source file drivers/pci/setup-res.c */
266 static struct resource pci_io = {
267 .name = "PCI I/O Space",
268 #if 1 // mask by Victor Yu. 01-09-2006
269 .start = PCI_IO_VA_BASE,
270 .end = PCI_IO_VA_END-1,
271 #else
272 .start = CPE_PCI_IO_BASE,
273 .end = CPE_PCI_IO_END-1,
274 #endif
275 .flags = IORESOURCE_IO,
277 /* using physical address for memory resource*/
278 static struct resource pci_mem = {
279 .name = "PCI Memory Space",
280 #if 1
281 .start = PCI_MEM_VA_BASE,
282 .end = PCI_MEM_VA_END-1,
283 #else
284 .start = PCI_MEM_BASE,
285 .end = PCI_MEM_END-1,
286 #endif
287 .flags = IORESOURCE_MEM,
290 // Luke Lee 03/23/2005 unrem 1 rem 1
291 int __init ftpci_setup_resource(struct resource **resource)
293 if ( ftpci_probed == 0 )
294 return 0;
295 if (request_resource(&ioport_resource, &pci_io)) {
296 printk(KERN_ERR "PCI: unable to allocate io region\n");
297 return 0;
299 if (request_resource(&iomem_resource, &pci_mem)) {
300 printk(KERN_ERR "PCI: unable to allocate non-prefetchable memory region\n");
301 return 0;
305 * bus->resource[0] is the IO resource for this bus
306 * bus->resource[1] is the mem resource for this bus
307 * bus->resource[2] is the prefetch mem resource for this bus
309 resource[0] = &pci_io;
310 resource[1] = &pci_mem;
311 resource[2] = NULL;
313 return 1;
316 inline int ftpci_get_irq(void)
318 unsigned int status;
320 ftpci_local_read_config_dword(FTPCI_IRQ_STATUS_ADDR, &status);
321 status >>= 28;
322 if ( status & 0x1 )
323 return 0;
324 if ( status & 0x2 )
325 return 1;
326 if ( status & 0x4 )
327 return 2;
328 if ( status & 0x8 )
329 return 3;
330 return -1;
333 void ftpci_clear_irq(unsigned int irq)
335 unsigned int status;
337 ftpci_local_read_config_dword(FTPCI_IRQ_STATUS_ADDR, &status);
338 status &= 0xfffffff;
339 switch ( irq ) {
340 case 0 :
341 status |= 0x10000000;
342 break;
343 case 1 :
344 status |= 0x20000000;
345 break;
346 case 2 :
347 status |= 0x40000000;
348 break;
349 case 3 :
350 status |= 0x80000000;
351 break;
353 ftpci_local_write_config_dword(FTPCI_IRQ_STATUS_ADDR, status);
356 static int ftpci_probe(void)
358 *(volatile unsigned int *)pci_config_addr=0x80000000;
359 if(*(volatile unsigned int *)pci_config_addr==0x80000000)
360 ftpci_probed=1;
361 else
362 ftpci_probed=0;
363 *(volatile unsigned int *)pci_config_addr=0x0;
365 return ftpci_probed;
368 void __init ftpci_preinit(void)
370 u16 val;
372 dbg_printk("[ftpci_preinit test01]\n");
373 pci_config_addr=CPE_PCI_VA_BASE+FTPCI_CFG_ADR_REG;
374 pci_config_data=CPE_PCI_VA_BASE+FTPCI_CFG_DATA_REG;
376 if( !ftpci_probe() )
377 return;
379 dbg_printk("[ftpci_preinit test03]\n");
380 spin_lock_init(&ftpci_lock);
382 #if 1 // add by Victor Yu. 05-24-2006
383 *(volatile unsigned int *)(CPE_PCI_VA_BASE+FTPCI_IOSIZE_REG) = FTPCI_BASE_IO_SIZE_4M;
384 *(volatile unsigned int *)(CPE_PCI_VA_BASE+FTPCI_PROT_REG) = 1;
385 ftpci_local_read_config_word(0x0c, &val);
386 val &= 0x7ff;
387 val |= 0xa800;
388 ftpci_local_write_config_word(0x0c, val);
389 #endif
390 ftpci_local_read_config_word(PCI_INT_MASK,&val);
391 val|=(PCI_INTA_ENABLE|PCI_INTB_ENABLE|PCI_INTC_ENABLE|PCI_INTD_ENABLE);
392 ftpci_local_write_config_word(PCI_INT_MASK,val);
393 ftpci_local_write_config_dword(PCI_MEM_BASE_SIZE1, FTPCI_BASE_ADR_SIZE_1GB);
397 * This routine handles multiple bridges.
399 static u8 __init cpe_swizzle(struct pci_dev *dev, u8 *pinp)
401 dbg_printk( "cpe_swizzle(%X,%X)\n\r",(unsigned)dev,(unsigned)pinp );
402 return 0;
405 static int __init cpe_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
407 dbg_printk("cpe_map_irq,slot=%d pin=%d\n",PCI_SLOT(dev->devfn),pin);
408 switch(PCI_SLOT(dev->devfn)) {
409 case 8:
411 case 12:
412 #ifndef CONFIG_MOXA_SMARTIO_PCIE
413 case 13:
414 #endif
415 return VIRQ_PCI_A;
416 case 9:
417 #ifdef CONFIG_MOXA_SMARTIO_PCIE
418 case 13:
419 #endif
420 return VIRQ_PCI_B;
421 case 10:
422 //johnson add IDSEL 0,14 for NGC project 2008-08-11
423 #ifdef CONFIG_MOXA_SMARTIO_PCIE
424 case 0:
425 if(dev->vendor==0x159b)break;
426 case 14:
427 #endif
428 return VIRQ_PCI_C;
429 case 11:
430 return VIRQ_PCI_B;
431 default:
432 dbg_printk("Not Support Slot %d\n",slot);
433 break;
436 return -1;
439 int __init ftpci_setup(int nr, struct pci_sys_data *sys)
441 int ret = 0;
443 dbg_printk("[ftpci_setup test01]\n");
444 if ( ftpci_probed == 0 || nr >= 1 )
445 return ret;
446 dbg_printk("[ftpci_setup test02]\n");
447 return ftpci_setup_resource(sys->resource);
450 static struct pci_bus *ftpci_scan_bus(int nr, struct pci_sys_data *sys)
452 dbg_printk("[ftpci_scan_bus test01]\n");
453 if ( ftpci_probed == 0 )
454 return NULL;
455 return pci_scan_bus(sys->busnr, &ftpci_ops, sys);
458 static struct hw_pci cpe_pci __initdata = {
459 .swizzle = cpe_swizzle,
460 .map_irq = cpe_map_irq,
461 .setup = ftpci_setup,
462 .nr_controllers = 1,
463 .scan = ftpci_scan_bus,
464 .preinit = ftpci_preinit,
467 static int __init a320_pci_init(void)
469 dbg_printk("[pci_init test01]\n");
470 if (machine_is_moxacpu())
471 pci_common_init(&cpe_pci);
472 return 0;
475 subsys_initcall(a320_pci_init);