diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gk20a.c | 7 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gk20a_sysfs.c | 59 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/pmu_gk20a.c | 23 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/pmu_gk20a.h | 6 |
4 files changed, 80 insertions, 15 deletions
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) | |||
1539 | gk20a->aelpg_enabled = | 1539 | gk20a->aelpg_enabled = |
1540 | tegra_platform_is_silicon() ? platform->enable_aelpg : false; | 1540 | tegra_platform_is_silicon() ? platform->enable_aelpg : false; |
1541 | 1541 | ||
1542 | /* set default values to aelpg parameters */ | ||
1543 | gk20a->pmu.aelpg_param[0] = APCTRL_SAMPLING_PERIOD_PG_DEFAULT_US; | ||
1544 | gk20a->pmu.aelpg_param[1] = APCTRL_MINIMUM_IDLE_FILTER_DEFAULT_US; | ||
1545 | gk20a->pmu.aelpg_param[2] = APCTRL_MINIMUM_TARGET_SAVING_DEFAULT_US; | ||
1546 | gk20a->pmu.aelpg_param[3] = APCTRL_POWER_BREAKEVEN_DEFAULT_US; | ||
1547 | gk20a->pmu.aelpg_param[4] = APCTRL_CYCLES_PER_SAMPLE_MAX_DEFAULT; | ||
1548 | |||
1542 | gk20a_create_sysfs(dev); | 1549 | gk20a_create_sysfs(dev); |
1543 | 1550 | ||
1544 | #ifdef CONFIG_DEBUG_FS | 1551 | #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 @@ | |||
29 | #include "gk20a.h" | 29 | #include "gk20a.h" |
30 | #include "gr_gk20a.h" | 30 | #include "gr_gk20a.h" |
31 | #include "fifo_gk20a.h" | 31 | #include "fifo_gk20a.h" |
32 | #include "pmu_gk20a.h" | ||
32 | 33 | ||
33 | 34 | ||
34 | #define PTIMER_FP_FACTOR 1000000 | 35 | #define PTIMER_FP_FACTOR 1000000 |
@@ -332,6 +333,62 @@ static ssize_t elpg_enable_read(struct device *device, | |||
332 | 333 | ||
333 | static DEVICE_ATTR(elpg_enable, ROOTRW, elpg_enable_read, elpg_enable_store); | 334 | static DEVICE_ATTR(elpg_enable, ROOTRW, elpg_enable_read, elpg_enable_store); |
334 | 335 | ||
336 | static ssize_t aelpg_param_store(struct device *device, | ||
337 | struct device_attribute *attr, const char *buf, size_t count) | ||
338 | { | ||
339 | struct platform_device *ndev = to_platform_device(device); | ||
340 | struct gk20a *g = get_gk20a(ndev); | ||
341 | int status = 0; | ||
342 | union pmu_ap_cmd ap_cmd; | ||
343 | int *paramlist = (int *)g->pmu.aelpg_param; | ||
344 | u32 defaultparam[5] = { | ||
345 | APCTRL_SAMPLING_PERIOD_PG_DEFAULT_US, | ||
346 | APCTRL_MINIMUM_IDLE_FILTER_DEFAULT_US, | ||
347 | APCTRL_MINIMUM_TARGET_SAVING_DEFAULT_US, | ||
348 | APCTRL_POWER_BREAKEVEN_DEFAULT_US, | ||
349 | APCTRL_CYCLES_PER_SAMPLE_MAX_DEFAULT | ||
350 | }; | ||
351 | |||
352 | /* Get each parameter value from input string*/ | ||
353 | sscanf(buf, "%d %d %d %d %d", ¶mlist[0], ¶mlist[1], | ||
354 | ¶mlist[2], ¶mlist[3], ¶mlist[4]); | ||
355 | |||
356 | /* If parameter value is 0 then reset to SW default values*/ | ||
357 | if ((paramlist[0] | paramlist[1] | paramlist[2] | ||
358 | | paramlist[3] | paramlist[4]) == 0x00) { | ||
359 | memcpy(paramlist, defaultparam, sizeof(defaultparam)); | ||
360 | } | ||
361 | |||
362 | /* If aelpg is enabled & pmu is ready then post values to | ||
363 | * PMU else store then post later | ||
364 | */ | ||
365 | if (g->aelpg_enabled && g->pmu.pmu_ready) { | ||
366 | /* Disable AELPG */ | ||
367 | ap_cmd.init.cmd_id = PMU_AP_CMD_ID_DISABLE_CTRL; | ||
368 | status = gk20a_pmu_ap_send_command(g, &ap_cmd, false); | ||
369 | |||
370 | /* Enable AELPG */ | ||
371 | gk20a_aelpg_init(g); | ||
372 | gk20a_aelpg_init_and_enable(g, PMU_AP_CTRL_ID_GRAPHICS); | ||
373 | } | ||
374 | |||
375 | return count; | ||
376 | } | ||
377 | |||
378 | static ssize_t aelpg_param_read(struct device *device, | ||
379 | struct device_attribute *attr, char *buf) | ||
380 | { | ||
381 | struct platform_device *ndev = to_platform_device(device); | ||
382 | struct gk20a *g = get_gk20a(ndev); | ||
383 | |||
384 | return sprintf(buf, "%d %d %d %d %d\n", g->pmu.aelpg_param[0], | ||
385 | g->pmu.aelpg_param[1], g->pmu.aelpg_param[2], | ||
386 | g->pmu.aelpg_param[3], g->pmu.aelpg_param[4]); | ||
387 | } | ||
388 | |||
389 | static DEVICE_ATTR(aelpg_param, S_IRWXUGO, | ||
390 | aelpg_param_read, aelpg_param_store); | ||
391 | |||
335 | #ifdef CONFIG_PM_RUNTIME | 392 | #ifdef CONFIG_PM_RUNTIME |
336 | static ssize_t force_idle_store(struct device *device, | 393 | static ssize_t force_idle_store(struct device *device, |
337 | struct device_attribute *attr, const char *buf, size_t count) | 394 | struct device_attribute *attr, const char *buf, size_t count) |
@@ -400,6 +457,7 @@ void gk20a_remove_sysfs(struct device *dev) | |||
400 | #ifdef CONFIG_PM_RUNTIME | 457 | #ifdef CONFIG_PM_RUNTIME |
401 | device_remove_file(dev, &dev_attr_force_idle); | 458 | device_remove_file(dev, &dev_attr_force_idle); |
402 | #endif | 459 | #endif |
460 | device_remove_file(dev, &dev_attr_aelpg_param); | ||
403 | 461 | ||
404 | if (g->host1x_dev && (dev->parent != &g->host1x_dev->dev)) | 462 | if (g->host1x_dev && (dev->parent != &g->host1x_dev->dev)) |
405 | sysfs_remove_link(&dev->kobj, dev_name(dev)); | 463 | sysfs_remove_link(&dev->kobj, dev_name(dev)); |
@@ -423,6 +481,7 @@ void gk20a_create_sysfs(struct platform_device *dev) | |||
423 | #ifdef CONFIG_PM_RUNTIME | 481 | #ifdef CONFIG_PM_RUNTIME |
424 | error |= device_create_file(&dev->dev, &dev_attr_force_idle); | 482 | error |= device_create_file(&dev->dev, &dev_attr_force_idle); |
425 | #endif | 483 | #endif |
484 | error |= device_create_file(&dev->dev, &dev_attr_aelpg_param); | ||
426 | 485 | ||
427 | if (g->host1x_dev && (dev->dev.parent != &g->host1x_dev->dev)) | 486 | if (g->host1x_dev && (dev->dev.parent != &g->host1x_dev->dev)) |
428 | error |= sysfs_create_link(&g->host1x_dev->dev.kobj, | 487 | 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, | |||
43 | static void ap_callback_init_and_enable_ctrl( | 43 | static void ap_callback_init_and_enable_ctrl( |
44 | struct gk20a *g, struct pmu_msg *msg, | 44 | struct gk20a *g, struct pmu_msg *msg, |
45 | void *param, u32 seq_desc, u32 status); | 45 | void *param, u32 seq_desc, u32 status); |
46 | static int gk20a_pmu_ap_send_command(struct gk20a *g, | ||
47 | union pmu_ap_cmd *p_ap_cmd, bool b_block); | ||
48 | 46 | ||
49 | static u32 pmu_cmdline_size_v0(struct pmu_gk20a *pmu) | 47 | static u32 pmu_cmdline_size_v0(struct pmu_gk20a *pmu) |
50 | { | 48 | { |
@@ -1803,9 +1801,6 @@ int gk20a_init_pmu_setup_hw1(struct gk20a *g) | |||
1803 | 1801 | ||
1804 | } | 1802 | } |
1805 | 1803 | ||
1806 | static int gk20a_aelpg_init(struct gk20a *g); | ||
1807 | static int gk20a_aelpg_init_and_enable(struct gk20a *g, u8 ctrl_id); | ||
1808 | |||
1809 | static void pmu_setup_hw_load_zbc(struct gk20a *g); | 1804 | static void pmu_setup_hw_load_zbc(struct gk20a *g); |
1810 | static void pmu_setup_hw_enable_elpg(struct gk20a *g); | 1805 | static void pmu_setup_hw_enable_elpg(struct gk20a *g); |
1811 | 1806 | ||
@@ -3441,7 +3436,7 @@ static int gk20a_pmu_get_elpg_residency_gating(struct gk20a *g, | |||
3441 | } | 3436 | } |
3442 | 3437 | ||
3443 | /* Send an Adaptive Power (AP) related command to PMU */ | 3438 | /* Send an Adaptive Power (AP) related command to PMU */ |
3444 | static int gk20a_pmu_ap_send_command(struct gk20a *g, | 3439 | int gk20a_pmu_ap_send_command(struct gk20a *g, |
3445 | union pmu_ap_cmd *p_ap_cmd, bool b_block) | 3440 | union pmu_ap_cmd *p_ap_cmd, bool b_block) |
3446 | { | 3441 | { |
3447 | struct pmu_gk20a *pmu = &g->pmu; | 3442 | struct pmu_gk20a *pmu = &g->pmu; |
@@ -3545,7 +3540,7 @@ static void ap_callback_init_and_enable_ctrl( | |||
3545 | } | 3540 | } |
3546 | } | 3541 | } |
3547 | 3542 | ||
3548 | static int gk20a_aelpg_init(struct gk20a *g) | 3543 | int gk20a_aelpg_init(struct gk20a *g) |
3549 | { | 3544 | { |
3550 | int status = 0; | 3545 | int status = 0; |
3551 | 3546 | ||
@@ -3554,30 +3549,28 @@ static int gk20a_aelpg_init(struct gk20a *g) | |||
3554 | 3549 | ||
3555 | /* TODO: Check for elpg being ready? */ | 3550 | /* TODO: Check for elpg being ready? */ |
3556 | ap_cmd.init.cmd_id = PMU_AP_CMD_ID_INIT; | 3551 | ap_cmd.init.cmd_id = PMU_AP_CMD_ID_INIT; |
3557 | ap_cmd.init.pg_sampling_period_us = | 3552 | ap_cmd.init.pg_sampling_period_us = g->pmu.aelpg_param[0]; |
3558 | APCTRL_SAMPLING_PERIOD_PG_DEFAULT_US; | ||
3559 | 3553 | ||
3560 | status = gk20a_pmu_ap_send_command(g, &ap_cmd, false); | 3554 | status = gk20a_pmu_ap_send_command(g, &ap_cmd, false); |
3561 | return status; | 3555 | return status; |
3562 | } | 3556 | } |
3563 | 3557 | ||
3564 | static int gk20a_aelpg_init_and_enable(struct gk20a *g, u8 ctrl_id) | 3558 | int gk20a_aelpg_init_and_enable(struct gk20a *g, u8 ctrl_id) |
3565 | { | 3559 | { |
3566 | int status = 0; | 3560 | int status = 0; |
3567 | union pmu_ap_cmd ap_cmd; | 3561 | union pmu_ap_cmd ap_cmd; |
3568 | 3562 | ||
3569 | /* TODO: Probably check if ELPG is ready? */ | 3563 | /* TODO: Probably check if ELPG is ready? */ |
3570 | |||
3571 | ap_cmd.init_and_enable_ctrl.cmd_id = PMU_AP_CMD_ID_INIT_AND_ENABLE_CTRL; | 3564 | ap_cmd.init_and_enable_ctrl.cmd_id = PMU_AP_CMD_ID_INIT_AND_ENABLE_CTRL; |
3572 | ap_cmd.init_and_enable_ctrl.ctrl_id = ctrl_id; | 3565 | ap_cmd.init_and_enable_ctrl.ctrl_id = ctrl_id; |
3573 | ap_cmd.init_and_enable_ctrl.params.min_idle_filter_us = | 3566 | ap_cmd.init_and_enable_ctrl.params.min_idle_filter_us = |
3574 | APCTRL_MINIMUM_IDLE_FILTER_DEFAULT_US; | 3567 | g->pmu.aelpg_param[1]; |
3575 | ap_cmd.init_and_enable_ctrl.params.min_target_saving_us = | 3568 | ap_cmd.init_and_enable_ctrl.params.min_target_saving_us = |
3576 | APCTRL_MINIMUM_TARGET_SAVING_DEFAULT_US; | 3569 | g->pmu.aelpg_param[2]; |
3577 | ap_cmd.init_and_enable_ctrl.params.power_break_even_us = | 3570 | ap_cmd.init_and_enable_ctrl.params.power_break_even_us = |
3578 | APCTRL_POWER_BREAKEVEN_DEFAULT_US; | 3571 | g->pmu.aelpg_param[3]; |
3579 | ap_cmd.init_and_enable_ctrl.params.cycles_per_sample_max = | 3572 | ap_cmd.init_and_enable_ctrl.params.cycles_per_sample_max = |
3580 | APCTRL_CYCLES_PER_SAMPLE_MAX_DEFAULT; | 3573 | g->pmu.aelpg_param[4]; |
3581 | 3574 | ||
3582 | switch (ctrl_id) { | 3575 | switch (ctrl_id) { |
3583 | case PMU_AP_CTRL_ID_GRAPHICS: | 3576 | 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 { | |||
1066 | bool perfmon_sampling_enabled; | 1066 | bool perfmon_sampling_enabled; |
1067 | u8 pmu_mode; /*Added for GM20b, and ACR*/ | 1067 | u8 pmu_mode; /*Added for GM20b, and ACR*/ |
1068 | u32 falcon_id; | 1068 | u32 falcon_id; |
1069 | u32 aelpg_param[5]; | ||
1069 | }; | 1070 | }; |
1070 | 1071 | ||
1071 | int gk20a_init_pmu_support(struct gk20a *g); | 1072 | int gk20a_init_pmu_support(struct gk20a *g); |
@@ -1109,4 +1110,9 @@ void pmu_seq_init(struct pmu_gk20a *pmu); | |||
1109 | 1110 | ||
1110 | int gk20a_init_pmu(struct pmu_gk20a *pmu); | 1111 | int gk20a_init_pmu(struct pmu_gk20a *pmu); |
1111 | 1112 | ||
1113 | int gk20a_pmu_ap_send_command(struct gk20a *g, | ||
1114 | union pmu_ap_cmd *p_ap_cmd, bool b_block); | ||
1115 | int gk20a_aelpg_init(struct gk20a *g); | ||
1116 | int gk20a_aelpg_init_and_enable(struct gk20a *g, u8 ctrl_id); | ||
1117 | |||
1112 | #endif /*__PMU_GK20A_H__*/ | 1118 | #endif /*__PMU_GK20A_H__*/ |