| .. SPDX-License-Identifier: GPL-2.0 | |
| =================================== | |
| Writing PCI Host Controller Drivers | |
| =================================== | |
| :Author: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com> | |
| Introduction | |
| ============ | |
| A PCI Host Controller driver controls PCI Root Complex (RC) hardware. The | |
| Root Complex hardware comprises a single PCI Host Bridge and one or more | |
| Root Port or Root Complex Integrated Endpoint (RCiEP) devices:: | |
| +------------------+ | |
| | CPU | | |
| +------------------+ | |
| | | |
| +--------------------------------------------+ | |
| | | Root | | |
| | +------------------+ Complex | | |
| | | Host Bridge | | | |
| | +------------------+ | | |
| | | | | |
| | Bus 0 | | | |
| | +------------|----------+ | | |
| | | | | | | |
| | +----------+ +----------+ +-------+ | | |
| | | Root | | Root | | RCiEP | | | |
| | | Port | | Port | +-------+ | | |
| | +----------+ +----------+ | | |
| | | | | | |
| | Bus 1 | Bus 2 | | | |
| | | | | | |
| +-------|-------------|----------------------+ | |
| | | | |
| +-----------+ +-----------+ | |
| | Endpoint | | Endpoint | | |
| +-----------+ +-----------+ | |
| Host Bridge: Used to connect CPU(s) to the PCI hierarchy. | |
| Root Port: Virtual PCI-PCI bridge connecting the Host Bridge to a PCI bus. | |
| RCiEP: Embedded PCIe Endpoint inside Root Complex connected to the Host | |
| Bridge. | |
| Endpoint: PCIe device connected to a Root Port through a Link. | |
| Enumeration | |
| =========== | |
| The Host Bridge device is not discoverable, so it is typically enumerated | |
| with the help of firmware interfaces like ACPI or Devicetree. But the Root | |
| Port and RCiEP devices are discoverable through the standard enumeration | |
| process defined in the PCIe spec. | |
| A Host Controller driver usually configures both Host Bridge and Root | |
| Port(s) based on platform requirements. In the case of ACPI on standardized | |
| platforms (e.g. x86), no platform-specific host controller driver is | |
| required as the firmware configures the Root Complex before OS boot and | |
| exposes the resource information through ACPI tables. For more info, refer | |
| to :doc:`../acpi-info`. | |
| For Devicetree platforms, a dedicated host controller driver is often | |
| required because the Root Complex hardware typically needs vendor-specific | |
| initialization like PHY, clocks, power domains, and there is no standard | |
| mechanism equivalent to ACPI/MCFG to convey resource information to the OS. | |
| So on these platforms, Root Complex hardware is enumerated through | |
| Devicetree nodes as below:: | |
| pcie@10000000 { | |
| compatible = "vendor,soc-pcie"; | |
| reg = <0x0 0x10000000 0x0 0x1000>, | |
| <0x0 0x10001000 0x0 0x1000>; | |
| reg-names = "cfg", "app"; | |
| device_type = "pci"; | |
| bus-range = <0x00 0xff>; | |
| linux,pci-domain = <0>; | |
| num-lanes = <4>; | |
| #address-cells = <3>; | |
| #size-cells = <2>; | |
| ranges = <0x01000000 0x0 0x00000000 0x0 0x20000000 0x0 0x00100000>, | |
| <0x02000000 0x0 0x20100000 0x0 0x20100000 0x0 0x1ff00000>; | |
| dma-ranges = <0x02000000 0x0 0x0 0x0 0x0 0x0 0x80000000>; | |
| clocks = <&clkc PCIE_CORE_CLK>, | |
| <&clkc PCIE_AUX_CLK>; | |
| clock-names = "core", "aux"; | |
| resets = <&reset PCIE_RESET>; | |
| power-domains = <&power PCIE_PD>; | |
| #interrupt-cells = <1>; | |
| interrupt-map-mask = <0 0 0 0x7>; | |
| interrupt-map = <0 0 0 1 &gic 0 0 GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>, | |
| <0 0 0 2 &gic 0 0 GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>, | |
| <0 0 0 3 &gic 0 0 GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>, | |
| <0 0 0 4 &gic 0 0 GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>; | |
| interrupts = <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>; | |
| interrupt-names = "msi"; | |
| pcie@0 { | |
| compatible = "pciclass,0604"; | |
| device_type = "pci"; | |
| reg = <0x0 0x0 0x0 0x0 0x0>; | |
| bus-range = <0x01 0xff>; | |
| #address-cells = <3>; | |
| #size-cells = <2>; | |
| ranges; | |
| phys = <&pcie_phy>; | |
| reset-gpios = <&gpio 10 GPIO_ACTIVE_LOW>; | |
| wake-gpios = <&gpio 11 GPIO_ACTIVE_LOW>; | |
| }; | |
| }; | |
| Note the presence of two nodes in the above example. The ``pcie@10000000`` | |
| node represents a PCI Host Bridge device, and ``pcie@0`` represents a | |
| single Root Port device. The Host Bridge node should contain properties | |
| associated with the Host Bridge device such as ranges, interrupts, clocks, | |
| power-domains etc... and the Root Port node should contain port-specific | |
| properties such as phys, reset-gpios, wake-gpios etc... | |
| NOTE: Legacy Devicetrees used a single node to describe both Host Bridge | |
| and Root Port devices, but that design is now deprecated. | |
| Driver Design | |
| ============= | |
| Prerequisites | |
| ------------- | |
| Before starting to write a new Host Controller driver, check if any of the | |
| existing drivers can be reused. For example, if the Root Complex supports | |
| the Enhanced Configuration Access Mechanism (ECAM) and the bootloader has | |
| configured the ECAM mapping before OS boot, the ``CONFIG_PCI_HOST_GENERIC`` | |
| driver can be used. | |
| If the Root Complex hardware (IP) is from IP vendors such as Synopsys or | |
| Cadence, the existing ``CONFIG_PCIE_DW_PLAT_HOST`` and | |
| ``CONFIG_PCIE_CADENCE_PLAT_HOST`` drivers can be reused. If not, then check | |
| if any of the existing glue drivers available for these IPs could be | |
| reused. | |
| If the Root Complex hardware is designed in-house by the SoC vendor, check | |
| if there is an existing driver from the vendor for their previous | |
| generation Root Complex hardware. Often, the existing driver can be | |
| reused with minimal modifications. | |
| Only if the Root Complex doesn't satisfy above prerequisites should a new | |
| Host Controller driver be written. | |
| Probe | |
| ----- | |
| During the Host Controller driver probe(), it initializes the Root Complex | |
| hardware and registers the Host Bridge with the PCI core. The typical steps | |
| are described below. | |
| Initialize Resources | |
| ~~~~~~~~~~~~~~~~~~~~ | |
| At the start of the probe(), initialize Host Bridge-specific resources such | |
| as clocks, PHYs, regulators, and resets. These resources are described in | |
| the Host Bridge Devicetree node and should be brought up before accessing | |
| the controller hardware. | |
| NOTE: Use the devm_*() managed APIs wherever possible so the resources are | |
| released automatically on probe failure and on driver detach. | |
| Configuration Space Access | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
| The PCI core accesses the Configuration Space of the enumerated devices | |
| through the callbacks provided by the driver in struct pci_ops. These | |
| callbacks abstract how the Root Complex generates a Configuration Request | |
| for a given Bus, Device and Function number. | |
| If the Root Complex supports ECAM, the generic accessors can be reused by | |
| using pci_ecam_map_bus() along with pci_generic_config_read() and | |
| pci_generic_config_write(). Such drivers can often be built on top of | |
| pci_host_common_probe() without providing any custom accessors. | |
| Setup Address Translation | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~ | |
| The Host Bridge translates accesses between the CPU address domain and the | |
| PCI address domain in both directions: | |
| - Outbound: CPU addresses are translated to PCI bus addresses for the | |
| Memory and I/O accesses initiated by the CPU towards the downstream | |
| devices. These windows are derived from the ``ranges`` property of the | |
| Host Bridge Devicetree node. | |
| - Inbound: PCI bus addresses are translated to system memory addresses for | |
| the accesses (such as DMA) initiated by the downstream devices. These | |
| windows are derived from the ``dma-ranges`` property. | |
| The PCI core parses ``ranges`` and ``dma-ranges`` into the Host Bridge | |
| resource lists, and the driver programs one translation window per entry. | |
| Note that the CPU address and the PCI bus address of a window may differ, | |
| so the offset between them has to be accounted for while programming the | |
| windows. | |
| NOTE: If the hardware supports ECAM, it is strongly recommended to use ECAM | |
| for the Configuration Space so a translation window need not be | |
| reprogrammed for every Configuration access. | |
| Interrupt Handling | |
| ~~~~~~~~~~~~~~~~~~ | |
| Downstream devices can signal interrupts either through INTx or through | |
| Message Signaled Interrupts (MSI/MSI-X). The driver has to enable the | |
| mechanisms supported by the Root Complex. | |
| INTx interrupts are conveyed to the Root Complex through the Assert_INTx | |
| and Deassert_INTx messages and are then reported as system interrupts. The | |
| driver typically creates an IRQ domain for the four interrupts (INTA to | |
| INTD) and demultiplexes an incoming interrupt to the corresponding virtual | |
| IRQ. | |
| An MSI/MSI-X is signaled by the downstream device as a Memory Write to a | |
| Root Complex-specific address. There are two ways to handle them: | |
| - If the Root Complex integrates its own MSI controller, the driver has to | |
| create an MSI IRQ domain, program the MSI target address and demultiplex | |
| the incoming MSIs to the corresponding virtual IRQs. MSI-X is handled | |
| through the same domain. | |
| - If the MSIs are handled by an external interrupt controller (such as the | |
| GIC ITS), the Root Complex Devicetree node needs to have an | |
| ``msi-parent`` property and the driver need not implement an MSI | |
| controller. | |
| Powering up the Slot/Endpoint | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
| Power ON any slots or Endpoints connected to the bus with the help of the | |
| PWRCTRL subsystem APIs such as pci_pwrctrl_create_devices() and | |
| pci_pwrctrl_power_on_devices(). Note that this requires defining the | |
| supplies in the Root Port or Endpoint Devicetree node. | |
| Link Training | |
| ~~~~~~~~~~~~~ | |
| Once the resources are initialized, the driver has to initiate Link | |
| training by enabling the LTSSM (Link Training and Status State Machine) of | |
| the Root Port. If a PERST# signal is present, it should be deasserted to | |
| bring the downstream device out of fundamental reset before enabling the | |
| LTSSM. | |
| Before PERST# is deasserted, the driver must satisfy the power sequencing | |
| delays defined by the PCI Express Card Electromechanical (CEM) | |
| Specification. The power supplies must be stable for at least T_PVPERL | |
| (``PCIE_T_PVPERL_MS``, 100 ms) and the reference clock must be stable for | |
| at least T_PERST-CLK (``PCIE_T_PERST_CLK_US``, 100 us) before PERST# is | |
| deasserted. | |
| After the LTSSM is enabled, the driver should wait (with a timeout) for the | |
| LTSSM to reach the L0 state, indicating that the Link is up. | |
| Once the Link is up, the PCI Express Base Specification (Conventional | |
| Reset) requires software to wait for at least ``PCIE_RESET_CONFIG_WAIT_MS`` | |
| (100 ms) before sending the first Configuration Request to the downstream | |
| device. For a Link operating up to 5.0 GT/s, this delay is counted from the | |
| exit of the Conventional Reset (PERST# deassertion), while for a Link | |
| operating above 5.0 GT/s it is counted from the completion of Link | |
| training. The driver should honor this delay before the bus is scanned. | |
| NOTE: A failure to establish the Link should NOT be treated as a probe | |
| failure unless the Root Port is not Hotplug capable. If the Root Port is | |
| Hotplug capable, then the driver should still register the Host Bridge and | |
| scan the bus, so that the downstream device can be discovered later when | |
| the Link comes up. | |
| Register the Host Bridge | |
| ~~~~~~~~~~~~~~~~~~~~~~~~ | |
| Finally, allocate the Host Bridge device with devm_pci_alloc_host_bridge(), | |
| assign the Configuration Space accessors (struct pci_ops) to it, and start | |
| the bus scan by calling pci_host_probe(). This is the last step of the | |
| probe(). pci_host_probe() creates the Root bus for the Host Bridge and | |
| scans/enumerates all the Root Port, RCiEP and Endpoint devices connected to | |
| the bus. | |
| If the Root Complex IP is from a known IP vendor, the IP specific helpers | |
| should be reused for the above operations wherever applicable. | |
| Power Management | |
| ---------------- | |
| A Host Controller driver participates in both runtime and system-wide power | |
| management. In both cases, the driver is responsible for the power state of | |
| the Root Complex hardware, while the PCI core manages the power state of | |
| the enumerated devices. | |
| Runtime PM | |
| ~~~~~~~~~~ | |
| Runtime PM allows the Root Complex hardware to be powered down when it is | |
| idle. The driver typically enables runtime PM with pm_runtime_enable() and | |
| takes a reference with pm_runtime_get_sync() during probe(), so that the | |
| controller stays powered while it is in use. The reference is dropped in | |
| remove(). | |
| If the Root Complex can be powered down when idle, the driver implements | |
| the runtime_suspend and runtime_resume callbacks to disable and enable the | |
| controller resources such as the clocks, PHYs, and power domain. These | |
| callbacks should manage only the controller resources and must not touch | |
| the state of the enumerated devices, which is handled by the PCI core. | |
| System PM | |
| ~~~~~~~~~ | |
| During system suspend and resume, the driver has to save and restore the | |
| state of the Root Complex and put the Link into a low power state. | |
| These operations are performed in the _noirq() PM callbacks (for example, | |
| using NOIRQ_SYSTEM_SLEEP_PM_OPS()), because the controller resources such | |
| as the clocks and PHY are shared by all the child devices. Suspending them | |
| earlier would break the child devices whose own suspend callbacks may still | |
| access their Configuration Space. | |
| In the suspend callback, the driver should: | |
| - Broadcast a PME_Turn_Off message and wait for the PME_TO_Ack, so that the | |
| Link can transition to the L2/L3 state. | |
| - Stop the LTSSM and disable the controller resources such as the clocks, | |
| PHY and power domain. | |
| - Save any controller state that is not retained across the low power | |
| state. | |
| - Power off the downstream devices using pci_pwrctrl_power_off_devices(). | |
| In the resume callback, the driver should reverse the above by enabling the | |
| controller resources, restoring the saved state, re-initializing the Root | |
| Complex and re-establishing the Link as done during probe(). | |
| NOTE: If the Link is in the ASPM L1 (or L1 substates) state, some drivers | |
| keep the Link in L1 across suspend for a faster resume, instead of | |
| transitioning it to L2/L3. This is a driver policy decision based on the | |
| platform and the devices connected. | |
| Shutdown | |
| -------- | |
| The shutdown() callback is invoked during system reboot or when | |
| transitioning to a new kernel through kexec. Its purpose is to quiesce the | |
| Root Complex so that the downstream devices cannot corrupt the memory or | |
| interrupt the new kernel. | |
| The driver should: | |
| - Disable the interrupts (INTx and MSI) reported by the Root Complex so | |
| that no spurious interrupt is delivered to the new kernel. | |
| - Broadcast a PME_Turn_Off message and stop the LTSSM to bring the Link | |
| down so that any in-flight DMA from the downstream devices is stopped | |
| before the reset. | |
| - Power down the controller resources. | |
| Unlike remove(), shutdown() does not need to tear down the software state | |
| such as the Root bus, since the system is going down anyway. | |
| NOTE: shutdown() is optional. It is mainly required on platforms where the | |
| downstream devices could perform DMA or raise interrupts during the | |
| transition to reboot or kexec. | |
| Remove | |
| ------ | |
| remove() is called when the driver is detached, and it should undo | |
| everything done in probe() in the reverse order. | |
| The first step is to remove the enumerated devices and the Root bus, by | |
| calling pci_stop_root_bus() followed by pci_remove_root_bus() under the | |
| pci_lock_rescan_remove() lock. This detaches all the child devices before | |
| the controller resources are released. | |
| After the bus is removed, the driver should: | |
| - Disable the interrupts reported by the Root Complex. | |
| - Stop the LTSSM to bring the Link down. | |
| - Power down the PHY and disable the clocks, regulators and resets. | |
| - Drop the runtime PM reference with pm_runtime_put_sync() and disable | |
| runtime PM with pm_runtime_disable(). | |
| Resources allocated through the devm_*() APIs are released automatically | |
| after remove() returns and need not be freed explicitly. | |
| NOTE: A Host Controller driver is encouraged to be built as a loadable | |
| module, but it should not be removed at runtime if it implements its own | |
| IRQ domains such as MSI or INTx controllers. The IRQ mappings created for | |
| such domains can persist even after the interrupts are released and cannot | |
| be disposed of safely, so tearing down the IRQ domains on removal is | |
| fragile. Such drivers should therefore prevent their removal. See the | |
| following thread for more details: | |
| https://lore.kernel.org/linux-pci/87k085xekg.wl-maz@kernel.org/ |