|  | /* SPDX-License-Identifier: GPL-2.0 */ | 
|  | #ifndef __PCI_BRIDGE_EMUL_H__ | 
|  | #define __PCI_BRIDGE_EMUL_H__ | 
|  |  | 
|  | #include <linux/kernel.h> | 
|  |  | 
|  | /* PCI configuration space of a PCI-to-PCI bridge. */ | 
|  | struct pci_bridge_emul_conf { | 
|  | __le16 vendor; | 
|  | __le16 device; | 
|  | __le16 command; | 
|  | __le16 status; | 
|  | __le32 class_revision; | 
|  | u8 cache_line_size; | 
|  | u8 latency_timer; | 
|  | u8 header_type; | 
|  | u8 bist; | 
|  | __le32 bar[2]; | 
|  | u8 primary_bus; | 
|  | u8 secondary_bus; | 
|  | u8 subordinate_bus; | 
|  | u8 secondary_latency_timer; | 
|  | u8 iobase; | 
|  | u8 iolimit; | 
|  | __le16 secondary_status; | 
|  | __le16 membase; | 
|  | __le16 memlimit; | 
|  | __le16 pref_mem_base; | 
|  | __le16 pref_mem_limit; | 
|  | __le32 prefbaseupper; | 
|  | __le32 preflimitupper; | 
|  | __le16 iobaseupper; | 
|  | __le16 iolimitupper; | 
|  | u8 capabilities_pointer; | 
|  | u8 reserve[3]; | 
|  | __le32 romaddr; | 
|  | u8 intline; | 
|  | u8 intpin; | 
|  | __le16 bridgectrl; | 
|  | }; | 
|  |  | 
|  | /* PCI configuration space of the PCIe capabilities */ | 
|  | struct pci_bridge_emul_pcie_conf { | 
|  | u8 cap_id; | 
|  | u8 next; | 
|  | __le16 cap; | 
|  | __le32 devcap; | 
|  | __le16 devctl; | 
|  | __le16 devsta; | 
|  | __le32 lnkcap; | 
|  | __le16 lnkctl; | 
|  | __le16 lnksta; | 
|  | __le32 slotcap; | 
|  | __le16 slotctl; | 
|  | __le16 slotsta; | 
|  | __le16 rootctl; | 
|  | __le16 rootcap; | 
|  | __le32 rootsta; | 
|  | __le32 devcap2; | 
|  | __le16 devctl2; | 
|  | __le16 devsta2; | 
|  | __le32 lnkcap2; | 
|  | __le16 lnkctl2; | 
|  | __le16 lnksta2; | 
|  | __le32 slotcap2; | 
|  | __le16 slotctl2; | 
|  | __le16 slotsta2; | 
|  | }; | 
|  |  | 
|  | struct pci_bridge_emul; | 
|  |  | 
|  | typedef enum { PCI_BRIDGE_EMUL_HANDLED, | 
|  | PCI_BRIDGE_EMUL_NOT_HANDLED } pci_bridge_emul_read_status_t; | 
|  |  | 
|  | struct pci_bridge_emul_ops { | 
|  | /* | 
|  | * Called when reading from the regular PCI bridge | 
|  | * configuration space. Return PCI_BRIDGE_EMUL_HANDLED when the | 
|  | * operation has handled the read operation and filled in the | 
|  | * *value, or PCI_BRIDGE_EMUL_NOT_HANDLED when the read should | 
|  | * be emulated by the common code by reading from the | 
|  | * in-memory copy of the configuration space. | 
|  | */ | 
|  | pci_bridge_emul_read_status_t (*read_base)(struct pci_bridge_emul *bridge, | 
|  | int reg, u32 *value); | 
|  |  | 
|  | /* | 
|  | * Same as ->read_base(), except it is for reading from the | 
|  | * PCIe capability configuration space. | 
|  | */ | 
|  | pci_bridge_emul_read_status_t (*read_pcie)(struct pci_bridge_emul *bridge, | 
|  | int reg, u32 *value); | 
|  |  | 
|  | /* | 
|  | * Same as ->read_base(), except it is for reading from the | 
|  | * PCIe extended capability configuration space. | 
|  | */ | 
|  | pci_bridge_emul_read_status_t (*read_ext)(struct pci_bridge_emul *bridge, | 
|  | int reg, u32 *value); | 
|  |  | 
|  | /* | 
|  | * Called when writing to the regular PCI bridge configuration | 
|  | * space. old is the current value, new is the new value being | 
|  | * written, and mask indicates which parts of the value are | 
|  | * being changed. | 
|  | */ | 
|  | void (*write_base)(struct pci_bridge_emul *bridge, int reg, | 
|  | u32 old, u32 new, u32 mask); | 
|  |  | 
|  | /* | 
|  | * Same as ->write_base(), except it is for writing from the | 
|  | * PCIe capability configuration space. | 
|  | */ | 
|  | void (*write_pcie)(struct pci_bridge_emul *bridge, int reg, | 
|  | u32 old, u32 new, u32 mask); | 
|  |  | 
|  | /* | 
|  | * Same as ->write_base(), except it is for writing from the | 
|  | * PCIe extended capability configuration space. | 
|  | */ | 
|  | void (*write_ext)(struct pci_bridge_emul *bridge, int reg, | 
|  | u32 old, u32 new, u32 mask); | 
|  | }; | 
|  |  | 
|  | struct pci_bridge_reg_behavior; | 
|  |  | 
|  | struct pci_bridge_emul { | 
|  | struct pci_bridge_emul_conf conf; | 
|  | struct pci_bridge_emul_pcie_conf pcie_conf; | 
|  | const struct pci_bridge_emul_ops *ops; | 
|  | struct pci_bridge_reg_behavior *pci_regs_behavior; | 
|  | struct pci_bridge_reg_behavior *pcie_cap_regs_behavior; | 
|  | void *data; | 
|  | u8 pcie_start; | 
|  | u8 ssid_start; | 
|  | bool has_pcie; | 
|  | u16 subsystem_vendor_id; | 
|  | u16 subsystem_id; | 
|  | }; | 
|  |  | 
|  | enum { | 
|  | /* | 
|  | * PCI bridge does not support forwarding of prefetchable memory | 
|  | * requests between primary and secondary buses. | 
|  | */ | 
|  | PCI_BRIDGE_EMUL_NO_PREFMEM_FORWARD = BIT(0), | 
|  |  | 
|  | /* | 
|  | * PCI bridge does not support forwarding of IO requests between | 
|  | * primary and secondary buses. | 
|  | */ | 
|  | PCI_BRIDGE_EMUL_NO_IO_FORWARD = BIT(1), | 
|  | }; | 
|  |  | 
|  | int pci_bridge_emul_init(struct pci_bridge_emul *bridge, | 
|  | unsigned int flags); | 
|  | void pci_bridge_emul_cleanup(struct pci_bridge_emul *bridge); | 
|  |  | 
|  | int pci_bridge_emul_conf_read(struct pci_bridge_emul *bridge, int where, | 
|  | int size, u32 *value); | 
|  | int pci_bridge_emul_conf_write(struct pci_bridge_emul *bridge, int where, | 
|  | int size, u32 value); | 
|  |  | 
|  | #endif /* __PCI_BRIDGE_EMUL_H__ */ |