blob: 736399a6682cbf57bad543f144f510169f80100d [file] [log] [blame]
/*
*
* (C) COPYRIGHT 2016-2017 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 licence.
*
* 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.
*
* SPDX-License-Identifier: GPL-2.0
*
*/
#ifndef _KBASE_IPA_H_
#define _KBASE_IPA_H_
#if defined(CONFIG_MALI_DEVFREQ) && defined(CONFIG_DEVFREQ_THERMAL)
struct devfreq;
struct kbase_ipa_model {
struct list_head link;
struct kbase_device *kbdev;
void *model_data;
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
* @current_freq: frequency the GPU has been running at for the
* previous sampling period.
*
* 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.
*/
int (*get_dynamic_coeff)(struct kbase_ipa_model *model, u32 *coeffp,
u32 current_freq);
/*
* 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);
/* If false, the model's get_dynamic_coeff() method accounts for how
* long the GPU was active over the sample period. If true, the
* framework will scale the calculated power according to the
* utilization stats recorded by devfreq in get_real_power(). */
bool do_utilization_scaling_in_framework;
};
/* Models can be registered only in the platform's platform_init_func call */
int kbase_ipa_model_ops_register(struct kbase_device *kbdev,
struct kbase_ipa_model_ops *new_model_ops);
struct kbase_ipa_model *kbase_ipa_get_model(struct kbase_device *kbdev,
const char *name);
int kbase_ipa_init(struct kbase_device *kbdev);
void kbase_ipa_term(struct kbase_device *kbdev);
void kbase_ipa_model_use_fallback_locked(struct kbase_device *kbdev);
void kbase_ipa_model_use_configured_locked(struct kbase_device *kbdev);
int kbase_ipa_model_recalculate(struct kbase_ipa_model *model);
struct kbase_ipa_model *kbase_ipa_init_model(struct kbase_device *kbdev,
struct kbase_ipa_model_ops *ops);
void kbase_ipa_term_model(struct kbase_ipa_model *model);
extern struct kbase_ipa_model_ops kbase_g71_ipa_model_ops;
#if MALI_UNIT_TEST
/**
* 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.
*
* This function is only exposed for use by unit tests. 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);
#endif /* MALI_UNIT_TEST */
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0)
extern struct devfreq_cooling_ops kbase_ipa_power_model_ops;
#else
extern struct devfreq_cooling_power kbase_ipa_power_model_ops;
#endif
#else /* !(defined(CONFIG_MALI_DEVFREQ) && defined(CONFIG_DEVFREQ_THERMAL)) */
static inline void kbase_ipa_model_use_fallback_locked(struct kbase_device *kbdev)
{ }
static inline void kbase_ipa_model_use_configured_locked(struct kbase_device *kbdev)
{ }
#endif /* (defined(CONFIG_MALI_DEVFREQ) && defined(CONFIG_DEVFREQ_THERMAL)) */
#endif