]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/evb64260/pci.c
585906d31d234af1a6cfa6fa042a505da9c450aa
[karo-tx-uboot.git] / board / evb64260 / pci.c
1 /* PCI.c - PCI functions */
2
3 /* Copyright - Galileo technology. */
4
5 #include <common.h>
6 #include <pci.h>
7
8 #include <galileo/pci.h>
9
10 static const unsigned char pci_irq_swizzle[2][PCI_MAX_DEVICES] = {
11 #ifdef CONFIG_ZUMA_V2
12     {0,0,0,0,0,0,0,29, [8 ... PCI_MAX_DEVICES-1]=0},
13     {0,0,0,0,0,0,0,28, [8 ... PCI_MAX_DEVICES-1]=0}
14 #else   /* EVB??? This is a guess */
15     {0,0,0,0,0,0,0,27,27, [9 ... PCI_MAX_DEVICES-1]=0},
16     {0,0,0,0,0,0,0,29,29, [9 ... PCI_MAX_DEVICES-1]=0}
17 #endif
18 };
19
20 static const unsigned int pci_p2p_configuration_reg[]={
21     PCI_0P2P_CONFIGURATION, PCI_1P2P_CONFIGURATION};
22
23 static const unsigned int pci_configuration_address[]={
24     PCI_0CONFIGURATION_ADDRESS, PCI_1CONFIGURATION_ADDRESS};
25
26 static const unsigned int pci_configuration_data[]={
27     PCI_0CONFIGURATION_DATA_VIRTUAL_REGISTER,
28     PCI_1CONFIGURATION_DATA_VIRTUAL_REGISTER};
29
30 static const unsigned int pci_error_cause_reg[]={
31     PCI_0ERROR_CAUSE, PCI_1ERROR_CAUSE};
32
33 static const unsigned int pci_arbiter_control[]={
34     PCI_0ARBITER_CONTROL, PCI_1ARBITER_CONTROL};
35
36 static const unsigned int pci_snoop_control_base_0_low[]={
37     PCI_0SNOOP_CONTROL_BASE_0_LOW, PCI_1SNOOP_CONTROL_BASE_0_LOW};
38 static const unsigned int pci_snoop_control_top_0[]={
39     PCI_0SNOOP_CONTROL_TOP_0, PCI_1SNOOP_CONTROL_TOP_0};
40
41 static const unsigned int pci_access_control_base_0_low[]={
42     PCI_0ACCESS_CONTROL_BASE_0_LOW, PCI_1ACCESS_CONTROL_BASE_0_LOW};
43 static const unsigned int pci_access_control_top_0[]={
44     PCI_0ACCESS_CONTROL_TOP_0, PCI_1ACCESS_CONTROL_TOP_0};
45
46 static const unsigned int pci_scs_bank_size[2][4] = {
47     {PCI_0SCS_0_BANK_SIZE, PCI_0SCS_1_BANK_SIZE,
48      PCI_0SCS_2_BANK_SIZE, PCI_0SCS_3_BANK_SIZE},
49     {PCI_1SCS_0_BANK_SIZE, PCI_1SCS_1_BANK_SIZE,
50      PCI_1SCS_2_BANK_SIZE, PCI_1SCS_3_BANK_SIZE}};
51
52 static const unsigned int pci_p2p_configuration[] = {
53     PCI_0P2P_CONFIGURATION, PCI_1P2P_CONFIGURATION};
54
55 /********************************************************************
56 * pciWriteConfigReg - Write to a PCI configuration register
57 *                    - Make sure the GT is configured as a master before writing
58 *                      to another device on the PCI.
59 *                    - The function takes care of Big/Little endian conversion.
60 *
61 *
62 * Inputs:   unsigned int regOffset: The register offset as it apears in the GT spec
63 *                   (or any other PCI device spec)
64 *           pciDevNum: The device number needs to be addressed.
65 *
66 *  Configuration Address 0xCF8:
67 *
68 *       31 30    24 23  16 15  11 10     8 7      2  0     <=bit Number
69 *  |congif|Reserved|  Bus |Device|Function|Register|00|
70 *  |Enable|        |Number|Number| Number | Number |  |    <=field Name
71 *
72 *********************************************************************/
73 void pciWriteConfigReg(PCI_HOST host, unsigned int regOffset,unsigned int pciDevNum,unsigned int data)
74 {
75     volatile unsigned int DataForAddrReg;
76     unsigned int functionNum;
77     unsigned int busNum = 0;
78     unsigned int addr;
79
80     if(pciDevNum > 32) /* illegal device Number */
81         return;
82     if(pciDevNum == SELF) /* configure our configuration space. */
83     {
84         pciDevNum = (GTREGREAD(pci_p2p_configuration_reg[host]) >> 24) & 0x1f;
85         busNum = GTREGREAD(pci_p2p_configuration_reg[host]) & 0xff0000;
86     }
87     functionNum =  regOffset & 0x00000700;
88     pciDevNum = pciDevNum << 11;
89     regOffset = regOffset & 0xfc;
90     DataForAddrReg = ( regOffset | pciDevNum | functionNum | busNum) | BIT31;
91     GT_REG_WRITE(pci_configuration_address[host],DataForAddrReg);
92     GT_REG_READ(pci_configuration_address[host], &addr);
93     if (addr != DataForAddrReg) return;
94     GT_REG_WRITE(pci_configuration_data[host],data);
95 }
96
97 /********************************************************************
98 * pciReadConfigReg  - Read from a PCI0 configuration register
99 *                    - Make sure the GT is configured as a master before reading
100 *                     from another device on the PCI.
101 *                   - The function takes care of Big/Little endian conversion.
102 * INPUTS:   regOffset: The register offset as it apears in the GT spec (or PCI
103 *                        spec)
104 *           pciDevNum: The device number needs to be addressed.
105 * RETURNS: data , if the data == 0xffffffff check the master abort bit in the
106 *                 cause register to make sure the data is valid
107 *
108 *  Configuration Address 0xCF8:
109 *
110 *       31 30    24 23  16 15  11 10     8 7      2  0     <=bit Number
111 *  |congif|Reserved|  Bus |Device|Function|Register|00|
112 *  |Enable|        |Number|Number| Number | Number |  |    <=field Name
113 *
114 *********************************************************************/
115 unsigned int pciReadConfigReg (PCI_HOST host, unsigned int regOffset,unsigned int pciDevNum)
116 {
117     volatile unsigned int DataForAddrReg;
118         unsigned int data;
119     unsigned int functionNum;
120     unsigned int busNum = 0;
121
122     if(pciDevNum > 32) /* illegal device Number */
123         return 0xffffffff;
124     if(pciDevNum == SELF) /* configure our configuration space. */
125     {
126         pciDevNum = (GTREGREAD(pci_p2p_configuration_reg[host]) >> 24) & 0x1f;
127         busNum = GTREGREAD(pci_p2p_configuration_reg[host]) & 0xff0000;
128     }
129     functionNum = regOffset & 0x00000700;
130     pciDevNum = pciDevNum << 11;
131     regOffset = regOffset & 0xfc;
132     DataForAddrReg = (regOffset | pciDevNum | functionNum | busNum) | BIT31 ;
133     GT_REG_WRITE(pci_configuration_address[host],DataForAddrReg);
134     GT_REG_READ(pci_configuration_address[host], &data);
135     if (data != DataForAddrReg)
136         return 0xffffffff;
137     GT_REG_READ(pci_configuration_data[host], &data);
138     return data;
139 }
140
141 /********************************************************************
142 * pciOverBridgeWriteConfigReg - Write to a PCI configuration register where
143 *                               the agent is placed on another Bus. For more
144 *                               information read P2P in the PCI spec.
145 *
146 * Inputs:   unsigned int regOffset - The register offset as it apears in the
147 *           GT spec (or any other PCI device spec).
148 *           unsigned int pciDevNum - The device number needs to be addressed.
149 *           unsigned int busNum - On which bus does the Target agent connect
150 *                                 to.
151 *           unsigned int data - data to be written.
152 *
153 *  Configuration Address 0xCF8:
154 *
155 *       31 30    24 23  16 15  11 10     8 7      2  0     <=bit Number
156 *  |congif|Reserved|  Bus |Device|Function|Register|01|
157 *  |Enable|        |Number|Number| Number | Number |  |    <=field Name
158 *
159 *  The configuration Address is configure as type-I (bits[1:0] = '01') due to
160 *   PCI spec referring to P2P.
161 *
162 *********************************************************************/
163 void pciOverBridgeWriteConfigReg(PCI_HOST host,
164                                  unsigned int regOffset,
165                                  unsigned int pciDevNum,
166                                  unsigned int busNum,unsigned int data)
167 {
168         unsigned int   DataForReg;
169     unsigned int   functionNum;
170
171         functionNum =  regOffset & 0x00000700;
172     pciDevNum = pciDevNum << 11;
173     regOffset = regOffset & 0xff;
174     busNum = busNum << 16;
175     if(pciDevNum == SELF) /* This board */
176     {
177         DataForReg = ( regOffset | pciDevNum | functionNum) | BIT0;
178     }
179     else
180     {
181         DataForReg = ( regOffset | pciDevNum | functionNum | busNum) |
182             BIT31 | BIT0;
183     }
184     GT_REG_WRITE(pci_configuration_address[host],DataForReg);
185     if(pciDevNum == SELF) /* This board */
186     {
187         GT_REG_WRITE(pci_configuration_data[host],data);
188     }
189     else /* configuration Transaction over the pci. */
190     {
191         /* The PCI is working in LE Mode So it swap the Data. */
192         GT_REG_WRITE(pci_configuration_data[host],WORD_SWAP(data));
193     }
194 }
195
196
197 /********************************************************************
198 * pciOverBridgeReadConfigReg  - Read from a PCIn configuration register where
199 *                               the agent target locate on another PCI bus.
200 *                             - Make sure the GT is configured as a master
201 *                               before reading from another device on the PCI.
202 *                             - The function takes care of Big/Little endian
203 *                               conversion.
204 * INPUTS:   regOffset: The register offset as it apears in the GT spec (or PCI
205 *                        spec). (configuration register offset.)
206 *           pciDevNum: The device number needs to be addressed.
207 *           busNum: the Bus number where the agent is place.
208 * RETURNS: data , if the data == 0xffffffff check the master abort bit in the
209 *                 cause register to make sure the data is valid
210 *
211 *  Configuration Address 0xCF8:
212 *
213 *       31 30    24 23  16 15  11 10     8 7      2  0     <=bit Number
214 *  |congif|Reserved|  Bus |Device|Function|Register|01|
215 *  |Enable|        |Number|Number| Number | Number |  |    <=field Name
216 *
217 *********************************************************************/
218 unsigned int pciOverBridgeReadConfigReg(PCI_HOST host,
219                                         unsigned int regOffset,
220                                         unsigned int pciDevNum,
221                                         unsigned int busNum)
222 {
223     unsigned int DataForReg;
224     unsigned int data;
225     unsigned int functionNum;
226
227     functionNum = regOffset & 0x00000700;
228     pciDevNum = pciDevNum << 11;
229     regOffset = regOffset & 0xff;
230     busNum = busNum << 16;
231     if (pciDevNum == SELF) /* This board */
232     {
233         DataForReg = (regOffset | pciDevNum | functionNum) | BIT31 ;
234     }
235     else /* agent on another bus */
236     {
237         DataForReg = (regOffset | pciDevNum | functionNum | busNum) |
238         BIT0 | BIT31 ;
239     }
240     GT_REG_WRITE(pci_configuration_address[host],DataForReg);
241     if (pciDevNum == SELF) /* This board */
242         {
243         GT_REG_READ(pci_configuration_data[host], &data);
244         return data;
245     }
246     else /* The PCI is working in LE Mode So it swap the Data. */
247     {
248         GT_REG_READ(pci_configuration_data[host], &data);
249         return WORD_SWAP(data);
250     }
251 }
252
253 /********************************************************************
254 * pciGetRegOffset - Gets the register offset for this region config.
255 *
256 * INPUT:   Bus, Region - The bus and region we ask for its base address.
257 * OUTPUT:   N/A
258 * RETURNS: PCI register base address
259 *********************************************************************/
260 static unsigned int pciGetRegOffset(PCI_HOST host, PCI_REGION region)
261 {
262     switch (host)
263     {
264         case PCI_HOST0:
265             switch(region) {
266                 case PCI_IO:            return PCI_0I_O_LOW_DECODE_ADDRESS;
267                 case PCI_REGION0:       return PCI_0MEMORY0_LOW_DECODE_ADDRESS;
268                 case PCI_REGION1:       return PCI_0MEMORY1_LOW_DECODE_ADDRESS;
269                 case PCI_REGION2:       return PCI_0MEMORY2_LOW_DECODE_ADDRESS;
270                 case PCI_REGION3:       return PCI_0MEMORY3_LOW_DECODE_ADDRESS;
271             }
272         case PCI_HOST1:
273             switch(region) {
274                 case PCI_IO:            return PCI_1I_O_LOW_DECODE_ADDRESS;
275                 case PCI_REGION0:       return PCI_1MEMORY0_LOW_DECODE_ADDRESS;
276                 case PCI_REGION1:       return PCI_1MEMORY1_LOW_DECODE_ADDRESS;
277                 case PCI_REGION2:       return PCI_1MEMORY2_LOW_DECODE_ADDRESS;
278                 case PCI_REGION3:       return PCI_1MEMORY3_LOW_DECODE_ADDRESS;
279             }
280     }
281     return PCI_0MEMORY0_LOW_DECODE_ADDRESS;
282 }
283
284 static unsigned int pciGetRemapOffset(PCI_HOST host, PCI_REGION region)
285 {
286     switch (host)
287     {
288         case PCI_HOST0:
289             switch(region) {
290                 case PCI_IO:            return PCI_0I_O_ADDRESS_REMAP;
291                 case PCI_REGION0:       return PCI_0MEMORY0_ADDRESS_REMAP;
292                 case PCI_REGION1:       return PCI_0MEMORY1_ADDRESS_REMAP;
293                 case PCI_REGION2:       return PCI_0MEMORY2_ADDRESS_REMAP;
294                 case PCI_REGION3:       return PCI_0MEMORY3_ADDRESS_REMAP;
295             }
296         case PCI_HOST1:
297             switch(region) {
298                 case PCI_IO:            return PCI_1I_O_ADDRESS_REMAP;
299                 case PCI_REGION0:       return PCI_1MEMORY0_ADDRESS_REMAP;
300                 case PCI_REGION1:       return PCI_1MEMORY1_ADDRESS_REMAP;
301                 case PCI_REGION2:       return PCI_1MEMORY2_ADDRESS_REMAP;
302                 case PCI_REGION3:       return PCI_1MEMORY3_ADDRESS_REMAP;
303             }
304     }
305     return PCI_0MEMORY0_ADDRESS_REMAP;
306 }
307
308 bool pciMapSpace(PCI_HOST host, PCI_REGION region, unsigned int remapBase, unsigned int bankBase,unsigned int bankLength)
309 {
310     unsigned int low=0xfff;
311     unsigned int high=0x0;
312     unsigned int regOffset=pciGetRegOffset(host, region);
313     unsigned int remapOffset=pciGetRemapOffset(host, region);
314
315     if(bankLength!=0) {
316         low = (bankBase >> 20) & 0xfff;
317         high=((bankBase+bankLength)>>20)-1;
318     }
319
320     GT_REG_WRITE(regOffset, low | (1<<24));     /* no swapping */
321     GT_REG_WRITE(regOffset+8, high);
322
323     if(bankLength!=0) { /* must do AFTER writing maps */
324         GT_REG_WRITE(remapOffset, remapBase>>20);       /* sorry, 32 bits only.
325                                                            dont support upper 32
326                                                            in this driver */
327     }
328     return true;
329 }
330
331 unsigned int pciGetSpaceBase(PCI_HOST host, PCI_REGION region)
332 {
333     unsigned int low;
334     unsigned int regOffset=pciGetRegOffset(host, region);
335     GT_REG_READ(regOffset,&low);
336     return (low&0xfff)<<20;
337 }
338
339 unsigned int pciGetSpaceSize(PCI_HOST host, PCI_REGION region)
340 {
341     unsigned int low,high;
342     unsigned int regOffset=pciGetRegOffset(host, region);
343     GT_REG_READ(regOffset,&low);
344     GT_REG_READ(regOffset+8,&high);
345     high&=0xfff;
346     low&=0xfff;
347     if(high<=low) return 0;
348     return (high+1-low)<<20;
349 }
350
351 /********************************************************************
352 * pciMapMemoryBank - Maps PCI_host memory bank "bank" for the slave.
353 *
354 * Inputs: base and size of PCI SCS
355 *********************************************************************/
356 void pciMapMemoryBank(PCI_HOST host, MEMORY_BANK bank, unsigned int pciDramBase,unsigned int pciDramSize)
357 {
358         pciDramBase = pciDramBase & 0xfffff000;
359     pciDramBase = pciDramBase | (pciReadConfigReg(host,
360         PCI_SCS_0_BASE_ADDRESS + 4*bank,SELF) & 0x00000fff);
361     pciWriteConfigReg(host,PCI_SCS_0_BASE_ADDRESS + 4*bank,SELF,pciDramBase);
362     if(pciDramSize == 0)
363         pciDramSize ++;
364     GT_REG_WRITE(pci_scs_bank_size[host][bank], pciDramSize-1);
365 }
366
367
368 /********************************************************************
369 * pciSetRegionFeatures - This function modifys one of the 8 regions with
370 *                         feature bits given as an input.
371 *                       - Be advised to check the spec before modifying them.
372 * Inputs: PCI_PROTECT_REGION region - one of the eight regions.
373 *         unsigned int features - See file: pci.h there are defintion for those
374 *                                 region features.
375 *         unsigned int baseAddress - The region base Address.
376 *         unsigned int topAddress - The region top Address.
377 * Returns: false if one of the parameters is erroneous true otherwise.
378 *********************************************************************/
379 bool pciSetRegionFeatures(PCI_HOST host, PCI_ACCESS_REGIONS region,unsigned int features,
380                            unsigned int baseAddress,unsigned int regionLength)
381 {
382     unsigned int accessLow;
383     unsigned int accessHigh;
384     unsigned int accessTop = baseAddress + regionLength;
385
386     if(regionLength == 0) /* close the region. */
387     {
388         pciDisableAccessRegion(host, region);
389         return true;
390     }
391     /* base Address is store is bits [11:0] */
392     accessLow = (baseAddress & 0xfff00000) >> 20;
393     /* All the features are update according to the defines in pci.h (to be on
394        the safe side we disable bits: [11:0] */
395     accessLow = accessLow | (features & 0xfffff000);
396     /* write to the Low Access Region register */
397     GT_REG_WRITE( pci_access_control_base_0_low[host] + 0x10*region,accessLow);
398
399     accessHigh = (accessTop & 0xfff00000) >> 20;
400
401     /* write to the High Access Region register */
402     GT_REG_WRITE(pci_access_control_top_0[host] + 0x10*region,accessHigh - 1);
403     return true;
404 }
405
406 /********************************************************************
407 * pciDisableAccessRegion - Disable The given Region by writing MAX size
408 *                           to its low Address and MIN size to its high Address.
409 *
410 * Inputs:   PCI_ACCESS_REGIONS region - The region we to be Disabled.
411 * Returns:  N/A.
412 *********************************************************************/
413 void pciDisableAccessRegion(PCI_HOST host, PCI_ACCESS_REGIONS region)
414 {
415     /* writing back the registers default values. */
416     GT_REG_WRITE(pci_access_control_base_0_low[host] + 0x10*region,0x01001fff);
417     GT_REG_WRITE(pci_access_control_top_0[host] + 0x10*region,0);
418 }
419
420 /********************************************************************
421 * pciArbiterEnable - Enables PCI-0`s Arbitration mechanism.
422 *
423 * Inputs:   N/A
424 * Returns:  true.
425 *********************************************************************/
426 bool pciArbiterEnable(PCI_HOST host)
427 {
428     unsigned int regData;
429
430     GT_REG_READ(pci_arbiter_control[host],&regData);
431     GT_REG_WRITE(pci_arbiter_control[host],regData | BIT31);
432     return true;
433 }
434
435 /********************************************************************
436 * pciArbiterDisable - Disable PCI-0`s Arbitration mechanism.
437 *
438 * Inputs:   N/A
439 * Returns:  true
440 *********************************************************************/
441 bool pciArbiterDisable(PCI_HOST host)
442 {
443     unsigned int regData;
444
445     GT_REG_READ(pci_arbiter_control[host],&regData);
446     GT_REG_WRITE(pci_arbiter_control[host],regData & 0x7fffffff);
447     return true;
448 }
449
450 /********************************************************************
451 * pciParkingDisable - Park on last option disable, with this function you can
452 *                      disable the park on last mechanism for each agent.
453 *                      disabling this option for all agents results parking
454 *                      on the internal master.
455 *
456 * Inputs: PCI_AGENT_PARK internalAgent -  parking Disable for internal agent.
457 *         PCI_AGENT_PARK externalAgent0 - parking Disable for external#0 agent.
458 *         PCI_AGENT_PARK externalAgent1 - parking Disable for external#1 agent.
459 *         PCI_AGENT_PARK externalAgent2 - parking Disable for external#2 agent.
460 *         PCI_AGENT_PARK externalAgent3 - parking Disable for external#3 agent.
461 *         PCI_AGENT_PARK externalAgent4 - parking Disable for external#4 agent.
462 *         PCI_AGENT_PARK externalAgent5 - parking Disable for external#5 agent.
463 * Returns:  true
464 *********************************************************************/
465 bool pciParkingDisable(PCI_HOST host, PCI_AGENT_PARK internalAgent,
466                         PCI_AGENT_PARK externalAgent0,
467                         PCI_AGENT_PARK externalAgent1,
468                         PCI_AGENT_PARK externalAgent2,
469                         PCI_AGENT_PARK externalAgent3,
470                         PCI_AGENT_PARK externalAgent4,
471                         PCI_AGENT_PARK externalAgent5)
472 {
473     unsigned int regData;
474     unsigned int writeData;
475
476     GT_REG_READ(pci_arbiter_control[host],&regData);
477     writeData = (internalAgent << 14) + (externalAgent0 << 15) +     \
478                 (externalAgent1 << 16) + (externalAgent2 << 17) +    \
479                 (externalAgent3 << 18) + (externalAgent4 << 19) +    \
480                 (externalAgent5 << 20);
481     regData = (regData & ~(0x7f<<14)) | writeData;
482     GT_REG_WRITE(pci_arbiter_control[host],regData);
483     return true;
484 }
485
486 /********************************************************************
487 * pciSetRegionSnoopMode - This function modifys one of the 4 regions which
488 *                          supports Cache Coherency in the PCI_n interface.
489 * Inputs: region - One of the four regions.
490 *         snoopType - There is four optional Types:
491 *                        1. No Snoop.
492 *                        2. Snoop to WT region.
493 *                        3. Snoop to WB region.
494 *                        4. Snoop & Invalidate to WB region.
495 *         baseAddress - Base Address of this region.
496 *         regionLength - Region length.
497 * Returns: false if one of the parameters is wrong otherwise return true.
498 *********************************************************************/
499 bool pciSetRegionSnoopMode(PCI_HOST host, PCI_SNOOP_REGION region,PCI_SNOOP_TYPE snoopType,
500                             unsigned int baseAddress,
501                             unsigned int regionLength)
502 {
503     unsigned int snoopXbaseAddress;
504     unsigned int snoopXtopAddress;
505     unsigned int data;
506     unsigned int snoopHigh = baseAddress + regionLength;
507
508     if( (region > PCI_SNOOP_REGION3) || (snoopType > PCI_SNOOP_WB) )
509         return false;
510     snoopXbaseAddress = pci_snoop_control_base_0_low[host] + 0x10 * region;
511     snoopXtopAddress = pci_snoop_control_top_0[host] + 0x10 * region;
512     if(regionLength == 0) /* closing the region */
513     {
514         GT_REG_WRITE(snoopXbaseAddress,0x0000ffff);
515         GT_REG_WRITE(snoopXtopAddress,0);
516         return true;
517     }
518     baseAddress = baseAddress & 0xfff00000; /* Granularity of 1MByte */
519     data = (baseAddress >> 20) | snoopType << 12;
520     GT_REG_WRITE(snoopXbaseAddress,data);
521     snoopHigh = (snoopHigh & 0xfff00000) >> 20;
522     GT_REG_WRITE(snoopXtopAddress,snoopHigh - 1);
523     return true;
524 }
525
526 /*
527  *
528  */
529
530 static int gt_read_config_dword(struct pci_controller *hose,
531                                 pci_dev_t dev,
532                                 int offset, u32* value)
533 {
534     *value = pciReadConfigReg((PCI_HOST) hose->cfg_addr, offset, PCI_DEV(dev));
535     return 0;
536 }
537
538 static int gt_write_config_dword(struct pci_controller *hose,
539                                  pci_dev_t dev,
540                                  int offset, u32 value)
541 {
542     pciWriteConfigReg((PCI_HOST)hose->cfg_addr, offset, PCI_DEV(dev), value);
543     return 0;
544 }
545
546 /*
547  *
548  */
549
550 static void gt_setup_ide(struct pci_controller *hose,
551                          pci_dev_t dev, struct pci_config_table *entry)
552 {
553     static const int ide_bar[]={8,4,8,4,0,0};
554     u32 bar_response, bar_value;
555     int bar;
556
557     for (bar=0; bar<6; bar++)
558     {
559         pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + bar*4, 0x0);
560         pci_read_config_dword(dev, PCI_BASE_ADDRESS_0 + bar*4, &bar_response);
561
562         pciauto_region_allocate(bar_response & PCI_BASE_ADDRESS_SPACE_IO ?
563                                 hose->pci_io : hose->pci_mem, ide_bar[bar], &bar_value);
564
565         pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + bar*4, bar_value);
566     }
567 }
568
569 static void gt_fixup_irq(struct pci_controller *hose, pci_dev_t dev)
570 {
571     unsigned char pin, irq;
572
573     pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
574
575     if(pin == 1) {      /* only allow INT A */
576         irq = pci_irq_swizzle[(PCI_HOST)hose->cfg_addr][PCI_DEV(dev)];
577         if(irq)
578             pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
579     }
580 }
581
582 struct pci_config_table gt_config_table[] = {
583     { PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE,
584       PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, gt_setup_ide},
585
586     { }
587 };
588
589 struct pci_controller pci0_hose = {
590     fixup_irq: gt_fixup_irq,
591     config_table: gt_config_table,
592 };
593
594 struct pci_controller pci1_hose = {
595     fixup_irq: gt_fixup_irq,
596     config_table: gt_config_table,
597 };
598
599 void
600 pci_init_board(void)
601 {
602     unsigned int command;
603
604     pci0_hose.first_busno = 0;
605     pci0_hose.last_busno = 0xff;
606
607     /* PCI memory space */
608     pci_set_region(pci0_hose.regions + 0,
609                    CFG_PCI0_0_MEM_SPACE,
610                    CFG_PCI0_0_MEM_SPACE,
611                    CFG_PCI0_MEM_SIZE,
612                    PCI_REGION_MEM);
613
614     /* PCI I/O space */
615     pci_set_region(pci0_hose.regions + 1,
616                    CFG_PCI0_IO_SPACE_PCI,
617                    CFG_PCI0_IO_SPACE,
618                    CFG_PCI0_IO_SIZE,
619                    PCI_REGION_IO);
620
621     pci_set_ops(&pci0_hose,
622                 pci_hose_read_config_byte_via_dword,
623                 pci_hose_read_config_word_via_dword,
624                 gt_read_config_dword,
625                 pci_hose_write_config_byte_via_dword,
626                 pci_hose_write_config_word_via_dword,
627                 gt_write_config_dword);
628
629     pci0_hose.region_count = 2;
630
631     pci0_hose.cfg_addr = (unsigned int*) PCI_HOST0;
632
633     pci_register_hose(&pci0_hose);
634
635     pciArbiterEnable(PCI_HOST0);
636     pciParkingDisable(PCI_HOST0,1,1,1,1,1,1,1);
637
638     command = pciReadConfigReg(PCI_HOST0, PCI_COMMAND, SELF);
639     command |= PCI_COMMAND_MASTER;
640     pciWriteConfigReg(PCI_HOST0, PCI_COMMAND, SELF, command);
641
642     pci0_hose.last_busno = pci_hose_scan(&pci0_hose);
643
644     command = pciReadConfigReg(PCI_HOST0, PCI_COMMAND, SELF);
645     command |= PCI_COMMAND_MEMORY;
646     pciWriteConfigReg(PCI_HOST0, PCI_COMMAND, SELF, command);
647
648     pci1_hose.first_busno = pci0_hose.last_busno + 1;
649     pci1_hose.last_busno = 0xff;
650
651     /* PCI memory space */
652     pci_set_region(pci1_hose.regions + 0,
653                    CFG_PCI1_0_MEM_SPACE,
654                    CFG_PCI1_0_MEM_SPACE,
655                    CFG_PCI1_MEM_SIZE,
656                    PCI_REGION_MEM);
657
658     /* PCI I/O space */
659     pci_set_region(pci1_hose.regions + 1,
660                    CFG_PCI1_IO_SPACE_PCI,
661                    CFG_PCI1_IO_SPACE,
662                    CFG_PCI1_IO_SIZE,
663                    PCI_REGION_IO);
664
665     pci_set_ops(&pci1_hose,
666                 pci_hose_read_config_byte_via_dword,
667                 pci_hose_read_config_word_via_dword,
668                 gt_read_config_dword,
669                 pci_hose_write_config_byte_via_dword,
670                 pci_hose_write_config_word_via_dword,
671                 gt_write_config_dword);
672
673     pci1_hose.region_count = 2;
674
675     pci1_hose.cfg_addr = (unsigned int*) PCI_HOST1;
676
677     pci_register_hose(&pci1_hose);
678
679     pciArbiterEnable(PCI_HOST1);
680     pciParkingDisable(PCI_HOST1,1,1,1,1,1,1,1);
681
682     command = pciReadConfigReg(PCI_HOST1, PCI_COMMAND, SELF);
683     command |= PCI_COMMAND_MASTER;
684     pciWriteConfigReg(PCI_HOST1, PCI_COMMAND, SELF, command);
685
686     pci1_hose.last_busno = pci_hose_scan(&pci1_hose);
687
688     command = pciReadConfigReg(PCI_HOST1, PCI_COMMAND, SELF);
689     command |= PCI_COMMAND_MEMORY;
690     pciWriteConfigReg(PCI_HOST1, PCI_COMMAND, SELF, command);
691 }