18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */ 28c2ecf20Sopenharmony_ci#ifndef _ASM_POWERPC_PCI_BRIDGE_H 38c2ecf20Sopenharmony_ci#define _ASM_POWERPC_PCI_BRIDGE_H 48c2ecf20Sopenharmony_ci#ifdef __KERNEL__ 58c2ecf20Sopenharmony_ci/* 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci#include <linux/pci.h> 88c2ecf20Sopenharmony_ci#include <linux/list.h> 98c2ecf20Sopenharmony_ci#include <linux/ioport.h> 108c2ecf20Sopenharmony_ci#include <linux/numa.h> 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_cistruct device_node; 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci/* 158c2ecf20Sopenharmony_ci * PCI controller operations 168c2ecf20Sopenharmony_ci */ 178c2ecf20Sopenharmony_cistruct pci_controller_ops { 188c2ecf20Sopenharmony_ci void (*dma_dev_setup)(struct pci_dev *pdev); 198c2ecf20Sopenharmony_ci void (*dma_bus_setup)(struct pci_bus *bus); 208c2ecf20Sopenharmony_ci bool (*iommu_bypass_supported)(struct pci_dev *pdev, 218c2ecf20Sopenharmony_ci u64 mask); 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci int (*probe_mode)(struct pci_bus *bus); 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci /* Called when pci_enable_device() is called. Returns true to 268c2ecf20Sopenharmony_ci * allow assignment/enabling of the device. */ 278c2ecf20Sopenharmony_ci bool (*enable_device_hook)(struct pci_dev *pdev); 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci void (*disable_device)(struct pci_dev *pdev); 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci void (*release_device)(struct pci_dev *pdev); 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci /* Called during PCI resource reassignment */ 348c2ecf20Sopenharmony_ci resource_size_t (*window_alignment)(struct pci_bus *bus, 358c2ecf20Sopenharmony_ci unsigned long type); 368c2ecf20Sopenharmony_ci void (*setup_bridge)(struct pci_bus *bus, 378c2ecf20Sopenharmony_ci unsigned long type); 388c2ecf20Sopenharmony_ci void (*reset_secondary_bus)(struct pci_dev *pdev); 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci#ifdef CONFIG_PCI_MSI 418c2ecf20Sopenharmony_ci int (*setup_msi_irqs)(struct pci_dev *pdev, 428c2ecf20Sopenharmony_ci int nvec, int type); 438c2ecf20Sopenharmony_ci void (*teardown_msi_irqs)(struct pci_dev *pdev); 448c2ecf20Sopenharmony_ci#endif 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci void (*shutdown)(struct pci_controller *hose); 478c2ecf20Sopenharmony_ci}; 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci/* 508c2ecf20Sopenharmony_ci * Structure of a PCI controller (host bridge) 518c2ecf20Sopenharmony_ci */ 528c2ecf20Sopenharmony_cistruct pci_controller { 538c2ecf20Sopenharmony_ci struct pci_bus *bus; 548c2ecf20Sopenharmony_ci char is_dynamic; 558c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC64 568c2ecf20Sopenharmony_ci int node; 578c2ecf20Sopenharmony_ci#endif 588c2ecf20Sopenharmony_ci struct device_node *dn; 598c2ecf20Sopenharmony_ci struct list_head list_node; 608c2ecf20Sopenharmony_ci struct device *parent; 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci int first_busno; 638c2ecf20Sopenharmony_ci int last_busno; 648c2ecf20Sopenharmony_ci int self_busno; 658c2ecf20Sopenharmony_ci struct resource busn; 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci void __iomem *io_base_virt; 688c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC64 698c2ecf20Sopenharmony_ci void __iomem *io_base_alloc; 708c2ecf20Sopenharmony_ci#endif 718c2ecf20Sopenharmony_ci resource_size_t io_base_phys; 728c2ecf20Sopenharmony_ci resource_size_t pci_io_size; 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci /* Some machines have a special region to forward the ISA 758c2ecf20Sopenharmony_ci * "memory" cycles such as VGA memory regions. Left to 0 768c2ecf20Sopenharmony_ci * if unsupported 778c2ecf20Sopenharmony_ci */ 788c2ecf20Sopenharmony_ci resource_size_t isa_mem_phys; 798c2ecf20Sopenharmony_ci resource_size_t isa_mem_size; 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci struct pci_controller_ops controller_ops; 828c2ecf20Sopenharmony_ci struct pci_ops *ops; 838c2ecf20Sopenharmony_ci unsigned int __iomem *cfg_addr; 848c2ecf20Sopenharmony_ci void __iomem *cfg_data; 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci /* 878c2ecf20Sopenharmony_ci * Used for variants of PCI indirect handling and possible quirks: 888c2ecf20Sopenharmony_ci * SET_CFG_TYPE - used on 4xx or any PHB that does explicit type0/1 898c2ecf20Sopenharmony_ci * EXT_REG - provides access to PCI-e extended registers 908c2ecf20Sopenharmony_ci * SURPRESS_PRIMARY_BUS - we suppress the setting of PCI_PRIMARY_BUS 918c2ecf20Sopenharmony_ci * on Freescale PCI-e controllers since they used the PCI_PRIMARY_BUS 928c2ecf20Sopenharmony_ci * to determine which bus number to match on when generating type0 938c2ecf20Sopenharmony_ci * config cycles 948c2ecf20Sopenharmony_ci * NO_PCIE_LINK - the Freescale PCI-e controllers have issues with 958c2ecf20Sopenharmony_ci * hanging if we don't have link and try to do config cycles to 968c2ecf20Sopenharmony_ci * anything but the PHB. Only allow talking to the PHB if this is 978c2ecf20Sopenharmony_ci * set. 988c2ecf20Sopenharmony_ci * BIG_ENDIAN - cfg_addr is a big endian register 998c2ecf20Sopenharmony_ci * BROKEN_MRM - the 440EPx/GRx chips have an errata that causes hangs on 1008c2ecf20Sopenharmony_ci * the PLB4. Effectively disable MRM commands by setting this. 1018c2ecf20Sopenharmony_ci * FSL_CFG_REG_LINK - Freescale controller version in which the PCIe 1028c2ecf20Sopenharmony_ci * link status is in a RC PCIe cfg register (vs being a SoC register) 1038c2ecf20Sopenharmony_ci */ 1048c2ecf20Sopenharmony_ci#define PPC_INDIRECT_TYPE_SET_CFG_TYPE 0x00000001 1058c2ecf20Sopenharmony_ci#define PPC_INDIRECT_TYPE_EXT_REG 0x00000002 1068c2ecf20Sopenharmony_ci#define PPC_INDIRECT_TYPE_SURPRESS_PRIMARY_BUS 0x00000004 1078c2ecf20Sopenharmony_ci#define PPC_INDIRECT_TYPE_NO_PCIE_LINK 0x00000008 1088c2ecf20Sopenharmony_ci#define PPC_INDIRECT_TYPE_BIG_ENDIAN 0x00000010 1098c2ecf20Sopenharmony_ci#define PPC_INDIRECT_TYPE_BROKEN_MRM 0x00000020 1108c2ecf20Sopenharmony_ci#define PPC_INDIRECT_TYPE_FSL_CFG_REG_LINK 0x00000040 1118c2ecf20Sopenharmony_ci u32 indirect_type; 1128c2ecf20Sopenharmony_ci /* Currently, we limit ourselves to 1 IO range and 3 mem 1138c2ecf20Sopenharmony_ci * ranges since the common pci_bus structure can't handle more 1148c2ecf20Sopenharmony_ci */ 1158c2ecf20Sopenharmony_ci struct resource io_resource; 1168c2ecf20Sopenharmony_ci struct resource mem_resources[3]; 1178c2ecf20Sopenharmony_ci resource_size_t mem_offset[3]; 1188c2ecf20Sopenharmony_ci int global_number; /* PCI domain number */ 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci resource_size_t dma_window_base_cur; 1218c2ecf20Sopenharmony_ci resource_size_t dma_window_size; 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC64 1248c2ecf20Sopenharmony_ci unsigned long buid; 1258c2ecf20Sopenharmony_ci struct pci_dn *pci_data; 1268c2ecf20Sopenharmony_ci#endif /* CONFIG_PPC64 */ 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci void *private_data; 1298c2ecf20Sopenharmony_ci struct npu *npu; 1308c2ecf20Sopenharmony_ci}; 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci/* These are used for config access before all the PCI probing 1338c2ecf20Sopenharmony_ci has been done. */ 1348c2ecf20Sopenharmony_ciextern int early_read_config_byte(struct pci_controller *hose, int bus, 1358c2ecf20Sopenharmony_ci int dev_fn, int where, u8 *val); 1368c2ecf20Sopenharmony_ciextern int early_read_config_word(struct pci_controller *hose, int bus, 1378c2ecf20Sopenharmony_ci int dev_fn, int where, u16 *val); 1388c2ecf20Sopenharmony_ciextern int early_read_config_dword(struct pci_controller *hose, int bus, 1398c2ecf20Sopenharmony_ci int dev_fn, int where, u32 *val); 1408c2ecf20Sopenharmony_ciextern int early_write_config_byte(struct pci_controller *hose, int bus, 1418c2ecf20Sopenharmony_ci int dev_fn, int where, u8 val); 1428c2ecf20Sopenharmony_ciextern int early_write_config_word(struct pci_controller *hose, int bus, 1438c2ecf20Sopenharmony_ci int dev_fn, int where, u16 val); 1448c2ecf20Sopenharmony_ciextern int early_write_config_dword(struct pci_controller *hose, int bus, 1458c2ecf20Sopenharmony_ci int dev_fn, int where, u32 val); 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ciextern int early_find_capability(struct pci_controller *hose, int bus, 1488c2ecf20Sopenharmony_ci int dev_fn, int cap); 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ciextern void setup_indirect_pci(struct pci_controller* hose, 1518c2ecf20Sopenharmony_ci resource_size_t cfg_addr, 1528c2ecf20Sopenharmony_ci resource_size_t cfg_data, u32 flags); 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ciextern int indirect_read_config(struct pci_bus *bus, unsigned int devfn, 1558c2ecf20Sopenharmony_ci int offset, int len, u32 *val); 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ciextern int __indirect_read_config(struct pci_controller *hose, 1588c2ecf20Sopenharmony_ci unsigned char bus_number, unsigned int devfn, 1598c2ecf20Sopenharmony_ci int offset, int len, u32 *val); 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ciextern int indirect_write_config(struct pci_bus *bus, unsigned int devfn, 1628c2ecf20Sopenharmony_ci int offset, int len, u32 val); 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_cistatic inline struct pci_controller *pci_bus_to_host(const struct pci_bus *bus) 1658c2ecf20Sopenharmony_ci{ 1668c2ecf20Sopenharmony_ci return bus->sysdata; 1678c2ecf20Sopenharmony_ci} 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci#ifndef CONFIG_PPC64 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ciextern int pci_device_from_OF_node(struct device_node *node, 1728c2ecf20Sopenharmony_ci u8 *bus, u8 *devfn); 1738c2ecf20Sopenharmony_ciextern void pci_create_OF_bus_map(void); 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci#else /* CONFIG_PPC64 */ 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ci/* 1788c2ecf20Sopenharmony_ci * PCI stuff, for nodes representing PCI devices, pointed to 1798c2ecf20Sopenharmony_ci * by device_node->data. 1808c2ecf20Sopenharmony_ci */ 1818c2ecf20Sopenharmony_cistruct iommu_table; 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_cistruct pci_dn { 1848c2ecf20Sopenharmony_ci int flags; 1858c2ecf20Sopenharmony_ci#define PCI_DN_FLAG_IOV_VF 0x01 1868c2ecf20Sopenharmony_ci#define PCI_DN_FLAG_DEAD 0x02 /* Device has been hot-removed */ 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci int busno; /* pci bus number */ 1898c2ecf20Sopenharmony_ci int devfn; /* pci device and function number */ 1908c2ecf20Sopenharmony_ci int vendor_id; /* Vendor ID */ 1918c2ecf20Sopenharmony_ci int device_id; /* Device ID */ 1928c2ecf20Sopenharmony_ci int class_code; /* Device class code */ 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci struct pci_dn *parent; 1958c2ecf20Sopenharmony_ci struct pci_controller *phb; /* for pci devices */ 1968c2ecf20Sopenharmony_ci struct iommu_table_group *table_group; /* for phb's or bridges */ 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci int pci_ext_config_space; /* for pci devices */ 1998c2ecf20Sopenharmony_ci#ifdef CONFIG_EEH 2008c2ecf20Sopenharmony_ci struct eeh_dev *edev; /* eeh device */ 2018c2ecf20Sopenharmony_ci#endif 2028c2ecf20Sopenharmony_ci#define IODA_INVALID_PE 0xFFFFFFFF 2038c2ecf20Sopenharmony_ci unsigned int pe_number; 2048c2ecf20Sopenharmony_ci#ifdef CONFIG_PCI_IOV 2058c2ecf20Sopenharmony_ci u16 vfs_expanded; /* number of VFs IOV BAR expanded */ 2068c2ecf20Sopenharmony_ci u16 num_vfs; /* number of VFs enabled*/ 2078c2ecf20Sopenharmony_ci unsigned int *pe_num_map; /* PE# for the first VF PE or array */ 2088c2ecf20Sopenharmony_ci bool m64_single_mode; /* Use M64 BAR in Single Mode */ 2098c2ecf20Sopenharmony_ci#define IODA_INVALID_M64 (-1) 2108c2ecf20Sopenharmony_ci int (*m64_map)[PCI_SRIOV_NUM_BARS]; /* Only used on powernv */ 2118c2ecf20Sopenharmony_ci int last_allow_rc; /* Only used on pseries */ 2128c2ecf20Sopenharmony_ci#endif /* CONFIG_PCI_IOV */ 2138c2ecf20Sopenharmony_ci int mps; /* Maximum Payload Size */ 2148c2ecf20Sopenharmony_ci struct list_head child_list; 2158c2ecf20Sopenharmony_ci struct list_head list; 2168c2ecf20Sopenharmony_ci struct resource holes[PCI_SRIOV_NUM_BARS]; 2178c2ecf20Sopenharmony_ci}; 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci/* Get the pointer to a device_node's pci_dn */ 2208c2ecf20Sopenharmony_ci#define PCI_DN(dn) ((struct pci_dn *) (dn)->data) 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ciextern struct pci_dn *pci_get_pdn_by_devfn(struct pci_bus *bus, 2238c2ecf20Sopenharmony_ci int devfn); 2248c2ecf20Sopenharmony_ciextern struct pci_dn *pci_get_pdn(struct pci_dev *pdev); 2258c2ecf20Sopenharmony_ciextern struct pci_dn *pci_add_device_node_info(struct pci_controller *hose, 2268c2ecf20Sopenharmony_ci struct device_node *dn); 2278c2ecf20Sopenharmony_ciextern void pci_remove_device_node_info(struct device_node *dn); 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci#ifdef CONFIG_PCI_IOV 2308c2ecf20Sopenharmony_cistruct pci_dn *add_sriov_vf_pdns(struct pci_dev *pdev); 2318c2ecf20Sopenharmony_civoid remove_sriov_vf_pdns(struct pci_dev *pdev); 2328c2ecf20Sopenharmony_ci#endif 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_cistatic inline int pci_device_from_OF_node(struct device_node *np, 2358c2ecf20Sopenharmony_ci u8 *bus, u8 *devfn) 2368c2ecf20Sopenharmony_ci{ 2378c2ecf20Sopenharmony_ci if (!PCI_DN(np)) 2388c2ecf20Sopenharmony_ci return -ENODEV; 2398c2ecf20Sopenharmony_ci *bus = PCI_DN(np)->busno; 2408c2ecf20Sopenharmony_ci *devfn = PCI_DN(np)->devfn; 2418c2ecf20Sopenharmony_ci return 0; 2428c2ecf20Sopenharmony_ci} 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci#if defined(CONFIG_EEH) 2458c2ecf20Sopenharmony_cistatic inline struct eeh_dev *pdn_to_eeh_dev(struct pci_dn *pdn) 2468c2ecf20Sopenharmony_ci{ 2478c2ecf20Sopenharmony_ci return pdn ? pdn->edev : NULL; 2488c2ecf20Sopenharmony_ci} 2498c2ecf20Sopenharmony_ci#else 2508c2ecf20Sopenharmony_ci#define pdn_to_eeh_dev(x) (NULL) 2518c2ecf20Sopenharmony_ci#endif 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci/** Find the bus corresponding to the indicated device node */ 2548c2ecf20Sopenharmony_ciextern struct pci_bus *pci_find_bus_by_node(struct device_node *dn); 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci/** Remove all of the PCI devices under this bus */ 2578c2ecf20Sopenharmony_ciextern void pci_hp_remove_devices(struct pci_bus *bus); 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ci/** Discover new pci devices under this bus, and add them */ 2608c2ecf20Sopenharmony_ciextern void pci_hp_add_devices(struct pci_bus *bus); 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_ciextern int pcibios_unmap_io_space(struct pci_bus *bus); 2638c2ecf20Sopenharmony_ciextern int pcibios_map_io_space(struct pci_bus *bus); 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ci#ifdef CONFIG_NUMA 2668c2ecf20Sopenharmony_ci#define PHB_SET_NODE(PHB, NODE) ((PHB)->node = (NODE)) 2678c2ecf20Sopenharmony_ci#else 2688c2ecf20Sopenharmony_ci#define PHB_SET_NODE(PHB, NODE) ((PHB)->node = NUMA_NO_NODE) 2698c2ecf20Sopenharmony_ci#endif 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci#endif /* CONFIG_PPC64 */ 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci/* Get the PCI host controller for an OF device */ 2748c2ecf20Sopenharmony_ciextern struct pci_controller *pci_find_hose_for_OF_device( 2758c2ecf20Sopenharmony_ci struct device_node* node); 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ciextern struct pci_controller *pci_find_controller_for_domain(int domain_nr); 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci/* Fill up host controller resources from the OF node */ 2808c2ecf20Sopenharmony_ciextern void pci_process_bridge_OF_ranges(struct pci_controller *hose, 2818c2ecf20Sopenharmony_ci struct device_node *dev, int primary); 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci/* Allocate & free a PCI host bridge structure */ 2848c2ecf20Sopenharmony_ciextern struct pci_controller *pcibios_alloc_controller(struct device_node *dev); 2858c2ecf20Sopenharmony_ciextern void pcibios_free_controller(struct pci_controller *phb); 2868c2ecf20Sopenharmony_ciextern void pcibios_free_controller_deferred(struct pci_host_bridge *bridge); 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_ci#ifdef CONFIG_PCI 2898c2ecf20Sopenharmony_ciextern int pcibios_vaddr_is_ioport(void __iomem *address); 2908c2ecf20Sopenharmony_ci#else 2918c2ecf20Sopenharmony_cistatic inline int pcibios_vaddr_is_ioport(void __iomem *address) 2928c2ecf20Sopenharmony_ci{ 2938c2ecf20Sopenharmony_ci return 0; 2948c2ecf20Sopenharmony_ci} 2958c2ecf20Sopenharmony_ci#endif /* CONFIG_PCI */ 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci#endif /* __KERNEL__ */ 2988c2ecf20Sopenharmony_ci#endif /* _ASM_POWERPC_PCI_BRIDGE_H */ 299