Simon Glass | b94dc89 | 2015-03-05 12:25:25 -0700 | [diff] [blame] | 1 | PCI with Driver Model |
| 2 | ===================== |
| 3 | |
| 4 | How busses are scanned |
| 5 | ---------------------- |
| 6 | |
| 7 | Any config read will end up at pci_read_config(). This uses |
| 8 | uclass_get_device_by_seq() to get the PCI bus for a particular bus number. |
Bin Meng | 8571ea5 | 2015-07-27 00:33:43 -0700 | [diff] [blame] | 9 | Bus number 0 will need to be requested first, and the alias in the device |
Simon Glass | b94dc89 | 2015-03-05 12:25:25 -0700 | [diff] [blame] | 10 | tree file will point to the correct device: |
| 11 | |
| 12 | |
| 13 | aliases { |
| 14 | pci0 = &pci; |
| 15 | }; |
| 16 | |
| 17 | pci: pci-controller { |
| 18 | compatible = "sandbox,pci"; |
| 19 | ... |
| 20 | }; |
| 21 | |
| 22 | |
| 23 | If there is no alias the devices will be numbered sequentially in the device |
| 24 | tree. |
| 25 | |
Bin Meng | 8571ea5 | 2015-07-27 00:33:43 -0700 | [diff] [blame] | 26 | The call to uclass_get_device() will cause the PCI bus to be probed. |
Simon Glass | b94dc89 | 2015-03-05 12:25:25 -0700 | [diff] [blame] | 27 | This does a scan of the bus to locate available devices. These devices are |
| 28 | bound to their appropriate driver if available. If there is no driver, then |
| 29 | they are bound to a generic PCI driver which does nothing. |
| 30 | |
| 31 | After probing a bus, the available devices will appear in the device tree |
| 32 | under that bus. |
| 33 | |
| 34 | Note that this is all done on a lazy basis, as needed, so until something is |
Bin Meng | 8571ea5 | 2015-07-27 00:33:43 -0700 | [diff] [blame] | 35 | touched on PCI (eg: a call to pci_find_devices()) it will not be probed. |
Simon Glass | b94dc89 | 2015-03-05 12:25:25 -0700 | [diff] [blame] | 36 | |
Bin Meng | 651ea8b | 2015-08-24 01:14:04 -0700 | [diff] [blame] | 37 | PCI devices can appear in the flattened device tree. If they do this serves to |
| 38 | specify the driver to use for the device. In this case they will be bound at |
| 39 | first. Each PCI device node must have a compatible string list as well as a |
| 40 | <reg> property, as defined by the IEEE Std 1275-1994 PCI bus binding document |
| 41 | v2.1. Note we must describe PCI devices with the same bus hierarchy as the |
| 42 | hardware, otherwise driver model cannot detect the correct parent/children |
| 43 | relationship during PCI bus enumeration thus PCI devices won't be bound to |
| 44 | their drivers accordingly. A working example like below: |
| 45 | |
| 46 | pci { |
| 47 | #address-cells = <3>; |
| 48 | #size-cells = <2>; |
| 49 | compatible = "pci-x86"; |
| 50 | u-boot,dm-pre-reloc; |
| 51 | ranges = <0x02000000 0x0 0x40000000 0x40000000 0 0x80000000 |
| 52 | 0x42000000 0x0 0xc0000000 0xc0000000 0 0x20000000 |
| 53 | 0x01000000 0x0 0x2000 0x2000 0 0xe000>; |
| 54 | |
| 55 | pcie@17,0 { |
| 56 | #address-cells = <3>; |
| 57 | #size-cells = <2>; |
| 58 | compatible = "pci-bridge"; |
| 59 | u-boot,dm-pre-reloc; |
| 60 | reg = <0x0000b800 0x0 0x0 0x0 0x0>; |
| 61 | |
| 62 | topcliff@0,0 { |
| 63 | #address-cells = <3>; |
| 64 | #size-cells = <2>; |
| 65 | compatible = "pci-bridge"; |
| 66 | u-boot,dm-pre-reloc; |
| 67 | reg = <0x00010000 0x0 0x0 0x0 0x0>; |
| 68 | |
| 69 | pciuart0: uart@a,1 { |
| 70 | compatible = "pci8086,8811.00", |
| 71 | "pci8086,8811", |
| 72 | "pciclass,070002", |
| 73 | "pciclass,0700", |
| 74 | "x86-uart"; |
| 75 | u-boot,dm-pre-reloc; |
| 76 | reg = <0x00025100 0x0 0x0 0x0 0x0 |
| 77 | 0x01025110 0x0 0x0 0x0 0x0>; |
| 78 | ...... |
| 79 | }; |
| 80 | |
| 81 | ...... |
| 82 | }; |
| 83 | }; |
| 84 | |
| 85 | ...... |
| 86 | }; |
| 87 | |
| 88 | In this example, the root PCI bus node is the "/pci" which matches "pci-x86" |
| 89 | driver. It has a subnode "pcie@17,0" with driver "pci-bridge". "pcie@17,0" |
| 90 | also has subnode "topcliff@0,0" which is a "pci-bridge" too. Under that bridge, |
| 91 | a PCI UART device "uart@a,1" is described. This exactly reflects the hardware |
| 92 | bus hierarchy: on the root PCI bus, there is a PCIe root port which connects |
| 93 | to a downstream device Topcliff chipset. Inside Topcliff chipset, it has a |
| 94 | PCIe-to-PCI bridge and all the chipset integrated devices like the PCI UART |
| 95 | device are on the PCI bus. Like other devices in the device tree, if we want |
| 96 | to bind PCI devices before relocation, "u-boot,dm-pre-reloc" must be declared |
| 97 | in each of these nodes. |
| 98 | |
| 99 | If PCI devices are not listed in the device tree, U_BOOT_PCI_DEVICE can be used |
| 100 | to specify the driver to use for the device. The device tree takes precedence |
| 101 | over U_BOOT_PCI_DEVICE. Plese note with U_BOOT_PCI_DEVICE, only drivers with |
| 102 | DM_FLAG_PRE_RELOC will be bound before relocation. If neither device tree nor |
| 103 | U_BOOT_PCI_DEVICE is provided, the built-in driver (either pci_bridge_drv or |
| 104 | pci_generic_drv) will be used. |
Simon Glass | b94dc89 | 2015-03-05 12:25:25 -0700 | [diff] [blame] | 105 | |
| 106 | |
| 107 | Sandbox |
| 108 | ------- |
| 109 | |
| 110 | With sandbox we need a device emulator for each device on the bus since there |
| 111 | is no real PCI bus. This works by looking in the device tree node for a |
| 112 | driver. For example: |
| 113 | |
| 114 | |
| 115 | pci@1f,0 { |
| 116 | compatible = "pci-generic"; |
| 117 | reg = <0xf800 0 0 0 0>; |
| 118 | emul@1f,0 { |
| 119 | compatible = "sandbox,swap-case"; |
| 120 | }; |
| 121 | }; |
| 122 | |
| 123 | This means that there is a 'sandbox,swap-case' driver at that bus position. |
| 124 | Note that the first cell in the 'reg' value is the bus/device/function. See |
| 125 | PCI_BDF() for the encoding (it is also specified in the IEEE Std 1275-1994 |
| 126 | PCI bus binding document, v2.1) |
| 127 | |
| 128 | When this bus is scanned we will end up with something like this: |
| 129 | |
| 130 | `- * pci-controller @ 05c660c8, 0 |
| 131 | `- pci@1f,0 @ 05c661c8, 63488 |
| 132 | `- emul@1f,0 @ 05c662c8 |
| 133 | |
| 134 | When accesses go to the pci@1f,0 device they are forwarded to its child, the |
| 135 | emulator. |
Bin Meng | 156bc6f | 2018-08-03 01:14:45 -0700 | [diff] [blame] | 136 | |
| 137 | The sandbox PCI drivers also support dynamic driver binding, allowing device |
| 138 | driver to declare the driver binding information via U_BOOT_PCI_DEVICE(), |
| 139 | eliminating the need to provide any device tree node under the host controller |
| 140 | node. It is required a "sandbox,dev-info" property must be provided in the |
| 141 | host controller node for this functionality to work. |
| 142 | |
| 143 | pci1: pci-controller1 { |
| 144 | compatible = "sandbox,pci"; |
| 145 | ... |
| 146 | sandbox,dev-info = <0x08 0x00 0x1234 0x5678 |
| 147 | 0x0c 0x00 0x1234 0x5678>; |
| 148 | }; |
| 149 | |
| 150 | The "sandbox,dev-info" property specifies all dynamic PCI devices on this bus. |
| 151 | Each dynamic PCI device is encoded as 4 cells a group. The first and second |
| 152 | cells are PCI device number and function number respectively. The third and |
| 153 | fourth cells are PCI vendor ID and device ID respectively. |
| 154 | |
| 155 | When this bus is scanned we will end up with something like this: |
| 156 | |
| 157 | pci [ + ] pci_sandbo |-- pci-controller1 |
| 158 | pci_emul [ ] sandbox_sw | |-- sandbox_swap_case_emul |
| 159 | pci_emul [ ] sandbox_sw | `-- sandbox_swap_case_emul |
| 160 | |
| 161 | Note the difference from the statically declared device nodes is that the |
| 162 | device is directly attached to the host controller, instead of via a container |
| 163 | device like pci@1f,0. |