MOXA linux-2.6.x / linux-2.6.19-uc1 from UC-7110-LX-BOOTLOADER-1.9_VERSION-4.2.tgz
[linux-2.6.19-moxart.git] / arch / arm / mach-moxart / pci.c
blob54218756a51addbf835cc5ca50019ac171cdbba1
1 /*
2 ftpci.h
3 maintened by ivan wang 2004/8/18 11:25
4 Modified by Luke Lee 03/21/2005
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/moxa.h>
23 #include <asm/arch/ftpci.h>
24 #include <asm/mach-types.h> // Luke Lee 03/23/2005 ins 1
26 #ifdef CONFIG_PCI
27 #ifdef CONFIG_CPE120_PLATFORM
28 #include <asm/arch/cpe/cpe_ext_int.h>
29 #endif
31 #define DEBUG_FTPCI 1
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;
38 int ftpci_probed=0;
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)
43 unsigned long flags;
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)
52 u32 org_val;
53 unsigned long flags;
54 unsigned int shift;
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)
67 unsigned long flags;
68 u32 v;
69 unsigned int shift;
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)
81 unsigned long flags;
82 u32 v;
83 unsigned int shift;
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)
96 unsigned long flags;
97 u32 v;
98 unsigned int shift;
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)
111 unsigned long flags;
112 u32 v;
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);
118 *val = v;
119 return PCIBIOS_SUCCESSFUL;
122 static int ftpci_write_config_byte(struct pci_bus *bus, unsigned int devfn, int where, u8 val)
124 u32 org_val;
125 unsigned long flags;
126 unsigned int shift;
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)
140 u32 org_val;
141 unsigned long flags;
142 unsigned int shift;
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)
156 unsigned long flags;
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,
167 int size, u32 *val)
169 int r;
170 switch (size) {
171 case 1:
172 r = ftpci_read_config_byte(bus,devfn,where,(u8*)val); // Luke Lee TOFIX 03/22/2005 : convert to (u8*) -- beware of endian !
173 break;
175 case 2:
176 r = ftpci_read_config_word(bus,devfn,where,(u16*)val); // Luke Lee TOFIX 03/22/2005 : convert to (u16*) -- beware of endian !
177 break;
179 default:
180 r = ftpci_read_config_dword(bus,devfn,where,val);
181 break;
184 return r;
187 static int ftpci_write_config(struct pci_bus *bus, unsigned int devfn, int where,
188 int size, u32 val)
190 int r;
191 switch (size) {
192 case 1:
193 r = ftpci_write_config_byte(bus, devfn, where, val);
194 break;
196 case 2:
197 r = ftpci_write_config_word(bus, devfn, where, val);
198 break;
200 case 4:
201 r = ftpci_write_config_dword(bus, devfn, where, val);
202 break;
203 default:
204 printk( "Invalid size for ftpci_write()\n" );
205 r = PCIBIOS_FUNC_NOT_SUPPORTED; // Luke Lee 03/23/2005 ins 1
208 return r;
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 = {
222 .name = "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,
231 .end = PCI_MEM_END,
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 "
245 "memory region\n");
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)
263 unsigned int status;
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);
266 status=(status>>28);
267 if(status&0x1)
268 return 0;
269 if(status&0x2)
270 return 1;
271 if(status&0x4)
272 return 2;
273 if(status&0x8)
274 return 3;
275 return -1;
278 void ftpci_clear_irq(unsigned int irq)
280 //int i;
281 unsigned int status;
282 ftpci_read_config_dword(pci_bridge->bus, pci_bridge->devfn, 0x4c, &status); // Luke Lee 03/22/2005 mod 1
283 if(irq==0)
284 status=(status&0xfffffff)|((0x1)<<28);
285 else if(irq==1)
286 status=(status&0xfffffff)|((0x2)<<28);
287 else if(irq==2)
288 status=(status&0xfffffff)|((0x4)<<28);
289 else if(irq==3)
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)
299 ftpci_probed=1;
300 else
301 ftpci_probed=0;
302 *(volatile unsigned int *)addr=0x0;
303 return ftpci_probed;
307 void __init ftpci_preinit(void /**sysdata*/) // Luke Lee 03/22/2005 mod 1
309 u16 val;
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;
313 #if 0
314 if(!ftpci_probe(pci_config_addr))
315 return;
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)
320 return;
321 #endif
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
339 return 0;
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))
347 case 8:
348 return VIRQ_PCI_A;
349 case 9:
350 return VIRQ_PCI_B;
351 case 10:
352 return VIRQ_PCI_C;
353 case 11:
354 return VIRQ_PCI_D;
355 default:
356 //printk("Not Support Slot %d\n",slot);
357 break;
359 return -1;
362 #if 0 // Luke Lee 03/22/2005 rem block
363 struct hw_pci cpe_pci __initdata = {
364 .setup_resources = ftpci_setup_resource,
365 .init = ftpci_init,
366 .swizzle = cpe_swizzle,
367 .map_irq = cpe_map_irq,
369 #endif
371 // Luke Lee 03/22/2005 ins begin
373 int __init ftpci_setup(int nr, struct pci_sys_data *sys)
375 int ret = 0;
377 if (nr == 0) {
378 sys->mem_offset = CPE_PCI_MEM; // Luke Lee TOFIX : 03/22/2005 : or CPE_PCI_BASE ???
379 ret = ftpci_setup_resource(sys->resource);
381 return ret;
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,
393 .nr_controllers = 1,
394 .scan = ftpci_scan_bus,
395 // TOFIX
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);
403 return 0;
406 subsys_initcall(a320_pci_init);
408 // Luke Lee 03/22/2005 ins begin
409 #endif //CONFIG_PCI