Skip to content
Open
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
17 changes: 17 additions & 0 deletions Documentation/devicetree/bindings/display/msm/gpu.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,22 @@ allOf:
- clocks
- clock-names

- if:
properties:
compatible:
contains:
const: qcom,adreno-44070001
then:
properties:
reg:
minItems: 2
maxItems: 2

reg-names:
items:
- const: kgsl_3d0_reg_memory
- const: cx_mem

- if:
properties:
compatible:
Expand All @@ -434,6 +450,7 @@ allOf:
- qcom,adreno-43050a01
- qcom,adreno-43050c01
- qcom,adreno-43051401
- qcom,adreno-44070001

then: # Starting with A6xx, the clocks are usually defined in the GMU node
properties:
Expand Down
4 changes: 3 additions & 1 deletion Documentation/devicetree/bindings/iommu/arm,smmu.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -566,7 +566,9 @@ allOf:
properties:
compatible:
items:
- const: qcom,sm8750-smmu-500
- enum:
- qcom,glymur-smmu-500
- qcom,sm8750-smmu-500
- const: qcom,adreno-smmu
- const: qcom,smmu-500
- const: arm,mmu-500
Expand Down
5 changes: 5 additions & 0 deletions drivers/gpu/drm/msm/adreno/a5xx_gpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -1281,6 +1281,11 @@ static irqreturn_t a5xx_irq(struct msm_gpu *gpu)
status & ~A5XX_RBBM_INT_0_MASK_RBBM_AHB_ERROR);

if (priv->disable_err_irq) {
/* Turn off interrupts to avoid interrupt storm */
gpu_write(gpu, REG_A5XX_RBBM_INT_0_MASK,
A5XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS |
A5XX_RBBM_INT_0_MASK_CP_SW);

status &= A5XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS |
A5XX_RBBM_INT_0_MASK_CP_SW;
}
Expand Down
172 changes: 172 additions & 0 deletions drivers/gpu/drm/msm/adreno/a6xx_catalog.c
Original file line number Diff line number Diff line change
Expand Up @@ -1799,6 +1799,90 @@ static const struct adreno_reglist_pipe x285_dyn_pwrup_reglist_regs[] = {
};
DECLARE_ADRENO_REGLIST_PIPE_LIST(x285_dyn_pwrup_reglist);

static const struct a6xx_hfi_clx_table_v2_cmd x285_clx_tbl = {
.version = (2 << 16) | 1,
.domain = {
/* GX DOMAIN */
{
.data = CLX_DATA(60, 11, 0, 1),
.clxt = 0,
.clxh = 0,
.urg_mode = 1,
.lkg_en = 0,
.curr_budget = 100,
},
/* MXG DOMAIN */
{
.data = CLX_DATA(60, 3, 1, 1),
.clxt = 0,
.clxh = 0,
.urg_mode = 1,
.lkg_en = 0,
.curr_budget = 100,
},
},
};

struct a6xx_hfi_limits_tbl x285_limits_tbl[] = {
{
.feature_id = GMU_MIT_IFF,
.domain = GMU_GX_DOMAIN,
.feature_rev = 0,
.cfg = {
.enable = 1,
.msg_path = 0,
.lkg_en = 0,
.mode = 0,
.sid = 12,
.mit_time = 5,
.curr_limit = 18000,
},
},
{
.feature_id = GMU_MIT_IFF,
.domain = GMU_MX_DOMAIN,
.feature_rev = 0,
.cfg = {
.enable = 1,
.msg_path = 0,
.lkg_en = 0,
.mode = 0,
.sid = 18,
.mit_time = 2000,
.curr_limit = 6000,
},
},
{
.feature_id = GMU_MIT_PCLX,
.domain = GMU_GX_DOMAIN,
.feature_rev = 0,
.cfg = {
.enable = 1,
.msg_path = 0,
.lkg_en = 0,
.mode = 0,
.sid = 6,
.mit_time = 3,
.curr_limit = 66000,
},
},
{
.feature_id = GMU_MIT_PCLX,
.domain = GMU_MX_DOMAIN,
.feature_rev = 0,
.cfg = {
.enable = 0,
.msg_path = 0,
.lkg_en = 0,
.mode = 0,
.sid = 6,
.mit_time = 3,
.curr_limit = 18000,
},
},
};
DECLARE_ADRENO_LIMITS_TABLE(x285_limits);

