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
28 #define FTPCI_IRQ_STATUS_ADDR 0x4c
30 //#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 static int ftpci_read_config_word(struct pci_bus
*bus
, unsigned int devfn
, int where
, u16
*val
)
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
81 #ifdef LOCAL_READ_WRITE_LOCK_IRQ // mask by Victor Yu. 05-15-2006
82 spin_lock_irqsave(&ftpci_lock
, flags
);
84 spin_lock(&ftpci_lock
);
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
);
91 spin_unlock(&ftpci_lock
);
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
)
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
);
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
117 #ifdef LOCAL_READ_WRITE_LOCK_IRQ // mask by Victor Yu. 05-15-2006
118 spin_lock_irqsave(&ftpci_lock
, flags
);
120 spin_lock(&ftpci_lock
);
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
);
127 spin_unlock(&ftpci_lock
);
132 static int ftpci_write_config_byte(struct pci_bus
*bus
, unsigned int devfn
, int where
, u8 val
)
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
)
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
)
167 #ifdef LOCAL_READ_WRITE_LOCK_IRQ // mask by Victor Yu. 05-15-2006
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
);
176 spin_lock(&ftpci_lock
);
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
);
185 spin_unlock(&ftpci_lock
);
189 static int ftpci_write_config_dword(struct pci_bus
*bus
, unsigned int devfn
, int where
, u32 val
)
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
203 spin_lock_irqsave(&ftpci_lock
, flags
);
205 spin_lock(&ftpci_lock
);
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
);
212 spin_unlock(&ftpci_lock
);
216 static int ftpci_read_config(struct pci_bus
*bus
, unsigned int devfn
, int where
,
223 r
= ftpci_read_config_byte(bus
,devfn
,where
,(u8
*)val
);
226 r
= ftpci_read_config_word(bus
,devfn
,where
,(u16
*)val
);
229 r
= ftpci_read_config_dword(bus
,devfn
,where
,val
);
236 static int ftpci_write_config(struct pci_bus
*bus
, unsigned int devfn
, int where
,
243 r
= ftpci_write_config_byte(bus
, devfn
, where
, (u8
)val
);
246 r
= ftpci_write_config_word(bus
, devfn
, where
, (u16
)val
);
249 r
= ftpci_write_config_dword(bus
, devfn
, where
, val
);
252 printk( "Invalid size for ftpci_write()\n" );
253 r
= PCIBIOS_FUNC_NOT_SUPPORTED
; // Luke Lee 03/23/2005 ins 1
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,
272 .start
= CPE_PCI_IO_BASE
,
273 .end
= CPE_PCI_IO_END
-1,
275 .flags
= IORESOURCE_IO
,
277 /* using physical address for memory resource*/
278 static struct resource pci_mem
= {
279 .name
= "PCI Memory Space",
281 .start
= PCI_MEM_VA_BASE
,
282 .end
= PCI_MEM_VA_END
-1,
284 .start
= PCI_MEM_BASE
,
285 .end
= PCI_MEM_END
-1,
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 )
295 if (request_resource(&ioport_resource
, &pci_io
)) {
296 printk(KERN_ERR
"PCI: unable to allocate io region\n");
299 if (request_resource(&iomem_resource
, &pci_mem
)) {
300 printk(KERN_ERR
"PCI: unable to allocate non-prefetchable memory region\n");
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
;
316 inline int ftpci_get_irq(void)
320 ftpci_local_read_config_dword(FTPCI_IRQ_STATUS_ADDR
, &status
);
333 void ftpci_clear_irq(unsigned int irq
)
337 ftpci_local_read_config_dword(FTPCI_IRQ_STATUS_ADDR
, &status
);
341 status
|= 0x10000000;
344 status
|= 0x20000000;
347 status
|= 0x40000000;
350 status
|= 0x80000000;
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)
363 *(volatile unsigned int *)pci_config_addr
=0x0;
368 void __init
ftpci_preinit(void)
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
;
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
);
388 ftpci_local_write_config_word(0x0c, val
);
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
);
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
)) {
412 #ifndef CONFIG_MOXA_SMARTIO_PCIE
417 #ifdef CONFIG_MOXA_SMARTIO_PCIE
422 //johnson add IDSEL 0,14 for NGC project 2008-08-11
423 #ifdef CONFIG_MOXA_SMARTIO_PCIE
425 if(dev
->vendor
==0x159b)break;
432 dbg_printk("Not Support Slot %d\n",slot
);
439 int __init
ftpci_setup(int nr
, struct pci_sys_data
*sys
)
443 dbg_printk("[ftpci_setup test01]\n");
444 if ( ftpci_probed
== 0 || nr
>= 1 )
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 )
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
,
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
);
475 subsys_initcall(a320_pci_init
);