2 * Copyright 2010 Andreas Färber <andreas.faerber@web.de>
3 * Copyright 2006, Ingo Weinhold <bonefish@cs.tu-berlin.de>.
4 * All rights reserved. Distributed under the terms of the MIT License.
7 * Copyright (c) 2000 Tsubai Masanari. All rights reserved.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. The name of the author may not be used to endorse or promote products
18 * derived from this software without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 #include <KernelExport.h>
35 #include <platform/openfirmware/devices.h>
36 #include <platform/openfirmware/openfirmware.h>
37 #include <platform/openfirmware/pci.h>
39 #include "pci_controller.h"
41 #include "pci_openfirmware_priv.h"
44 //#define TRACE_GRACKLE
47 #define TRACE(fmt...) dprintf(fmt)
49 #define TRACE(fmt...) ;
53 struct grackle_range
{
63 struct grackle_host_bridge
{
65 addr_t address_registers
;
66 addr_t data_registers
;
68 struct grackle_range ranges
[6];
73 #define out8rb(address, value) ppc_out8((vuint8*)(address), value)
74 #define out16rb(address, value) ppc_out16_reverse((vuint16*)(address), value)
75 #define out32rb(address, value) ppc_out32_reverse((vuint32*)(address), value)
76 #define in8rb(address) ppc_in8((const vuint8*)(address))
77 #define in16rb(address) ppc_in16_reverse((const vuint16*)(address))
78 #define in32rb(address) ppc_in32_reverse((const vuint32*)(address))
82 grackle_read_pci_config(void *cookie
, uint8 bus
, uint8 device
, uint8 function
,
83 uint16 offset
, uint8 size
, uint32
*value
)
85 grackle_host_bridge
*bridge
= (grackle_host_bridge
*)cookie
;
86 TRACE("grackle_read_pci_config(bus=%u, dev=%u, func=%u, offset=%u, "
87 "size=%u)\n", (int)bus
, (int)device
, (int)function
, (int)offset
,
93 out32rb(bridge
->address_registers
, (1 << 31)
94 | (bus
<< 16) | ((device
& 0x1f) << 11) | ((function
& 0x7) << 8)
97 addr_t dataAddress
= bridge
->data_registers
+ (offset
& 0x3);
100 *value
= in8rb(dataAddress
);
103 *value
= in16rb(dataAddress
);
106 *value
= in32rb(dataAddress
);
113 out32rb(bridge
->address_registers
, 0);
120 grackle_write_pci_config(void *cookie
, uint8 bus
, uint8 device
, uint8 function
,
121 uint16 offset
, uint8 size
, uint32 value
)
123 grackle_host_bridge
*bridge
= (grackle_host_bridge
*)cookie
;
124 TRACE("grackle_write_pci_config(bus=%u, dev=%u, func=%u, offset=%u, "
125 "size=%u, value=%lu)\n", (int)bus
, (int)device
, (int)function
,
126 (int)offset
, (int)size
, value
);
131 out32rb(bridge
->address_registers
, (1 << 31)
132 | (bus
<< 16) | ((device
& 0x1f) << 11) | ((function
& 0x7) << 8)
135 addr_t dataAddress
= bridge
->data_registers
+ (offset
& 0x3);
138 out8rb(dataAddress
, (uint8
)value
);
141 out16rb(dataAddress
, (uint16
)value
);
144 out32rb(dataAddress
, value
);
148 out32rb(bridge
->address_registers
, 0);
155 grackle_get_max_bus_devices(void *cookie
, int32
*count
)
163 grackle_read_pci_irq(void *cookie
, uint8 bus
, uint8 device
, uint8 function
,
164 uint8 pin
, uint8
*irq
)
171 grackle_write_pci_irq(void *cookie
, uint8 bus
, uint8 device
, uint8 function
,
172 uint8 pin
, uint8 irq
)
178 static pci_controller sGracklePCIController
= {
179 grackle_read_pci_config
,
180 grackle_write_pci_config
,
181 grackle_get_max_bus_devices
,
182 grackle_read_pci_irq
,
183 grackle_write_pci_irq
,
188 ppc_openfirmware_probe_grackle(int deviceNode
,
189 const StringArrayPropertyValue
&compatibleValue
)
191 if (!compatibleValue
.ContainsElement("grackle"))
194 uint32_t busrange
[2];
195 if (of_getprop(deviceNode
, "bus-range", busrange
, sizeof(busrange
)) != 8)
198 grackle_host_bridge
*bridge
=
199 (grackle_host_bridge
*)malloc(sizeof(grackle_host_bridge
));
203 bridge
->device_node
= deviceNode
;
204 bridge
->address_registers
= 0xfec00000;
205 bridge
->data_registers
= 0xfee00000;
206 bridge
->bus
= busrange
[0];
208 memset(bridge
->ranges
, 0, sizeof(bridge
->ranges
));
209 int bytesRead
= of_getprop(deviceNode
, "ranges", bridge
->ranges
,
210 sizeof(bridge
->ranges
));
212 dprintf("ppc_openfirmware_probe_grackle: Could not get ranges.\n");
216 bridge
->range_count
= bytesRead
/ sizeof(grackle_range
);
218 grackle_range
*ioRange
= NULL
;
219 grackle_range
*memoryRanges
[2];
220 int memoryRangeCount
= 0;
222 for (int i
= 0; i
< bridge
->range_count
; i
++) {
223 grackle_range
*range
= bridge
->ranges
+ i
;
224 switch (range
->pci_hi
& OFW_PCI_PHYS_HI_SPACEMASK
) {
225 case OFW_PCI_PHYS_HI_SPACE_CONFIG
:
227 case OFW_PCI_PHYS_HI_SPACE_IO
:
230 case OFW_PCI_PHYS_HI_SPACE_MEM32
:
231 memoryRanges
[memoryRangeCount
++] = range
;
233 case OFW_PCI_PHYS_HI_SPACE_MEM64
:
238 if (ioRange
== NULL
) {
239 dprintf("ppc_openfirmware_probe_grackle: Can't find io range.\n");
244 if (memoryRangeCount
== 0) {
245 dprintf("ppc_openfirmware_probe_grackle: Can't find mem ranges.\n");
250 status_t error
= pci_controller_add(&sGracklePCIController
, bridge
);