/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef __ARM_PCI_H__ #define __ARM_PCI_H__ #ifdef CONFIG_HAS_PCI #include #define pci_to_dev(pcidev) (&(pcidev)->arch.dev) extern bool pci_passthrough_enabled; /* Arch pci dev struct */ struct arch_pci_dev { struct device dev; }; /* Arch-specific MSI data for vPCI. */ struct vpci_arch_msi { }; /* Arch-specific MSI-X entry data for vPCI. */ struct vpci_arch_msix_entry { }; /* * Because of the header cross-dependencies, e.g. we need both * struct pci_dev and struct arch_pci_dev at the same time, this cannot be * done with an inline here. Macro can be implemented, but looks scary. */ struct pci_dev *dev_to_pci(struct device *dev); /* * struct to hold the mappings of a config space window. This * is expected to be used as sysdata for PCI controllers that * use ECAM. */ struct pci_config_window { paddr_t phys_addr; paddr_t size; uint8_t busn_start; uint8_t busn_end; void __iomem *win; }; /* * struct to hold pci host bridge information * for a PCI controller. */ struct pci_host_bridge { struct dt_device_node *dt_node; /* Pointer to the associated DT node */ struct list_head node; /* Node in list of host bridges */ uint16_t segment; /* Segment number */ struct pci_config_window* cfg; /* Pointer to the bridge config window */ const struct pci_ops *ops; }; struct pci_ops { void __iomem *(*map_bus)(struct pci_host_bridge *bridge, pci_sbdf_t sbdf, uint32_t offset); int (*read)(struct pci_host_bridge *bridge, pci_sbdf_t sbdf, uint32_t reg, uint32_t len, uint32_t *value); int (*write)(struct pci_host_bridge *bridge, pci_sbdf_t sbdf, uint32_t reg, uint32_t len, uint32_t value); bool (*need_p2m_hwdom_mapping)(struct domain *d, struct pci_host_bridge *bridge, uint64_t addr); }; /* * struct to hold pci ops and bus shift of the config window * for a PCI controller. */ struct pci_ecam_ops { unsigned int bus_shift; struct pci_ops pci_ops; int (*cfg_reg_index)(struct dt_device_node *dev); int (*init)(struct pci_config_window *); }; /* Default ECAM ops */ extern const struct pci_ecam_ops pci_generic_ecam_ops; int pci_host_common_probe(struct dt_device_node *dev, const struct pci_ecam_ops *ops); int pci_generic_config_read(struct pci_host_bridge *bridge, pci_sbdf_t sbdf, uint32_t reg, uint32_t len, uint32_t *value); int pci_generic_config_write(struct pci_host_bridge *bridge, pci_sbdf_t sbdf, uint32_t reg, uint32_t len, uint32_t value); void __iomem *pci_ecam_map_bus(struct pci_host_bridge *bridge, pci_sbdf_t sbdf, uint32_t where); bool pci_ecam_need_p2m_hwdom_mapping(struct domain *d, struct pci_host_bridge *bridge, uint64_t addr); struct pci_host_bridge *pci_find_host_bridge(uint16_t segment, uint8_t bus); const struct dt_device_node * pci_find_host_bridge_node(const struct pci_dev *pdev); int pci_get_host_bridge_segment(const struct dt_device_node *node, uint16_t *segment); static always_inline bool is_pci_passthrough_enabled(void) { return pci_passthrough_enabled; } void arch_pci_init_pdev(struct pci_dev *pdev); int pci_get_new_domain_nr(void); int pci_host_iterate_bridges_and_count(struct domain *d, int (*cb)(struct domain *d, struct pci_host_bridge *bridge)); int pci_host_bridge_mappings(struct domain *d); bool pci_check_bar(const struct pci_dev *pdev, mfn_t start, mfn_t end); #else /*!CONFIG_HAS_PCI*/ struct arch_pci_dev { }; static always_inline bool is_pci_passthrough_enabled(void) { return false; } struct pci_dev; static inline void arch_pci_init_pdev(struct pci_dev *pdev) {} static inline int pci_get_host_bridge_segment(const struct dt_device_node *node, uint16_t *segment) { ASSERT_UNREACHABLE(); return -EINVAL; } static inline int pci_get_new_domain_nr(void) { ASSERT_UNREACHABLE(); return -1; } #endif /*!CONFIG_HAS_PCI*/ #endif /* __ARM_PCI_H__ */