Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

a2xx/a3xx/a4xx: gpu fixes / opp table Samsung J5 #332

Draft
wants to merge 8 commits into
base: msm8916/6.6-rc5
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions arch/arm64/boot/dts/qcom/msm8916.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -492,6 +492,16 @@
#address-cells = <1>;
#size-cells = <1>;

speedbin_efuse_version: speedbin@4{
reg = <0x6 0x1>;
bits = <2 2>;
};

speedbin_efuse: speedbin@c{
reg = <0xc 0x1>;
bits = <2 3>;
};

tsens_base1: base1@d0 {
reg = <0xd0 0x1>;
bits = <0 7>;
Expand Down Expand Up @@ -1828,14 +1838,53 @@
iommus = <&gpu_iommu 1>, <&gpu_iommu 2>;
status = "disabled";

// opp-avg-kBps / opp-peak-kBps:
// need CONFIG_INTERCONNECT=y working, it's bugged:
// interconnects = <&bimc MASTER_GRAPHICS_3D &bimc SLAVE_EBI_CH0>;
// interconnect-names = "gfx-mem";

// defining speed bin, we must define opp-supported-hw!
// if speedbin val is 0, driver must version 0x1
nvmem-cells = <&speedbin_efuse_version>, <&speedbin_efuse>;
nvmem-cell-names = "speed_bin_version", "speed_bin";

gpu_opp_table: opp-table {
compatible = "operating-points-v2";

opp-465000000 {
opp-hz = /bits/ 64 <465000000>;
opp-supported-hw = <0x02>;
// interconnect:
// opp-avg-kBps = <1190400>;
// opp-peak-kBps = <4761600>;
};
opp-400000000 {
opp-hz = /bits/ 64 <400000000>;
opp-supported-hw = <0xffffffff>;
// opp-avg-kBps = <1066000>;
// opp-peak-kBps = <4264000>;
};
opp-310000000 {
opp-hz = /bits/ 64 <310000000>;
opp-supported-hw = <0xffffffff>;
// opp-avg-kBps = <800000>;
// opp-peak-kBps = <3200000>;
};
opp-200000000 {
opp-hz = /bits/ 64 <200000000>;
opp-supported-hw = <0xffffffff>;
// opp-avg-kBps = <160000>;
// opp-peak-kBps = <1600000>;
};
opp-100000000 {
opp-hz = /bits/ 64 <100000000>;
opp-supported-hw = <0xffffffff>;
};
opp-19200000 {
opp-hz = /bits/ 64 <19200000>;
opp-supported-hw = <0xffffffff>;
// opp-avg-kBps = <0>;
// opp-peak-kBps = <0>;
};
};
};
Expand Down
3 changes: 2 additions & 1 deletion drivers/clk/qcom/gcc-msm8916.c
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ static const struct parent_map gcc_xo_gpll0a_gpll1_gpll2a_map[] = {
{ P_XO, 0 },
{ P_GPLL0_AUX, 3 },
{ P_GPLL1, 1 },
{ P_GPLL2_AUX, 2 },
{ P_GPLL2, 2 },
};

static const struct clk_parent_data gcc_xo_gpll0a_gpll1_gpll2a[] = {
Expand Down Expand Up @@ -488,6 +488,7 @@ static const struct freq_tbl ftbl_gcc_oxili_gfx3d_clk[] = {
F(294912000, P_GPLL1, 3, 0, 0),
F(310000000, P_GPLL2, 3, 0, 0),
F(400000000, P_GPLL0_AUX, 2, 0, 0),
F(465000000, P_GPLL2, 2, 0, 0),
{ }
};

Expand Down
22 changes: 22 additions & 0 deletions drivers/devfreq/devfreq.c
Original file line number Diff line number Diff line change
Expand Up @@ -1766,6 +1766,27 @@ static ssize_t trans_stat_store(struct device *dev,
}
static DEVICE_ATTR_RW(trans_stat);

static ssize_t load_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct devfreq *df = to_devfreq(dev);

if (!df->profile)
return -EINVAL;

unsigned long total_time = df->last_status.total_time;
if (total_time) {
uint32_t load = 1000 * df->last_status.busy_time / total_time;
return sprintf(buf, "%d.%02d %%%s\n",
load / 10, load % 10,
(df->stop_polling == true ? " suspend" : "")
);
}

return sprintf(buf, "?\n");
}
static DEVICE_ATTR_RO(load);

