// SPDX-License-Identifier: GPL-2.0 /* * Freescale data path resource container (DPRC) driver * * Copyright (C) 2014-2016 Freescale Semiconductor, Inc. * Copyright 2019-2020 NXP * Author: German Rivera <[email protected]> * */ #include <linux/module.h> #include <linux/slab.h> #include <linux/interrupt.h> #include <linux/fsl/mc.h> #include "fsl-mc-private.h" #define FSL_MC_DPRC_DRIVER_NAME … struct fsl_mc_child_objs { … }; static bool fsl_mc_device_match(struct fsl_mc_device *mc_dev, struct fsl_mc_obj_desc *obj_desc) { … } static bool fsl_mc_obj_desc_is_allocatable(struct fsl_mc_obj_desc *obj) { … } static int __fsl_mc_device_remove_if_not_in_mc(struct device *dev, void *data) { … } static int __fsl_mc_device_remove(struct device *dev, void *data) { … } /** * dprc_remove_devices - Removes devices for objects removed from a DPRC * * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object * @obj_desc_array: array of object descriptors for child objects currently * present in the DPRC in the MC. * @num_child_objects_in_mc: number of entries in obj_desc_array * * Synchronizes the state of the Linux bus driver with the actual state of * the MC by removing devices that represent MC objects that have * been dynamically removed in the physical DPRC. */ void dprc_remove_devices(struct fsl_mc_device *mc_bus_dev, struct fsl_mc_obj_desc *obj_desc_array, int num_child_objects_in_mc) { … } EXPORT_SYMBOL_GPL(…); static int __fsl_mc_device_match(struct device *dev, void *data) { … } struct fsl_mc_device *fsl_mc_device_lookup(struct fsl_mc_obj_desc *obj_desc, struct fsl_mc_device *mc_bus_dev) { … } /** * check_plugged_state_change - Check change in an MC object's plugged state * * @mc_dev: pointer to the fsl-mc device for a given MC object * @obj_desc: pointer to the MC object's descriptor in the MC * * If the plugged state has changed from unplugged to plugged, the fsl-mc * device is bound to the corresponding device driver. * If the plugged state has changed from plugged to unplugged, the fsl-mc * device is unbound from the corresponding device driver. */ static void check_plugged_state_change(struct fsl_mc_device *mc_dev, struct fsl_mc_obj_desc *obj_desc) { … } static void fsl_mc_obj_device_add(struct fsl_mc_device *mc_bus_dev, struct fsl_mc_obj_desc *obj_desc) { … } /** * dprc_add_new_devices - Adds devices to the logical bus for a DPRC * * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object * @obj_desc_array: array of device descriptors for child devices currently * present in the physical DPRC. * @num_child_objects_in_mc: number of entries in obj_desc_array * * Synchronizes the state of the Linux bus driver with the actual * state of the MC by adding objects that have been newly discovered * in the physical DPRC. */ static void dprc_add_new_devices(struct fsl_mc_device *mc_bus_dev, struct fsl_mc_obj_desc *obj_desc_array, int num_child_objects_in_mc) { … } /** * dprc_scan_objects - Discover objects in a DPRC * * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object * @alloc_interrupts: if true the function allocates the interrupt pool, * otherwise the interrupt allocation is delayed * * Detects objects added and removed from a DPRC and synchronizes the * state of the Linux bus driver, MC by adding and removing * devices accordingly. * Two types of devices can be found in a DPRC: allocatable objects (e.g., * dpbp, dpmcp) and non-allocatable devices (e.g., dprc, dpni). * All allocatable devices needed to be probed before all non-allocatable * devices, to ensure that device drivers for non-allocatable * devices can allocate any type of allocatable devices. * That is, we need to ensure that the corresponding resource pools are * populated before they can get allocation requests from probe callbacks * of the device drivers for the non-allocatable devices. */ int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev, bool alloc_interrupts) { … } /** * dprc_scan_container - Scans a physical DPRC and synchronizes Linux bus state * * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object * @alloc_interrupts: if true the function allocates the interrupt pool, * otherwise the interrupt allocation is delayed * Scans the physical DPRC and synchronizes the state of the Linux * bus driver with the actual state of the MC by adding and removing * devices as appropriate. */ int dprc_scan_container(struct fsl_mc_device *mc_bus_dev, bool alloc_interrupts) { … } EXPORT_SYMBOL_GPL(…); /** * dprc_irq0_handler - Regular ISR for DPRC interrupt 0 * * @irq_num: IRQ number of the interrupt being handled * @arg: Pointer to device structure */ static irqreturn_t dprc_irq0_handler(int irq_num, void *arg) { … } /** * dprc_irq0_handler_thread - Handler thread function for DPRC interrupt 0 * * @irq_num: IRQ number of the interrupt being handled * @arg: Pointer to device structure */ static irqreturn_t dprc_irq0_handler_thread(int irq_num, void *arg) { … } /* * Disable and clear interrupt for a given DPRC object */ int disable_dprc_irq(struct fsl_mc_device *mc_dev) { … } int get_dprc_irq_state(struct fsl_mc_device *mc_dev) { … } static int register_dprc_irq_handler(struct fsl_mc_device *mc_dev) { … } int enable_dprc_irq(struct fsl_mc_device *mc_dev) { … } /* * Setup interrupt for a given DPRC device */ static int dprc_setup_irq(struct fsl_mc_device *mc_dev) { … } /** * dprc_setup - opens and creates a mc_io for DPRC * * @mc_dev: Pointer to fsl-mc device representing a DPRC * * It opens the physical DPRC in the MC. * It configures the DPRC portal used to communicate with MC */ int dprc_setup(struct fsl_mc_device *mc_dev) { … } EXPORT_SYMBOL_GPL(…); /** * dprc_probe - callback invoked when a DPRC is being bound to this driver * * @mc_dev: Pointer to fsl-mc device representing a DPRC * * It opens the physical DPRC in the MC. * It scans the DPRC to discover the MC objects contained in it. * It creates the interrupt pool for the MC bus associated with the DPRC. * It configures the interrupts for the DPRC device itself. */ static int dprc_probe(struct fsl_mc_device *mc_dev) { … } /* * Tear down interrupt for a given DPRC object */ static void dprc_teardown_irq(struct fsl_mc_device *mc_dev) { … } /** * dprc_cleanup - function that cleanups a DPRC * * @mc_dev: Pointer to fsl-mc device representing the DPRC * * It closes the DPRC device in the MC. * It destroys the interrupt pool associated with this MC bus. */ int dprc_cleanup(struct fsl_mc_device *mc_dev) { … } EXPORT_SYMBOL_GPL(…); /** * dprc_remove - callback invoked when a DPRC is being unbound from this driver * * @mc_dev: Pointer to fsl-mc device representing the DPRC * * It removes the DPRC's child objects from Linux (not from the MC) and * closes the DPRC device in the MC. * It tears down the interrupts that were configured for the DPRC device. * It destroys the interrupt pool associated with this MC bus. */ static void dprc_remove(struct fsl_mc_device *mc_dev) { … } static const struct fsl_mc_device_id match_id_table[] = …; static struct fsl_mc_driver dprc_driver = …; int __init dprc_driver_init(void) { … } void dprc_driver_exit(void) { … }