From ca17315d7f6d673eb7c348a024e3f15612bcd9da Mon Sep 17 00:00:00 2001 From: Abhishek Shah Date: Mon, 4 May 2020 12:37:34 +0530 Subject: [PATCH] pcie: endpoint: Add public APIs for PCIe endpoint driver Add public APIs for PCIe endpoint driver: - EP configuration space read/write - Mapping/Unmapping of Host buffer and PCIe outbound region - Raise interrupt to Host These are minimal base APIs to make PCIe EP functional. Also, add a Kconfig and an empty CMakeLists.txt for drivers to extend. Signed-off-by: Abhishek Shah --- drivers/pcie/CMakeLists.txt | 2 + drivers/pcie/Kconfig | 2 + drivers/pcie/endpoint/CMakeLists.txt | 1 + drivers/pcie/endpoint/Kconfig | 9 ++ include/drivers/pcie/endpoint/pcie_ep.h | 163 ++++++++++++++++++++++++ 5 files changed, 177 insertions(+) create mode 100644 drivers/pcie/endpoint/CMakeLists.txt create mode 100644 drivers/pcie/endpoint/Kconfig create mode 100644 include/drivers/pcie/endpoint/pcie_ep.h diff --git a/drivers/pcie/CMakeLists.txt b/drivers/pcie/CMakeLists.txt index c6443fcb6ab..9ede6778767 100644 --- a/drivers/pcie/CMakeLists.txt +++ b/drivers/pcie/CMakeLists.txt @@ -1,3 +1,5 @@ zephyr_sources(pcie.c) zephyr_sources_ifdef(CONFIG_PCIE_MSI msi.c) zephyr_sources_ifdef(CONFIG_PCIE_SHELL shell.c) + +add_subdirectory_ifdef(CONFIG_PCIE_ENDPOINT endpoint) diff --git a/drivers/pcie/Kconfig b/drivers/pcie/Kconfig index 4cbc1e45830..2c531fa5dbc 100644 --- a/drivers/pcie/Kconfig +++ b/drivers/pcie/Kconfig @@ -24,4 +24,6 @@ config PCIE_SHELL help Enable commands for debugging PCI(e) using the built-in shell. +source "drivers/pcie/endpoint/Kconfig" + endif # PCIE diff --git a/drivers/pcie/endpoint/CMakeLists.txt b/drivers/pcie/endpoint/CMakeLists.txt new file mode 100644 index 00000000000..9881313609a --- /dev/null +++ b/drivers/pcie/endpoint/CMakeLists.txt @@ -0,0 +1 @@ +# SPDX-License-Identifier: Apache-2.0 diff --git a/drivers/pcie/endpoint/Kconfig b/drivers/pcie/endpoint/Kconfig new file mode 100644 index 00000000000..617b4392f57 --- /dev/null +++ b/drivers/pcie/endpoint/Kconfig @@ -0,0 +1,9 @@ +# PCIe Endpoint configuration options + +# Copyright 2020 Broadcom +# SPDX-License-Identifier: Apache-2.0 + +menuconfig PCIE_ENDPOINT + bool "Enable PCIe Endpoint support" + help + This option enables PCIe Endpoint support. diff --git a/include/drivers/pcie/endpoint/pcie_ep.h b/include/drivers/pcie/endpoint/pcie_ep.h new file mode 100644 index 00000000000..3baf1d9c1b2 --- /dev/null +++ b/include/drivers/pcie/endpoint/pcie_ep.h @@ -0,0 +1,163 @@ +/** + * @file + * + * @brief Public APIs for the PCIe EP drivers. + */ + +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2020 Broadcom + * + */ +#ifndef ZEPHYR_INCLUDE_DRIVERS_PCIE_EP_H_ +#define ZEPHYR_INCLUDE_DRIVERS_PCIE_EP_H_ + +#include +#include +#include +#include + +enum pcie_ob_mem_type { + PCIE_OB_ANYMEM, /**< PCIe OB window within any address range */ + PCIE_OB_LOWMEM, /**< PCIe OB window within 32-bit address range */ + PCIE_OB_HIGHMEM, /**< PCIe OB window above 32-bit address range */ +}; + +enum pci_ep_irq_type { + PCIE_EP_IRQ_LEGACY, /**< Raise Legacy interrupt */ + PCIE_EP_IRQ_MSI, /**< Raise MSI interrupt */ + PCIE_EP_IRQ_MSIX, /**< Raise MSIX interrupt */ +}; + +struct pcie_ep_driver_api { + int (*conf_read)(struct device *dev, uint32_t offset, uint32_t *data); + void (*conf_write)(struct device *dev, uint32_t offset, uint32_t data); + int (*map_addr)(struct device *dev, uint64_t pcie_addr, + uint64_t *mapped_addr, uint32_t size, + enum pcie_ob_mem_type ob_mem_type); + void (*unmap_addr)(struct device *dev, uint64_t mapped_addr); + int (*raise_irq)(struct device *dev, enum pci_ep_irq_type irq_type, + uint32_t irq_num); +}; + +/** + * @brief Read PCIe EP configuration space + * + * @details This API reads EP's own configuration space + * + * @param dev Pointer to the device structure for the driver instance + * @param offset Offset within configuration space + * @param data Pointer to data read from the offset + * + * @return 0 if successful, negative errno code if failure. + */ + +static inline int pcie_ep_conf_read(struct device *dev, + uint32_t offset, uint32_t *data) +{ + const struct pcie_ep_driver_api *api = + (const struct pcie_ep_driver_api *)dev->driver_api; + + return api->conf_read(dev, offset, data); +} + +/** + * @brief Write PCIe EP configuration space + * + * @details This API writes EP's own configuration space + * + * @param dev Pointer to the device structure for the driver instance + * @param offset Offset within configuration space + * @param data Data to be written at the offset + * + * @return N/A + */ + +static inline void pcie_ep_conf_write(struct device *dev, + uint32_t offset, uint32_t data) +{ + const struct pcie_ep_driver_api *api = + (const struct pcie_ep_driver_api *)dev->driver_api; + + api->conf_write(dev, offset, data); +} + +/** + * @brief Map a host memory buffer to PCIe outbound region + * + * @details This API maps a host memory buffer to PCIe outbound region, + * It is left to EP driver to manage multiple mappings through + * multiple PCIe outbound regions if supported by SoC + * + * @param dev Pointer to the device structure for the driver instance + * @param pcie_addr Host memory buffer address to be mapped + * @param mapped_addr Mapped PCIe outbound region address + * @param size Host memory buffer size (bytes) + * @param ob_mem_type Hint if lowmem/highmem outbound region has to be used, + * this is useful in cases where bus master cannot generate + * more than 32-bit address; it becomes essential to use + * lowmem outbound region + * + * @return Mapped size : If mapped size is less than requested size, + * then requestor has to call the same API again to map + * the unmapped host buffer after data transfer is done with + * mapped size. This situation may arise because of the + * mapping alignment requirements. + * + * @return Negative errno code if failure. + */ + +static inline int pcie_ep_map_addr(struct device *dev, uint64_t pcie_addr, + uint64_t *mapped_addr, uint32_t size, + enum pcie_ob_mem_type ob_mem_type) +{ + const struct pcie_ep_driver_api *api = + (const struct pcie_ep_driver_api *)dev->driver_api; + + return api->map_addr(dev, pcie_addr, mapped_addr, size, ob_mem_type); +} + +/** + * @brief Remove mapping to PCIe outbound region + * + * @details This API removes mapping to PCIe outbound region. + * Mapped PCIe outbound region address is given as argument + * to figure out the outbound region to be unmapped + * + * @param dev Pointer to the device structure for the driver instance + * @param mapped_addr PCIe outbound region address + * + * @return N/A + */ + +static inline void pcie_ep_unmap_addr(struct device *dev, uint64_t mapped_addr) +{ + const struct pcie_ep_driver_api *api = + (const struct pcie_ep_driver_api *)dev->driver_api; + + api->unmap_addr(dev, mapped_addr); +} + +/** + * @brief Raise interrupt to Host + * + * @details This API raises interrupt to Host + * + * @param dev Pointer to the device structure for the driver instance + * @param irq_type Type of Interrupt be raised (legacy, MSI or MSI-X) + * @param irq_num MSI or MSI-X interrupt number + * + * @return 0 if successful, negative errno code if failure. + */ + +static inline int pcie_ep_raise_irq(struct device *dev, + enum pci_ep_irq_type irq_type, + uint32_t irq_num) +{ + const struct pcie_ep_driver_api *api = + (const struct pcie_ep_driver_api *)dev->driver_api; + return api->raise_irq(dev, irq_type, irq_num); +} + +#endif /* ZEPHYR_INCLUDE_DRIVERS_PCIE_EP_H_ */