/* * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ /* * @file device.h * @brief Bus abstraction for libmetal. */ #ifndef __METAL_BUS__H__ #define __METAL_BUS__H__ #include #include #include #include #include #ifdef __cplusplus extern "C" { #endif /** \defgroup device Bus Abstraction * @{ */ #ifndef METAL_MAX_DEVICE_REGIONS #define METAL_MAX_DEVICE_REGIONS 32 #endif struct metal_bus; struct metal_device; /** Bus operations. */ struct metal_bus_ops { void (*bus_close)(struct metal_bus *bus); int (*dev_open)(struct metal_bus *bus, const char *dev_name, struct metal_device **device); void (*dev_close)(struct metal_bus *bus, struct metal_device *device); void (*dev_irq_ack)(struct metal_bus *bus, struct metal_device *device, int irq); int (*dev_dma_map)(struct metal_bus *bus, struct metal_device *device, uint32_t dir, struct metal_sg *sg_in, int nents_in, struct metal_sg *sg_out); void (*dev_dma_unmap)(struct metal_bus *bus, struct metal_device *device, uint32_t dir, struct metal_sg *sg, int nents); }; /** Libmetal bus structure. */ struct metal_bus { const char *name; struct metal_bus_ops ops; struct metal_list devices; struct metal_list node; }; /** Libmetal generic bus. */ extern struct metal_bus metal_generic_bus; /** Libmetal device structure. */ struct metal_device { const char *name; /**< Device name */ struct metal_bus *bus; /**< Bus that contains device */ unsigned int num_regions; /**< Number of I/O regions in device */ struct metal_io_region regions[METAL_MAX_DEVICE_REGIONS]; /**< Array of I/O regions in device*/ struct metal_list node; /**< Node on bus' list of devices */ int irq_num; /**< Number of IRQs per device */ void *irq_info; /**< IRQ ID */ }; /** * @brief Register a libmetal bus. * @param[in] bus Pre-initialized bus structure. * @return 0 on success, or -errno on failure. */ extern int metal_bus_register(struct metal_bus *bus); /** * @brief Unregister a libmetal bus. * @param[in] bus Pre-registered bus structure. * @return 0 on success, or -errno on failure. */ extern int metal_bus_unregister(struct metal_bus *bus); /** * @brief Find a libmetal bus by name. * @param[in] name Bus name. * @param[out] bus Returned bus handle. * @return 0 on success, or -errno on failure. */ extern int metal_bus_find(const char *name, struct metal_bus **bus); /** * @brief Statically register a generic libmetal device. * * In non-Linux systems, devices are always required to be statically * registered at application initialization. * In Linux system, devices can be dynamically opened via sysfs or libfdt based * enumeration at runtime. * This interface is used for static registration of devices. Subsequent calls * to metal_device_open() look up in this list of pre-registered devices on the * "generic" bus. * "generic" bus is used on non-Linux system to group the memory mapped devices. * * @param[in] device Generic device. * @return 0 on success, or -errno on failure. */ extern int metal_register_generic_device(struct metal_device *device); /** * @brief Open a libmetal device by name. * @param[in] bus_name Bus name. * @param[in] dev_name Device name. * @param[out] device Returned device handle. * @return 0 on success, or -errno on failure. */ extern int metal_device_open(const char *bus_name, const char *dev_name, struct metal_device **device); /** * @brief Close a libmetal device. * @param[in] device Device handle. */ extern void metal_device_close(struct metal_device *device); /** * @brief Get an I/O region accessor for a device region. * * @param[in] device Device handle. * @param[in] index Region index. * @return I/O accessor handle, or NULL on failure. */ static inline struct metal_io_region * metal_device_io_region(struct metal_device *device, unsigned int index) { return (index < device->num_regions ? &device->regions[index] : NULL); } /** @} */ #ifdef METAL_INTERNAL extern int metal_generic_dev_sys_open(struct metal_device *dev); extern int metal_generic_dev_open(struct metal_bus *bus, const char *dev_name, struct metal_device **device); extern int metal_generic_dev_dma_map(struct metal_bus *bus, struct metal_device *device, uint32_t dir, struct metal_sg *sg_in, int nents_in, struct metal_sg *sg_out); extern void metal_generic_dev_dma_unmap(struct metal_bus *bus, struct metal_device *device, uint32_t dir, struct metal_sg *sg, int nents); #endif /* METAL_INTERNAL */ #ifdef __cplusplus } #endif #endif /* __METAL_BUS__H__ */