1 | /** |
---|
2 | * @file |
---|
3 | * @ingroup cchip |
---|
4 | * @bief Companion Chip PCI board driver |
---|
5 | */ |
---|
6 | |
---|
7 | /* |
---|
8 | * GR-701 (Companion Chip) PCI board driver |
---|
9 | * |
---|
10 | * The license and distribution terms for this file may be |
---|
11 | * found in the file LICENSE in this distribution or at |
---|
12 | * http://www.rtems.com/license/LICENSE. |
---|
13 | */ |
---|
14 | |
---|
15 | #include <bsp.h> |
---|
16 | #include <rtems/bspIo.h> |
---|
17 | #include <rtems.h> |
---|
18 | #include <string.h> |
---|
19 | |
---|
20 | #include <rtems.h> |
---|
21 | #include <leon.h> |
---|
22 | #include <ambapp.h> |
---|
23 | #include <pci.h> |
---|
24 | |
---|
25 | #include <b1553brm_pci.h> |
---|
26 | #include <occan_pci.h> |
---|
27 | #include <grspw_pci.h> |
---|
28 | #include <apbuart_pci.h> |
---|
29 | |
---|
30 | #include <cchip.h> |
---|
31 | |
---|
32 | /* |
---|
33 | #define DEBUG |
---|
34 | #define DEBUG_IRQS |
---|
35 | */ |
---|
36 | #define BOARD_INFO |
---|
37 | /*#define PRINT_SPURIOUS*/ |
---|
38 | |
---|
39 | /* AT697 Register MAP */ |
---|
40 | static LEON_Register_Map *regs = (LEON_Register_Map *)0x80000000; |
---|
41 | |
---|
42 | /* initializes interrupt management for companionship board */ |
---|
43 | void cchip1_irq_init(void); |
---|
44 | |
---|
45 | /* register interrupt handler (called from drivers) */ |
---|
46 | void cchip1_set_isr(void *handler, int irqno, void *arg); |
---|
47 | |
---|
48 | #define READ_REG(address) _READ_REG((unsigned int)address) |
---|
49 | static __inline__ unsigned int _READ_REG(unsigned int addr) { |
---|
50 | unsigned int tmp; |
---|
51 | __asm__ ("lda [%1]1, %0 " |
---|
52 | : "=r"(tmp) |
---|
53 | : "r"(addr) |
---|
54 | ); |
---|
55 | return tmp; |
---|
56 | } |
---|
57 | |
---|
58 | /* PCI bride reg layout on AMBA side */ |
---|
59 | typedef struct { |
---|
60 | unsigned int bar0; |
---|
61 | unsigned int bar1; |
---|
62 | unsigned int bar2; |
---|
63 | unsigned int bar3; |
---|
64 | unsigned int bar4;/* 0x10 */ |
---|
65 | |
---|
66 | unsigned int unused[4*3-1]; |
---|
67 | |
---|
68 | unsigned int ambabars[1]; /* 0x40 */ |
---|
69 | } amba_bridge_regs; |
---|
70 | |
---|
71 | /* PCI bride reg layout on PCI side */ |
---|
72 | typedef struct { |
---|
73 | unsigned int bar0; |
---|
74 | unsigned int bar1; |
---|
75 | unsigned int bar2; |
---|
76 | unsigned int bar3; |
---|
77 | unsigned int bar4; /* 0x10 */ |
---|
78 | |
---|
79 | unsigned int ilevel; |
---|
80 | unsigned int ipend; |
---|
81 | unsigned int iforce; |
---|
82 | unsigned int istatus; |
---|
83 | unsigned int iclear; |
---|
84 | unsigned int imask; |
---|
85 | } pci_bridge_regs; |
---|
86 | |
---|
87 | typedef struct { |
---|
88 | pci_bridge_regs *pcib; |
---|
89 | amba_bridge_regs *ambab; |
---|
90 | |
---|
91 | /* AT697 PCI */ |
---|
92 | unsigned int bars[5]; |
---|
93 | int bus, dev, fun; |
---|
94 | |
---|
95 | /* AMBA bus */ |
---|
96 | struct ambapp_bus amba_bus; |
---|
97 | struct ambapp_mmap amba_maps[2]; |
---|
98 | |
---|
99 | /* FT AHB SRAM */ |
---|
100 | int ftsram_size; /* kb */ |
---|
101 | unsigned int ftsram_start; |
---|
102 | unsigned int ftsram_end; |
---|
103 | |
---|
104 | } cchip1; |
---|
105 | |
---|
106 | cchip1 cc1; |
---|
107 | |
---|
108 | int init_pcif(void){ |
---|
109 | unsigned int com1; |
---|
110 | int i,bus,dev,fun; |
---|
111 | pci_bridge_regs *pcib; |
---|
112 | amba_bridge_regs *ambab; |
---|
113 | struct ambapp_bus *abus; |
---|
114 | |
---|
115 | if ( BSP_pciFindDevice(0x1AC8, 0x0701, 0, &bus, &dev, &fun) == 0 ) { |
---|
116 | ; |
---|
117 | }else if (BSP_pciFindDevice(0x16E3, 0x0210, 0, &bus, &dev, &fun) == 0) { |
---|
118 | ; |
---|
119 | } else { |
---|
120 | /* didn't find any Companionship board on the PCI bus. */ |
---|
121 | return -1; |
---|
122 | } |
---|
123 | |
---|
124 | /* found Companionship PCI board, Set it up: */ |
---|
125 | |
---|
126 | pci_read_config_dword(bus, dev, fun, 0x10, &cc1.bars[0]); |
---|
127 | pci_read_config_dword(bus, dev, fun, 0x14, &cc1.bars[1]); |
---|
128 | pci_read_config_dword(bus, dev, fun, 0x18, &cc1.bars[2]); |
---|
129 | pci_read_config_dword(bus, dev, fun, 0x1c, &cc1.bars[3]); |
---|
130 | pci_read_config_dword(bus, dev, fun, 0x20, &cc1.bars[4]); |
---|
131 | |
---|
132 | #ifdef DEBUG |
---|
133 | for(i=0; i<5; i++){ |
---|
134 | printk("PCI: BAR%d: 0x%x\n\r",i,cc1.bars[i]); |
---|
135 | } |
---|
136 | #endif |
---|
137 | |
---|
138 | /* Set up PCI ==> AMBA */ |
---|
139 | pcib = (void *)cc1.bars[0]; |
---|
140 | pcib->bar0 = 0xfc000000; |
---|
141 | /* pcib->bar1 = 0xff000000;*/ |
---|
142 | #ifdef BOARD_INFO |
---|
143 | printk("Found CCHIP1 Board at 0x%lx\n\r",(unsigned int)pcib); |
---|
144 | #endif |
---|
145 | |
---|
146 | /* AMBA MAP cc1.bars[1] (in CPU) ==> 0xf0000000(remote amba address) */ |
---|
147 | cc1.amba_maps[0].size = 0x04000000; |
---|
148 | cc1.amba_maps[0].local_adr = cc1.bars[1]; |
---|
149 | cc1.amba_maps[0].remote_adr = 0xfc000000; |
---|
150 | |
---|
151 | /* Mark end of table */ |
---|
152 | cc1.amba_maps[1].size=0; |
---|
153 | cc1.amba_maps[1].local_adr = 0; |
---|
154 | cc1.amba_maps[1].remote_adr = 0; |
---|
155 | |
---|
156 | /* Enable I/O and Mem accesses */ |
---|
157 | pci_read_config_dword(bus, dev, fun, 0x4, &com1); |
---|
158 | com1 |= 0x3; |
---|
159 | pci_write_config_dword(bus, dev, fun, 0x4, com1); |
---|
160 | pci_read_config_dword(bus, dev, fun, 0x4, &com1); |
---|
161 | |
---|
162 | /* Set up AMBA Masters ==> PCI */ |
---|
163 | ambab = (void *)(cc1.bars[1]+0x400); |
---|
164 | #ifdef DEBUG |
---|
165 | printk("AMBA: PCIBAR[%d]: 0x%x, 0x%x\n\r",0,ambab->bar0,pcib->bar0); |
---|
166 | printk("AMBA: PCIBAR[%d]: 0x%x, 0x%x\n\r",1,ambab->bar1,pcib->bar1); |
---|
167 | printk("AMBA: PCIBAR[%d]: 0x%x, 0x%x\n\r",2,ambab->bar2,pcib->bar2); |
---|
168 | #endif |
---|
169 | ambab->ambabars[0] = 0x40000000; /* 0xe0000000(AMBA) ==> 0x40000000(PCI) ==> 0x40000000(AT697 AMBA) */ |
---|
170 | |
---|
171 | /* Scan bus for AMBA devices */ |
---|
172 | abus = &cc1.amba_bus; |
---|
173 | memset(abus,0,sizeof(*abus)); |
---|
174 | ambapp_scan(abus, cc1.bars[1]+0x3f00000, NULL, &cc1.amba_maps[0]); |
---|
175 | |
---|
176 | /* Init all msters, max 16 */ |
---|
177 | for(i=1; i<16; i++) { |
---|
178 | ambab->ambabars[i] = 0x40000000; |
---|
179 | if (READ_REG(&ambab->ambabars[i]) != 0x40000000) |
---|
180 | break; |
---|
181 | } |
---|
182 | |
---|
183 | /* Enable PCI Master */ |
---|
184 | pci_read_config_dword(bus, dev, fun, 0x4, &com1); |
---|
185 | com1 |= 0x4; |
---|
186 | pci_write_config_dword(bus, dev, fun, 0x4, com1); |
---|
187 | pci_read_config_dword(bus, dev, fun, 0x4, &com1); |
---|
188 | |
---|
189 | cc1.pcib = pcib; |
---|
190 | cc1.ambab = ambab; |
---|
191 | cc1.bus = bus; |
---|
192 | cc1.dev = dev; |
---|
193 | cc1.fun = fun; |
---|
194 | |
---|
195 | return 0; |
---|
196 | } |
---|
197 | |
---|
198 | #ifndef GAISLER_FTAHBRAM |
---|
199 | #define GAISLER_FTAHBRAM 0x50 |
---|
200 | #endif |
---|
201 | int init_onboard_sram(void){ |
---|
202 | struct ambapp_ahb_info ahb; |
---|
203 | struct ambapp_apb_info apb; |
---|
204 | unsigned int conf, size; |
---|
205 | |
---|
206 | /* Find SRAM controller |
---|
207 | * 1. AHB slave interface |
---|
208 | * 2. APB slave interface |
---|
209 | */ |
---|
210 | if ( ambapp_find_apbslv(&cc1.amba_bus, VENDOR_GAISLER, GAISLER_FTAHBRAM, |
---|
211 | &apb) != 1 ){ |
---|
212 | printk("On Board FT SRAM not found (APB)\n"); |
---|
213 | return -1; |
---|
214 | } |
---|
215 | |
---|
216 | if ( ambapp_find_ahbslv(&cc1.amba_bus, VENDOR_GAISLER, GAISLER_FTAHBRAM, |
---|
217 | &ahb) != 1 ){ |
---|
218 | printk("On Board FT SRAM not found (AHB)\n"); |
---|
219 | return -1; |
---|
220 | } |
---|
221 | |
---|
222 | /* We have found the controller. |
---|
223 | * Get it going. |
---|
224 | * |
---|
225 | * Get size of SRAM |
---|
226 | */ |
---|
227 | conf = *(unsigned int *)apb.start; |
---|
228 | size = (conf >>10) & 0x7; |
---|
229 | |
---|
230 | /* 2^x kb */ |
---|
231 | cc1.ftsram_size = 1<<size; |
---|
232 | cc1.ftsram_start = ahb.start[0]; |
---|
233 | cc1.ftsram_end = size*1024 + cc1.ftsram_start; |
---|
234 | #ifdef BOARD_INFO |
---|
235 | printk("Found FT AHB SRAM %dkb at 0x%lx\n",cc1.ftsram_size,cc1.ftsram_start); |
---|
236 | #endif |
---|
237 | return 0; |
---|
238 | } |
---|
239 | |
---|
240 | int cchip1_register(void){ |
---|
241 | |
---|
242 | /* Init AT697 PCI Controller */ |
---|
243 | init_pci(); |
---|
244 | |
---|
245 | /* Find & init CChip board . |
---|
246 | * Also scan AMBA Plug&Play info for us. |
---|
247 | */ |
---|
248 | if ( init_pcif() ){ |
---|
249 | printk("Failed to initialize CCHIP board\n\r"); |
---|
250 | return -1; |
---|
251 | } |
---|
252 | |
---|
253 | /* Set interrupt common board stuff */ |
---|
254 | cchip1_irq_init(); |
---|
255 | |
---|
256 | /* Find on board SRAM */ |
---|
257 | if ( init_onboard_sram() ){ |
---|
258 | printk("Failed to register On Board SRAM. It is needed by b1553BRM\n"); |
---|
259 | return -1; |
---|
260 | } |
---|
261 | |
---|
262 | /* Register interrupt install functions */ |
---|
263 | b1553brm_pci_int_reg = cchip1_set_isr; |
---|
264 | occan_pci_int_reg = cchip1_set_isr; |
---|
265 | grspw_pci_int_reg = cchip1_set_isr; |
---|
266 | apbuart_pci_int_reg = cchip1_set_isr; |
---|
267 | |
---|
268 | /* register the BRM PCI driver, use 16k FTSRAM... */ |
---|
269 | if ( b1553brm_pci_register(&cc1.amba_bus,0,0,3,cc1.ftsram_start,0xffa00000) ){ |
---|
270 | printk("Failed to register BRM PCI driver\n"); |
---|
271 | return -1; |
---|
272 | } |
---|
273 | |
---|
274 | /* register the BRM PCI driver, no DMA memory... */ |
---|
275 | if ( occan_pci_register(&cc1.amba_bus) ){ |
---|
276 | printk("Failed to register OC_CAN PCI driver\n"); |
---|
277 | return -1; |
---|
278 | } |
---|
279 | |
---|
280 | /* register the GRSPW PCI driver, use malloc... */ |
---|
281 | if ( grspw_pci_register(&cc1.amba_bus,0,0xe0000000) ){ |
---|
282 | printk("Failed to register GRSPW PCI driver\n"); |
---|
283 | return -1; |
---|
284 | } |
---|
285 | |
---|
286 | /* register the APBUART PCI driver, no DMA memory */ |
---|
287 | if ( apbuart_pci_register(&cc1.amba_bus) ){ |
---|
288 | printk("Failed to register APBUART PCI driver\n"); |
---|
289 | return -1; |
---|
290 | } |
---|
291 | |
---|
292 | return 0; |
---|
293 | } |
---|
294 | |
---|
295 | static rtems_isr cchip1_interrupt_dispatcher(rtems_vector_number v); |
---|
296 | static unsigned int cchip1_spurious_cnt; |
---|
297 | |
---|
298 | typedef struct { |
---|
299 | unsigned int (*handler)(int irqno, void *arg); |
---|
300 | void *arg; |
---|
301 | } int_handler; |
---|
302 | |
---|
303 | static int_handler int_handlers[16]; |
---|
304 | |
---|
305 | void cchip1_irq_init(void){ |
---|
306 | |
---|
307 | /* Configure AT697 ioport bit 7 to input pci irq */ |
---|
308 | regs->PIO_Direction &= ~(1<<7); |
---|
309 | regs->PIO_Interrupt = 0x87; /* level sensitive */ |
---|
310 | |
---|
311 | /* Set up irq controller (mask all IRQs) */ |
---|
312 | cc1.pcib->imask = 0x0000; |
---|
313 | cc1.pcib->ipend = 0; |
---|
314 | cc1.pcib->iclear = 0xffff; |
---|
315 | cc1.pcib->iforce = 0; |
---|
316 | cc1.pcib->ilevel = 0x0; |
---|
317 | |
---|
318 | memset(int_handlers,0,sizeof(int_handlers)); |
---|
319 | |
---|
320 | /* Reset spurious counter */ |
---|
321 | cchip1_spurious_cnt = 0; |
---|
322 | |
---|
323 | /* Register interrupt handler */ |
---|
324 | set_vector(cchip1_interrupt_dispatcher,LEON_TRAP_TYPE(CCHIP_IRQ),1); |
---|
325 | } |
---|
326 | |
---|
327 | void cchip1_set_isr(void *handler, int irqno, void *arg){ |
---|
328 | int_handlers[irqno].handler = handler; |
---|
329 | int_handlers[irqno].arg = arg; |
---|
330 | #ifdef DEBUG |
---|
331 | printk("Registering IRQ %d to 0x%lx(%d,0x%lx)\n\r",irqno,(unsigned int)handler,irqno,(unsigned int)arg); |
---|
332 | #endif |
---|
333 | cc1.pcib->imask |= 1<<irqno; /* Enable the registered IRQ */ |
---|
334 | } |
---|
335 | |
---|
336 | static rtems_isr cchip1_interrupt_dispatcher(rtems_vector_number v){ |
---|
337 | unsigned int pending = READ_REG(&cc1.pcib->ipend); |
---|
338 | unsigned int (*handler)(int irqno, void *arg); |
---|
339 | unsigned int clr = pending; |
---|
340 | int irq=1; |
---|
341 | |
---|
342 | if ( !pending ){ |
---|
343 | #ifdef PRINT_SPURIOUS |
---|
344 | printk("Spurious IRQ %d: %d\n",v,cchip1_spurious_cnt); |
---|
345 | #endif |
---|
346 | cchip1_spurious_cnt++; |
---|
347 | return; |
---|
348 | } |
---|
349 | #ifdef DEBUG_IRQS |
---|
350 | printk("CCIRQ: 0x%x\n",(unsigned int)pending); |
---|
351 | #endif |
---|
352 | /* IRQ 0 doesn't exist */ |
---|
353 | irq=1; |
---|
354 | pending = pending>>1; |
---|
355 | |
---|
356 | while ( pending ){ |
---|
357 | if ( (pending & 1) && (handler=int_handlers[irq].handler) ){ |
---|
358 | handler(irq,int_handlers[irq].arg); |
---|
359 | } |
---|
360 | irq++; |
---|
361 | pending = pending>>1; |
---|
362 | } |
---|
363 | |
---|
364 | cc1.pcib->iclear = clr; |
---|
365 | |
---|
366 | /*LEON_Clear_interrupt( brd->irq );*/ |
---|
367 | } |
---|