replace common qcom sources with samsung ones

This commit is contained in:
SaschaNes
2025-08-12 22:13:00 +02:00
parent ba24dcded9
commit 6f7753de11
5682 changed files with 2450203 additions and 103634 deletions

View File

@@ -1,12 +1,18 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2010-2021, The Linux Foundation. All rights reserved.
* Copyright (c) 2022-2025, Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) 2022-2024, Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/clk/qcom.h>
#include <linux/interconnect.h>
#include <linux/iopoll.h>
#include <linux/version.h>
#if (KERNEL_VERSION(6, 3, 0) <= LINUX_VERSION_CODE)
#include <linux/firmware/qcom/qcom_scm.h>
#else
#include <linux/qcom_scm.h>
#endif
#include <linux/of_device.h>
#include <linux/pm_domain.h>
#include <linux/pm_runtime.h>
@@ -16,10 +22,10 @@
#include <linux/msm_kgsl.h>
#include <linux/units.h>
#include <soc/qcom/dcvs.h>
#include <linux/cx_gdsc_debug.h>
#include "kgsl_device.h"
#include "kgsl_bus.h"
#include "kgsl_power_trace.h"
#include "kgsl_pwrscale.h"
#include "kgsl_sysfs.h"
#include "kgsl_trace.h"
@@ -31,6 +37,8 @@
#define GX_GDSC_TIMEOUT_MS 200
#define BUF_SIZE 1000
/* Order deeply matters here because reasons. New entries go on the end */
static const char * const clocks[KGSL_MAX_CLKS] = {
"src_clk",
@@ -250,7 +258,7 @@ void kgsl_pwrctrl_pwrlevel_change(struct kgsl_device *device,
pwr->previous_pwrlevel,
pwr->pwrlevels[old_level].gpu_freq);
KGSL_TRACE_GPU_FREQ(pwrlevel->gpu_freq/1000, 0);
trace_gpu_frequency(pwrlevel->gpu_freq/1000, 0);
/* Update the bus after GPU clock decreases. */
if (new_level > old_level)
@@ -421,7 +429,7 @@ static void kgsl_pwrctrl_min_pwrlevel_set(struct kgsl_device *device,
if (level > pwr->min_render_pwrlevel)
level = pwr->min_render_pwrlevel;
mutex_lock(&device->mutex);
/* You can't set a minimum power level lower than the maximum */
@@ -1060,6 +1068,91 @@ static ssize_t temp_show(struct device *dev,
return _gpu_tmu_show(device, buf);
}
struct reg_pairs {
u32 address;
char *str;
bool secure;
};
static struct reg_pairs pairs[] = {
{ 0x3D99080, "GPUCC_GPU_CC_CX_GDSCR", false },
{ 0x3D99084, "GPUCC_GPU_CC_CX_CFG_GDSCR", false },
{ 0x3D99094, "GPUCC_GPU_CC_CX_HW_CTRL_CFG1_GDSR", false },
{ 0x3D99098, "GPUCC_GPU_CC_CX_HW_CTRL_CFG2_GDSR", false },
{ 0x3D9909C, "GPUCC_GPU_CC_CX_HW_CTRL_DVM_STATUS_GDSR", false },
{ 0x3D990A0, "GPUCC_GPU_CC_CX_HW_CTRL_HALT1_STATUS_GDSR", false },
{ 0x3D990A4, "GPUCC_GPU_CC_CX_HW_CTRL_HALT2_STATUS_GDSR", false },
{ 0x3D990A8, "GPUCC_GPU_CC_CX_HW_CTRL_REQ_SW_GDSR", false },
{ 0x3D990AC, "GPUCC_GPU_CC_CX_HW_CTRL_IRQ_STATUS_GDSR", false },
{ 0x3D99550, "GPUCC_GPU_CC_CX_GDS_HW_CTL_SMMU_HALT_STATUS", false },
{ 0x3D95004, "GPUCC_GPU_CC_TZ_VOTE_GPU_SMMU_GDS", false },
{ 0x3D96004, "GPUCC_GPU_CC_HYP_VOTE_GPU_SMMU_GDS", false },
{ 0x3D97004, "GPUCC_GPU_CC_HLOS1_VOTE_GPU_SMMU_GDS", false },
{ 0x3D98004, "GPUCC_GPU_CC_SPARE_VOTE_GPU_SMMU_GDS", false },
{ 0x3D99088, "GPUCC_GPU_CC_CX_CFG2_GDSCR", false },
{ 0x3D9908C, "GPUCC_GPU_CC_CX_CFG3_GDSCR", false },
{ 0x3D99090, "GPUCC_GPU_CC_CX_CFG4_GDSCR", false },
};
static void log_debug_data(void)
{
int i;
u32 val;
for (i = 0; i < (sizeof(pairs) / sizeof(struct reg_pairs)); i++) {
void __iomem *tmp;
if (pairs[i].secure) {
qcom_scm_io_readl(pairs[i].address, &val);
} else {
tmp = ioremap(pairs[i].address, 4);
val = __raw_readl(tmp);
iounmap(tmp);
}
pr_err("kgsl: register: %s, address: 0x%x, value 0x%x",
pairs[i].str, pairs[i].address, val);
}
}
static ssize_t _gpu_info_store(struct kgsl_device *device,
const char *buf, size_t count)
{
if (buf == NULL)
return -EINVAL;
if ((buf[0] == 'c') && ((buf[1] == '\0') || (buf[1] == '\n'))) {
atomic_set(&device->gpu_exception_count[GPU_HANG], 0);
atomic_set(&device->gpu_exception_count[GPU_PAGE_FAULT], 0);
atomic_set(&device->gpu_exception_count[GPU_TIMEOUT], 0);
atomic_set(&device->gpu_exception_count[GPU_PREEMPTION_FAULT], 0);
atomic_set(&device->gpu_exception_count[GPU_CXWAIT_TIMEOUT], 0);
atomic_set(&device->gpu_exception_count[GPU_HFI_ERROR], 0);
}
return count;
}
static ssize_t _gpu_info_show(struct kgsl_device *device,
char *buf)
{
ssize_t ret = 0;
if(buf == NULL)
return -EINVAL;
ret += scnprintf(buf+ret, BUF_SIZE-ret, "\"GHG_Q\":\"%d\",", atomic_read(&device->gpu_exception_count[GPU_HANG]));
ret += scnprintf(buf+ret, BUF_SIZE-ret, "\"GPF_Q\":\"%d\",", atomic_read(&device->gpu_exception_count[GPU_PAGE_FAULT]));
ret += scnprintf(buf+ret, BUF_SIZE-ret, "\"GTO_Q\":\"%d\",", atomic_read(&device->gpu_exception_count[GPU_TIMEOUT]));
ret += scnprintf(buf+ret, BUF_SIZE-ret, "\"PFT_Q\":\"%d\",", atomic_read(&device->gpu_exception_count[GPU_PREEMPTION_FAULT]));
ret += scnprintf(buf+ret, BUF_SIZE-ret, "\"CXT_Q\":\"%d\",", atomic_read(&device->gpu_exception_count[GPU_CXWAIT_TIMEOUT]));
ret += scnprintf(buf+ret, BUF_SIZE-ret, "\"GHE_Q\":\"%d\"", atomic_read(&device->gpu_exception_count[GPU_HFI_ERROR]));
buf[ret++] = '\n';
return ret;
}
static ssize_t pwrscale_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
@@ -1160,6 +1253,7 @@ static GPU_SYSFS_ATTR(gpu_max_clock, 0644, _max_clock_mhz_show,
static GPU_SYSFS_ATTR(gpu_clock, 0444, _clock_mhz_show, NULL);
static GPU_SYSFS_ATTR(gpu_freq_table, 0444, _freq_table_mhz_show, NULL);
static GPU_SYSFS_ATTR(gpu_tmu, 0444, _gpu_tmu_show, NULL);
static GPU_SYSFS_ATTR(gpu_info, 0660, _gpu_info_show, _gpu_info_store);
static const struct attribute *gpu_sysfs_attr_list[] = {
&gpu_sysfs_attr_gpu_busy.attr,
@@ -1168,6 +1262,7 @@ static const struct attribute *gpu_sysfs_attr_list[] = {
&gpu_sysfs_attr_gpu_clock.attr,
&gpu_sysfs_attr_gpu_freq_table.attr,
&gpu_sysfs_attr_gpu_tmu.attr,
&gpu_sysfs_attr_gpu_info.attr,
NULL,
};
@@ -1369,12 +1464,18 @@ int kgsl_pwrctrl_enable_cx_gdsc(struct kgsl_device *device)
ret = wait_for_completion_timeout(&pwr->cx_gdsc_gate, msecs_to_jiffies(5000));
if (!ret) {
atomic_inc(&device->gpu_exception_count[GPU_CXWAIT_TIMEOUT]);
/* Dump the cx regulator consumer list */
if (pwr->cx_regulator) {
dev_err(device->dev, "GPU CX wait timeout. Dumping CX votes:\n");
qcom_clk_dump(NULL, pwr->cx_regulator, false);
} else {
dev_err(device->dev, "GPU CX wait timeout\n");
dev_err(device->dev, "GPU CX wait timeout, Dumping CX votes:\n");
print_cx_gdsc_log();
qcom_gdsc_pd_dump(pwr->cx_pd);
/* Dump GPUCC registers */
log_debug_data();
}
}
@@ -1580,8 +1681,18 @@ static int kgsl_cx_gdsc_event(struct notifier_block *nb,
if (pwr->cx_cfg_gdsc_offset) {
if (kgsl_regmap_read_poll_timeout(&device->regmap, pwr->cx_cfg_gdsc_offset,
val, (val & BIT(15)), 100, 100 * 1000))
val, (val & BIT(15)), 100, 100 * 1000)) {
atomic_inc(&device->gpu_exception_count[GPU_CXWAIT_TIMEOUT]);
dev_err(device->dev, "GPU CX wait timeout.\n");
/* Dump GPUCC registers */
log_debug_data();
/* Dump SMMU registers */
val = qcom_scm_io_writel(0xdeaddead, 0xdeaddead);
if (val)
dev_err(device->dev, "SCM write failed, ret = %d", val);
}
}
pwr->cx_gdsc_wait = false;
@@ -2257,7 +2368,7 @@ static int _wake(struct kgsl_device *device)
kgsl_pwrctrl_axi(device, true);
kgsl_pwrscale_wake(device);
kgsl_pwrctrl_irq(device, true);
KGSL_TRACE_GPU_FREQ(
trace_gpu_frequency(
pwr->pwrlevels[pwr->active_pwrlevel].gpu_freq/1000, 0);
kgsl_bus_update(device, KGSL_BUS_VOTE_ON);
@@ -2348,7 +2459,7 @@ _slumber(struct kgsl_device *device)
device->ftbl->stop(device);
kgsl_pwrctrl_disable(device);
kgsl_pwrscale_sleep(device);
KGSL_TRACE_GPU_FREQ(0, 0);
trace_gpu_frequency(0, 0);
kgsl_pwrctrl_set_state(device, KGSL_STATE_SLUMBER);
break;
case KGSL_STATE_SUSPEND:
@@ -2358,7 +2469,7 @@ _slumber(struct kgsl_device *device)
break;
case KGSL_STATE_AWARE:
kgsl_pwrctrl_disable(device);
KGSL_TRACE_GPU_FREQ(0, 0);
trace_gpu_frequency(0, 0);
kgsl_pwrctrl_set_state(device, KGSL_STATE_SLUMBER);
break;
default:
@@ -2460,6 +2571,7 @@ void kgsl_pwrctrl_set_state(struct kgsl_device *device,
device->state = state;
device->requested_state = KGSL_STATE_NONE;
cx_gdsc_log("%s: name: %s, state : %d\n", __func__, device->name, state);
if (state == KGSL_STATE_SLUMBER)
device->pwrctrl.wake_on_touch = false;
@@ -2474,8 +2586,10 @@ void kgsl_pwrctrl_set_state(struct kgsl_device *device,
void kgsl_pwrctrl_request_state(struct kgsl_device *device,
unsigned int state)
{
if (state != KGSL_STATE_NONE && state != device->requested_state)
if (state != KGSL_STATE_NONE && state != device->requested_state) {
cx_gdsc_log("%s: name: %s, state : %d\n", __func__, device->name, state);
trace_kgsl_pwr_request_state(device, state);
}
device->requested_state = state;
}