diff options
Diffstat (limited to 'bifrost/r25p0/kernel/drivers/gpu/arm/midgard/platform/devicetree/mpgpu.c')
-rw-r--r-- | bifrost/r25p0/kernel/drivers/gpu/arm/midgard/platform/devicetree/mpgpu.c | 326 |
1 files changed, 326 insertions, 0 deletions
diff --git a/bifrost/r25p0/kernel/drivers/gpu/arm/midgard/platform/devicetree/mpgpu.c b/bifrost/r25p0/kernel/drivers/gpu/arm/midgard/platform/devicetree/mpgpu.c new file mode 100644 index 0000000..ee7c1da --- /dev/null +++ b/bifrost/r25p0/kernel/drivers/gpu/arm/midgard/platform/devicetree/mpgpu.c @@ -0,0 +1,326 @@ +/* + * mpgpu.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + +/* Standard Linux headers */ +#include <linux/platform_device.h> +#include <linux/version.h> +#include <linux/types.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/device.h> +#include <linux/string.h> +#include <linux/slab.h> +#include <linux/list.h> + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 29)) +#include <mach/io.h> +#include <plat/io.h> +#include <asm/io.h> +#endif + +#include <mali_kbase.h> +#include <mali_kbase_defs.h> + +#include "meson_main2.h" + +int meson_gpu_data_invalid_count = 0; +int meson_gpu_fault = 0; + +extern u64 kbase_pm_get_ready_cores(struct kbase_device *kbdev, enum kbase_pm_core_type type); +static ssize_t domain_stat_read(struct class *class, + struct class_attribute *attr, char *buf) +{ + unsigned int val; + u64 core_ready; + mali_plat_info_t* pmali_plat = get_mali_plat_data(); + struct platform_device* ptr_plt_dev = pmali_plat->pdev; + struct kbase_device *kbdev = dev_get_drvdata(&ptr_plt_dev->dev); + + core_ready = kbase_pm_get_ready_cores(kbdev, KBASE_PM_CORE_SHADER); + val = core_ready; + return sprintf(buf, "%x\n", val); +} + +#define PREHEAT_CMD "preheat" +#define PLL2_CMD "mpl2" /* mpl2 [11] or [0xxxxxxx] */ +#define SCMPP_CMD "scmpp" /* scmpp [number of pp your want in most of time]. */ +#define BSTGPU_CMD "bstgpu" /* bstgpu [0-256] */ +#define BSTPP_CMD "bstpp" /* bstpp [0-256] */ +#define LIMIT_CMD "lmt" /* lmt [0 or 1] */ +#define MAX_TOKEN 20 +#define FULL_UTILIZATION 256 + +static ssize_t mpgpu_write(struct class *class, + struct class_attribute *attr, const char *buf, size_t count) +{ + char *pstart, *cprt = NULL; + u32 val = 0; + mali_plat_info_t* pmali_plat = get_mali_plat_data(); + + cprt = skip_spaces(buf); + pstart = strsep(&cprt," "); + if (strlen(pstart) < 1) + goto quit; + + if (!strncmp(pstart, PREHEAT_CMD, MAX_TOKEN)) { + if (pmali_plat->plat_preheat) { + pmali_plat->plat_preheat(); + } + } else if (!strncmp(pstart, PLL2_CMD, MAX_TOKEN)) { + int base = 10; + if ((strlen(cprt) > 2) && (cprt[0] == '0') && + (cprt[1] == 'x' || cprt[1] == 'X')) + base = 16; + if (kstrtouint(cprt, base, &val) <0) + goto quit; + if (val < 11) + pmali_plat->cfg_clock = pmali_plat->cfg_clock_bkup; + else + pmali_plat->cfg_clock = pmali_plat->turbo_clock; + pmali_plat->scale_info.maxclk = pmali_plat->cfg_clock; + set_str_src(val); + } else if (!strncmp(pstart, SCMPP_CMD, MAX_TOKEN)) { + if ((kstrtouint(cprt, 10, &val) <0) || pmali_plat == NULL) + goto quit; + if ((val > 0) && (val < pmali_plat->cfg_pp)) { + pmali_plat->sc_mpp = val; + } + } else if (!strncmp(pstart, BSTGPU_CMD, MAX_TOKEN)) { + if ((kstrtouint(cprt, 10, &val) <0) || pmali_plat == NULL) + goto quit; + if ((val > 0) && (val < FULL_UTILIZATION)) { + pmali_plat->bst_gpu = val; + } + } else if (!strncmp(pstart, BSTPP_CMD, MAX_TOKEN)) { + if ((kstrtouint(cprt, 10, &val) <0) || pmali_plat == NULL) + goto quit; + if ((val > 0) && (val < FULL_UTILIZATION)) { + pmali_plat->bst_pp = val; + } + } else if (!strncmp(pstart, LIMIT_CMD, MAX_TOKEN)) { + if ((kstrtouint(cprt, 10, &val) <0) || pmali_plat == NULL) + goto quit; + + if (val < 2) { + pmali_plat->limit_on = val; + if (val == 0) { + pmali_plat->scale_info.maxclk = pmali_plat->cfg_clock; + pmali_plat->scale_info.maxpp = pmali_plat->cfg_pp; + revise_mali_rt(); + } + } + } +quit: + return count; +} + +static ssize_t scale_mode_read(struct class *class, + struct class_attribute *attr, char *buf) +{ + return sprintf(buf, "%d\n", get_mali_schel_mode()); +} + +static ssize_t scale_mode_write(struct class *class, + struct class_attribute *attr, const char *buf, size_t count) +{ + int ret; + unsigned int val; + + ret = kstrtouint(buf, 10, &val); + if (0 != ret) + { + return -EINVAL; + } + + set_mali_schel_mode(val); + + return count; +} + +static ssize_t max_freq_read(struct class *class, + struct class_attribute *attr, char *buf) +{ + mali_plat_info_t* pmali_plat = get_mali_plat_data(); + printk("maxclk:%d, maxclk_sys:%d, max gpu level=%d\n", + pmali_plat->scale_info.maxclk, pmali_plat->maxclk_sysfs, get_gpu_max_clk_level()); + return sprintf(buf, "%d\n", get_gpu_max_clk_level()); +} + +static ssize_t max_freq_write(struct class *class, + struct class_attribute *attr, const char *buf, size_t count) +{ + int ret; + unsigned int val; + mali_plat_info_t* pmali_plat; + mali_scale_info_t* pinfo; + + pmali_plat = get_mali_plat_data(); + pinfo = &pmali_plat->scale_info; + + ret = kstrtouint(buf, 10, &val); + if ((0 != ret) || (val > pmali_plat->cfg_clock) || (val < pinfo->minclk)) + return -EINVAL; + + pmali_plat->maxclk_sysfs = val; + pinfo->maxclk = val; + revise_mali_rt(); + + return count; +} + +static ssize_t min_freq_read(struct class *class, + struct class_attribute *attr, char *buf) +{ + mali_plat_info_t* pmali_plat = get_mali_plat_data(); + return sprintf(buf, "%d\n", pmali_plat->scale_info.minclk); +} + +static ssize_t min_freq_write(struct class *class, + struct class_attribute *attr, const char *buf, size_t count) +{ + int ret; + unsigned int val; + mali_plat_info_t* pmali_plat; + mali_scale_info_t* pinfo; + + pmali_plat = get_mali_plat_data(); + pinfo = &pmali_plat->scale_info; + + ret = kstrtouint(buf, 10, &val); + if ((0 != ret) || (val > pinfo->maxclk)) + return -EINVAL; + + pinfo->minclk = val; + revise_mali_rt(); + + return count; +} + +static ssize_t freq_read(struct class *class, + struct class_attribute *attr, char *buf) +{ + return sprintf(buf, "%d\n", get_current_frequency()); +} + +static ssize_t freq_write(struct class *class, + struct class_attribute *attr, const char *buf, size_t count) +{ + int ret; + unsigned int val; + u32 clk, pp; + get_mali_rt_clkpp(&clk, &pp); + + ret = kstrtouint(buf, 10, &val); + if (0 != ret) + return -EINVAL; + + set_mali_rt_clkpp(val, pp, 1); + + return count; +} + +static ssize_t utilization_read(struct class *class, + struct class_attribute *attr, char *buf) +{ + return sprintf(buf, "%d\n", mpgpu_get_utilization()); +} + +static ssize_t util_gl_share_read(struct class *class, + struct class_attribute *attr, char *buf) +{ + return sprintf(buf, "%d\n", mpgpu_get_util_gl_share()); +} + +static ssize_t util_cl_share_read(struct class *class, + struct class_attribute *attr, char *buf) +{ + u32 val[2]; + + mpgpu_get_util_cl_share(val); + + return sprintf(buf, "%d %d\n", val[0], val[1]); +} + +u32 mpgpu_get_gpu_err_count(void) +{ + return (meson_gpu_fault + meson_gpu_data_invalid_count); +} + +static ssize_t meson_gpu_get_err_count(struct class *class, + struct class_attribute *attr, char *buf) +{ + return sprintf(buf, "%d\n", mpgpu_get_gpu_err_count()); +} + +static ssize_t mpgpu_set_err_count(struct class *class, + struct class_attribute *attr, const char *buf, size_t count) +{ + int ret; + unsigned int val; + + ret = kstrtouint(buf, 10, &val); + if (0 != ret) + return -EINVAL; + + meson_gpu_fault = val; + + return count; +} + +static struct class_attribute mali_class_attrs[] = { + __ATTR(domain_stat, 0644, domain_stat_read, NULL), + __ATTR(mpgpucmd, 0644, NULL, mpgpu_write), + __ATTR(scale_mode, 0644, scale_mode_read, scale_mode_write), + __ATTR(min_freq, 0644, min_freq_read, min_freq_write), + __ATTR(max_freq, 0644, max_freq_read, max_freq_write), + __ATTR(cur_freq, 0644, freq_read, freq_write), + __ATTR(utilization, 0644, utilization_read, NULL), + __ATTR(util_gl, 0644, util_gl_share_read, NULL), + __ATTR(util_cl, 0644, util_cl_share_read, NULL), + __ATTR(gpu_err, 0644, meson_gpu_get_err_count, mpgpu_set_err_count), +}; + +static struct class mpgpu_class = { + .name = "mpgpu", +}; + +int mpgpu_class_init(void) +{ + int ret = 0; + int i; + int attr_num = ARRAY_SIZE(mali_class_attrs); + + ret = class_register(&mpgpu_class); + if (ret) { + printk(KERN_ERR "%s: class_register failed\n", __func__); + return ret; + } + for (i = 0; i< attr_num; i++) { + ret = class_create_file(&mpgpu_class, &mali_class_attrs[i]); + if (ret) { + printk(KERN_ERR "%d ST: class item failed to register\n", i); + } + } + return ret; +} + +void mpgpu_class_exit(void) +{ + class_unregister(&mpgpu_class); +} + |