3 maintened by ivan wang 2004/8/18 11:25
4 Modified by Luke Lee 03/21/2005
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/moxa.h>
23 #include <asm/arch/ftpci.h>
24 #include <asm/mach-types.h> // Luke Lee 03/23/2005 ins 1
27 #ifdef CONFIG_CPE120_PLATFORM
28 #include <asm/arch/cpe/cpe_ext_int.h>
33 #define CONFIG_CMD(bus, device_fn, where) (0x80000000 | (bus << 16) | (device_fn << 8) | (where & ~3) )
34 static spinlock_t ftpci_lock
;
35 struct pci_dev
*pci_bridge
=NULL
;
36 static unsigned int pci_config_addr
;
37 static unsigned int pci_config_data
;
40 // Luke Lee 03/21/2005 mod begin
41 static int ftpci_write_config_dlocal(struct pci_bus
*bus
, unsigned int devfn
, int where
, u32 val
)
44 spin_lock_irqsave(&ftpci_lock
, flags
);
45 *(volatile unsigned int *)pci_config_addr
=CONFIG_CMD(0, 0, where
);
46 *(volatile unsigned int *)pci_config_data
=val
;
47 spin_unlock_irqrestore(&ftpci_lock
, flags
);
48 return PCIBIOS_SUCCESSFUL
;
50 static int ftpci_write_config_wlocal(struct pci_bus
*bus
, unsigned int devfn
, int where
, u16 val
)
56 shift
= (where
&0x3)*8;
57 spin_lock_irqsave(&ftpci_lock
, flags
);
58 *(volatile unsigned int *)pci_config_addr
=CONFIG_CMD(0,0 , where
);
59 org_val
=*(volatile unsigned int *)pci_config_data
;
60 org_val
=(org_val
&~(0xffff<<shift
))|((u32
)val
<<shift
);
61 *(volatile unsigned int *)pci_config_data
=org_val
;
62 spin_unlock_irqrestore(&ftpci_lock
, flags
);
63 return PCIBIOS_SUCCESSFUL
;
65 static int ftpci_read_config_wlocal(struct pci_bus
*bus
, unsigned int devfn
, int where
, u16
*val
)
71 spin_lock_irqsave(&ftpci_lock
, flags
);
72 *(volatile unsigned int *)pci_config_addr
=CONFIG_CMD(0,0,where
);
73 v
=*(volatile unsigned int *)pci_config_data
;
74 spin_unlock_irqrestore(&ftpci_lock
, flags
);
75 shift
= (where
&0x3)*8;
76 *val
= (v
>>shift
)&0xffff;
77 return PCIBIOS_SUCCESSFUL
;
79 static int ftpci_read_config_byte(struct pci_bus
*bus
, unsigned int devfn
, int where
, u8
*val
)
85 spin_lock_irqsave(&ftpci_lock
, flags
);
86 *(volatile unsigned int *)pci_config_addr
=CONFIG_CMD(bus
->number
,devfn
,where
);
87 v
=*(volatile unsigned int *)pci_config_data
;
88 spin_unlock_irqrestore(&ftpci_lock
, flags
);
89 shift
= (where
&0x3)*8;
90 *val
= (v
>>shift
)&0xff;
91 return PCIBIOS_SUCCESSFUL
;
94 static int ftpci_read_config_word(struct pci_bus
*bus
, unsigned int devfn
, int where
, u16
*val
)
100 spin_lock_irqsave(&ftpci_lock
, flags
);
101 *(volatile unsigned int *)pci_config_addr
=CONFIG_CMD(bus
->number
,devfn
,where
);
102 v
=*(volatile unsigned int *)pci_config_data
;
103 spin_unlock_irqrestore(&ftpci_lock
, flags
);
104 shift
= (where
&0x3)*8;
105 *val
= (v
>>shift
)&0xffff;
106 return PCIBIOS_SUCCESSFUL
;
109 static int ftpci_read_config_dword(struct pci_bus
*bus
, unsigned int devfn
, int where
, u32
*val
)
114 spin_lock_irqsave(&ftpci_lock
, flags
);
115 *(volatile unsigned int *)pci_config_addr
=CONFIG_CMD(bus
->number
,devfn
,where
);
116 v
=*(volatile unsigned int *)pci_config_data
;
117 spin_unlock_irqrestore(&ftpci_lock
, flags
);
119 return PCIBIOS_SUCCESSFUL
;
122 static int ftpci_write_config_byte(struct pci_bus
*bus
, unsigned int devfn
, int where
, u8 val
)
128 shift
= (where
&0x3)*8;
129 spin_lock_irqsave(&ftpci_lock
, flags
);
130 *(volatile unsigned int *)pci_config_addr
=CONFIG_CMD(bus
->number
,devfn
,where
);
131 org_val
=*(volatile unsigned int *)pci_config_data
;
132 org_val
=(org_val
&~(0xff<<shift
))|((u32
)val
<<shift
);
133 *(volatile unsigned int *)pci_config_data
=org_val
;
134 spin_unlock_irqrestore(&ftpci_lock
, flags
);
135 return PCIBIOS_SUCCESSFUL
;
138 static int ftpci_write_config_word(struct pci_bus
*bus
, unsigned int devfn
, int where
, u16 val
)
144 shift
= (where
&0x3)*8;
145 spin_lock_irqsave(&ftpci_lock
, flags
);
146 *(volatile unsigned int *)pci_config_addr
=CONFIG_CMD(bus
->number
, devfn
, where
);
147 org_val
=*(volatile unsigned int *)pci_config_data
;
148 org_val
=(org_val
&~(0xffff<<shift
))|((u32
)val
<<shift
);
149 *(volatile unsigned int *)pci_config_data
=org_val
;
150 spin_unlock_irqrestore(&ftpci_lock
, flags
);
151 return PCIBIOS_SUCCESSFUL
;
154 static int ftpci_write_config_dword(struct pci_bus
*bus
, unsigned int devfn
, int where
, u32 val
)
157 spin_lock_irqsave(&ftpci_lock
, flags
);
158 *(volatile unsigned int *)pci_config_addr
=CONFIG_CMD(bus
->number
, devfn
, where
);
159 *(volatile unsigned int *)pci_config_data
=val
;
160 spin_unlock_irqrestore(&ftpci_lock
, flags
);
161 return PCIBIOS_SUCCESSFUL
;
163 // Luke Lee 03/21/2005 mod end
165 // Luke Lee 03/21/2005 ins begin
166 static int ftpci_read_config(struct pci_bus
*bus
, unsigned int devfn
, int where
,
172 r
= ftpci_read_config_byte(bus
,devfn
,where
,(u8
*)val
); // Luke Lee TOFIX 03/22/2005 : convert to (u8*) -- beware of endian !
176 r
= ftpci_read_config_word(bus
,devfn
,where
,(u16
*)val
); // Luke Lee TOFIX 03/22/2005 : convert to (u16*) -- beware of endian !
180 r
= ftpci_read_config_dword(bus
,devfn
,where
,val
);
187 static int ftpci_write_config(struct pci_bus
*bus
, unsigned int devfn
, int where
,
193 r
= ftpci_write_config_byte(bus
, devfn
, where
, val
);
197 r
= ftpci_write_config_word(bus
, devfn
, where
, val
);
201 r
= ftpci_write_config_dword(bus
, devfn
, where
, val
);
204 printk( "Invalid size for ftpci_write()\n" );
205 r
= PCIBIOS_FUNC_NOT_SUPPORTED
; // Luke Lee 03/23/2005 ins 1
211 // Luke Lee 03/21/2005 ins end
213 static struct pci_ops ftpci_ops
= {
214 // Luke Lee 03/21/2005 mod begin
215 .read
= ftpci_read_config
,
216 .write
= ftpci_write_config
,
217 // Luke Lee 03/21/2005 mod end
220 /* using virtual address for pci_resource_start() function*/
221 static struct resource pci_io
= {
223 .start
= PCI_IO_VA_BASE
,
224 .end
= PCI_IO_VA_END
,
225 .flags
= IORESOURCE_IO
,
227 /* using physical address for memory resource*/
228 static struct resource pci_mem
= {
229 .name
= "PCI non-prefetchable",
230 .start
= PCI_MEM_BASE
,
232 .flags
= IORESOURCE_MEM
,
235 // Luke Lee 03/23/2005 unrem 1 rem 1
236 int __init
ftpci_setup_resource(struct resource
**resource
)
237 //void __init ftpci_setup_resource(struct resource **resource)
239 if (request_resource(&ioport_resource
, &pci_io
)) {
240 printk(KERN_ERR
"PCI: unable to allocate io region\n");
241 return -EBUSY
; // Luke Lee 03/23/2005 unrem 1
243 if (request_resource(&iomem_resource
, &pci_mem
)) {
244 printk(KERN_ERR
"PCI: unable to allocate non-prefetchable "
246 return -EBUSY
; // Luke Lee 03/23/2005 unrem 1
250 * bus->resource[0] is the IO resource for this bus
251 * bus->resource[1] is the mem resource for this bus
252 * bus->resource[2] is the prefetch mem resource for this bus
255 resource
[0] = &pci_io
;
256 resource
[1] = &pci_mem
;
258 return 1; // Luke Lee 03/23/2005 unrem 1
261 inline int ftpci_get_irq(void)
264 ftpci_read_config_dword(pci_bridge
->bus
, pci_bridge
->devfn
, 0x4c, &status
); // Luke Lee 03/22/2005 mod 1
265 printk("ftpci_get_irq,status=0x%x\n",status
);
278 void ftpci_clear_irq(unsigned int irq
)
282 ftpci_read_config_dword(pci_bridge
->bus
, pci_bridge
->devfn
, 0x4c, &status
); // Luke Lee 03/22/2005 mod 1
284 status
=(status
&0xfffffff)|((0x1)<<28);
286 status
=(status
&0xfffffff)|((0x2)<<28);
288 status
=(status
&0xfffffff)|((0x4)<<28);
290 status
=(status
&0xfffffff)|((0x8)<<28);
291 ftpci_write_config_dword(pci_bridge
->bus
, pci_bridge
->devfn
, 0x4c, status
); // Luke Lee 03/22/2005 mod 1
294 static int ftpci_probe(unsigned int addr_p
)
296 unsigned int *addr
=(unsigned int*)addr_p
;
297 *(volatile unsigned int *)addr
=0x80000000;
298 if(*(volatile unsigned int *)addr
==0x80000000)
302 *(volatile unsigned int *)addr
=0x0;
307 void __init
ftpci_preinit(void /**sysdata*/) // Luke Lee 03/22/2005 mod 1
310 printk( "ftpci_init()\n\r" ); // Luke Lee 03/22/2005 ins 1
311 pci_config_addr
=CPE_PCI_VA_BASE
+FTPCI_CFG_ADR_REG
;
312 pci_config_data
=CPE_PCI_VA_BASE
+FTPCI_CFG_DATA_REG
;
314 if(!ftpci_probe(pci_config_addr
))
317 //pci_scan_bus(0, &ftpci_ops, sysdata); // Luke Lee 03/22/2005 rem 1
318 pci_bridge
=pci_find_device(PCI_BRIDGE_VENID
,PCI_BRIDGE_DEVID
,NULL
);
319 if (pci_bridge
== NULL
)
322 spin_lock_init(&ftpci_lock
);
324 // Enable the Interrupt Mask (INTA/INTB/INTC/INTD)
325 ftpci_read_config_wlocal(pci_bridge
->bus
,pci_bridge
->devfn
,PCI_INT_MASK
,&val
); // Luke Lee 03/22/2005 mod 1
326 val
|=(PCI_INTA_ENABLE
|PCI_INTB_ENABLE
|PCI_INTC_ENABLE
|PCI_INTD_ENABLE
);
327 ftpci_write_config_wlocal(pci_bridge
->bus
,pci_bridge
->devfn
,PCI_INT_MASK
,val
);// Luke Lee 03/22/2005 mod 1
329 // Write DMA Start Address/Size Data to the Bridge configuration space
330 ftpci_write_config_dlocal(pci_bridge
->bus
, pci_bridge
->devfn
, PCI_MEM_BASE_SIZE1
, FTPCI_BASE_ADR_SIZE_1GB
); // Luke Lee 03/22/2005 mod 1
334 * This routine handles multiple bridges.
336 static u8 __init
cpe_swizzle(struct pci_dev
*dev
, u8
*pinp
)
338 printk( "cpe_swizzle(%X,%X)\n\r",(unsigned)dev
,(unsigned)pinp
); // Luke Lee 03/22/2005 ins 1
342 static int __init
cpe_map_irq(struct pci_dev
*dev
, u8 slot
, u8 pin
)
344 printk("cpe_map_irq,slot=%d pin=%d\n",PCI_SLOT(dev
->devfn
),pin
);
345 switch(PCI_SLOT(dev
->devfn
))
356 //printk("Not Support Slot %d\n",slot);
362 #if 0 // Luke Lee 03/22/2005 rem block
363 struct hw_pci cpe_pci __initdata
= {
364 .setup_resources
= ftpci_setup_resource
,
366 .swizzle
= cpe_swizzle
,
367 .map_irq
= cpe_map_irq
,
371 // Luke Lee 03/22/2005 ins begin
373 int __init
ftpci_setup(int nr
, struct pci_sys_data
*sys
)
378 sys
->mem_offset
= CPE_PCI_MEM
; // Luke Lee TOFIX : 03/22/2005 : or CPE_PCI_BASE ???
379 ret
= ftpci_setup_resource(sys
->resource
);
384 static struct pci_bus
*ftpci_scan_bus(int nr
, struct pci_sys_data
*sys
)
386 return pci_scan_bus(sys
->busnr
, &ftpci_ops
, sys
);
389 static struct hw_pci cpe_pci __initdata
= {
390 .swizzle
= cpe_swizzle
,
391 .map_irq
= cpe_map_irq
,
392 .setup
= ftpci_setup
,
394 .scan
= ftpci_scan_bus
,
396 .preinit
= ftpci_preinit
,
397 //.postinit = pci_v3_postinit, // no post init function
400 static int __init
a320_pci_init(void)
402 pci_common_init(&cpe_pci
);
406 subsys_initcall(a320_pci_init
);
408 // Luke Lee 03/22/2005 ins begin