From 6dc277b783bca9170c43c725884878ba63ce64da Mon Sep 17 00:00:00 2001 From: Mahantesh Kumbar Date: Thu, 12 Jun 2014 16:16:15 +0530 Subject: gpu:nvgpu:sysfs node to update aelpg parameter Added sysfs node to update aelpg parameter. Pass parameter as below sequence, SAMPLING_PERIOD_PG_DEFAULT_US, MINIMUM_IDLE_FILTER_DEFAULT_US, MINIMUM_TARGET_SAVING_DEFAULT_US, POWER_BREAKEVEN_DEFAULT_US, CYCLES_PER_SAMPLE_MAX_DEFAULT Bug 1464737 Change-Id: I46873c463820f30f190c722d7ed038622cb2710f Signed-off-by: Mahantesh Kumbar Reviewed-on: http://git-master/r/422702 Reviewed-by: Bharat Nihalani Tested-by: Bharat Nihalani --- drivers/gpu/nvgpu/gk20a/gk20a.c | 7 +++++ drivers/gpu/nvgpu/gk20a/gk20a_sysfs.c | 59 +++++++++++++++++++++++++++++++++++ drivers/gpu/nvgpu/gk20a/pmu_gk20a.c | 23 +++++--------- drivers/gpu/nvgpu/gk20a/pmu_gk20a.h | 6 ++++ 4 files changed, 80 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.c b/drivers/gpu/nvgpu/gk20a/gk20a.c index c72b8735..3388a2ff 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/gk20a.c @@ -1539,6 +1539,13 @@ static int gk20a_probe(struct platform_device *dev) gk20a->aelpg_enabled = tegra_platform_is_silicon() ? platform->enable_aelpg : false; + /* set default values to aelpg parameters */ + gk20a->pmu.aelpg_param[0] = APCTRL_SAMPLING_PERIOD_PG_DEFAULT_US; + gk20a->pmu.aelpg_param[1] = APCTRL_MINIMUM_IDLE_FILTER_DEFAULT_US; + gk20a->pmu.aelpg_param[2] = APCTRL_MINIMUM_TARGET_SAVING_DEFAULT_US; + gk20a->pmu.aelpg_param[3] = APCTRL_POWER_BREAKEVEN_DEFAULT_US; + gk20a->pmu.aelpg_param[4] = APCTRL_CYCLES_PER_SAMPLE_MAX_DEFAULT; + gk20a_create_sysfs(dev); #ifdef CONFIG_DEBUG_FS diff --git a/drivers/gpu/nvgpu/gk20a/gk20a_sysfs.c b/drivers/gpu/nvgpu/gk20a/gk20a_sysfs.c index eb0aa5d1..2debe235 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a_sysfs.c +++ b/drivers/gpu/nvgpu/gk20a/gk20a_sysfs.c @@ -29,6 +29,7 @@ #include "gk20a.h" #include "gr_gk20a.h" #include "fifo_gk20a.h" +#include "pmu_gk20a.h" #define PTIMER_FP_FACTOR 1000000 @@ -332,6 +333,62 @@ static ssize_t elpg_enable_read(struct device *device, static DEVICE_ATTR(elpg_enable, ROOTRW, elpg_enable_read, elpg_enable_store); +static ssize_t aelpg_param_store(struct device *device, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct platform_device *ndev = to_platform_device(device); + struct gk20a *g = get_gk20a(ndev); + int status = 0; + union pmu_ap_cmd ap_cmd; + int *paramlist = (int *)g->pmu.aelpg_param; + u32 defaultparam[5] = { + APCTRL_SAMPLING_PERIOD_PG_DEFAULT_US, + APCTRL_MINIMUM_IDLE_FILTER_DEFAULT_US, + APCTRL_MINIMUM_TARGET_SAVING_DEFAULT_US, + APCTRL_POWER_BREAKEVEN_DEFAULT_US, + APCTRL_CYCLES_PER_SAMPLE_MAX_DEFAULT + }; + + /* Get each parameter value from input string*/ + sscanf(buf, "%d %d %d %d %d", ¶mlist[0], ¶mlist[1], + ¶mlist[2], ¶mlist[3], ¶mlist[4]); + + /* If parameter value is 0 then reset to SW default values*/ + if ((paramlist[0] | paramlist[1] | paramlist[2] + | paramlist[3] | paramlist[4]) == 0x00) { + memcpy(paramlist, defaultparam, sizeof(defaultparam)); + } + + /* If aelpg is enabled & pmu is ready then post values to + * PMU else store then post later + */ + if (g->aelpg_enabled && g->pmu.pmu_ready) { + /* Disable AELPG */ + ap_cmd.init.cmd_id = PMU_AP_CMD_ID_DISABLE_CTRL; + status = gk20a_pmu_ap_send_command(g, &ap_cmd, false); + + /* Enable AELPG */ + gk20a_aelpg_init(g); + gk20a_aelpg_init_and_enable(g, PMU_AP_CTRL_ID_GRAPHICS); + } + + return count; +} + +static ssize_t aelpg_param_read(struct device *device, + struct device_attribute *attr, char *buf) +{ + struct platform_device *ndev = to_platform_device(device); + struct gk20a *g = get_gk20a(ndev); + + return sprintf(buf, "%d %d %d %d %d\n", g->pmu.aelpg_param[0], + g->pmu.aelpg_param[1], g->pmu.aelpg_param[2], + g->pmu.aelpg_param[3], g->pmu.aelpg_param[4]); +} + +static DEVICE_ATTR(aelpg_param, S_IRWXUGO, + aelpg_param_read, aelpg_param_store); + #ifdef CONFIG_PM_RUNTIME static ssize_t force_idle_store(struct device *device, struct device_attribute *attr, const char *buf, size_t count) @@ -400,6 +457,7 @@ void gk20a_remove_sysfs(struct device *dev) #ifdef CONFIG_PM_RUNTIME device_remove_file(dev, &dev_attr_force_idle); #endif + device_remove_file(dev, &dev_attr_aelpg_param); if (g->host1x_dev && (dev->parent != &g->host1x_dev->dev)) sysfs_remove_link(&dev->kobj, dev_name(dev)); @@ -423,6 +481,7 @@ void gk20a_create_sysfs(struct platform_device *dev) #ifdef CONFIG_PM_RUNTIME error |= device_create_file(&dev->dev, &dev_attr_force_idle); #endif + error |= device_create_file(&dev->dev, &dev_attr_aelpg_param); if (g->host1x_dev && (dev->dev.parent != &g->host1x_dev->dev)) error |= sysfs_create_link(&g->host1x_dev->dev.kobj, diff --git a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c index 808bf015..a5b9f05f 100644 --- a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c @@ -43,8 +43,6 @@ static int gk20a_pmu_get_elpg_residency_gating(struct gk20a *g, static void ap_callback_init_and_enable_ctrl( struct gk20a *g, struct pmu_msg *msg, void *param, u32 seq_desc, u32 status); -static int gk20a_pmu_ap_send_command(struct gk20a *g, - union pmu_ap_cmd *p_ap_cmd, bool b_block); static u32 pmu_cmdline_size_v0(struct pmu_gk20a *pmu) { @@ -1803,9 +1801,6 @@ int gk20a_init_pmu_setup_hw1(struct gk20a *g) } -static int gk20a_aelpg_init(struct gk20a *g); -static int gk20a_aelpg_init_and_enable(struct gk20a *g, u8 ctrl_id); - static void pmu_setup_hw_load_zbc(struct gk20a *g); static void pmu_setup_hw_enable_elpg(struct gk20a *g); @@ -3441,7 +3436,7 @@ static int gk20a_pmu_get_elpg_residency_gating(struct gk20a *g, } /* Send an Adaptive Power (AP) related command to PMU */ -static int gk20a_pmu_ap_send_command(struct gk20a *g, +int gk20a_pmu_ap_send_command(struct gk20a *g, union pmu_ap_cmd *p_ap_cmd, bool b_block) { struct pmu_gk20a *pmu = &g->pmu; @@ -3545,7 +3540,7 @@ static void ap_callback_init_and_enable_ctrl( } } -static int gk20a_aelpg_init(struct gk20a *g) +int gk20a_aelpg_init(struct gk20a *g) { int status = 0; @@ -3554,30 +3549,28 @@ static int gk20a_aelpg_init(struct gk20a *g) /* TODO: Check for elpg being ready? */ ap_cmd.init.cmd_id = PMU_AP_CMD_ID_INIT; - ap_cmd.init.pg_sampling_period_us = - APCTRL_SAMPLING_PERIOD_PG_DEFAULT_US; + ap_cmd.init.pg_sampling_period_us = g->pmu.aelpg_param[0]; status = gk20a_pmu_ap_send_command(g, &ap_cmd, false); return status; } -static int gk20a_aelpg_init_and_enable(struct gk20a *g, u8 ctrl_id) +int gk20a_aelpg_init_and_enable(struct gk20a *g, u8 ctrl_id) { int status = 0; union pmu_ap_cmd ap_cmd; /* TODO: Probably check if ELPG is ready? */ - ap_cmd.init_and_enable_ctrl.cmd_id = PMU_AP_CMD_ID_INIT_AND_ENABLE_CTRL; ap_cmd.init_and_enable_ctrl.ctrl_id = ctrl_id; ap_cmd.init_and_enable_ctrl.params.min_idle_filter_us = - APCTRL_MINIMUM_IDLE_FILTER_DEFAULT_US; + g->pmu.aelpg_param[1]; ap_cmd.init_and_enable_ctrl.params.min_target_saving_us = - APCTRL_MINIMUM_TARGET_SAVING_DEFAULT_US; + g->pmu.aelpg_param[2]; ap_cmd.init_and_enable_ctrl.params.power_break_even_us = - APCTRL_POWER_BREAKEVEN_DEFAULT_US; + g->pmu.aelpg_param[3]; ap_cmd.init_and_enable_ctrl.params.cycles_per_sample_max = - APCTRL_CYCLES_PER_SAMPLE_MAX_DEFAULT; + g->pmu.aelpg_param[4]; switch (ctrl_id) { case PMU_AP_CTRL_ID_GRAPHICS: diff --git a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.h b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.h index 5c8a3215..fec0a572 100644 --- a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.h @@ -1066,6 +1066,7 @@ struct pmu_gk20a { bool perfmon_sampling_enabled; u8 pmu_mode; /*Added for GM20b, and ACR*/ u32 falcon_id; + u32 aelpg_param[5]; }; int gk20a_init_pmu_support(struct gk20a *g); @@ -1109,4 +1110,9 @@ void pmu_seq_init(struct pmu_gk20a *pmu); int gk20a_init_pmu(struct pmu_gk20a *pmu); +int gk20a_pmu_ap_send_command(struct gk20a *g, + union pmu_ap_cmd *p_ap_cmd, bool b_block); +int gk20a_aelpg_init(struct gk20a *g); +int gk20a_aelpg_init_and_enable(struct gk20a *g, u8 ctrl_id); + #endif /*__PMU_GK20A_H__*/ -- cgit v1.2.2