static struct attribute *devfreq_attrs[] = {
&dev_attr_name.attr,
&dev_attr_governor.attr,
Expand All @@ -1776,6 +1797,7 @@ static struct attribute *devfreq_attrs[] = {
&dev_attr_min_freq.attr,
&dev_attr_max_freq.attr,
&dev_attr_trans_stat.attr,
&dev_attr_load.attr,
NULL,
};
ATTRIBUTE_GROUPS(devfreq);
Expand Down
44 changes: 43 additions & 1 deletion drivers/gpu/drm/msm/adreno/a3xx_gpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*/

#include "a3xx_gpu.h"
#include <linux/nvmem-consumer.h>

#define A3XX_INT0_MASK \
(A3XX_INT0_RBBM_AHB_ERROR | \
Expand Down Expand Up @@ -481,7 +482,8 @@ static u64 a3xx_gpu_busy(struct msm_gpu *gpu, unsigned long *out_sample_rate)
{
u64 busy_cycles;

busy_cycles = gpu_read64(gpu, REG_A3XX_RBBM_PERFCTR_RBBM_1_LO);
busy_cycles = gpu_read64(gpu, REG_A3XX_RBBM_PERFCTR_PWR_1_LO);
//busy_cycles = gpu_read64(gpu, REG_A3XX_RBBM_PERFCTR_RBBM_1_LO);
*out_sample_rate = clk_get_rate(gpu->core_clk);

return busy_cycles;
Expand All @@ -493,6 +495,43 @@ static u32 a3xx_get_rptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
return ring->memptrs->rptr;
}

static int a3xx_set_supported_hw(struct device *dev, struct adreno_gpu *adreno_gpu)
{
u32 speedbin, version;
int ret;

ret = nvmem_cell_read_variable_le_u32(dev, "speed_bin_version", &version);
/*
* -ENOENT means that the platform doesn't support speedbin which is
* fine
*/
if (ret == -ENOENT) {
return 0;
} else if (ret) {
dev_err_probe(dev, ret,
"failed to read speed-bin-version. Some OPPs may not be supported by hardware\n");
return ret;
}

ret = nvmem_cell_read_variable_le_u32(dev, "speed_bin", &speedbin);
if (ret) {
dev_err_probe(dev, ret,
"failed to read speed-bin. Some OPPs may not be supported by hardware\n");
return ret;
}
dev_info(dev, "speed-bin version: %u value: %u\n", version, speedbin);

// if (version > 0)
// we must set at least version 0x1 otherwise no opp gets selected
// having opp-supported-hw property
if (speedbin == 0)
speedbin = 0x1;

return devm_pm_opp_set_supported_hw(dev, &speedbin, 1);

return 0;
}

static const struct adreno_gpu_funcs funcs = {
.base = {
.get_param = adreno_get_param,
Expand Down Expand Up @@ -554,6 +593,9 @@ struct msm_gpu *a3xx_gpu_init(struct drm_device *dev)

adreno_gpu->registers = a3xx_registers;

/* speed-bin */
a3xx_set_supported_hw(&pdev->dev, adreno_gpu);

ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, 1);
if (ret)
goto fail;
Expand Down
1 change: 0 additions & 1 deletion drivers/gpu/drm/msm/msm_fence.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ static void deadline_work(struct kthread_work *work)
if (msm_fence_completed(fctx, fctx->next_deadline_fence))
return;

msm_devfreq_boost(fctx2gpu(fctx), 2);
}


Expand Down
29 changes: 22 additions & 7 deletions drivers/gpu/drm/msm/msm_gpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,31 +57,44 @@ static int disable_pwrrail(struct msm_gpu *gpu)

static int enable_clk(struct msm_gpu *gpu)
{
int ret;
ret = clk_bulk_prepare_enable(gpu->nr_clocks, gpu->grp_clks);
if (ret)
return ret;
/*
devfreq_resume_device() can do set_rate
if an "opp-suspend" exists,
I actually see no need ...

if (gpu->core_clk && gpu->fast_rate)
dev_pm_opp_set_rate(&gpu->pdev->dev, gpu->fast_rate);
*/

/* Set the RBBM timer rate to 19.2Mhz */
if (gpu->rbbmtimer_clk)
clk_set_rate(gpu->rbbmtimer_clk, 19200000);

return clk_bulk_prepare_enable(gpu->nr_clocks, gpu->grp_clks);
return 0;
}

static int disable_clk(struct msm_gpu *gpu)
{
clk_bulk_disable_unprepare(gpu->nr_clocks, gpu->grp_clks);

/*
* Set the clock to a deliberately low rate. On older targets the clock
* speed had to be non zero to avoid problems. On newer targets this
* will be rounded down to zero anyway so it all works out.
*/

Can declare "opp-suspend" if theres need ...

if (gpu->core_clk)
dev_pm_opp_set_rate(&gpu->pdev->dev, 27000000);
dev_pm_opp_set_rate(&gpu->pdev->dev, 1);
*/

if (gpu->rbbmtimer_clk)
clk_set_rate(gpu->rbbmtimer_clk, 0);

clk_bulk_disable_unprepare(gpu->nr_clocks, gpu->grp_clks);

return 0;
}

Expand All @@ -101,6 +114,7 @@ int msm_gpu_pm_resume(struct msm_gpu *gpu)
int ret;

DBG("%s", gpu->name);
dev_dbg(&gpu->pdev->dev, "%s\n", __func__);
trace_msm_gpu_resume(0);

ret = enable_pwrrail(gpu);
Expand All @@ -118,6 +132,7 @@ int msm_gpu_pm_resume(struct msm_gpu *gpu)
msm_devfreq_resume(gpu);

gpu->needs_hw_init = true;
dev_dbg(&gpu->pdev->dev, "%s done\n", __func__);

return 0;
}
Expand All @@ -127,6 +142,7 @@ int msm_gpu_pm_suspend(struct msm_gpu *gpu)
int ret;

DBG("%s", gpu->name);
dev_dbg(&gpu->pdev->dev, "%s\n", __func__);
trace_msm_gpu_suspend(0);

msm_devfreq_suspend(gpu);
Expand All @@ -144,6 +160,7 @@ int msm_gpu_pm_suspend(struct msm_gpu *gpu)
return ret;

gpu->suspend_count++;
dev_dbg(&gpu->pdev->dev, "%s done\n", __func__);

return 0;
}
Expand Down Expand Up @@ -682,7 +699,6 @@ static void retire_submit(struct msm_gpu *gpu, struct msm_ringbuffer *ring,
gpu->active_submits--;
WARN_ON(gpu->active_submits < 0);
if (!gpu->active_submits) {
msm_devfreq_idle(gpu);
pm_runtime_put_autosuspend(&gpu->pdev->dev);
}

Expand Down Expand Up @@ -771,7 +787,6 @@ void msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
mutex_lock(&gpu->active_lock);
if (!gpu->active_submits) {
pm_runtime_get(&gpu->pdev->dev);
msm_devfreq_active(gpu);
}
gpu->active_submits++;
mutex_unlock(&gpu->active_lock);
Expand Down
43 changes: 4 additions & 39 deletions drivers/gpu/drm/msm/msm_gpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,25 +113,6 @@ struct msm_gpu_devfreq {
/** lock: lock for "suspended", "busy_cycles", and "time" */
struct mutex lock;

/**
* idle_freq:
*
* Shadow frequency used while the GPU is idle. From the PoV of
* the devfreq governor, we are continuing to sample busyness and
* adjust frequency while the GPU is idle, but we use this shadow
* value as the GPU is actually clamped to minimum frequency while
* it is inactive.
*/
unsigned long idle_freq;

/**
* boost_constraint:
*
* A PM QoS constraint to boost min freq for a period of time
* until the boost expires.
*/
struct dev_pm_qos_request boost_freq;

/**
* busy_cycles: Last busy counter value, for calculating elapsed busy
* cycles since last sampling period.
Expand All @@ -141,23 +122,9 @@ struct msm_gpu_devfreq {
/** time: Time of last sampling period. */
ktime_t time;

/** idle_time: Time of last transition to idle: */
ktime_t idle_time;

/**
* idle_work:
*
* Used to delay clamping to idle freq on active->idle transition.
*/
struct msm_hrtimer_work idle_work;

/**
* boost_work:
*
* Used to reset the boost_constraint after the boost period has
* elapsed
*/
struct msm_hrtimer_work boost_work;
/** load avg **/
unsigned long load;
unsigned long load_avg;

/** suspended: tracks if we're suspended */
bool suspended;
Expand Down Expand Up @@ -251,6 +218,7 @@ struct msm_gpu {
/* Hang and Inactivity Detection:
*/
#define DRM_MSM_INACTIVE_PERIOD 66 /* in ms (roughly four frames) */
// #define DRM_MSM_INACTIVE_PERIOD 120

#define DRM_MSM_HANGCHECK_DEFAULT_PERIOD 500 /* in ms */
#define DRM_MSM_HANGCHECK_PROGRESS_RETRIES 3
Expand Down Expand Up @@ -638,9 +606,6 @@ void msm_devfreq_init(struct msm_gpu *gpu);
void msm_devfreq_cleanup(struct msm_gpu *gpu);
void msm_devfreq_resume(struct msm_gpu *gpu);
void msm_devfreq_suspend(struct msm_gpu *gpu);
void msm_devfreq_boost(struct msm_gpu *gpu, unsigned factor);
void msm_devfreq_active(struct msm_gpu *gpu);
void msm_devfreq_idle(struct msm_gpu *gpu);

int msm_gpu_hw_init(struct msm_gpu *gpu);

Expand Down
Loading
Loading