static const struct adreno_reglist_pipe a840_nonctxt_regs[] = {
{ REG_A8XX_CP_SMMU_STREAM_ID_LPAC, 0x00000101, BIT(PIPE_NONE) },
{ REG_A8XX_GRAS_DBG_ECO_CNTL, 0x00000800, BIT(PIPE_BV) | BIT(PIPE_BR) },
Expand Down Expand Up @@ -2108,6 +2192,90 @@ static const struct adreno_reglist_pipe a840_dyn_pwrup_reglist_regs[] = {
};
DECLARE_ADRENO_REGLIST_PIPE_LIST(a840_dyn_pwrup_reglist);

static const struct a6xx_hfi_clx_table_v2_cmd a840_clx_tbl = {
.version = (2 << 16) | 1,
.domain = {
/* GX DOMAIN */
{
.data = CLX_DATA(60, 5, 1, 1),
.clxt = 0,
.clxh = 0,
.urg_mode = 1,
.lkg_en = 0,
.curr_budget = 100,
},
/* MXG DOMAIN */
{
.data = CLX_DATA(60, 1, 1, 1),
.clxt = 0,
.clxh = 0,
.urg_mode = 1,
.lkg_en = 0,
.curr_budget = 50,
},
},
};

struct a6xx_hfi_limits_tbl a840_limits_tbl[] = {
{
.feature_id = GMU_MIT_IFF,
.domain = GMU_GX_DOMAIN,
.feature_rev = 0,
.cfg = {
.enable = 1,
.msg_path = 0,
.lkg_en = 0,
.mode = 0,
.sid = 12,
.mit_time = 5,
.curr_limit = 6000,
},
},
{
.feature_id = GMU_MIT_IFF,
.domain = GMU_MX_DOMAIN,
.feature_rev = 0,
.cfg = {
.enable = 1,
.msg_path = 0,
.lkg_en = 0,
.mode = 0,
.sid = 9,
.mit_time = 2000,
.curr_limit = 6000,
},
},
{
.feature_id = GMU_MIT_PCLX,
.domain = GMU_GX_DOMAIN,
.feature_rev = 0,
.cfg = {
.enable = 1,
.msg_path = 0,
.lkg_en = 0,
.mode = 0,
.sid = 7,
.mit_time = 3,
.curr_limit = 30000,
},
},
{
.feature_id = GMU_MIT_PCLX,
.domain = GMU_MX_DOMAIN,
.feature_rev = 0,
.cfg = {
.enable = 0,
.msg_path = 0,
.lkg_en = 0,
.mode = 0,
.sid = 7,
.mit_time = 3,
.curr_limit = 6000,
},
},
};
DECLARE_ADRENO_LIMITS_TABLE(a840_limits);

static const struct adreno_info a8xx_gpus[] = {
{
.chip_ids = ADRENO_CHIP_IDS(0x44070001),
Expand Down Expand Up @@ -2143,6 +2311,8 @@ static const struct adreno_info a8xx_gpus[] = {
},
{ /* sentinel */ },
},
.clx_tbl = &x285_clx_tbl,
.limits_tbl = &x285_limits,
},
.speedbins = ADRENO_SPEEDBINS(
{ 0, 0 },
Expand Down Expand Up @@ -2185,6 +2355,8 @@ static const struct adreno_info a8xx_gpus[] = {
},
{ /* sentinel */ },
},
.clx_tbl = &a840_clx_tbl,
.limits_tbl = &a840_limits,
},
.preempt_record_size = 19708 * SZ_1K,
.speedbins = ADRENO_SPEEDBINS(
Expand Down
76 changes: 64 additions & 12 deletions drivers/gpu/drm/msm/adreno/a6xx_gmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -642,7 +642,7 @@ static void a6xx_rpmh_stop(struct a6xx_gmu *gmu)
int ret;
u32 val;

if (test_and_clear_bit(GMU_STATUS_FW_START, &gmu->status))
if (!test_and_clear_bit(GMU_STATUS_FW_START, &gmu->status))
return;

if (adreno_is_a840(adreno_gpu))
Expand Down Expand Up @@ -1250,6 +1250,56 @@ static int a6xx_gmu_secure_init(struct a6xx_gpu *a6xx_gpu)
return 0;
}

static int a6xx_gmu_gxpd_get(struct a6xx_gmu *gmu)
{
struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu);
struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;

if (IS_ERR_OR_NULL(gmu->gxpd))
return 0;

/*
* On A8xx HW, GX GDSC is moved to a new clk controller block under GX
* power domain. The clock driver for this new block keeps the GX rail
* voted when gxpd is voted. So, use the gxpd only during gpu recovery.
*/
if (adreno_gpu->info->family >= ADRENO_8XX_GEN1)
return 0;

