diff --git a/drivers/gpu/msm/Kconfig b/drivers/gpu/msm/Kconfig index 923ba9a5a8af..aec807e3e2a7 100644 --- a/drivers/gpu/msm/Kconfig +++ b/drivers/gpu/msm/Kconfig @@ -13,3 +13,11 @@ config QCOM_ADRENO_DEFAULT_GOVERNOR string "devfreq governor for the adreno core" default "simple_ondemand" depends on QCOM_KGSL + +config QCOM_KGSL_CORESIGHT + bool "Enable coresight support for the Adreno GPU" + depends on QCOM_KGSL && CORESIGHT + help + When enabled, the Adreno GPU is available as a source for Coresight + data. On a6xx targets there are two sources available for the GX and + CX domains respectively. Debug kernels should say 'Y' here. diff --git a/drivers/gpu/msm/Makefile b/drivers/gpu/msm/Makefile index dcbea390d782..5cccee583291 100644 --- a/drivers/gpu/msm/Makefile +++ b/drivers/gpu/msm/Makefile @@ -37,7 +37,6 @@ msm_kgsl-y += \ adreno_a6xx_preempt.o \ adreno_a6xx_rgmu.o \ adreno_a6xx_snapshot.o \ - adreno_coresight.o \ adreno_cp_parser.o \ adreno_dispatch.o \ adreno_drawctxt.o \ @@ -49,5 +48,6 @@ msm_kgsl-y += \ adreno_trace.o msm_kgsl-$(CONFIG_COMPAT) += adreno_compat.o +msm_kgsl-$(CONFIG_QCOM_KGSL_CORESIGHT) += adreno_coresight.o msm_kgsl-$(CONFIG_DEBUG_FS) += adreno_debugfs.o adreno_profile.o msm_kgsl-$(CONFIG_ARM_SMMU) += adreno_iommu.o diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h index 32794d03da9b..86c00ff08e09 100644 --- a/drivers/gpu/msm/adreno.h +++ b/drivers/gpu/msm/adreno.h @@ -5,6 +5,7 @@ #ifndef __ADRENO_H #define __ADRENO_H +#include "adreno_coresight.h" #include "adreno_dispatch.h" #include "adreno_drawctxt.h" #include "adreno_perfcounter.h" @@ -364,12 +365,6 @@ struct adreno_gpu_core { u32 bus_width; }; -enum gpu_coresight_sources { - GPU_CORESIGHT_GX = 0, - GPU_CORESIGHT_CX = 1, - GPU_CORESIGHT_MAX, -}; - /** * struct adreno_device - The mothership structure for all adreno related info * @dev: Reference to struct kgsl_device @@ -520,7 +515,7 @@ struct adreno_device { unsigned int highest_bank_bit; unsigned int quirks; - struct coresight_device *csdev[GPU_CORESIGHT_MAX]; + struct coresight_device *csdev[2]; uint32_t gpmu_throttle_counters[ADRENO_GPMU_THROTTLE_COUNTERS]; struct work_struct irq_storm_work; @@ -733,53 +728,6 @@ struct adreno_vbif_snapshot_registers { const int count; }; -/** - * struct adreno_coresight_register - Definition for a coresight (tracebus) - * debug register - * @offset: Offset of the debug register in the KGSL mmio region - * @initial: Default value to write when coresight is enabled - * @value: Current shadow value of the register (to be reprogrammed after power - * collapse) - */ -struct adreno_coresight_register { - unsigned int offset; - unsigned int initial; - unsigned int value; -}; - -struct adreno_coresight_attr { - struct device_attribute attr; - struct adreno_coresight_register *reg; -}; - -ssize_t adreno_coresight_show_register(struct device *device, - struct device_attribute *attr, char *buf); - -ssize_t adreno_coresight_store_register(struct device *dev, - struct device_attribute *attr, const char *buf, size_t size); - -#define ADRENO_CORESIGHT_ATTR(_attrname, _reg) \ - struct adreno_coresight_attr coresight_attr_##_attrname = { \ - __ATTR(_attrname, 0644, \ - adreno_coresight_show_register, \ - adreno_coresight_store_register), \ - (_reg), } - -/** - * struct adreno_coresight - GPU specific coresight definition - * @registers - Array of GPU specific registers to configure trace bus output - * @count - Number of registers in the array - * @groups - Pointer to an attribute list of control files - * @atid - The unique ATID value of the coresight device - */ -struct adreno_coresight { - struct adreno_coresight_register *registers; - unsigned int count; - const struct attribute_group **groups; - unsigned int atid; -}; - - struct adreno_irq_funcs { void (*func)(struct adreno_device *adreno_dev, int mask); }; @@ -819,7 +767,7 @@ struct adreno_gpudev { struct adreno_perfcounters *perfcounters; - struct adreno_coresight *coresight[GPU_CORESIGHT_MAX]; + struct adreno_coresight *coresight[2]; struct adreno_irq *irq; int num_prio_levels; @@ -988,13 +936,6 @@ void adreno_fault_skipcmd_detached(struct adreno_device *adreno_dev, struct adreno_context *drawctxt, struct kgsl_drawobj *drawobj); -void adreno_coresight_init(struct adreno_device *adreno_dev); - -void adreno_coresight_start(struct adreno_device *adreno_dev); -void adreno_coresight_stop(struct adreno_device *adreno_dev); - -void adreno_coresight_remove(struct adreno_device *adreno_dev); - bool adreno_hw_isidle(struct adreno_device *adreno_dev); void adreno_fault_detect_start(struct adreno_device *adreno_dev); diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c index 824d85c639f4..7f39a897e3cd 100644 --- a/drivers/gpu/msm/adreno_a3xx.c +++ b/drivers/gpu/msm/adreno_a3xx.c @@ -1142,6 +1142,7 @@ static void a3xx_start(struct adreno_device *adreno_dev) } +#ifdef CONFIG_QCOM_KGSL_CORESIGHT static struct adreno_coresight_register a3xx_coresight_registers[] = { { A3XX_RBBM_DEBUG_BUS_CTL, 0x0001093F }, { A3XX_RBBM_EXT_TRACE_STOP_CNT, 0x00017fff }, @@ -1191,6 +1192,7 @@ static struct adreno_coresight a3xx_coresight = { .count = ARRAY_SIZE(a3xx_coresight_registers), .groups = a3xx_coresight_groups, }; +#endif static unsigned int a3xx_int_bits[ADRENO_INT_BITS_MAX] = { ADRENO_INT_DEFINE(ADRENO_INT_RBBM_AHB_ERROR, A3XX_INT_RBBM_AHB_ERROR), @@ -1445,6 +1447,8 @@ struct adreno_gpudev adreno_a3xx_gpudev = { .microcode_read = a3xx_microcode_read, .start = a3xx_start, .snapshot = a3xx_snapshot, +#ifdef CONFIG_QCOM_KGSL_CORESIGHT .coresight = {&a3xx_coresight}, +#endif .clk_set_options = a3xx_clk_set_options, }; diff --git a/drivers/gpu/msm/adreno_a5xx.c b/drivers/gpu/msm/adreno_a5xx.c index c3a5faa7c739..7ea4a4ea562a 100644 --- a/drivers/gpu/msm/adreno_a5xx.c +++ b/drivers/gpu/msm/adreno_a5xx.c @@ -2857,6 +2857,7 @@ static struct adreno_irq a5xx_irq = { .mask = A5XX_INT_MASK, }; +#ifdef CONFIG_QCOM_KGSL_CORESIGHT static struct adreno_coresight_register a5xx_coresight_registers[] = { { A5XX_RBBM_CFG_DBGBUS_SEL_A }, { A5XX_RBBM_CFG_DBGBUS_SEL_B }, @@ -3049,13 +3050,16 @@ static struct adreno_coresight a5xx_coresight = { .count = ARRAY_SIZE(a5xx_coresight_registers), .groups = a5xx_coresight_groups, }; +#endif struct adreno_gpudev adreno_a5xx_gpudev = { .reg_offsets = a5xx_register_offsets, .int_bits = a5xx_int_bits, .ft_perf_counters = a5xx_ft_perf_counters, .ft_perf_counters_count = ARRAY_SIZE(a5xx_ft_perf_counters), +#ifdef CONFIG_QCOM_KGSL_CORESIGHT .coresight = {&a5xx_coresight}, +#endif .start = a5xx_start, .snapshot = a5xx_snapshot, .irq = &a5xx_irq, diff --git a/drivers/gpu/msm/adreno_a6xx.c b/drivers/gpu/msm/adreno_a6xx.c index 8b42c118d1ab..633a0412e342 100644 --- a/drivers/gpu/msm/adreno_a6xx.c +++ b/drivers/gpu/msm/adreno_a6xx.c @@ -1428,6 +1428,7 @@ static struct adreno_irq a6xx_irq = { .mask = A6XX_INT_MASK, }; +#ifdef CONFIG_QCOM_KGSL_CORESIGHT static struct adreno_coresight_register a6xx_coresight_regs[] = { { A6XX_DBGC_CFG_DBGBUS_SEL_A }, { A6XX_DBGC_CFG_DBGBUS_SEL_B }, @@ -1841,6 +1842,7 @@ static struct adreno_coresight a6xx_coresight_cx = { .count = ARRAY_SIZE(a6xx_coresight_regs_cx), .groups = a6xx_coresight_groups_cx, }; +#endif static struct adreno_perfcount_register a6xx_perfcounters_cp[] = { { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A6XX_RBBM_PERFCTR_CP_0_LO, @@ -2614,6 +2616,8 @@ struct adreno_gpudev adreno_a6xx_gpudev = { .sptprac_is_on = a6xx_sptprac_is_on, .ccu_invalidate = a6xx_ccu_invalidate, .perfcounter_update = a6xx_perfcounter_update, +#ifdef CONFIG_QCOM_KGSL_CORESIGHT .coresight = {&a6xx_coresight, &a6xx_coresight_cx}, +#endif .clk_set_options = a6xx_clk_set_options, }; diff --git a/drivers/gpu/msm/adreno_coresight.c b/drivers/gpu/msm/adreno_coresight.c index a049f095b153..67b35b4660cf 100644 --- a/drivers/gpu/msm/adreno_coresight.c +++ b/drivers/gpu/msm/adreno_coresight.c @@ -9,6 +9,11 @@ #include "adreno.h" +enum gpu_coresight_sources { + GPU_CORESIGHT_GX = 0, + GPU_CORESIGHT_CX = 1, +}; + #define TO_ADRENO_CORESIGHT_ATTR(_attr) \ container_of(_attr, struct adreno_coresight_attr, attr) @@ -129,18 +134,10 @@ out: return size; } -/** - * adreno_coresight_disable() - Generic function to disable coresight debugging - * @csdev: Pointer to coresight's device struct - * - * This is a generic function to disable coresight debug bus on adreno - * devices. This should be used in all cases of disabling - * coresight debug bus for adreno devices. This function in turn calls - * the adreno device specific function through the gpudev hook. - * This function is registered as the coresight disable function - * with coresight driver. It should only be called through coresight driver - * as that would ensure that the necessary setup required to be done on - * coresight driver's part is also done. +/* + * This is a generic function to disable coresight debug bus on Adreno + * devices. This function in turn calls the device specific function + * through the gpudev hook. */ static void adreno_coresight_disable(struct coresight_device *csdev, struct perf_event *event) @@ -190,12 +187,6 @@ static void adreno_coresight_disable(struct coresight_device *csdev, mutex_unlock(&device->mutex); } -/** - * _adreno_coresight_get_and_clear(): Save the current value of coresight - * registers and clear the registers subsequently. Clearing registers - * has the effect of disabling coresight. - * @adreno_dev: Pointer to adreno device struct - */ static int _adreno_coresight_get_and_clear(struct adreno_device *adreno_dev, int cs_id) { @@ -254,17 +245,7 @@ static int _adreno_coresight_set(struct adreno_device *adreno_dev, int cs_id) } return 0; } -/** - * adreno_coresight_enable() - Generic function to enable coresight debugging - * @csdev: Pointer to coresight's device struct - * - * This is a generic function to enable coresight debug bus on adreno - * devices. This should be used in all cases of enabling - * coresight debug bus for adreno devices. This function is registered as the - * coresight enable function with coresight driver. It should only be called - * through coresight driver as that would ensure that the necessary setup - * required to be done on coresight driver's part is also done. - */ +/* Generic function to enable coresight debug bus on adreno devices */ static int adreno_coresight_enable(struct coresight_device *csdev, struct perf_event *event, u32 mode) { @@ -321,51 +302,22 @@ static int adreno_coresight_enable(struct coresight_device *csdev, return ret; } -/** - * adreno_coresight_stop() - Reprogram coresight registers after power collapse - * @adreno_dev: Pointer to the adreno device structure - * - * Cache the current coresight register values so they can be restored after - * power collapse - */ void adreno_coresight_stop(struct adreno_device *adreno_dev) { - int i, adreno_dev_flag = -EINVAL; + if (test_bit(ADRENO_DEVICE_CORESIGHT, &adreno_dev->priv)) + _adreno_coresight_get_and_clear(adreno_dev, GPU_CORESIGHT_GX); - for (i = 0; i < GPU_CORESIGHT_MAX; ++i) { - if (i == GPU_CORESIGHT_GX) - adreno_dev_flag = ADRENO_DEVICE_CORESIGHT; - else if (i == GPU_CORESIGHT_CX) - adreno_dev_flag = ADRENO_DEVICE_CORESIGHT_CX; - else - return; - - if (test_bit(adreno_dev_flag, &adreno_dev->priv)) - _adreno_coresight_get_and_clear(adreno_dev, i); - } + if (test_bit(ADRENO_DEVICE_CORESIGHT_CX, &adreno_dev->priv)) + _adreno_coresight_get_and_clear(adreno_dev, GPU_CORESIGHT_CX); } -/** - * adreno_coresight_start() - Reprogram coresight registers after power collapse - * @adreno_dev: Pointer to the adreno device structure - * - * Reprogram the cached values to the coresight registers on power up - */ void adreno_coresight_start(struct adreno_device *adreno_dev) { - int i, adreno_dev_flag = -EINVAL; + if (test_bit(ADRENO_DEVICE_CORESIGHT, &adreno_dev->priv)) + _adreno_coresight_set(adreno_dev, GPU_CORESIGHT_GX); - for (i = 0; i < GPU_CORESIGHT_MAX; ++i) { - if (i == GPU_CORESIGHT_GX) - adreno_dev_flag = ADRENO_DEVICE_CORESIGHT; - else if (i == GPU_CORESIGHT_CX) - adreno_dev_flag = ADRENO_DEVICE_CORESIGHT_CX; - else - return; - - if (test_bit(adreno_dev_flag, &adreno_dev->priv)) - _adreno_coresight_set(adreno_dev, i); - } + if (test_bit(ADRENO_DEVICE_CORESIGHT_CX, &adreno_dev->priv)) + _adreno_coresight_set(adreno_dev, GPU_CORESIGHT_CX); } static int adreno_coresight_trace_id(struct coresight_device *csdev) @@ -396,12 +348,9 @@ void adreno_coresight_remove(struct adreno_device *adreno_dev) { int i; - for (i = 0; i < ARRAY_SIZE(adreno_dev->csdev); i++) { - if (!IS_ERR_OR_NULL(adreno_dev->csdev[i])) { + for (i = 0; i < ARRAY_SIZE(adreno_dev->csdev); i++) + if (!IS_ERR_OR_NULL(adreno_dev->csdev[i])) coresight_unregister(adreno_dev->csdev[i]); - adreno_dev->csdev[i] = NULL; - } - } } static struct coresight_device * @@ -437,7 +386,6 @@ adreno_coresight_dev_probe(struct kgsl_device *device, void adreno_coresight_init(struct adreno_device *adreno_dev) { - int ret = 0; struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev); struct kgsl_device *device = KGSL_DEVICE(adreno_dev); int i = 0; @@ -456,5 +404,4 @@ void adreno_coresight_init(struct adreno_device *adreno_dev) } of_node_put(node); - return ret; } diff --git a/drivers/gpu/msm/adreno_coresight.h b/drivers/gpu/msm/adreno_coresight.h new file mode 100644 index 000000000000..e0e8d0121a29 --- /dev/null +++ b/drivers/gpu/msm/adreno_coresight.h @@ -0,0 +1,132 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _ADRENO_CORESIGHT_H_ +#define _ADRENO_CORESIGHT_H_ + +#include + +struct adreno_device; + +/** + * struct adreno_coresight_register - Definition for a coresight (tracebus) + * debug register + */ +struct adreno_coresight_register { + /** @offset: Offset of the debug register in the KGSL register space */ + unsigned int offset; + /** @initial: Default value to write when coresight is enabled */ + unsigned int initial; + /** + * @value: Current shadow value of the register (to be reprogrammed + * after power collapse) + */ + unsigned int value; +}; + +/** + * struct adreno_coresight_attr - Local attribute struct for coresight sysfs + * + * files + */ +struct adreno_coresight_attr { + /** @attr: Base device attribute */ + struct device_attribute attr; + /** + * @reg: Pointer to the &struct adreno_coresight_register definition + * for this register + */ + struct adreno_coresight_register *reg; +}; + +/** + * adreno_coresight_show_register - Callback function for sysfs show + * @device: Pointer to a device handle + * @attr: Pointer to the device attribute + * @buf: Contains the output buffer for sysfs + * + * Callback function to write the value of the register into the sysfs node. + * Return: The size of the data written to the buffer or negative on error. + */ +ssize_t adreno_coresight_show_register(struct device *device, + struct device_attribute *attr, char *buf); + +/** + * adreno_coresight_show_register - Callback function for sysfs store + * @device: Pointer to a device handle + * @attr: Pointer to the device attribute + * @buf: Contains the input buffer for sysfs + * @size: Size of the data stored in buf + * + * Callback function to read the value of a register from a sysfs node. + * Return: The size of the data consumed or negative on error. + */ +ssize_t adreno_coresight_store_register(struct device *dev, + struct device_attribute *attr, const char *buf, size_t size); + +#define ADRENO_CORESIGHT_ATTR(_attrname, _reg) \ + struct adreno_coresight_attr coresight_attr_##_attrname = { \ + __ATTR(_attrname, 0644, \ + adreno_coresight_show_register, \ + adreno_coresight_store_register), \ + (_reg), } + +/** + * struct adreno_coresight - GPU specific coresight definition + */ +struct adreno_coresight { + /** + * @registers: Array of GPU specific registers to configure trace + * bus output + */ + struct adreno_coresight_register *registers; + /** @count: Number of registers in the array */ + unsigned int count; + /** @groups: Pointer to an attribute list of control files */ + const struct attribute_group **groups; + /** @atid: The unique ATID value of the coresight device */ + unsigned int atid; +}; + +#ifdef CONFIG_QCOM_KGSL_CORESIGHT +/** + * adreno_coresight_init - Initialize coresight for the GPU device + * @adreno_dev: An Adreno GPU device handle + * + * Initialize devices for the GPU target. + */ +void adreno_coresight_init(struct adreno_device *adreno_dev); + +/** + * adreno_coresight_start - Reprogram coresight registers after power collapse + * @adreno_dev: An Adreno GPU device handle + * + * Reprogram the cached values to the coresight registers on power up. + */ +void adreno_coresight_start(struct adreno_device *adreno_dev); + +/** + * adreno_coresight_stop - Reprogram coresight registers after power collapse + * @adreno_dev: An Adreno GPU device handle + * + * Cache the current coresight register values so they can be restored after + * power collapse. + */ +void adreno_coresight_stop(struct adreno_device *adreno_dev); + +/** + * adreno_coresight_remove - Destroy active coresight devices + * @adreno_dev: An Adreno GPU device handle + * + * Destroy any active coresight devices. + */ +void adreno_coresight_remove(struct adreno_device *adreno_dev); +#else +static inline void adreno_coresight_init(struct adreno_device *adreno_dev) { } +static inline void adreno_coresight_start(struct adreno_device *adreno_dev) { } +static inline void adreno_coresight_stop(struct adreno_device *adreno_dev) { } +static inline void adreno_coresight_remove(struct adreno_device *adreno_dev) { } +#endif +#endif