162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci#ifndef __PCI_BRIDGE_EMUL_H__ 362306a36Sopenharmony_ci#define __PCI_BRIDGE_EMUL_H__ 462306a36Sopenharmony_ci 562306a36Sopenharmony_ci#include <linux/kernel.h> 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci/* PCI configuration space of a PCI-to-PCI bridge. */ 862306a36Sopenharmony_cistruct pci_bridge_emul_conf { 962306a36Sopenharmony_ci __le16 vendor; 1062306a36Sopenharmony_ci __le16 device; 1162306a36Sopenharmony_ci __le16 command; 1262306a36Sopenharmony_ci __le16 status; 1362306a36Sopenharmony_ci __le32 class_revision; 1462306a36Sopenharmony_ci u8 cache_line_size; 1562306a36Sopenharmony_ci u8 latency_timer; 1662306a36Sopenharmony_ci u8 header_type; 1762306a36Sopenharmony_ci u8 bist; 1862306a36Sopenharmony_ci __le32 bar[2]; 1962306a36Sopenharmony_ci u8 primary_bus; 2062306a36Sopenharmony_ci u8 secondary_bus; 2162306a36Sopenharmony_ci u8 subordinate_bus; 2262306a36Sopenharmony_ci u8 secondary_latency_timer; 2362306a36Sopenharmony_ci u8 iobase; 2462306a36Sopenharmony_ci u8 iolimit; 2562306a36Sopenharmony_ci __le16 secondary_status; 2662306a36Sopenharmony_ci __le16 membase; 2762306a36Sopenharmony_ci __le16 memlimit; 2862306a36Sopenharmony_ci __le16 pref_mem_base; 2962306a36Sopenharmony_ci __le16 pref_mem_limit; 3062306a36Sopenharmony_ci __le32 prefbaseupper; 3162306a36Sopenharmony_ci __le32 preflimitupper; 3262306a36Sopenharmony_ci __le16 iobaseupper; 3362306a36Sopenharmony_ci __le16 iolimitupper; 3462306a36Sopenharmony_ci u8 capabilities_pointer; 3562306a36Sopenharmony_ci u8 reserve[3]; 3662306a36Sopenharmony_ci __le32 romaddr; 3762306a36Sopenharmony_ci u8 intline; 3862306a36Sopenharmony_ci u8 intpin; 3962306a36Sopenharmony_ci __le16 bridgectrl; 4062306a36Sopenharmony_ci}; 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci/* PCI configuration space of the PCIe capabilities */ 4362306a36Sopenharmony_cistruct pci_bridge_emul_pcie_conf { 4462306a36Sopenharmony_ci u8 cap_id; 4562306a36Sopenharmony_ci u8 next; 4662306a36Sopenharmony_ci __le16 cap; 4762306a36Sopenharmony_ci __le32 devcap; 4862306a36Sopenharmony_ci __le16 devctl; 4962306a36Sopenharmony_ci __le16 devsta; 5062306a36Sopenharmony_ci __le32 lnkcap; 5162306a36Sopenharmony_ci __le16 lnkctl; 5262306a36Sopenharmony_ci __le16 lnksta; 5362306a36Sopenharmony_ci __le32 slotcap; 5462306a36Sopenharmony_ci __le16 slotctl; 5562306a36Sopenharmony_ci __le16 slotsta; 5662306a36Sopenharmony_ci __le16 rootctl; 5762306a36Sopenharmony_ci __le16 rootcap; 5862306a36Sopenharmony_ci __le32 rootsta; 5962306a36Sopenharmony_ci __le32 devcap2; 6062306a36Sopenharmony_ci __le16 devctl2; 6162306a36Sopenharmony_ci __le16 devsta2; 6262306a36Sopenharmony_ci __le32 lnkcap2; 6362306a36Sopenharmony_ci __le16 lnkctl2; 6462306a36Sopenharmony_ci __le16 lnksta2; 6562306a36Sopenharmony_ci __le32 slotcap2; 6662306a36Sopenharmony_ci __le16 slotctl2; 6762306a36Sopenharmony_ci __le16 slotsta2; 6862306a36Sopenharmony_ci}; 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_cistruct pci_bridge_emul; 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_citypedef enum { PCI_BRIDGE_EMUL_HANDLED, 7362306a36Sopenharmony_ci PCI_BRIDGE_EMUL_NOT_HANDLED } pci_bridge_emul_read_status_t; 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_cistruct pci_bridge_emul_ops { 7662306a36Sopenharmony_ci /* 7762306a36Sopenharmony_ci * Called when reading from the regular PCI bridge 7862306a36Sopenharmony_ci * configuration space. Return PCI_BRIDGE_EMUL_HANDLED when the 7962306a36Sopenharmony_ci * operation has handled the read operation and filled in the 8062306a36Sopenharmony_ci * *value, or PCI_BRIDGE_EMUL_NOT_HANDLED when the read should 8162306a36Sopenharmony_ci * be emulated by the common code by reading from the 8262306a36Sopenharmony_ci * in-memory copy of the configuration space. 8362306a36Sopenharmony_ci */ 8462306a36Sopenharmony_ci pci_bridge_emul_read_status_t (*read_base)(struct pci_bridge_emul *bridge, 8562306a36Sopenharmony_ci int reg, u32 *value); 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci /* 8862306a36Sopenharmony_ci * Same as ->read_base(), except it is for reading from the 8962306a36Sopenharmony_ci * PCIe capability configuration space. 9062306a36Sopenharmony_ci */ 9162306a36Sopenharmony_ci pci_bridge_emul_read_status_t (*read_pcie)(struct pci_bridge_emul *bridge, 9262306a36Sopenharmony_ci int reg, u32 *value); 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci /* 9562306a36Sopenharmony_ci * Same as ->read_base(), except it is for reading from the 9662306a36Sopenharmony_ci * PCIe extended capability configuration space. 9762306a36Sopenharmony_ci */ 9862306a36Sopenharmony_ci pci_bridge_emul_read_status_t (*read_ext)(struct pci_bridge_emul *bridge, 9962306a36Sopenharmony_ci int reg, u32 *value); 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci /* 10262306a36Sopenharmony_ci * Called when writing to the regular PCI bridge configuration 10362306a36Sopenharmony_ci * space. old is the current value, new is the new value being 10462306a36Sopenharmony_ci * written, and mask indicates which parts of the value are 10562306a36Sopenharmony_ci * being changed. 10662306a36Sopenharmony_ci */ 10762306a36Sopenharmony_ci void (*write_base)(struct pci_bridge_emul *bridge, int reg, 10862306a36Sopenharmony_ci u32 old, u32 new, u32 mask); 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci /* 11162306a36Sopenharmony_ci * Same as ->write_base(), except it is for writing from the 11262306a36Sopenharmony_ci * PCIe capability configuration space. 11362306a36Sopenharmony_ci */ 11462306a36Sopenharmony_ci void (*write_pcie)(struct pci_bridge_emul *bridge, int reg, 11562306a36Sopenharmony_ci u32 old, u32 new, u32 mask); 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci /* 11862306a36Sopenharmony_ci * Same as ->write_base(), except it is for writing from the 11962306a36Sopenharmony_ci * PCIe extended capability configuration space. 12062306a36Sopenharmony_ci */ 12162306a36Sopenharmony_ci void (*write_ext)(struct pci_bridge_emul *bridge, int reg, 12262306a36Sopenharmony_ci u32 old, u32 new, u32 mask); 12362306a36Sopenharmony_ci}; 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_cistruct pci_bridge_reg_behavior; 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_cistruct pci_bridge_emul { 12862306a36Sopenharmony_ci struct pci_bridge_emul_conf conf; 12962306a36Sopenharmony_ci struct pci_bridge_emul_pcie_conf pcie_conf; 13062306a36Sopenharmony_ci const struct pci_bridge_emul_ops *ops; 13162306a36Sopenharmony_ci struct pci_bridge_reg_behavior *pci_regs_behavior; 13262306a36Sopenharmony_ci struct pci_bridge_reg_behavior *pcie_cap_regs_behavior; 13362306a36Sopenharmony_ci void *data; 13462306a36Sopenharmony_ci u8 pcie_start; 13562306a36Sopenharmony_ci u8 ssid_start; 13662306a36Sopenharmony_ci bool has_pcie; 13762306a36Sopenharmony_ci u16 subsystem_vendor_id; 13862306a36Sopenharmony_ci u16 subsystem_id; 13962306a36Sopenharmony_ci}; 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_cienum { 14262306a36Sopenharmony_ci /* 14362306a36Sopenharmony_ci * PCI bridge does not support forwarding of prefetchable memory 14462306a36Sopenharmony_ci * requests between primary and secondary buses. 14562306a36Sopenharmony_ci */ 14662306a36Sopenharmony_ci PCI_BRIDGE_EMUL_NO_PREFMEM_FORWARD = BIT(0), 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci /* 14962306a36Sopenharmony_ci * PCI bridge does not support forwarding of IO requests between 15062306a36Sopenharmony_ci * primary and secondary buses. 15162306a36Sopenharmony_ci */ 15262306a36Sopenharmony_ci PCI_BRIDGE_EMUL_NO_IO_FORWARD = BIT(1), 15362306a36Sopenharmony_ci}; 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ciint pci_bridge_emul_init(struct pci_bridge_emul *bridge, 15662306a36Sopenharmony_ci unsigned int flags); 15762306a36Sopenharmony_civoid pci_bridge_emul_cleanup(struct pci_bridge_emul *bridge); 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ciint pci_bridge_emul_conf_read(struct pci_bridge_emul *bridge, int where, 16062306a36Sopenharmony_ci int size, u32 *value); 16162306a36Sopenharmony_ciint pci_bridge_emul_conf_write(struct pci_bridge_emul *bridge, int where, 16262306a36Sopenharmony_ci int size, u32 value); 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci#endif /* __PCI_BRIDGE_EMUL_H__ */ 165