4 11-04-2005 Victor Yu. Create it.
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>
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
29 //#define DEBUG_FTPCI 1
32 #define dbg_printk(x...) printk(x)
34 #define dbg_printk(x...)
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;
43 static int ftpci_read_config_byte(struct pci_bus *bus, unsigned int devfn, int where, u8 *val)
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 #if 0 // mask by Victor Yu. 01-09-2006, No used, so I mask it.
59 static int ftpci_local_read_config_byte(int where, u8 *val)
65 spin_lock_irqsave(&ftpci_lock, flags);
66 *(volatile unsigned int *)pci_config_addr=CONFIG_CMD(0,0,where);
67 v=*(volatile unsigned int *)pci_config_data;
68 spin_unlock_irqrestore(&ftpci_lock, flags);
69 shift = (where&0x3)*8;
70 *val = (v>>shift)&0xff;
71 return PCIBIOS_SUCCESSFUL;
75 static int ftpci_read_config_word(struct pci_bus *bus, unsigned int devfn, int where, u16 *val)
81 spin_lock_irqsave(&ftpci_lock, flags);
82 *(volatile unsigned int *)pci_config_addr=CONFIG_CMD(bus->number,devfn,where);
83 v=*(volatile unsigned int *)pci_config_data;
84 spin_unlock_irqrestore(&ftpci_lock, flags);
85 shift = (where&0x3)*8;
86 *val = (v>>shift)&0xffff;
87 return PCIBIOS_SUCCESSFUL;
90 static void ftpci_local_read_config_word(int where, u16 *val)
92 #if LOCAL_READ_WRITE_LOCK_IRQ // mask by Victor Yu. 05-15-2006
98 #if LOCAL_READ_WRITE_LOCK_IRQ // mask by Victor Yu. 05-15-2006
99 spin_lock_irqsave(&ftpci_lock, flags);
101 *(volatile unsigned int *)pci_config_addr=CONFIG_CMD(0,0,where);
102 v=*(volatile unsigned int *)pci_config_data;
103 #if LOCAL_READ_WRITE_LOCK_IRQ // mask by Victor Yu. 05-15-2006
104 spin_unlock_irqrestore(&ftpci_lock, flags);
106 shift = (where&0x3)*8;
107 *val = (v>>shift)&0xffff;
110 static int ftpci_read_config_dword(struct pci_bus *bus, unsigned int devfn, int where, u32 *val)
115 spin_lock_irqsave(&ftpci_lock, flags);
116 *(volatile unsigned int *)pci_config_addr=CONFIG_CMD(bus->number,devfn,where);
117 v=*(volatile unsigned int *)pci_config_data;
118 spin_unlock_irqrestore(&ftpci_lock, flags);
120 return PCIBIOS_SUCCESSFUL;
123 static void ftpci_local_read_config_dword(int where, u32 *val)
125 #if LOCAL_READ_WRITE_LOCK_IRQ // mask by Victor Yu. 05-15-2006
130 #if LOCAL_READ_WRITE_LOCK_IRQ // mask by Victor Yu. 05-15-2006
131 spin_lock_irqsave(&ftpci_lock, flags);
133 *(volatile unsigned int *)pci_config_addr=CONFIG_CMD(0,0,where);
134 v=*(volatile unsigned int *)pci_config_data;
135 #if LOCAL_READ_WRITE_LOCK_IRQ // mask by Victor Yu. 05-15-2006
136 spin_unlock_irqrestore(&ftpci_lock, flags);
141 static int ftpci_write_config_byte(struct pci_bus *bus, unsigned int devfn, int where, u8 val)
147 shift = (where&0x3)*8;
148 spin_lock_irqsave(&ftpci_lock, flags);
149 *(volatile unsigned int *)pci_config_addr=CONFIG_CMD(bus->number,devfn,where);
150 org_val=*(volatile unsigned int *)pci_config_data;
151 org_val=(org_val&~(0xff<<shift))|((u32)val<<shift);
152 *(volatile unsigned int *)pci_config_data=org_val;
153 spin_unlock_irqrestore(&ftpci_lock, flags);
154 return PCIBIOS_SUCCESSFUL;
157 #if 0 // mask by Victor Yu. 01-09-2006, No used, so I mask it.
158 static int ftpci_local_write_config_byte(int where, u8 val)
164 shift = (where&0x3)*8;
165 spin_lock_irqsave(&ftpci_lock, flags);
166 *(volatile unsigned int *)pci_config_addr=CONFIG_CMD(0,0,where);
167 org_val=*(volatile unsigned int *)pci_config_data;
168 org_val=(org_val&~(0xff<<shift))|((u32)val<<shift);
169 *(volatile unsigned int *)pci_config_data=org_val;
170 spin_unlock_irqrestore(&ftpci_lock, flags);
171 return PCIBIOS_SUCCESSFUL;
175 static int ftpci_write_config_word(struct pci_bus *bus, unsigned int devfn, int where, u16 val)
181 shift = (where&0x3)*8;
182 spin_lock_irqsave(&ftpci_lock, flags);
183 *(volatile unsigned int *)pci_config_addr=CONFIG_CMD(bus->number, devfn, where);
184 org_val=*(volatile unsigned int *)pci_config_data;
185 org_val=(org_val&~(0xffff<<shift))|((u32)val<<shift);
186 *(volatile unsigned int *)pci_config_data=org_val;
187 spin_unlock_irqrestore(&ftpci_lock, flags);
188 return PCIBIOS_SUCCESSFUL;
191 static void ftpci_local_write_config_word(int where, u16 val)
194 #if LOCAL_READ_WRITE_LOCK_IRQ // mask by Victor Yu. 05-15-2006
199 shift = (where&0x3)*8;
200 #if LOCAL_READ_WRITE_LOCK_IRQ // mask by Victor Yu. 05-15-2006
201 spin_lock_irqsave(&ftpci_lock, flags);
203 *(volatile unsigned int *)pci_config_addr=CONFIG_CMD(0, 0, where);
204 org_val=*(volatile unsigned int *)pci_config_data;
205 org_val=(org_val&~(0xffff<<shift))|((u32)val<<shift);
206 *(volatile unsigned int *)pci_config_data=org_val;
207 #if LOCAL_READ_WRITE_LOCK_IRQ // mask by Victor Yu. 05-15-2006
208 spin_unlock_irqrestore(&ftpci_lock, flags);
212 static int ftpci_write_config_dword(struct pci_bus *bus, unsigned int devfn, int where, u32 val)
215 spin_lock_irqsave(&ftpci_lock, flags);
216 *(volatile unsigned int *)pci_config_addr=CONFIG_CMD(bus->number, devfn, where);
217 *(volatile unsigned int *)pci_config_data=val;
218 spin_unlock_irqrestore(&ftpci_lock, flags);
219 return PCIBIOS_SUCCESSFUL;
222 static void ftpci_local_write_config_dword(int where, u32 val)
224 #if LOCAL_READ_WRITE_LOCK_IRQ // mask by Victor Yu. 05-15-2006
226 spin_lock_irqsave(&ftpci_lock, flags);
228 *(volatile unsigned int *)pci_config_addr=CONFIG_CMD(0, 0, where);
229 *(volatile unsigned int *)pci_config_data=val;
230 #if LOCAL_READ_WRITE_LOCK_IRQ // mask by Victor Yu. 05-15-2006
231 spin_unlock_irqrestore(&ftpci_lock, flags);
235 static int ftpci_read_config(struct pci_bus *bus, unsigned int devfn, int where,
242 r = ftpci_read_config_byte(bus,devfn,where,(u8*)val);
246 r = ftpci_read_config_word(bus,devfn,where,(u16*)val);
250 r = ftpci_read_config_dword(bus,devfn,where,val);
257 static int ftpci_write_config(struct pci_bus *bus, unsigned int devfn, int where,
264 r = ftpci_write_config_byte(bus, devfn, where, (u8)val);
268 r = ftpci_write_config_word(bus, devfn, where, (u16)val);
272 r = ftpci_write_config_dword(bus, devfn, where, val);
275 printk( "Invalid size for ftpci_write()\n" );
276 r = PCIBIOS_FUNC_NOT_SUPPORTED; // Luke Lee 03/23/2005 ins 1
282 static struct pci_ops ftpci_ops = {
283 .read = ftpci_read_config,
284 .write = ftpci_write_config,
287 /* You need to write the physical address to PCI mapping for bridge */
288 /* You need to modify the source file drivers/pci/setup-res.c */
289 static struct resource pci_io = {
290 .name = "PCI I/O Space",
291 #if 1 // mask by Victor Yu. 01-09-2006
292 .start = PCI_IO_VA_BASE,
293 .end = PCI_IO_VA_END-1,
295 .start = CPE_PCI_IO_BASE,
296 .end = CPE_PCI_IO_END-1,
298 .flags = IORESOURCE_IO,
300 /* using physical address for memory resource*/
301 static struct resource pci_mem = {
302 .name = "PCI Memory Space",
304 .start = PCI_MEM_VA_BASE,
305 .end = PCI_MEM_VA_END-1,
307 .start = PCI_MEM_BASE,
308 .end = PCI_MEM_END-1,
310 .flags = IORESOURCE_MEM,
313 // Luke Lee 03/23/2005 unrem 1 rem 1
314 int __init ftpci_setup_resource(struct resource **resource)
316 if ( ftpci_probed == 0 )
319 if (request_resource(&ioport_resource, &pci_io)) {
320 printk(KERN_ERR "PCI: unable to allocate io region\n");
323 if (request_resource(&iomem_resource, &pci_mem)) {
324 printk(KERN_ERR "PCI: unable to allocate non-prefetchable "
330 * bus->resource[0] is the IO resource for this bus
331 * bus->resource[1] is the mem resource for this bus
332 * bus->resource[2] is the prefetch mem resource for this bus
335 resource[0] = &pci_io;
336 resource[1] = &pci_mem;
342 inline int ftpci_get_irq(void)
346 ftpci_local_read_config_dword(0x4c, &status);
359 void ftpci_clear_irq(unsigned int irq)
363 ftpci_local_read_config_dword(0x4c, &status);
365 status=(status&0xfffffff)|((0x1)<<28);
367 status=(status&0xfffffff)|((0x2)<<28);
369 status=(status&0xfffffff)|((0x4)<<28);
371 status=(status&0xfffffff)|((0x8)<<28);
372 ftpci_local_write_config_dword(0x4c, status);
375 static int ftpci_probe(void)
377 *(volatile unsigned int *)pci_config_addr=0x80000000;
378 if(*(volatile unsigned int *)pci_config_addr==0x80000000)
382 *(volatile unsigned int *)pci_config_addr=0x0;
387 void __init ftpci_preinit(void)
391 dbg_printk("[ftpci_preinit test01]\n");
392 pci_config_addr=CPE_PCI_VA_BASE+FTPCI_CFG_ADR_REG;
393 pci_config_data=CPE_PCI_VA_BASE+FTPCI_CFG_DATA_REG;
398 dbg_printk("[ftpci_preinit test03]\n");
399 spin_lock_init(&ftpci_lock);
401 ftpci_local_read_config_word(PCI_INT_MASK,&val);
402 val|=(PCI_INTA_ENABLE|PCI_INTB_ENABLE|PCI_INTC_ENABLE|PCI_INTD_ENABLE);
403 ftpci_local_write_config_word(PCI_INT_MASK,val);
405 ftpci_local_write_config_dword(PCI_MEM_BASE_SIZE1, FTPCI_BASE_ADR_SIZE_1GB);
407 ftpci_local_write_config_dword(PCI_MEM_BASE_SIZE1, FTPCI_BASE_ADR_SIZE_1GB);
408 ftpci_local_write_config_dword(PCI_MEM_BASE_SIZE2, FTPCI_BASE_ADR_SIZE_1GB);
409 ftpci_local_write_config_dword(PCI_MEM_BASE_SIZE3, FTPCI_BASE_ADR_SIZE_1GB);
414 * This routine handles multiple bridges.
416 static u8 __init cpe_swizzle(struct pci_dev *dev, u8 *pinp)
418 dbg_printk( "cpe_swizzle(%X,%X)\n\r",(unsigned)dev,(unsigned)pinp );
422 static int __init cpe_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
424 dbg_printk("cpe_map_irq,slot=%d pin=%d\n",PCI_SLOT(dev->devfn),pin);
425 #if 1 // mask by Victor Yu. 12-28-2005
426 switch(PCI_SLOT(dev->devfn)) {
437 #else // add by Victor Yu. 12-28-2005
438 switch( PCI_SLOT(dev->devfn) & 0x3 ) {
449 dbg_printk("Not Support Slot %d\n",slot);
456 int __init ftpci_setup(int nr, struct pci_sys_data *sys)
460 dbg_printk("[ftpci_setup test01]\n");
461 if ( ftpci_probed == 0 || nr >= 1 )
463 dbg_printk("[ftpci_setup test02]\n");
464 #if 0 // mask by Victor Yu. 10-27-2005
466 sys->mem_offset = CPE_PCI_MEM;
467 ret = ftpci_setup_resource(sys->resource);
470 #else // add by Victor Yu. 10-27-2005
471 return ftpci_setup_resource(sys->resource);
475 static struct pci_bus *ftpci_scan_bus(int nr, struct pci_sys_data *sys)
477 dbg_printk("[ftpci_scan_bus test01]\n");
478 if ( ftpci_probed == 0 )
480 return pci_scan_bus(sys->busnr, &ftpci_ops, sys);
483 static struct hw_pci cpe_pci __initdata = {
484 .swizzle = cpe_swizzle,
485 .map_irq = cpe_map_irq,
486 .setup = ftpci_setup,
488 .scan = ftpci_scan_bus,
489 .preinit = ftpci_preinit,
492 static int __init a320_pci_init(void)
494 dbg_printk("[pci_init test01]\n");
495 if (machine_is_moxacpu())
496 pci_common_init(&cpe_pci);
500 subsys_initcall(a320_pci_init);