// SPDX-License-Identifier: GPL-2.0 /* * FPGA Manager Core * * Copyright (C) 2013-2015 Altera Corporation * Copyright (C) 2017 Intel Corporation * * With code from the mailing list: * Copyright (C) 2013 Xilinx, Inc. */ #include <linux/firmware.h> #include <linux/fpga/fpga-mgr.h> #include <linux/idr.h> #include <linux/module.h> #include <linux/of.h> #include <linux/mutex.h> #include <linux/slab.h> #include <linux/scatterlist.h> #include <linux/highmem.h> static DEFINE_IDA(fpga_mgr_ida); static const struct class fpga_mgr_class; struct fpga_mgr_devres { … }; static inline void fpga_mgr_fpga_remove(struct fpga_manager *mgr) { … } static inline enum fpga_mgr_states fpga_mgr_state(struct fpga_manager *mgr) { … } static inline u64 fpga_mgr_status(struct fpga_manager *mgr) { … } static inline int fpga_mgr_write(struct fpga_manager *mgr, const char *buf, size_t count) { … } /* * After all the FPGA image has been written, do the device specific steps to * finish and set the FPGA into operating mode. */ static inline int fpga_mgr_write_complete(struct fpga_manager *mgr, struct fpga_image_info *info) { … } static inline int fpga_mgr_parse_header(struct fpga_manager *mgr, struct fpga_image_info *info, const char *buf, size_t count) { … } static inline int fpga_mgr_write_init(struct fpga_manager *mgr, struct fpga_image_info *info, const char *buf, size_t count) { … } static inline int fpga_mgr_write_sg(struct fpga_manager *mgr, struct sg_table *sgt) { … } /** * fpga_image_info_alloc - Allocate an FPGA image info struct * @dev: owning device * * Return: struct fpga_image_info or NULL */ struct fpga_image_info *fpga_image_info_alloc(struct device *dev) { … } EXPORT_SYMBOL_GPL(…); /** * fpga_image_info_free - Free an FPGA image info struct * @info: FPGA image info struct to free */ void fpga_image_info_free(struct fpga_image_info *info) { … } EXPORT_SYMBOL_GPL(…); /* * Call the low level driver's parse_header function with entire FPGA image * buffer on the input. This will set info->header_size and info->data_size. */ static int fpga_mgr_parse_header_mapped(struct fpga_manager *mgr, struct fpga_image_info *info, const char *buf, size_t count) { … } /* * Call the low level driver's parse_header function with first fragment of * scattered FPGA image on the input. If header fits first fragment, * parse_header will set info->header_size and info->data_size. If it is not, * parse_header will set desired size to info->header_size and -EAGAIN will be * returned. */ static int fpga_mgr_parse_header_sg_first(struct fpga_manager *mgr, struct fpga_image_info *info, struct sg_table *sgt) { … } /* * Copy scattered FPGA image fragments to temporary buffer and call the * low level driver's parse_header function. This should be called after * fpga_mgr_parse_header_sg_first() returned -EAGAIN. In case of success, * pointer to the newly allocated image header copy will be returned and * its size will be set into *ret_size. Returned buffer needs to be freed. */ static void *fpga_mgr_parse_header_sg(struct fpga_manager *mgr, struct fpga_image_info *info, struct sg_table *sgt, size_t *ret_size) { … } /* * Call the low level driver's write_init function. This will do the * device-specific things to get the FPGA into the state where it is ready to * receive an FPGA image. The low level driver gets to see at least first * info->header_size bytes in the buffer. If info->header_size is 0, * write_init will not get any bytes of image buffer. */ static int fpga_mgr_write_init_buf(struct fpga_manager *mgr, struct fpga_image_info *info, const char *buf, size_t count) { … } static int fpga_mgr_prepare_sg(struct fpga_manager *mgr, struct fpga_image_info *info, struct sg_table *sgt) { … } /** * fpga_mgr_buf_load_sg - load fpga from image in buffer from a scatter list * @mgr: fpga manager * @info: fpga image specific information * @sgt: scatterlist table * * Step the low level fpga manager through the device-specific steps of getting * an FPGA ready to be configured, writing the image to it, then doing whatever * post-configuration steps necessary. This code assumes the caller got the * mgr pointer from of_fpga_mgr_get() or fpga_mgr_get() and checked that it is * not an error code. * * This is the preferred entry point for FPGA programming, it does not require * any contiguous kernel memory. * * Return: 0 on success, negative error code otherwise. */ static int fpga_mgr_buf_load_sg(struct fpga_manager *mgr, struct fpga_image_info *info, struct sg_table *sgt) { … } static int fpga_mgr_buf_load_mapped(struct fpga_manager *mgr, struct fpga_image_info *info, const char *buf, size_t count) { … } /** * fpga_mgr_buf_load - load fpga from image in buffer * @mgr: fpga manager * @info: fpga image info * @buf: buffer contain fpga image * @count: byte count of buf * * Step the low level fpga manager through the device-specific steps of getting * an FPGA ready to be configured, writing the image to it, then doing whatever * post-configuration steps necessary. This code assumes the caller got the * mgr pointer from of_fpga_mgr_get() and checked that it is not an error code. * * Return: 0 on success, negative error code otherwise. */ static int fpga_mgr_buf_load(struct fpga_manager *mgr, struct fpga_image_info *info, const char *buf, size_t count) { … } /** * fpga_mgr_firmware_load - request firmware and load to fpga * @mgr: fpga manager * @info: fpga image specific information * @image_name: name of image file on the firmware search path * * Request an FPGA image using the firmware class, then write out to the FPGA. * Update the state before each step to provide info on what step failed if * there is a failure. This code assumes the caller got the mgr pointer * from of_fpga_mgr_get() or fpga_mgr_get() and checked that it is not an error * code. * * Return: 0 on success, negative error code otherwise. */ static int fpga_mgr_firmware_load(struct fpga_manager *mgr, struct fpga_image_info *info, const char *image_name) { … } /** * fpga_mgr_load - load FPGA from scatter/gather table, buffer, or firmware * @mgr: fpga manager * @info: fpga image information. * * Load the FPGA from an image which is indicated in @info. If successful, the * FPGA ends up in operating mode. * * Return: 0 on success, negative error code otherwise. */ int fpga_mgr_load(struct fpga_manager *mgr, struct fpga_image_info *info) { … } EXPORT_SYMBOL_GPL(…); static const char * const state_str[] = …; static ssize_t name_show(struct device *dev, struct device_attribute *attr, char *buf) { … } static ssize_t state_show(struct device *dev, struct device_attribute *attr, char *buf) { … } static ssize_t status_show(struct device *dev, struct device_attribute *attr, char *buf) { … } static DEVICE_ATTR_RO(name); static DEVICE_ATTR_RO(state); static DEVICE_ATTR_RO(status); static struct attribute *fpga_mgr_attrs[] = …; ATTRIBUTE_GROUPS(…); static struct fpga_manager *__fpga_mgr_get(struct device *mgr_dev) { … } static int fpga_mgr_dev_match(struct device *dev, const void *data) { … } /** * fpga_mgr_get - Given a device, get a reference to an fpga mgr. * @dev: parent device that fpga mgr was registered with * * Return: fpga manager struct or IS_ERR() condition containing error code. */ struct fpga_manager *fpga_mgr_get(struct device *dev) { … } EXPORT_SYMBOL_GPL(…); /** * of_fpga_mgr_get - Given a device node, get a reference to an fpga mgr. * * @node: device node * * Return: fpga manager struct or IS_ERR() condition containing error code. */ struct fpga_manager *of_fpga_mgr_get(struct device_node *node) { … } EXPORT_SYMBOL_GPL(…); /** * fpga_mgr_put - release a reference to an fpga manager * @mgr: fpga manager structure */ void fpga_mgr_put(struct fpga_manager *mgr) { … } EXPORT_SYMBOL_GPL(…); /** * fpga_mgr_lock - Lock FPGA manager for exclusive use * @mgr: fpga manager * * Given a pointer to FPGA Manager (from fpga_mgr_get() or * of_fpga_mgr_put()) attempt to get the mutex. The user should call * fpga_mgr_lock() and verify that it returns 0 before attempting to * program the FPGA. Likewise, the user should call fpga_mgr_unlock * when done programming the FPGA. * * Return: 0 for success or -EBUSY */ int fpga_mgr_lock(struct fpga_manager *mgr) { … } EXPORT_SYMBOL_GPL(…); /** * fpga_mgr_unlock - Unlock FPGA manager after done programming * @mgr: fpga manager */ void fpga_mgr_unlock(struct fpga_manager *mgr) { … } EXPORT_SYMBOL_GPL(…); /** * __fpga_mgr_register_full - create and register an FPGA Manager device * @parent: fpga manager device from pdev * @info: parameters for fpga manager * @owner: owner module containing the ops * * The caller of this function is responsible for calling fpga_mgr_unregister(). * Using devm_fpga_mgr_register_full() instead is recommended. * * Return: pointer to struct fpga_manager pointer or ERR_PTR() */ struct fpga_manager * __fpga_mgr_register_full(struct device *parent, const struct fpga_manager_info *info, struct module *owner) { … } EXPORT_SYMBOL_GPL(…); /** * __fpga_mgr_register - create and register an FPGA Manager device * @parent: fpga manager device from pdev * @name: fpga manager name * @mops: pointer to structure of fpga manager ops * @priv: fpga manager private data * @owner: owner module containing the ops * * The caller of this function is responsible for calling fpga_mgr_unregister(). * Using devm_fpga_mgr_register() instead is recommended. This simple * version of the register function should be sufficient for most users. The * fpga_mgr_register_full() function is available for users that need to pass * additional, optional parameters. * * Return: pointer to struct fpga_manager pointer or ERR_PTR() */ struct fpga_manager * __fpga_mgr_register(struct device *parent, const char *name, const struct fpga_manager_ops *mops, void *priv, struct module *owner) { … } EXPORT_SYMBOL_GPL(…); /** * fpga_mgr_unregister - unregister an FPGA manager * @mgr: fpga manager struct * * This function is intended for use in an FPGA manager driver's remove function. */ void fpga_mgr_unregister(struct fpga_manager *mgr) { … } EXPORT_SYMBOL_GPL(…); static void devm_fpga_mgr_unregister(struct device *dev, void *res) { … } /** * __devm_fpga_mgr_register_full - resource managed variant of fpga_mgr_register() * @parent: fpga manager device from pdev * @info: parameters for fpga manager * @owner: owner module containing the ops * * Return: fpga manager pointer on success, negative error code otherwise. * * This is the devres variant of fpga_mgr_register_full() for which the unregister * function will be called automatically when the managing device is detached. */ struct fpga_manager * __devm_fpga_mgr_register_full(struct device *parent, const struct fpga_manager_info *info, struct module *owner) { … } EXPORT_SYMBOL_GPL(…); /** * __devm_fpga_mgr_register - resource managed variant of fpga_mgr_register() * @parent: fpga manager device from pdev * @name: fpga manager name * @mops: pointer to structure of fpga manager ops * @priv: fpga manager private data * @owner: owner module containing the ops * * Return: fpga manager pointer on success, negative error code otherwise. * * This is the devres variant of fpga_mgr_register() for which the * unregister function will be called automatically when the managing * device is detached. */ struct fpga_manager * __devm_fpga_mgr_register(struct device *parent, const char *name, const struct fpga_manager_ops *mops, void *priv, struct module *owner) { … } EXPORT_SYMBOL_GPL(…); static void fpga_mgr_dev_release(struct device *dev) { … } static const struct class fpga_mgr_class = …; static int __init fpga_mgr_class_init(void) { … } static void __exit fpga_mgr_class_exit(void) { … } MODULE_AUTHOR(…) …; MODULE_DESCRIPTION(…) …; MODULE_LICENSE(…) …; subsys_initcall(fpga_mgr_class_init); module_exit(fpga_mgr_class_exit);