zephyr/include/drivers/pcie/endpoint/pcie_ep.h
Abhishek Shah 3c2fa8cd51 pcie: endpoint: Introduce API to achieve PCIe data transfer
Introduce common API to achieve data transfer using memcpy
to/from outbound region of PCIe EP.

Signed-off-by: Abhishek Shah <abhishek.shah@broadcom.com>
2020-06-13 01:35:19 -07:00

179 lines
5.4 KiB
C

/**
* @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 <device.h>
#include <init.h>
#include <kernel.h>
#include <stdint.h>
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 */
};
enum xfer_direction {
HOST_TO_DEVICE, /**< Read from Host */
DEVICE_TO_HOST, /**< Write to Host */
};
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);
}
/**
* @brief Data transfer using memcpy
*
* @details Helper API to achieve data transfer with memcpy
* through PCIe outbound memory
*/
int pcie_ep_xfer_data_memcpy(struct device *dev, uint64_t pcie_addr,
uintptr_t *local_addr, uint32_t size,
enum pcie_ob_mem_type ob_mem_type,
enum xfer_direction dir);
#endif /* ZEPHYR_INCLUDE_DRIVERS_PCIE_EP_H_ */