/*
* On A6x/A7x, "enable" the GX power domain which won't actually do
* anything but it will make sure that the refcounting is correct in
* case we need to bring down the GX after a GMU failure
*/
return pm_runtime_get_sync(gmu->gxpd);
}

static int a6xx_gmu_gxpd_put(struct a6xx_gmu *gmu)
{
struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu);
struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;

if (IS_ERR_OR_NULL(gmu->gxpd))
return 0;

if (adreno_gpu->info->family < ADRENO_8XX_GEN1)
return pm_runtime_put_sync(gmu->gxpd);

/*
* On A8x, GX GDSC collapse should be triggered only when it is stuck ON
*/
if (adreno_gpu->funcs->gx_is_on(adreno_gpu)) {
pm_runtime_get_sync(gmu->gxpd);
/*
* Hint to gfxclkctl driver to do a hw collapse during the next
* RPM PUT. This is a special behavior in the gfxclkctl driver
*/
dev_pm_genpd_synced_poweroff(gmu->gxpd);
pm_runtime_put_sync(gmu->gxpd);
}

return 0;
}

int a6xx_gmu_resume(struct a6xx_gpu *a6xx_gpu)
{
Expand All @@ -1266,13 +1316,7 @@ int a6xx_gmu_resume(struct a6xx_gpu *a6xx_gpu)
/* Turn on the resources */
pm_runtime_get_sync(gmu->dev);

/*
* "enable" the GX power domain which won't actually do anything but it
* will make sure that the refcounting is correct in case we need to
* bring down the GX after a GMU failure
*/
if (!IS_ERR_OR_NULL(gmu->gxpd))
pm_runtime_get_sync(gmu->gxpd);
a6xx_gmu_gxpd_get(gmu);

/* Use a known rate to bring up the GMU */
clk_set_rate(gmu->core_clk, 200000000);
Expand Down Expand Up @@ -1339,7 +1383,8 @@ int a6xx_gmu_resume(struct a6xx_gpu *a6xx_gpu)
disable_clk:
clk_bulk_disable_unprepare(gmu->nr_clocks, gmu->clocks);
rpm_put:
pm_runtime_put(gmu->gxpd);
a6xx_gmu_gxpd_put(gmu);

pm_runtime_put(gmu->dev);

return ret;
Expand Down Expand Up @@ -1420,6 +1465,9 @@ static void a6xx_gmu_shutdown(struct a6xx_gmu *gmu)
/* Stop the interrupts and mask the hardware */
a6xx_gmu_irq_disable(gmu);

/* Halt the gmu cm3 core */
gmu_write(gmu, REG_A6XX_GMU_CM3_SYSRESET, 1);

/* Tell RPMh to power off the GPU */
a6xx_rpmh_stop(gmu);

Expand Down Expand Up @@ -1455,8 +1503,7 @@ int a6xx_gmu_stop(struct a6xx_gpu *a6xx_gpu)
* domain. Usually the GMU does this but only if the shutdown sequence
* was successful
*/
if (!IS_ERR_OR_NULL(gmu->gxpd))
pm_runtime_put_sync(gmu->gxpd);
a6xx_gmu_gxpd_put(gmu);

clk_bulk_disable_unprepare(gmu->nr_clocks, gmu->clocks);

Expand Down Expand Up @@ -2357,7 +2404,12 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
goto err_mmio;
}
} else if (adreno_is_a8xx(adreno_gpu)) {
gmu->rscc = gmu->mmio + 0x19000;
/*
* On a8xx , RSCC lives at GPU base + 0x50000, which falls
* inside the GPU's kgsl_3d0_reg_memory range rather than the
* GMU's.
*/
gmu->rscc = gpu->mmio + 0x50000;
} else {
gmu->rscc = gmu->mmio + 0x23000;
}
Expand Down
5 changes: 4 additions & 1 deletion drivers/gpu/drm/msm/adreno/a6xx_gpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -1989,8 +1989,11 @@ static irqreturn_t a6xx_irq(struct msm_gpu *gpu)

gpu_write(gpu, REG_A6XX_RBBM_INT_CLEAR_CMD, status);

if (priv->disable_err_irq)
if (priv->disable_err_irq) {
/* Turn off interrupts to avoid interrupt storm */
gpu_write(gpu, REG_A6XX_RBBM_INT_0_MASK, A6XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS);
status &= A6XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS;
}

if (status & A6XX_RBBM_INT_0_MASK_RBBM_HANG_DETECT)
a6xx_fault_detect_irq(gpu);
Expand Down
Loading