From 19baa2bf4560fb83c4be6a15fd3a7df9e464877a Mon Sep 17 00:00:00 2001 From: George Shen Date: Mon, 29 Aug 2016 11:34:41 -0700 Subject: [PATCH] msm: kgsl: restructure GPU power initialization Move target specific initialization and setup into target specific init functions. The change is required to port the GPU driver to support future generation GPUs. CRs-Fixed: 1053516 Change-Id: I808e247669fab61a6a64131858fe2f9e19754242 Signed-off-by: George Shen --- drivers/gpu/msm/adreno.c | 130 ++----------------------- drivers/gpu/msm/adreno.h | 24 +++++ drivers/gpu/msm/adreno_a5xx.c | 138 +++++++++++++++++++++++---- drivers/gpu/msm/adreno_perfcounter.c | 27 +----- 4 files changed, 160 insertions(+), 159 deletions(-) diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c index 1356835d0e93..956c858ba278 100644 --- a/drivers/gpu/msm/adreno.c +++ b/drivers/gpu/msm/adreno.c @@ -1242,86 +1242,6 @@ static bool regulators_left_on(struct kgsl_device *device) return false; } -static void _setup_throttling_counters(struct adreno_device *adreno_dev) -{ - int i, ret; - - if (!adreno_is_a540(adreno_dev)) - return; - - if (!ADRENO_FEATURE(adreno_dev, ADRENO_GPMU)) - return; - - for (i = 0; i < ADRENO_GPMU_THROTTLE_COUNTERS; i++) { - /* reset throttled cycles ivalue */ - adreno_dev->busy_data.throttle_cycles[i] = 0; - - if (adreno_dev->gpmu_throttle_counters[i] != 0) - continue; - ret = adreno_perfcounter_get(adreno_dev, - KGSL_PERFCOUNTER_GROUP_GPMU_PWR, - ADRENO_GPMU_THROTTLE_COUNTERS_BASE_REG + i, - &adreno_dev->gpmu_throttle_counters[i], - NULL, - PERFCOUNTER_FLAG_KERNEL); - WARN_ONCE(ret, "Unable to get clock throttling counter %x\n", - ADRENO_GPMU_THROTTLE_COUNTERS_BASE_REG + i); - } -} - -/* FW driven idle 10% throttle */ -#define IDLE_10PCT 0 -/* number of cycles when clock is throttled by 50% (CRC) */ -#define CRC_50PCT 1 -/* number of cycles when clock is throttled by more than 50% (CRC) */ -#define CRC_MORE50PCT 2 -/* number of cycles when clock is throttle by less than 50% (CRC) */ -#define CRC_LESS50PCT 3 - -static uint64_t _read_throttling_counters(struct adreno_device *adreno_dev) -{ - int i, adj; - uint32_t th[ADRENO_GPMU_THROTTLE_COUNTERS]; - struct adreno_busy_data *busy = &adreno_dev->busy_data; - - if (!adreno_is_a540(adreno_dev)) - return 0; - - if (!ADRENO_FEATURE(adreno_dev, ADRENO_GPMU)) - return 0; - - if (!test_bit(ADRENO_THROTTLING_CTRL, &adreno_dev->pwrctrl_flag)) - return 0; - - for (i = 0; i < ADRENO_GPMU_THROTTLE_COUNTERS; i++) { - if (!adreno_dev->gpmu_throttle_counters[i]) - return 0; - - th[i] = counter_delta(KGSL_DEVICE(adreno_dev), - adreno_dev->gpmu_throttle_counters[i], - &busy->throttle_cycles[i]); - } - adj = th[CRC_MORE50PCT] - th[IDLE_10PCT]; - adj = th[CRC_50PCT] + th[CRC_LESS50PCT] / 3 + (adj < 0 ? 0 : adj) * 3; - - trace_kgsl_clock_throttling( - th[IDLE_10PCT], th[CRC_50PCT], - th[CRC_MORE50PCT], th[CRC_LESS50PCT], - adj); - return adj; -} - -static void _update_threshold_count(struct adreno_device *adreno_dev, - uint64_t adj) -{ - if (adreno_is_a530(adreno_dev)) - kgsl_regread(KGSL_DEVICE(adreno_dev), - adreno_dev->lm_threshold_count, - &adreno_dev->lm_threshold_cross); - else if (adreno_is_a540(adreno_dev)) - adreno_dev->lm_threshold_cross = adj; -} - static void _set_secvid(struct kgsl_device *device) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); @@ -1418,8 +1338,8 @@ static int _adreno_start(struct adreno_device *adreno_dev) } } - if (device->pwrctrl.bus_control) { + if (device->pwrctrl.bus_control) { /* VBIF waiting for RAM */ if (adreno_dev->starved_ram_lo == 0) { ret = adreno_perfcounter_get(adreno_dev, @@ -1455,20 +1375,6 @@ static int _adreno_start(struct adreno_device *adreno_dev) adreno_dev->busy_data.vbif_ram_cycles = 0; adreno_dev->busy_data.vbif_starved_ram = 0; - if (adreno_is_a530(adreno_dev) && ADRENO_FEATURE(adreno_dev, ADRENO_LM) - && adreno_dev->lm_threshold_count == 0) { - - ret = adreno_perfcounter_get(adreno_dev, - KGSL_PERFCOUNTER_GROUP_GPMU_PWR, 27, - &adreno_dev->lm_threshold_count, NULL, - PERFCOUNTER_FLAG_KERNEL); - /* Ignore noncritical ret - used for debugfs */ - if (ret) - adreno_dev->lm_threshold_count = 0; - } - - _setup_throttling_counters(adreno_dev); - /* Restore performance counter registers with saved values */ adreno_perfcounter_restore(adreno_dev); @@ -2580,27 +2486,6 @@ static inline s64 adreno_ticks_to_us(u32 ticks, u32 freq) return ticks / freq; } -static unsigned int counter_delta(struct kgsl_device *device, - unsigned int reg, unsigned int *counter) -{ - unsigned int val; - unsigned int ret = 0; - - /* Read the value */ - kgsl_regread(device, reg, &val); - - /* Return 0 for the first read */ - if (*counter != 0) { - if (val < *counter) - ret = (0xFFFFFFFF - *counter) + val; - else - ret = val - *counter; - } - - *counter = val; - return ret; -} - /** * adreno_power_stats() - Reads the counters needed for freq decisions * @device: Pointer to device whose counters are read @@ -2612,6 +2497,7 @@ static void adreno_power_stats(struct kgsl_device *device, struct kgsl_power_stats *stats) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); + struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev); struct kgsl_pwrctrl *pwr = &device->pwrctrl; struct adreno_busy_data *busy = &adreno_dev->busy_data; uint64_t adj = 0; @@ -2625,8 +2511,11 @@ static void adreno_power_stats(struct kgsl_device *device, gpu_busy = counter_delta(device, adreno_dev->perfctr_pwr_lo, &busy->gpu_busy); - adj = _read_throttling_counters(adreno_dev); - gpu_busy += adj; + if (gpudev->read_throttling_counters) { + adj = gpudev->read_throttling_counters(adreno_dev); + gpu_busy += adj; + } + stats->busy_time = adreno_ticks_to_us(gpu_busy, kgsl_pwrctrl_active_freq(pwr)); } @@ -2647,8 +2536,9 @@ static void adreno_power_stats(struct kgsl_device *device, stats->ram_time = ram_cycles; stats->ram_wait = starved_ram; } - if (adreno_dev->lm_threshold_count) - _update_threshold_count(adreno_dev, adj); + if (adreno_dev->lm_threshold_count && + gpudev->count_throttles) + gpudev->count_throttles(adreno_dev, adj); } static unsigned int adreno_gpuid(struct kgsl_device *device, diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h index d4858f3f818e..176f23ad52a0 100644 --- a/drivers/gpu/msm/adreno.h +++ b/drivers/gpu/msm/adreno.h @@ -756,6 +756,10 @@ struct adreno_gpudev { void (*pwrlevel_change_settings)(struct adreno_device *, unsigned int prelevel, unsigned int postlevel, bool post); + uint64_t (*read_throttling_counters)(struct adreno_device *); + void (*count_throttles)(struct adreno_device *, uint64_t adj); + int (*enable_pwr_counters)(struct adreno_device *, + unsigned int counter); unsigned int (*preemption_pre_ibsubmit)(struct adreno_device *, struct adreno_ringbuffer *rb, unsigned int *, struct kgsl_context *); @@ -1467,4 +1471,24 @@ static inline void adreno_ringbuffer_set_pagetable(struct adreno_ringbuffer *rb, spin_unlock_irqrestore(&rb->preempt_lock, flags); } +static inline unsigned int counter_delta(struct kgsl_device *device, + unsigned int reg, unsigned int *counter) +{ + unsigned int val; + unsigned int ret = 0; + + /* Read the value */ + kgsl_regread(device, reg, &val); + + /* Return 0 for the first read */ + if (*counter != 0) { + if (val < *counter) + ret = (0xFFFFFFFF - *counter) + val; + else + ret = val - *counter; + } + + *counter = val; + return ret; +} #endif /*__ADRENO_H */ diff --git a/drivers/gpu/msm/adreno_a5xx.c b/drivers/gpu/msm/adreno_a5xx.c index d52981d10ff5..d745f679287a 100644 --- a/drivers/gpu/msm/adreno_a5xx.c +++ b/drivers/gpu/msm/adreno_a5xx.c @@ -27,6 +27,7 @@ #include "kgsl_sharedmem.h" #include "kgsl_log.h" #include "kgsl.h" +#include "kgsl_trace.h" #include "adreno_a5xx_packets.h" static int zap_ucode_loaded; @@ -1646,6 +1647,76 @@ static void a5xx_clk_set_options(struct adreno_device *adreno_dev, } } +static void a5xx_count_throttles(struct adreno_device *adreno_dev, + uint64_t adj) +{ + if (adreno_is_a530(adreno_dev)) + kgsl_regread(KGSL_DEVICE(adreno_dev), + adreno_dev->lm_threshold_count, + &adreno_dev->lm_threshold_cross); + else if (adreno_is_a540(adreno_dev)) + adreno_dev->lm_threshold_cross = adj; +} + +static int a5xx_enable_pwr_counters(struct adreno_device *adreno_dev, + unsigned int counter) +{ + /* + * On 5XX we have to emulate the PWR counters which are physically + * missing. Program countable 6 on RBBM_PERFCTR_RBBM_0 as a substitute + * for PWR:1. Don't emulate PWR:0 as nobody uses it and we don't want + * to take away too many of the generic RBBM counters. + */ + + if (counter == 0) + return -EINVAL; + + kgsl_regwrite(KGSL_DEVICE(adreno_dev), A5XX_RBBM_PERFCTR_RBBM_SEL_0, 6); + + return 0; +} + +/* FW driven idle 10% throttle */ +#define IDLE_10PCT 0 +/* number of cycles when clock is throttled by 50% (CRC) */ +#define CRC_50PCT 1 +/* number of cycles when clock is throttled by more than 50% (CRC) */ +#define CRC_MORE50PCT 2 +/* number of cycles when clock is throttle by less than 50% (CRC) */ +#define CRC_LESS50PCT 3 + +static uint64_t a5xx_read_throttling_counters(struct adreno_device *adreno_dev) +{ + int i, adj; + uint32_t th[ADRENO_GPMU_THROTTLE_COUNTERS]; + struct adreno_busy_data *busy = &adreno_dev->busy_data; + + if (!adreno_is_a540(adreno_dev)) + return 0; + + if (!ADRENO_FEATURE(adreno_dev, ADRENO_GPMU)) + return 0; + + if (!test_bit(ADRENO_THROTTLING_CTRL, &adreno_dev->pwrctrl_flag)) + return 0; + + for (i = 0; i < ADRENO_GPMU_THROTTLE_COUNTERS; i++) { + if (!adreno_dev->gpmu_throttle_counters[i]) + return 0; + + th[i] = counter_delta(KGSL_DEVICE(adreno_dev), + adreno_dev->gpmu_throttle_counters[i], + &busy->throttle_cycles[i]); + } + adj = th[CRC_MORE50PCT] - th[IDLE_10PCT]; + adj = th[CRC_50PCT] + th[CRC_LESS50PCT] / 3 + (adj < 0 ? 0 : adj) * 3; + + trace_kgsl_clock_throttling( + th[IDLE_10PCT], th[CRC_50PCT], + th[CRC_MORE50PCT], th[CRC_LESS50PCT], + adj); + return adj; +} static void a5xx_enable_64bit(struct adreno_device *adreno_dev) { @@ -1712,12 +1783,44 @@ static void a5xx_gpmu_reset(struct work_struct *work) /* Soft reset of the GPMU block */ kgsl_regwrite(device, A5XX_RBBM_BLOCK_SW_RESET_CMD, BIT(16)); + /* GPU comes up in secured mode, make it unsecured by default */ + if (!ADRENO_FEATURE(adreno_dev, ADRENO_CONTENT_PROTECTION)) + kgsl_regwrite(device, A5XX_RBBM_SECVID_TRUST_CNTL, 0x0); + + a5xx_gpmu_init(adreno_dev); out: mutex_unlock(&device->mutex); } +static void _setup_throttling_counters(struct adreno_device *adreno_dev) +{ + int i, ret; + + if (!adreno_is_a540(adreno_dev)) + return; + + if (!ADRENO_FEATURE(adreno_dev, ADRENO_GPMU)) + return; + + for (i = 0; i < ADRENO_GPMU_THROTTLE_COUNTERS; i++) { + /* reset throttled cycles ivalue */ + adreno_dev->busy_data.throttle_cycles[i] = 0; + + if (adreno_dev->gpmu_throttle_counters[i] != 0) + continue; + ret = adreno_perfcounter_get(adreno_dev, + KGSL_PERFCOUNTER_GROUP_GPMU_PWR, + ADRENO_GPMU_THROTTLE_COUNTERS_BASE_REG + i, + &adreno_dev->gpmu_throttle_counters[i], + NULL, + PERFCOUNTER_FLAG_KERNEL); + WARN_ONCE(ret, "Unable to get clock throttling counter %x\n", + ADRENO_GPMU_THROTTLE_COUNTERS_BASE_REG + i); + } +} + /* * a5xx_start() - Device start * @adreno_dev: Pointer to adreno device @@ -1729,6 +1832,21 @@ static void a5xx_start(struct adreno_device *adreno_dev) struct kgsl_device *device = KGSL_DEVICE(adreno_dev); struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev); unsigned int bit; + int ret; + + if (adreno_is_a530(adreno_dev) && ADRENO_FEATURE(adreno_dev, ADRENO_LM) + && adreno_dev->lm_threshold_count == 0) { + + ret = adreno_perfcounter_get(adreno_dev, + KGSL_PERFCOUNTER_GROUP_GPMU_PWR, 27, + &adreno_dev->lm_threshold_count, NULL, + PERFCOUNTER_FLAG_KERNEL); + /* Ignore noncritical ret - used for debugfs */ + if (ret) + adreno_dev->lm_threshold_count = 0; + } + + _setup_throttling_counters(adreno_dev); adreno_vbif_start(adreno_dev, a5xx_vbif_platforms, ARRAY_SIZE(a5xx_vbif_platforms)); @@ -2034,11 +2152,6 @@ static int a5xx_post_start(struct adreno_device *adreno_dev) static int a5xx_gpmu_init(struct adreno_device *adreno_dev) { int ret; - struct kgsl_device *device = KGSL_DEVICE(adreno_dev); - - /* GPU comes up in secured mode, make it unsecured by default */ - if (!ADRENO_FEATURE(adreno_dev, ADRENO_CONTENT_PROTECTION)) - kgsl_regwrite(device, A5XX_RBBM_SECVID_TRUST_CNTL, 0x0); /* Set up LM before initializing the GPMU */ a5xx_lm_init(adreno_dev); @@ -2359,20 +2472,10 @@ static int a5xx_rb_start(struct adreno_device *adreno_dev, if (ret) return ret; - /* Set up LM before initializing the GPMU */ - a5xx_lm_init(adreno_dev); - - /* Enable SPTP based power collapse before enabling GPMU */ - a5xx_enable_pc(adreno_dev); - - /* Program the GPMU */ - ret = a5xx_gpmu_start(adreno_dev); + ret = a5xx_gpmu_init(adreno_dev); if (ret) return ret; - /* Enable limits management */ - a5xx_lm_enable(adreno_dev); - a5xx_post_start(adreno_dev); return 0; @@ -3534,6 +3637,9 @@ struct adreno_gpudev adreno_a5xx_gpudev = { .regulator_enable = a5xx_regulator_enable, .regulator_disable = a5xx_regulator_disable, .pwrlevel_change_settings = a5xx_pwrlevel_change_settings, + .read_throttling_counters = a5xx_read_throttling_counters, + .count_throttles = a5xx_count_throttles, + .enable_pwr_counters = a5xx_enable_pwr_counters, .preemption_pre_ibsubmit = a5xx_preemption_pre_ibsubmit, .preemption_yield_enable = a5xx_preemption_yield_enable, diff --git a/drivers/gpu/msm/adreno_perfcounter.c b/drivers/gpu/msm/adreno_perfcounter.c index 8e354d71a291..42f8119ad8b4 100644 --- a/drivers/gpu/msm/adreno_perfcounter.c +++ b/drivers/gpu/msm/adreno_perfcounter.c @@ -598,28 +598,6 @@ int adreno_perfcounter_put(struct adreno_device *adreno_dev, return -EINVAL; } -static int _perfcounter_enable_pwr(struct adreno_device *adreno_dev, - unsigned int counter) -{ - /* PWR counters enabled by default on A3XX/A4XX so nothing to do */ - if (adreno_is_a3xx(adreno_dev) || adreno_is_a4xx(adreno_dev)) - return 0; - - /* - * On 5XX we have to emulate the PWR counters which are physically - * missing. Program countable 6 on RBBM_PERFCTR_RBBM_0 as a substitute - * for PWR:1. Don't emulate PWR:0 as nobody uses it and we don't want - * to take away too many of the generic RBBM counters. - */ - - if (counter == 0) - return -EINVAL; - - kgsl_regwrite(KGSL_DEVICE(adreno_dev), A5XX_RBBM_PERFCTR_RBBM_SEL_0, 6); - - return 0; -} - static void _perfcounter_enable_vbif(struct adreno_device *adreno_dev, struct adreno_perfcounters *counters, unsigned int counter, unsigned int countable) @@ -771,6 +749,7 @@ static int adreno_perfcounter_enable(struct adreno_device *adreno_dev, unsigned int group, unsigned int counter, unsigned int countable) { struct adreno_perfcounters *counters = ADRENO_PERFCOUNTERS(adreno_dev); + struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev); if (counters == NULL) return -EINVAL; @@ -786,7 +765,9 @@ static int adreno_perfcounter_enable(struct adreno_device *adreno_dev, /* alwayson counter is global, so init value is 0 */ break; case KGSL_PERFCOUNTER_GROUP_PWR: - return _perfcounter_enable_pwr(adreno_dev, counter); + if (gpudev->enable_pwr_counters) + return gpudev->enable_pwr_counters(adreno_dev, counter); + return 0; case KGSL_PERFCOUNTER_GROUP_VBIF: if (countable > VBIF2_PERF_CNT_SEL_MASK) return -EINVAL;