/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ /* * * (C) COPYRIGHT 2016-2023 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software * Foundation, and any use by you of this program is subject to the terms * of such GNU license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, you can access it online at * http://www.gnu.org/licenses/gpl-2.0.html. * */ #ifndef _KBASE_IPA_H_ #define _KBASE_IPA_H_ #if defined(CONFIG_MALI_DEVFREQ) && defined(CONFIG_DEVFREQ_THERMAL) struct devfreq; /** * enum kbase_ipa_block_type - Type of block for which power estimation is done. * * @KBASE_IPA_BLOCK_TYPE_TOP_LEVEL: Top-level block, that covers CSHW, * MEMSYS, Tiler. * @KBASE_IPA_BLOCK_TYPE_SHADER_CORES: All Shader cores. * @KBASE_IPA_BLOCK_TYPE_NUM: Number of blocks. */ enum kbase_ipa_block_type { KBASE_IPA_BLOCK_TYPE_TOP_LEVEL, KBASE_IPA_BLOCK_TYPE_SHADER_CORES, KBASE_IPA_BLOCK_TYPE_NUM }; /** * struct kbase_ipa_model - Object describing a particular IPA model. * @kbdev: pointer to kbase device * @model_data: opaque pointer to model specific data, accessed * only by model specific methods. * @ops: pointer to object containing model specific methods. * @params: head of the list of debugfs params added for model * @missing_dt_node_warning: flag to limit the matching power model DT not found * warning to once. */ struct kbase_ipa_model { struct kbase_device *kbdev; void *model_data; const struct kbase_ipa_model_ops *ops; struct list_head params; bool missing_dt_node_warning; }; /** * kbase_ipa_model_add_param_s32 - Add an integer model parameter * @model: pointer to IPA model * @name: name of corresponding debugfs entry * @addr: address where the value is stored * @num_elems: number of elements (1 if not an array) * @dt_required: if false, a corresponding devicetree entry is not required, * and the current value will be used. If true, a warning is * output and the data is zeroed * * Return: 0 on success, or an error code */ int kbase_ipa_model_add_param_s32(struct kbase_ipa_model *model, const char *name, s32 *addr, size_t num_elems, bool dt_required); /** * kbase_ipa_model_add_param_string - Add a string model parameter * @model: pointer to IPA model * @name: name of corresponding debugfs entry * @addr: address where the value is stored * @size: size, in bytes, of the value storage (so the maximum string * length is size - 1) * @dt_required: if false, a corresponding devicetree entry is not required, * and the current value will be used. If true, a warning is * output and the data is zeroed * * Return: 0 on success, or an error code */ int kbase_ipa_model_add_param_string(struct kbase_ipa_model *model, const char *name, char *addr, size_t size, bool dt_required); struct kbase_ipa_model_ops { char *name; /* The init, recalculate and term ops on the default model are always * called. However, all the other models are only invoked if the model * is selected in the device tree. Otherwise they are never * initialized. Additional resources can be acquired by models in * init(), however they must be terminated in the term(). */ int (*init)(struct kbase_ipa_model *model); /* Called immediately after init(), or when a parameter is changed, so * that any coefficients derived from model parameters can be * recalculated */ int (*recalculate)(struct kbase_ipa_model *model); void (*term)(struct kbase_ipa_model *model); /* * get_dynamic_coeff() - calculate dynamic power coefficient * @model: pointer to model * @coeffp: pointer to return value location * * Calculate a dynamic power coefficient, with units pW/(Hz V^2), which * is then scaled by the IPA framework according to the current OPP's * frequency and voltage. * * Return: 0 on success, or an error code. -EOVERFLOW error code will * indicate that sampling interval was too large and no meaningful * scaling for GPU utiliation can be done. */ int (*get_dynamic_coeff)(struct kbase_ipa_model *model, u32 *coeffp); /* * get_static_coeff() - calculate static power coefficient * @model: pointer to model * @coeffp: pointer to return value location * * Calculate a static power coefficient, with units uW/(V^3), which is * scaled by the IPA framework according to the current OPP's voltage. * * Return: 0 on success, or an error code. */ int (*get_static_coeff)(struct kbase_ipa_model *model, u32 *coeffp); /* * reset_counter_data() - Reset the HW counter data used for calculating * dynamic power coefficient * @model: pointer to model * * This method is currently applicable only to the counter based model. * The next call to get_dynamic_coeff() will have to calculate the * dynamic power coefficient based on the HW counter data generated * from this point onwards. */ void (*reset_counter_data)(struct kbase_ipa_model *model); }; /** * kbase_ipa_init - Initialize the IPA feature * @kbdev: pointer to kbase device * * simple IPA power model is initialized as a fallback model and if that * initialization fails then IPA is not used. * The device tree is read for the name of ipa model to be used, by using the * property string "ipa-model". If that ipa model is supported then it is * initialized but if the initialization fails then simple power model is used. * * Return: 0 on success, negative -errno on error */ int kbase_ipa_init(struct kbase_device *kbdev); /** * kbase_ipa_term - Terminate the IPA feature * @kbdev: pointer to kbase device * * Both simple IPA power model and model retrieved from device tree are * terminated. */ void kbase_ipa_term(struct kbase_device *kbdev); /** * kbase_ipa_model_recalculate - Recalculate the model coefficients * @model: pointer to the IPA model object, already initialized * * It shall be called immediately after the model has been initialized * or when the model parameter has changed, so that any coefficients * derived from parameters can be recalculated. * Its a wrapper for the module specific recalculate() method. * * Return: 0 on success, negative -errno on error */ int kbase_ipa_model_recalculate(struct kbase_ipa_model *model); /** * kbase_ipa_model_ops_find - Lookup an IPA model using its name * @kbdev: pointer to kbase device * @name: name of model to lookup * * Return: Pointer to model's 'ops' structure, or NULL if the lookup failed. */ const struct kbase_ipa_model_ops *kbase_ipa_model_ops_find(struct kbase_device *kbdev, const char *name); /** * kbase_ipa_counter_model_ops_find - Lookup an IPA counter model using its name * @kbdev: pointer to kbase device * @name: name of counter model to lookup * * Return: Pointer to counter model's 'ops' structure, or NULL if the lookup * failed. */ const struct kbase_ipa_model_ops *kbase_ipa_counter_model_ops_find(struct kbase_device *kbdev, const char *name); /** * kbase_ipa_model_name_from_id - Find the best model for a given GPU ID * @gpu_id: GPU ID of GPU the model will be used for * * Return: The name of the appropriate counter-based model, or the name of the * fallback model if no counter model exists. */ const char *kbase_ipa_model_name_from_id(struct kbase_gpu_id_props *gpu_id); /** * kbase_ipa_counter_model_name_from_id - Find the best counter model for a * given GPU ID * @gpu_id: GPU ID of GPU the counter model will be used for * * Return: The name of the appropriate counter-based model, or NULL if the * no counter model exists. */ const char *kbase_ipa_counter_model_name_from_id(struct kbase_gpu_id_props *gpu_id); /** * kbase_ipa_init_model - Initilaize the particular IPA model * @kbdev: pointer to kbase device * @ops: pointer to object containing model specific methods. * * Initialize the model corresponding to the @ops pointer passed. * The init() method specified in @ops would be called. * * Return: pointer to kbase_ipa_model on success, NULL on error */ struct kbase_ipa_model *kbase_ipa_init_model(struct kbase_device *kbdev, const struct kbase_ipa_model_ops *ops); /** * kbase_ipa_term_model - Terminate the particular IPA model * @model: pointer to the IPA model object, already initialized * * Terminate the model, using the term() method. * Module specific parameters would be freed. */ void kbase_ipa_term_model(struct kbase_ipa_model *model); /** * kbase_ipa_protection_mode_switch_event - Inform IPA of the GPU's entry into * protected mode * @kbdev: pointer to kbase device * * Makes IPA aware of the GPU switching to protected mode. */ void kbase_ipa_protection_mode_switch_event(struct kbase_device *kbdev); /** * kbase_get_real_power() - get the real power consumption of the GPU * @df: dynamic voltage and frequency scaling information for the GPU. * @power: where to store the power consumption, in mW. * @freq: a frequency, in HZ. * @voltage: a voltage, in mV. * * The returned value incorporates both static and dynamic power consumption. * * Return: 0 on success, or an error code. */ int kbase_get_real_power(struct devfreq *df, u32 *power, unsigned long freq, unsigned long voltage); /* Called by kbase_get_real_power() to invoke the power models. * Must be called with kbdev->ipa.lock held. * This function is only exposed for use by unit tests. */ int kbase_get_real_power_locked(struct kbase_device *kbdev, u32 *power, unsigned long freq, unsigned long voltage); extern struct devfreq_cooling_power kbase_ipa_power_model_ops; /** * kbase_ipa_reset_data() - Reset the data required for power estimation. * @kbdev: Pointer to kbase device. * * This function is called to ensure a meaningful baseline for * kbase_get_real_power(), when thermal governor starts the polling, and * that is achieved by updating the GPU utilization metrics and retrieving * the accumulated value of HW counters. * Basically this function collects all the data required for power estimation * but does not process it. */ void kbase_ipa_reset_data(struct kbase_device *kbdev); #else /* !(defined(CONFIG_MALI_DEVFREQ) && defined(CONFIG_DEVFREQ_THERMAL)) */ static inline void kbase_ipa_protection_mode_switch_event(struct kbase_device *kbdev) { } #endif /* (defined(CONFIG_MALI_DEVFREQ) && defined(CONFIG_DEVFREQ_THERMAL)) */ #endif