mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-27 06:34:11 +08:00
ce292991d8
Add support for a generic PCI host controller, such as a firmware-initialised device with static windows or an emulation by something such as kvmtool. The controller itself has no configuration registers and has its address spaces described entirely by the device-tree (using the bindings from ePAPR). Both CAM and ECAM are supported for Config Space accesses. Add corresponding documentation for the DT binding. [bhelgaas: currently uses the ARM-specific pci_common_init_dev() interface] Signed-off-by: Will Deacon <will.deacon@arm.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Reviewed-by: Liviu Dudau <liviu.dudau@arm.com>
101 lines
3.5 KiB
Plaintext
101 lines
3.5 KiB
Plaintext
* Generic PCI host controller
|
|
|
|
Firmware-initialised PCI host controllers and PCI emulations, such as the
|
|
virtio-pci implementations found in kvmtool and other para-virtualised
|
|
systems, do not require driver support for complexities such as regulator
|
|
and clock management. In fact, the controller may not even require the
|
|
configuration of a control interface by the operating system, instead
|
|
presenting a set of fixed windows describing a subset of IO, Memory and
|
|
Configuration Spaces.
|
|
|
|
Such a controller can be described purely in terms of the standardized device
|
|
tree bindings communicated in pci.txt:
|
|
|
|
|
|
Properties of the host controller node:
|
|
|
|
- compatible : Must be "pci-host-cam-generic" or "pci-host-ecam-generic"
|
|
depending on the layout of configuration space (CAM vs
|
|
ECAM respectively).
|
|
|
|
- device_type : Must be "pci".
|
|
|
|
- ranges : As described in IEEE Std 1275-1994, but must provide
|
|
at least a definition of non-prefetchable memory. One
|
|
or both of prefetchable Memory and IO Space may also
|
|
be provided.
|
|
|
|
- bus-range : Optional property (also described in IEEE Std 1275-1994)
|
|
to indicate the range of bus numbers for this controller.
|
|
If absent, defaults to <0 255> (i.e. all buses).
|
|
|
|
- #address-cells : Must be 3.
|
|
|
|
- #size-cells : Must be 2.
|
|
|
|
- reg : The Configuration Space base address and size, as accessed
|
|
from the parent bus.
|
|
|
|
|
|
Properties of the /chosen node:
|
|
|
|
- linux,pci-probe-only
|
|
: Optional property which takes a single-cell argument.
|
|
If '0', then Linux will assign devices in its usual manner,
|
|
otherwise it will not try to assign devices and instead use
|
|
them as they are configured already.
|
|
|
|
Configuration Space is assumed to be memory-mapped (as opposed to being
|
|
accessed via an ioport) and laid out with a direct correspondence to the
|
|
geography of a PCI bus address by concatenating the various components to
|
|
form an offset.
|
|
|
|
For CAM, this 24-bit offset is:
|
|
|
|
cfg_offset(bus, device, function, register) =
|
|
bus << 16 | device << 11 | function << 8 | register
|
|
|
|
Whilst ECAM extends this by 4 bits to accomodate 4k of function space:
|
|
|
|
cfg_offset(bus, device, function, register) =
|
|
bus << 20 | device << 15 | function << 12 | register
|
|
|
|
Interrupt mapping is exactly as described in `Open Firmware Recommended
|
|
Practice: Interrupt Mapping' and requires the following properties:
|
|
|
|
- #interrupt-cells : Must be 1
|
|
|
|
- interrupt-map : <see aforementioned specification>
|
|
|
|
- interrupt-map-mask : <see aforementioned specification>
|
|
|
|
|
|
Example:
|
|
|
|
pci {
|
|
compatible = "pci-host-cam-generic"
|
|
device_type = "pci";
|
|
#address-cells = <3>;
|
|
#size-cells = <2>;
|
|
bus-range = <0x0 0x1>;
|
|
|
|
// CPU_PHYSICAL(2) SIZE(2)
|
|
reg = <0x0 0x40000000 0x0 0x1000000>;
|
|
|
|
// BUS_ADDRESS(3) CPU_PHYSICAL(2) SIZE(2)
|
|
ranges = <0x01000000 0x0 0x01000000 0x0 0x01000000 0x0 0x00010000>,
|
|
<0x02000000 0x0 0x41000000 0x0 0x41000000 0x0 0x3f000000>;
|
|
|
|
|
|
#interrupt-cells = <0x1>;
|
|
|
|
// PCI_DEVICE(3) INT#(1) CONTROLLER(PHANDLE) CONTROLLER_DATA(3)
|
|
interrupt-map = < 0x0 0x0 0x0 0x1 &gic 0x0 0x4 0x1
|
|
0x800 0x0 0x0 0x1 &gic 0x0 0x5 0x1
|
|
0x1000 0x0 0x0 0x1 &gic 0x0 0x6 0x1
|
|
0x1800 0x0 0x0 0x1 &gic 0x0 0x7 0x1>;
|
|
|
|
// PCI_DEVICE(3) INT#(1)
|
|
interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
|
|
}
|