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