/**
* @file mali_platform.c
- * Platform specific Mali driver functions for a default platform
+ * Platform specific Mali driver functions
+ * for a default platform
*/
+
+/* #define ENABLE_DEBUG_LOG */
+#include "custom_log.h"
+
#include <linux/workqueue.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include "mali_platform.h"
+/**
+ * 是否使能 core_scaling 机制.
+ * .DP : core_scaling : 根据当前 mali_utilization_data,
+ * 配置 mali_gpu 中具体使用的 pp_core 的个数.
+ */
static int mali_core_scaling_enable;
u32 mali_group_error;
-struct device *mali_dev;
+/**
+ * anchor_of_device_of_mali_gpu.
+ */
+static struct device *mali_dev;
+/**
+ * 设置 current_dvfs_level.
+ *
+ * @param level
+ * 待设置为 current 的 dvfs_level 实例,
+ * 在 dvfs_level_list 中的 index,
+ * 即 index_of_new_current_level.
+ *
+ * @return
+ * 0, 成功.
+ * 其他 value, 失败.
+ */
int mali_set_level(struct device *dev, int level)
{
struct mali_platform_drv_data *drv_data = dev_get_drvdata(dev);
+ /* gpu_clk_freq_of_new_current_level. */
unsigned long freq;
int ret;
+ /* index_of_old_current_level. */
unsigned int current_level;
_mali_osk_mutex_wait(drv_data->clock_set_lock);
freq = drv_data->fv_info[level].freq;
if (level == current_level) {
+ D("we are already in the target level, to exit.");
_mali_osk_mutex_signal(drv_data->clock_set_lock);
return 0;
}
+ /* .KP : 调用 dvfs_module 的接口, 将 cpu_clk 设置为 'freq'. */
ret = dvfs_clk_set_rate(drv_data->clk, freq);
if (ret) {
_mali_osk_mutex_signal(drv_data->clock_set_lock);
return ret;
}
- dev_dbg(dev, "set freq %lu\n", freq);
-
+ D("have set gpu_clk to %lu of new_level %d, " "the old_level is %d.",
+ freq,
+ level,
+ current_level);
+ /* update index_of_current_dvfs_level. */
drv_data->dvfs.current_level = level;
_mali_osk_mutex_signal(drv_data->clock_set_lock);
return 0;
}
+/**
+ * 初始化 gpu_dvfs_node 和 gpu_power_domain.
+ */
static int mali_clock_init(struct device *dev)
{
int ret;
drv_data->power_state = false;
}
+/*---------------------------------------------------------------------------*/
+
static ssize_t show_available_frequencies(struct device *dev,
struct device_attribute *attr,
char *buf)
dvfs_clk_get_rate(drv_data->clk));
}
-static ssize_t set_clock(struct device *dev, struct device_attribute *attr,
+static ssize_t set_clock(struct device *dev,
+ struct device_attribute *attr,
const char *buf, size_t count)
{
struct mali_platform_drv_data *drv_data = dev_get_drvdata(dev);
.attrs = mali_sysfs_entries,
};
+/**
+ * 创建 sysfs_nodes_of_platform_dependent_part.
+ */
static int mali_create_sysfs(struct device *dev)
{
int ret;
return ret;
}
-void mali_remove_sysfs(struct device *dev)
+static void mali_remove_sysfs(struct device *dev)
{
sysfs_remove_group(&dev->kobj, &mali_attr_group);
}
+/*---------------------------------------------------------------------------*/
+
+/**
+ * 对 platform_device_of_mali_gpu,
+ * 完成仅和 platform_dependent_part 有关的初始化.
+ */
_mali_osk_errcode_t mali_platform_init(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
+ /* mali_driver_private_data. */
struct mali_platform_drv_data *mali_drv_data;
int ret;
struct device *dev = &pdev->dev;
struct mali_platform_drv_data *drv_data = dev_get_drvdata(dev);
+ mali_remove_sysfs(dev);
+
mali_core_scaling_term();
mali_clock_term(dev);
_mali_osk_mutex_term(drv_data->clock_set_lock);
return 0;
}
-_mali_osk_errcode_t mali_power_domain_control(u32 bpower_off)
+/*---------------------------------------------------------------------------*/
+
+/**
+ * 对 gpu_power_domain(mali_power_domain), "上电, 开 clk" / "下电, 关 clk".
+ * @param bpower_off
+ * true, 下电.
+ * false, 对 gpu_power_domain 上电.
+ */
+static _mali_osk_errcode_t mali_power_domain_control(bool bpower_off)
{
struct mali_platform_drv_data *drv_data = dev_get_drvdata(mali_dev);
- if (bpower_off == 0) {
+ /* 若要 上电, 则 ... */
+ if (!bpower_off) {
if (!drv_data->power_state) {
+ D("to ENABLE clk to gpu_dvfs_node.");
dvfs_clk_prepare_enable(drv_data->clk);
- if (drv_data->pd)
+
+ if (drv_data->pd) {
+ D("to power UP gpu_power_domain.");
clk_prepare_enable(drv_data->pd);
+ }
+
drv_data->power_state = true;
}
- } else if (bpower_off == 1) {
+ } else {
if (drv_data->power_state) {
+ D("to DISABLE clk to gpu_dvfs_node.");
dvfs_clk_disable_unprepare(drv_data->clk);
- if (drv_data->pd)
+
+ if (drv_data->pd) {
+ D("to power DOWN gpu_power_domain.");
clk_disable_unprepare(drv_data->pd);
+ }
+
drv_data->power_state = false;
}
}
_mali_osk_errcode_t mali_platform_power_mode_change(
enum mali_power_mode power_mode)
{
+ bool bpower_off;/* 下电. */
+
switch (power_mode) {
case MALI_POWER_MODE_ON:
MALI_DEBUG_PRINT(2, ("MALI_POWER_MODE_ON\r\n"));
- mali_power_domain_control(MALI_POWER_MODE_ON);
+ mali_dvfs_enable(mali_dev);
+ bpower_off = false;
break;
+
case MALI_POWER_MODE_LIGHT_SLEEP:
MALI_DEBUG_PRINT(2, ("MALI_POWER_MODE_LIGHT_SLEEP\r\n"));
- mali_power_domain_control(MALI_POWER_MODE_LIGHT_SLEEP);
+ mali_dvfs_disable(mali_dev);
+ /* 预置将下电. */
+ bpower_off = true;
break;
+
case MALI_POWER_MODE_DEEP_SLEEP:
MALI_DEBUG_PRINT(2, ("MALI_POWER_MODE_DEEP_SLEEP\r\n"));
- mali_power_domain_control(MALI_POWER_MODE_DEEP_SLEEP);
+ mali_dvfs_disable(mali_dev);
+ /* 预置将下电. */
+ bpower_off = true;
break;
+
default:
MALI_DEBUG_PRINT(2,
- (":power_mode(%d) not support \r\n",
- power_mode));
+ ("power_mode(%d) not support\n", power_mode));
+ return _MALI_OSK_ERR_INVALID_ARGS;
}
+ mali_power_domain_control(bpower_off);
+
return 0;
}
+
+/*---------------------------------------------------------------------------*/
+
+/**
+ * 将注册到 common_part 中的, 对 mali_utilization_event 的 handler,
+ * 即 common_part 会直接将 mali_utilization_event 通知回调到本函数.
+ */
void mali_gpu_utilization_handler(struct mali_gpu_utilization_data *data)
{
if (data->utilization_pp > 256)
extern "C" {
#endif
-/** @brief description of power change reasons
+/**
+ * @brief
+ * description of power change reasons
*/
enum mali_power_mode {
MALI_POWER_MODE_ON, /**< Power Mali on */
MALI_POWER_MODE_DEEP_SLEEP, /**< Mali has been idle for a long time, or OS suspend */
};
+/**
+ * dvfs_level_t, 标识一个 dvfs_level (的具体配置).
+ * .DP : dvfs_level.
+ */
struct mali_fv_info {
+ /**
+ * 当前 dvfs_level 使用的 gpu_clk_freq.
+ */
unsigned long freq;
+ /**
+ * .DP : min_mali_utilization_in_percentage_in_this_level.
+ * 若当前的 mali_utilization_in_percentage
+ * 小于 min_mali_utilization_in_percentage_in_this_level,
+ * 则触发一次 requests_to_jump_down_in_dvfs_level_table,
+ * 当 对 requests_to_jump_down_in_dvfs_level_table 的连续计数
+ * (.DP : continuous_count_of_requests_to_jump_down) 达到一定数值,
+ * 则 dvfs_facility 会下跳一个 level.
+ */
unsigned int min;
+ /**
+ * .DP : max_mali_utilization_in_percentage_in_this_level.
+ * 若当前的 mali_utilization_in_percentage
+ * 大于 max_mali_utilization_in_percentage_in_this_level,
+ * 则触发一次 requests_to_jump_up_in_dvfs_level_table,
+ * 当 对 requests_to_jump_up_in_dvfs_level_table 的连续计数
+ * (.DP : continuous_count_of_requests_to_jump_up) 达到一定数值,
+ * 则 dvfs_facility 会上跳一个 level.
+ */
unsigned int max;
};
+/**
+ * mali_driver_private_data_t.
+ * 和 平台相关的 mali_driver 的私有数据,
+ * 包含 clk, power_domain handles, mali_dvfs_facility 等.
+ *
+ * 该类型在 platform_dependent_part 中定义,
+ * 显然也只会在 platform_dependent_part 中使用.
+ */
struct mali_platform_drv_data {
+ /**
+ * gpu_dvfs_node
+ */
struct dvfs_node *clk;
+
+ /**
+ * gpu_power_domain.
+ */
struct clk *pd;
+
+ /**
+ * available_dvfs_level_list.
+ * 将用于保存 系统配置支持的所有 dvfs_level.
+ * .R : 实际上, 放在 mali_dvfs_context 中为宜.
+ */
struct mali_fv_info *fv_info;
+ /**
+ * len_of_available_dvfs_level_list, 也即 根据系统配置得到的 available_dvfs_level 的个数.
+ */
unsigned int fv_info_length;
+
+ /**
+ * mali_dvfs_context.
+ */
struct mali_dvfs dvfs;
+
+ /**
+ * device_of_mali_gpu.
+ */
struct device *dev;
+
+ /**
+ * gpu 是否 "被上电, 且被送入 clk".
+ */
bool power_state;
+
_mali_osk_mutex_t *clock_set_lock;
};
enum mali_power_mode power_mode);
-/** @brief Platform specific handling of GPU utilization data
+/**
+ * @brief
+ * Platform specific handling
+ * of GPU utilization data
*
- * When GPU utilization data is enabled, this function will be
- * periodically called.
+ * When GPU utilization data is enabled,
+ * this function
+ * will be periodically called.
*
- * @param utilization The workload utilization of the Mali GPU. 0 = no utilization, 256 = full utilization.
+ * @param utilization
+ * The workload utilization
+ * of the Mali GPU.
+ * 0 = no utilization,
+ * 256 = full utilization.
*/
void mali_gpu_utilization_handler(struct mali_gpu_utilization_data *data);
+
int mali_set_level(struct device *dev, int level);
#ifdef __cplusplus
* by a licensing agreement from ARM Limited.
*/
+
+/**
+ * @file rk3066.c
+ * 实现 rk30_platform 中的 platform_specific_strategy_callbacks,
+ * 实际上也是 platform_dependent_part 的顶层.
+ *
+ * mali_device_driver(mdd) 包含两部分 :
+ * .DP : platform_dependent_part :
+ * 依赖 platform 部分,
+ * 源码在 <mdd_src_dir>/mali/platform/<platform_name> 目录下.
+ * .DP : common_parts : ARM 实现的通用的部分.
+ */
+
+/* #define ENABLE_DEBUG_LOG */
+#include "custom_log.h"
+
#include <linux/platform_device.h>
#include <linux/version.h>
#include <linux/pm.h>
.pm = &mali_gpu_device_type_pm_ops,
};
+/**
+ * platform_specific_data_of_platform_device_of_mali_gpu.
+ *
+ * 类型 'struct mali_gpu_device_data' 由 common_part 定义,
+ * 实例也将被 common_part 引用,
+ * 比如通知 mali_utilization_event 等.
+ */
static const struct mali_gpu_device_data mali_gpu_data = {
.shared_mem_size = 1024 * 1024 * 1024, /* 1GB */
.fb_start = 0x40000000,
pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
}
+/*---------------------------------------------------------------------------*/
+
+/**
+ * 将被 common_part 回调的, 对 platform_device_of_mali_gpu 初始化的策略回调实现.
+ *
+ * .DP : platform_specific_strategy_callbacks_called_by_common_part,
+ * platform_specific_strategy_callbacks :
+ * 被 common_part 调用的 平台相关的策略回调.
+ */
int mali_platform_device_init(struct platform_device *pdev)
{
int err = 0;
mali_platform_device_add_config(pdev);
+ /* 将 platform_specific_data 添加到 platform_device_of_mali_gpu.
+ * 这里的 platform_specific_data 的类型由 common_part 定义. */
err = platform_device_add_data(pdev, &mali_gpu_data,
sizeof(mali_gpu_data));
if (err == 0) {
+ /* .KP : 初始化 platform_device_of_mali_gpu 中,
+ * 仅和 platform_dependent_part 相关的部分. */
err = mali_platform_init(pdev);
if (err == 0) {
#ifdef CONFIG_PM_RUNTIME
return err;
}
+/**
+ * 将被 common_part 回调的, 对 platform_device_of_mali_gpu 终止化的策略回调实现.
+ */
void mali_platform_device_deinit(struct platform_device *pdev)
{
MALI_DEBUG_PRINT(4, ("mali_platform_device_unregister() called\n"));