162306a36Sopenharmony_ci.. SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci
362306a36Sopenharmony_ci============================================
462306a36Sopenharmony_ciAccessing PCI device resources through sysfs
562306a36Sopenharmony_ci============================================
662306a36Sopenharmony_ci
762306a36Sopenharmony_cisysfs, usually mounted at /sys, provides access to PCI resources on platforms
862306a36Sopenharmony_cithat support it.  For example, a given bus might look like this::
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci     /sys/devices/pci0000:17
1162306a36Sopenharmony_ci     |-- 0000:17:00.0
1262306a36Sopenharmony_ci     |   |-- class
1362306a36Sopenharmony_ci     |   |-- config
1462306a36Sopenharmony_ci     |   |-- device
1562306a36Sopenharmony_ci     |   |-- enable
1662306a36Sopenharmony_ci     |   |-- irq
1762306a36Sopenharmony_ci     |   |-- local_cpus
1862306a36Sopenharmony_ci     |   |-- remove
1962306a36Sopenharmony_ci     |   |-- resource
2062306a36Sopenharmony_ci     |   |-- resource0
2162306a36Sopenharmony_ci     |   |-- resource1
2262306a36Sopenharmony_ci     |   |-- resource2
2362306a36Sopenharmony_ci     |   |-- revision
2462306a36Sopenharmony_ci     |   |-- rom
2562306a36Sopenharmony_ci     |   |-- subsystem_device
2662306a36Sopenharmony_ci     |   |-- subsystem_vendor
2762306a36Sopenharmony_ci     |   `-- vendor
2862306a36Sopenharmony_ci     `-- ...
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ciThe topmost element describes the PCI domain and bus number.  In this case,
3162306a36Sopenharmony_cithe domain number is 0000 and the bus number is 17 (both values are in hex).
3262306a36Sopenharmony_ciThis bus contains a single function device in slot 0.  The domain and bus
3362306a36Sopenharmony_cinumbers are reproduced for convenience.  Under the device directory are several
3462306a36Sopenharmony_cifiles, each with their own function.
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci       =================== =====================================================
3762306a36Sopenharmony_ci       file		   function
3862306a36Sopenharmony_ci       =================== =====================================================
3962306a36Sopenharmony_ci       class		   PCI class (ascii, ro)
4062306a36Sopenharmony_ci       config		   PCI config space (binary, rw)
4162306a36Sopenharmony_ci       device		   PCI device (ascii, ro)
4262306a36Sopenharmony_ci       enable	           Whether the device is enabled (ascii, rw)
4362306a36Sopenharmony_ci       irq		   IRQ number (ascii, ro)
4462306a36Sopenharmony_ci       local_cpus	   nearby CPU mask (cpumask, ro)
4562306a36Sopenharmony_ci       remove		   remove device from kernel's list (ascii, wo)
4662306a36Sopenharmony_ci       resource		   PCI resource host addresses (ascii, ro)
4762306a36Sopenharmony_ci       resource0..N	   PCI resource N, if present (binary, mmap, rw\ [1]_)
4862306a36Sopenharmony_ci       resource0_wc..N_wc  PCI WC map resource N, if prefetchable (binary, mmap)
4962306a36Sopenharmony_ci       revision		   PCI revision (ascii, ro)
5062306a36Sopenharmony_ci       rom		   PCI ROM resource, if present (binary, ro)
5162306a36Sopenharmony_ci       subsystem_device	   PCI subsystem device (ascii, ro)
5262306a36Sopenharmony_ci       subsystem_vendor	   PCI subsystem vendor (ascii, ro)
5362306a36Sopenharmony_ci       vendor		   PCI vendor (ascii, ro)
5462306a36Sopenharmony_ci       =================== =====================================================
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci::
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci  ro - read only file
5962306a36Sopenharmony_ci  rw - file is readable and writable
6062306a36Sopenharmony_ci  wo - write only file
6162306a36Sopenharmony_ci  mmap - file is mmapable
6262306a36Sopenharmony_ci  ascii - file contains ascii text
6362306a36Sopenharmony_ci  binary - file contains binary data
6462306a36Sopenharmony_ci  cpumask - file contains a cpumask type
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci.. [1] rw for IORESOURCE_IO (I/O port) regions only
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ciThe read only files are informational, writes to them will be ignored, with
6962306a36Sopenharmony_cithe exception of the 'rom' file.  Writable files can be used to perform
7062306a36Sopenharmony_ciactions on the device (e.g. changing config space, detaching a device).
7162306a36Sopenharmony_cimmapable files are available via an mmap of the file at offset 0 and can be
7262306a36Sopenharmony_ciused to do actual device programming from userspace.  Note that some platforms
7362306a36Sopenharmony_cidon't support mmapping of certain resources, so be sure to check the return
7462306a36Sopenharmony_civalue from any attempted mmap.  The most notable of these are I/O port
7562306a36Sopenharmony_ciresources, which also provide read/write access.
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ciThe 'enable' file provides a counter that indicates how many times the device
7862306a36Sopenharmony_cihas been enabled.  If the 'enable' file currently returns '4', and a '1' is
7962306a36Sopenharmony_ciechoed into it, it will then return '5'.  Echoing a '0' into it will decrease
8062306a36Sopenharmony_cithe count.  Even when it returns to 0, though, some of the initialisation
8162306a36Sopenharmony_cimay not be reversed.
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ciThe 'rom' file is special in that it provides read-only access to the device's
8462306a36Sopenharmony_ciROM file, if available.  It's disabled by default, however, so applications
8562306a36Sopenharmony_cishould write the string "1" to the file to enable it before attempting a read
8662306a36Sopenharmony_cicall, and disable it following the access by writing "0" to the file.  Note
8762306a36Sopenharmony_cithat the device must be enabled for a rom read to return data successfully.
8862306a36Sopenharmony_ciIn the event a driver is not bound to the device, it can be enabled using the
8962306a36Sopenharmony_ci'enable' file, documented above.
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ciThe 'remove' file is used to remove the PCI device, by writing a non-zero
9262306a36Sopenharmony_ciinteger to the file.  This does not involve any kind of hot-plug functionality,
9362306a36Sopenharmony_cie.g. powering off the device.  The device is removed from the kernel's list of
9462306a36Sopenharmony_ciPCI devices, the sysfs directory for it is removed, and the device will be
9562306a36Sopenharmony_ciremoved from any drivers attached to it. Removal of PCI root buses is
9662306a36Sopenharmony_cidisallowed.
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ciAccessing legacy resources through sysfs
9962306a36Sopenharmony_ci----------------------------------------
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ciLegacy I/O port and ISA memory resources are also provided in sysfs if the
10262306a36Sopenharmony_ciunderlying platform supports them.  They're located in the PCI class hierarchy,
10362306a36Sopenharmony_cie.g.::
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci	/sys/class/pci_bus/0000:17/
10662306a36Sopenharmony_ci	|-- bridge -> ../../../devices/pci0000:17
10762306a36Sopenharmony_ci	|-- cpuaffinity
10862306a36Sopenharmony_ci	|-- legacy_io
10962306a36Sopenharmony_ci	`-- legacy_mem
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ciThe legacy_io file is a read/write file that can be used by applications to
11262306a36Sopenharmony_cido legacy port I/O.  The application should open the file, seek to the desired
11362306a36Sopenharmony_ciport (e.g. 0x3e8) and do a read or a write of 1, 2 or 4 bytes.  The legacy_mem
11462306a36Sopenharmony_cifile should be mmapped with an offset corresponding to the memory offset
11562306a36Sopenharmony_cidesired, e.g. 0xa0000 for the VGA frame buffer.  The application can then
11662306a36Sopenharmony_cisimply dereference the returned pointer (after checking for errors of course)
11762306a36Sopenharmony_cito access legacy memory space.
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ciSupporting PCI access on new platforms
12062306a36Sopenharmony_ci--------------------------------------
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ciIn order to support PCI resource mapping as described above, Linux platform
12362306a36Sopenharmony_cicode should ideally define ARCH_GENERIC_PCI_MMAP_RESOURCE and use the generic
12462306a36Sopenharmony_ciimplementation of that functionality. To support the historical interface of
12562306a36Sopenharmony_cimmap() through files in /proc/bus/pci, platforms may also set HAVE_PCI_MMAP.
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ciAlternatively, platforms which set HAVE_PCI_MMAP may provide their own
12862306a36Sopenharmony_ciimplementation of pci_mmap_resource_range() instead of defining
12962306a36Sopenharmony_ciARCH_GENERIC_PCI_MMAP_RESOURCE.
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ciPlatforms which support write-combining maps of PCI resources must define
13262306a36Sopenharmony_ciarch_can_pci_mmap_wc() which shall evaluate to non-zero at runtime when
13362306a36Sopenharmony_ciwrite-combining is permitted. Platforms which support maps of I/O resources
13462306a36Sopenharmony_cidefine arch_can_pci_mmap_io() similarly.
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_ciLegacy resources are protected by the HAVE_PCI_LEGACY define.  Platforms
13762306a36Sopenharmony_ciwishing to support legacy functionality should define it and provide
13862306a36Sopenharmony_cipci_legacy_read, pci_legacy_write and pci_mmap_legacy_page_range functions.
139