1 /* arch/sh/kernel/pci.c
2 * $Id: altpci.c,v 1.1 2006/07/05 06:23:17 gerg Exp $
4 * Copyright (c) 2002 M. R. Brown <mrbrown@linux-sh.org>
7 * These functions are collected here to reduce duplication of common
8 * code amongst the many platform-specific PCI support code files.
10 * These routines require the following board-specific routines:
11 * void pcibios_fixup_irqs();
13 * See include/asm-sh/pci.h for more information.
16 #include <linux/kernel.h>
17 #include <linux/pci.h>
18 #include <linux/init.h>
21 * Direct access to PCI hardware...
23 #define pcicfg_space (na_pci_compiler_0_PCI_Bus_Access) // avalon space
24 #define pciio (pcicfg_space+0x100000) // pci io device base in avalon space
25 #define pcimm (pcicfg_space+0x200000) // pci mem device base in avalon space
26 // idsel of ad11=dev0,ad12=dev1 , using type 0 config request
27 #define pcicfg(dev,fun,reg) (pcicfg_space | ((dev)<<11) | ((fun)<<8) | (reg)) // cfg space
29 // FIX ME for your board, dram device for external pci masters access
30 static int __init
alt_pci_init(void)
35 outl(nasys_program_mem
,pcicfg(dev
,fun
,0x10)); // mem space
36 outw(0x0006,pcicfg(dev
,fun
,0x04)); // enable master, mem space
40 subsys_initcall(alt_pci_init
);
42 #define PCICFG(bus, devfn, where) (pcicfg_space | (bus->number << 16) | (devfn << 8) | (where & ~3))
43 #define ALT_PCI_IO_BASE (pciio)
44 #define ALT_PCI_IO_SIZE 0x100000
45 #define ALT_PCI_MEMORY_BASE (pcimm)
46 #define ALT_PCI_MEM_SIZE 0x100000
49 * Functions for accessing PCI configuration space with type 1 accesses
52 // FIX ME for your board, number of pci bus, and number of devices
53 static inline int pci_range_ck(struct pci_bus
*bus
, unsigned int devfn
)
55 if (bus
->number
> 0 || PCI_SLOT(devfn
) == 0 || PCI_SLOT(devfn
) > 2)
61 static int alt_pci_read(struct pci_bus
*bus
, unsigned int devfn
,
62 int where
, int size
, u32
*val
)
66 if (pci_range_ck(bus
, devfn
))
67 return PCIBIOS_DEVICE_NOT_FOUND
;
69 // local_irq_save(flags);
70 data
= inl(PCICFG(bus
, devfn
, where
));
71 // local_irq_restore(flags);
75 *val
= (data
>> ((where
& 3) << 3)) & 0xff;
78 *val
= (data
>> ((where
& 2) << 3)) & 0xffff;
84 return PCIBIOS_FUNC_NOT_SUPPORTED
;
87 return PCIBIOS_SUCCESSFUL
;
92 * mask,write operation.
93 * We'll allow an odd byte offset, though it should be illegal.
95 static int alt_pci_write(struct pci_bus
*bus
, unsigned int devfn
,
96 int where
, int size
, u32 val
)
101 if (pci_range_ck(bus
, devfn
))
102 return PCIBIOS_DEVICE_NOT_FOUND
;
104 // local_irq_save(flags);
105 data
= inl(PCICFG(bus
, devfn
, where
));
106 // local_irq_restore(flags);
110 shift
= (where
& 3) << 3;
111 data
&= ~(0xff << shift
);
112 data
|= ((val
& 0xff) << shift
);
115 shift
= (where
& 2) << 3;
116 data
&= ~(0xffff << shift
);
117 data
|= ((val
& 0xffff) << shift
);
123 return PCIBIOS_FUNC_NOT_SUPPORTED
;
126 outl(data
, PCICFG(bus
, devfn
, where
));
128 return PCIBIOS_SUCCESSFUL
;
131 struct pci_ops alt_pci_ops
= {
132 .read
= alt_pci_read
,
133 .write
= alt_pci_write
,
136 static struct resource alt_io_resource
= {
138 .start
= ALT_PCI_IO_BASE
,
139 .end
= ALT_PCI_IO_BASE
+ ALT_PCI_IO_SIZE
- 1,
140 .flags
= IORESOURCE_IO
143 static struct resource alt_mem_resource
= {
144 .name
= "ALTPCI mem",
145 .start
= ALT_PCI_MEMORY_BASE
,
146 .end
= ALT_PCI_MEMORY_BASE
+ ALT_PCI_MEM_SIZE
- 1,
147 .flags
= IORESOURCE_MEM
150 extern struct pci_ops alt_pci_ops
;
152 struct pci_channel board_pci_channels
[] = {
153 { &alt_pci_ops
, &alt_io_resource
, &alt_mem_resource
, 0, 0xff },
154 { NULL
, NULL
, NULL
, 0, 0 },
157 char *pcibios_setup(char *option
)
159 /* Nothing for us to handle. */
163 void pcibios_fixup_bus(struct pci_bus
*b
)
170 static u8 __init
altpci_no_swizzle(struct pci_dev
*dev
, u8
*pin
)
173 return PCI_SLOT(dev
->devfn
);
176 // FIX ME for your board, nios2 irqn mapping
177 int __init
pcibios_map_platform_irq(u8 slot
, u8 pin
)
179 int irq
= na_irqn_0_irq
+ ((slot
-1)*4) + (pin
-1);
180 // printk("map slot %d pin %d irq %d\n",slot,pin,irq);
184 static int altpci_pci_lookup_irq(struct pci_dev
*dev
, u8 slot
, u8 pin
)
188 /* now lookup the actual IRQ on a platform specific basis (pci-'platform'.c) */
189 irq
= pcibios_map_platform_irq(slot
,pin
);
191 // printk("PCI: Error mapping IRQ on device %s\n", pci_name(dev));
195 // printk("Setting IRQ for slot %s to %d\n", pci_name(dev), irq);
200 void __init
pcibios_fixup_irqs(void)
202 pci_fixup_irqs(altpci_no_swizzle
, altpci_pci_lookup_irq
);