diff --git a/Documentation/devicetree/bindings/display/msm/gmu.yaml b/Documentation/devicetree/bindings/display/msm/gmu.yaml
index 9e459f12ce3f5..d10d6147358e9 100644
--- a/Documentation/devicetree/bindings/display/msm/gmu.yaml
+++ b/Documentation/devicetree/bindings/display/msm/gmu.yaml
@@ -363,7 +363,9 @@ allOf:
properties:
compatible:
contains:
- const: qcom,adreno-gmu-x285.1
+ enum:
+ - qcom,adreno-gmu-x285.0
+ - qcom,adreno-gmu-x290.1
then:
properties:
reg:
diff --git a/Documentation/devicetree/bindings/display/msm/gpu.yaml b/Documentation/devicetree/bindings/display/msm/gpu.yaml
index e5efe2d35ddcc..8a103f998dd87 100644
--- a/Documentation/devicetree/bindings/display/msm/gpu.yaml
+++ b/Documentation/devicetree/bindings/display/msm/gpu.yaml
@@ -452,6 +452,7 @@ allOf:
- qcom,adreno-43051401
- qcom,adreno-44010000
- qcom,adreno-44050a01
+ - qcom,adreno-44060000
- qcom,adreno-44070001
then: # Starting with A6xx, the clocks are usually defined in the GMU node
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_catalog.c b/drivers/gpu/drm/msm/adreno/a6xx_catalog.c
index 418edde9104ea..641382714f9a6 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_catalog.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_catalog.c
@@ -2685,6 +2685,366 @@ static const struct adreno_reglist_pipe a840_dyn_pwrup_reglist_regs[] = {
};
DECLARE_ADRENO_REGLIST_PIPE_LIST(a840_dyn_pwrup_reglist);
+static const struct adreno_reglist_pipe a845_nonctxt_regs[] = {
+ { REG_A8XX_CP_SMMU_STREAM_ID_LPAC, 0x00000101, BIT(PIPE_NONE) },
+ { REG_A8XX_CP_MULTIDRAW_CNTL, 0x00000001, BIT(PIPE_NONE) },
+ { REG_A8XX_GRAS_DBG_ECO_CNTL, 0x01000800, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_GRAS_TSEFE_DBG_ECO_CNTL, 0x00200000, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A6XX_PC_AUTO_VERTEX_STRIDE, 0x00000001, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_PC_VIS_STREAM_CNTL, 0x10010000, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_PC_CONTEXT_SWITCH_STABILIZE_CNTL_1, 0x00000002, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_PC_CHICKEN_BITS_1, 0x00000803, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_PC_CHICKEN_BITS_2, 0x00000200, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_PC_CHICKEN_BITS_3, 0x00400000, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_PC_CHICKEN_BITS_4, 0x00500050, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_PC_CHICKEN_BITS_5, BIT(28) | BIT(30), BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A7XX_RB_CCU_CNTL, 0x00000068, BIT(PIPE_BR) },
+ { REG_A7XX_RB_CCU_DBG_ECO_CNTL, BIT(10) | BIT(9), BIT(PIPE_BR) },
+ { REG_A6XX_RB_DBG_ECO_CNTL, BIT(17), BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_RB_GC_GMEM_PROTECT, 0x0C000000, BIT(PIPE_BR) },
+ { REG_A6XX_RB_RBP_CNTL, BIT(5) | BIT(6), BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_RB_RESOLVE_PREFETCH_CNTL, 0x00000007, BIT(PIPE_BR) },
+ { REG_A8XX_RB_CMP_DBG_ECO_CNTL, 0x00004000, BIT(PIPE_BR) },
+ { REG_A8XX_RBBM_NC_MODE_CNTL, 0x00000001, BIT(PIPE_NONE) },
+ { REG_A8XX_RBBM_SLICE_NC_MODE_CNTL, 0x00000001, BIT(PIPE_NONE) },
+ { REG_A8XX_RBBM_SLICE_PERFCTR_CNTL, BIT(0), BIT(PIPE_NONE) },
+ { REG_A8XX_RBBM_POWER_UP_RESET_SW_OVERRIDE, 0x70809060, BIT(PIPE_NONE) },
+ { REG_A8XX_RBBM_POWER_UP_RESET_SW_BV_OVERRIDE, 0x30000000, BIT(PIPE_NONE) },
+ { REG_A8XX_RBBM_WAIT_IDLE_CLOCKS_CNTL, 0x00000030, BIT(PIPE_NONE) },
+ { REG_A8XX_RBBM_WAIT_IDLE_CLOCKS_CNTL2, 0x00000030, BIT(PIPE_NONE) },
+ { REG_A8XX_RBBM_GBIF_CLIENT_QOS_CNTL, 0x22122212, BIT(PIPE_NONE) },
+ { REG_A8XX_RBBM_CGC_P2S_CNTL, 0x00000040, BIT(PIPE_NONE) },
+ { REG_A6XX_SP_CHICKEN_BITS, BIT(24), BIT(PIPE_NONE) },
+ { REG_A7XX_SP_CHICKEN_BITS_2, 0x00820800, BIT(PIPE_NONE) },
+ { REG_A7XX_SP_CHICKEN_BITS_3, 0x00300000, BIT(PIPE_NONE) },
+ { REG_A8XX_SP_CHICKEN_BITS_5, BIT(3), BIT(PIPE_NONE) },
+ { REG_A6XX_SP_PERFCTR_SHADER_MASK, 0x0000003f, BIT(PIPE_NONE) },
+ { REG_A7XX_SP_HLSQ_DBG_ECO_CNTL, 0x04000000, BIT(PIPE_NONE) },
+ { REG_A7XX_SP_HLSQ_DBG_ECO_CNTL_1, BIT(17), BIT(PIPE_NONE) },
+ { REG_A8XX_SP_HLSQ_DBG_ECO_CNTL_3, BIT(1), BIT(PIPE_NONE) },
+ { REG_A7XX_SP_HLSQ_TIMEOUT_THRESHOLD_DP, 0x00000080, BIT(PIPE_NONE) },
+ { REG_A7XX_SP_READ_SEL, 0x0001ff00, BIT(PIPE_NONE) },
+ { REG_A8XX_SP_L0_PERF_TUNE, 0x00000024, BIT(PIPE_NONE) },
+ { REG_A6XX_TPL1_DBG_ECO_CNTL, 0x10100000, BIT(PIPE_NONE) },
+ { REG_A6XX_TPL1_DBG_ECO_CNTL1, 0x00000720, BIT(PIPE_NONE) },
+ { REG_A6XX_UCHE_MODE_CNTL, 0x80080000, BIT(PIPE_NONE) },
+ { REG_A8XX_UCHE_CCHE_MODE_CNTL, 0x00001000, BIT(PIPE_NONE) },
+ { REG_A8XX_UCHE_DBG_ECO_CNTL_0, BIT(31), BIT(PIPE_NONE) },
+ { REG_A8XX_UCHE_HW_DBG_CNTL, 0x01410000, BIT(PIPE_NONE) },
+ { REG_A8XX_UCHE_CCHE_CACHE_WAYS, 0x00000800, BIT(PIPE_NONE) },
+ { REG_A8XX_UCHE_GBIF_GX_CONFIG, 0x010240e0, BIT(PIPE_NONE) },
+ { REG_A8XX_UCHE_VARB_IDLE_TIMEOUT, 0x00000020, BIT(PIPE_NONE) },
+ { REG_A7XX_VFD_DBG_ECO_CNTL, 0x00008000, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_VFD_CB_BV_THRESHOLD, 0x00500050, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_VFD_CB_BR_THRESHOLD, 0x00600060, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_VFD_CB_BUSY_REQ_CNT, 0x00200020, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_VFD_CB_LP_REQ_CNT, 0x00080020, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_VPC_FLATSHADE_MODE_CNTL, 0x00000001, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_VSC_VISIBILITY_FLUSH_CNTL, 0x00080004, BIT(PIPE_NONE) },
+ { },
+};
+
+static const struct adreno_reglist_pipe a850_nonctxt_regs[] = {
+ { REG_A8XX_CP_SMMU_STREAM_ID_LPAC, 0x00000101, BIT(PIPE_NONE) },
+ { REG_A8XX_CP_MULTIDRAW_CNTL, 0x00000001, BIT(PIPE_NONE) },
+ { REG_A8XX_GRAS_DBG_ECO_CNTL, 0x01000800, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_GRAS_TSEFE_DBG_ECO_CNTL, 0x00200000, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A6XX_PC_AUTO_VERTEX_STRIDE, 0x00000001, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_PC_VIS_STREAM_CNTL, 0x10010000, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_PC_CONTEXT_SWITCH_STABILIZE_CNTL_1, 0x00000002, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_PC_CHICKEN_BITS_1, 0x00000003, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_PC_CHICKEN_BITS_2, 0x00000200, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_PC_CHICKEN_BITS_3, 0x00400000, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_PC_CHICKEN_BITS_4, 0x00500050, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_PC_CHICKEN_BITS_5, BIT(28), BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A7XX_RB_CCU_CNTL, 0x00000068, BIT(PIPE_BR) },
+ { REG_A7XX_RB_CCU_DBG_ECO_CNTL, BIT(10) | BIT(9), BIT(PIPE_BR) },
+ { REG_A6XX_RB_DBG_ECO_CNTL, BIT(17), BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_RB_GC_GMEM_PROTECT, 0x12000000, BIT(PIPE_BR) },
+ { REG_A6XX_RB_RBP_CNTL, BIT(5) | BIT(6), BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_RB_RESOLVE_PREFETCH_CNTL, 0x00000007, BIT(PIPE_BR) },
+ { REG_A8XX_RB_CMP_DBG_ECO_CNTL, 0x00004000, BIT(PIPE_BR) },
+ { REG_A8XX_RBBM_NC_MODE_CNTL, 0x00000001, BIT(PIPE_NONE) },
+ { REG_A8XX_RBBM_SLICE_NC_MODE_CNTL, 0x00000001, BIT(PIPE_NONE) },
+ { REG_A8XX_RBBM_SLICE_PERFCTR_CNTL, BIT(0), BIT(PIPE_NONE) },
+ { REG_A8XX_RBBM_POWER_UP_RESET_SW_OVERRIDE, 0x70809060, BIT(PIPE_NONE) },
+ { REG_A8XX_RBBM_POWER_UP_RESET_SW_BV_OVERRIDE, 0x30000000, BIT(PIPE_NONE) },
+ { REG_A8XX_RBBM_WAIT_IDLE_CLOCKS_CNTL, 0x00000030, BIT(PIPE_NONE) },
+ { REG_A8XX_RBBM_WAIT_IDLE_CLOCKS_CNTL2, 0x00000030, BIT(PIPE_NONE) },
+ { REG_A8XX_RBBM_GBIF_CLIENT_QOS_CNTL, 0x22122212, BIT(PIPE_NONE) },
+ { REG_A8XX_RBBM_CGC_P2S_CNTL, 0x00000040, BIT(PIPE_NONE) },
+ { REG_A6XX_SP_CHICKEN_BITS, BIT(24), BIT(PIPE_NONE) },
+ { REG_A7XX_SP_CHICKEN_BITS_2, 0x00820800, BIT(PIPE_NONE) },
+ { REG_A7XX_SP_CHICKEN_BITS_3, 0x00300000, BIT(PIPE_NONE) },
+ { REG_A8XX_SP_CHICKEN_BITS_5, BIT(3), BIT(PIPE_NONE) },
+ { REG_A6XX_SP_PERFCTR_SHADER_MASK, 0x0000003f, BIT(PIPE_NONE) },
+ { REG_A7XX_SP_HLSQ_DBG_ECO_CNTL, 0x04000000, BIT(PIPE_NONE) },
+ { REG_A7XX_SP_HLSQ_DBG_ECO_CNTL_1, BIT(17), BIT(PIPE_NONE) },
+ { REG_A8XX_SP_HLSQ_DBG_ECO_CNTL_3, BIT(1), BIT(PIPE_NONE) },
+ { REG_A7XX_SP_HLSQ_TIMEOUT_THRESHOLD_DP, 0x00000080, BIT(PIPE_NONE) },
+ { REG_A7XX_SP_READ_SEL, 0x0001ff00, BIT(PIPE_NONE) },
+ { REG_A8XX_SP_L0_PERF_TUNE, 0x00000024, BIT(PIPE_NONE) },
+ { REG_A6XX_TPL1_DBG_ECO_CNTL, 0x10100000, BIT(PIPE_NONE) },
+ { REG_A6XX_TPL1_DBG_ECO_CNTL1, 0x00000720, BIT(PIPE_NONE) },
+ { REG_A6XX_UCHE_MODE_CNTL, 0x80080000, BIT(PIPE_NONE) },
+ { REG_A8XX_UCHE_CCHE_MODE_CNTL, 0x00001000, BIT(PIPE_NONE) },
+ { REG_A8XX_UCHE_DBG_ECO_CNTL_0, BIT(31), BIT(PIPE_NONE) },
+ { REG_A8XX_UCHE_HW_DBG_CNTL, 0x01410000, BIT(PIPE_NONE) },
+ { REG_A8XX_UCHE_CCHE_CACHE_WAYS, 0x00000800, BIT(PIPE_NONE) },
+ { REG_A8XX_UCHE_GBIF_GX_CONFIG, 0x010240e0, BIT(PIPE_NONE) },
+ { REG_A8XX_UCHE_VARB_IDLE_TIMEOUT, 0x00000020, BIT(PIPE_NONE) },
+ { REG_A7XX_VFD_DBG_ECO_CNTL, 0x00008000, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_VFD_CB_BV_THRESHOLD, 0x00500050, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_VFD_CB_BR_THRESHOLD, 0x00600060, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_VFD_CB_BUSY_REQ_CNT, 0x00200020, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_VFD_CB_LP_REQ_CNT, 0x00080020, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_VPC_FLATSHADE_MODE_CNTL, 0x00000001, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_VSC_VISIBILITY_FLUSH_CNTL, 0x00080004, BIT(PIPE_NONE) },
+ { },
+};
+
+static const u32 a850_protect_regs[] = {
+ A6XX_PROTECT_RDONLY(0x00008, 0x039b),
+ A6XX_PROTECT_RDONLY(0x003b4, 0x008b),
+ A6XX_PROTECT_NORDWR(0x00440, 0x001f),
+ A6XX_PROTECT_RDONLY(0x00580, 0x005f),
+ A6XX_PROTECT_NORDWR(0x005e0, 0x011f),
+ A6XX_PROTECT_RDONLY(0x0074a, 0x0005),
+ A6XX_PROTECT_RDONLY(0x00759, 0x001b),
+ A6XX_PROTECT_NORDWR(0x00775, 0x000a),
+ A6XX_PROTECT_RDONLY(0x00789, 0x0000),
+ A6XX_PROTECT_RDONLY(0x0078c, 0x0013),
+ A6XX_PROTECT_NORDWR(0x00800, 0x0029),
+ A6XX_PROTECT_NORDWR(0x00837, 0x00af),
+ A6XX_PROTECT_RDONLY(0x008e7, 0x00c9),
+ A6XX_PROTECT_NORDWR(0x008ec, 0x00c3),
+ A6XX_PROTECT_NORDWR(0x009b1, 0x0250),
+ A6XX_PROTECT_NORDWR(0x00c07, 0x0008),
+ A6XX_PROTECT_RDONLY(0x00ce0, 0x0001),
+ A6XX_PROTECT_RDONLY(0x00df0, 0x0000),
+ A6XX_PROTECT_NORDWR(0x00df1, 0x0000),
+ A6XX_PROTECT_NORDWR(0x00df5, 0x0003),
+ A6XX_PROTECT_RDONLY(0x00df9, 0x0007),
+ A6XX_PROTECT_NORDWR(0x00e01, 0x0000),
+ A6XX_PROTECT_NORDWR(0x00e03, 0x1fff),
+ A6XX_PROTECT_NORDWR(0x03c00, 0x00c5),
+ A6XX_PROTECT_RDONLY(0x03cc6, 0x0039),
+ A6XX_PROTECT_NORDWR(0x03d00, 0x1fff),
+ A6XX_PROTECT_NORDWR(0x08600, 0x01ff),
+ A6XX_PROTECT_NORDWR(0x08e00, 0x00ff),
+ A6XX_PROTECT_RDONLY(0x08f00, 0x0000),
+ A6XX_PROTECT_NORDWR(0x08f01, 0x01be),
+ A6XX_PROTECT_NORDWR(0x09600, 0x01ff),
+ A6XX_PROTECT_RDONLY(0x0981a, 0x02e5),
+ A6XX_PROTECT_NORDWR(0x09e00, 0x01ff),
+ A6XX_PROTECT_NORDWR(0x0a600, 0x01ff),
+ A6XX_PROTECT_NORDWR(0x0a82e, 0x0000),
+ A6XX_PROTECT_NORDWR(0x0ae00, 0x0000),
+ A6XX_PROTECT_NORDWR(0x0ae02, 0x0004),
+ A6XX_PROTECT_NORDWR(0x0ae08, 0x0006),
+ A6XX_PROTECT_NORDWR(0x0ae10, 0x00bf),
+ A6XX_PROTECT_RDONLY(0x0aed0, 0x002f),
+ A6XX_PROTECT_NORDWR(0x0af00, 0x027f),
+ A6XX_PROTECT_NORDWR(0x0b600, 0x1fff),
+ A6XX_PROTECT_NORDWR(0x0dc00, 0x1fff),
+ A6XX_PROTECT_RDONLY(0x0fc00, 0x1fff),
+ A6XX_PROTECT_NORDWR(0x18400, 0x003f),
+ A6XX_PROTECT_RDONLY(0x18440, 0x013f),
+ A6XX_PROTECT_NORDWR(0x18580, 0x1fff),
+ A6XX_PROTECT_NORDWR(0x1ac00, 0x1fff),
+ A6XX_PROTECT_NORDWR(0x1cc00, 0x1fff),
+ A6XX_PROTECT_NORDWR(0x1f400, 0x0477),
+ A6XX_PROTECT_RDONLY(0x1f878, 0x0507),
+ A6XX_PROTECT_NORDWR(0x1f930, 0x0329),
+ A6XX_PROTECT_NORDWR(0x1fd80, 0x1fff),
+ A6XX_PROTECT_NORDWR(0x27800, 0x007f),
+ A6XX_PROTECT_RDONLY(0x27880, 0x0385),
+ A6XX_PROTECT_NORDWR(0x27882, 0x0035),
+ A6XX_PROTECT_NORDWR(0x27c06, 0x0000),
+};
+DECLARE_ADRENO_PROTECT(a850_protect, 15);
+
+static const u32 a850_pwrup_reglist_regs[] = {
+ REG_A8XX_RB_CMP_NC_MODE_CNTL,
+ REG_A8XX_SP_HLSQ_GC_GMEM_RANGE_MIN,
+ REG_A8XX_SP_HLSQ_GC_GMEM_RANGE_MIN + 1,
+ REG_A7XX_SP_HLSQ_TIMEOUT_THRESHOLD_DP,
+ REG_A7XX_SP_READ_SEL,
+ REG_A8XX_CP_MULTIDRAW_CNTL,
+ REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(0),
+ REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(1),
+ REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(2),
+ REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(3),
+ REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(4),
+ REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(5),
+ REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(6),
+ REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(7),
+ REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(8),
+ REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(9),
+ REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(10),
+ REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(11),
+ REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(12),
+ REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(13),
+ REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(14),
+ REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(15),
+ REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(16),
+ REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(17),
+ REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(18),
+ REG_A8XX_TPL1_BICUBIC_WEIGHTS_TABLE(19),
+ REG_A6XX_TPL1_DBG_ECO_CNTL,
+ REG_A6XX_TPL1_DBG_ECO_CNTL1,
+ REG_A6XX_TPL1_NC_MODE_CNTL,
+ REG_A6XX_UCHE_MODE_CNTL,
+ REG_A8XX_UCHE_CCHE_MODE_CNTL,
+ REG_A8XX_UCHE_HW_DBG_CNTL,
+ REG_A8XX_UCHE_CCHE_CACHE_WAYS,
+ REG_A8XX_UCHE_CCHE_GC_GMEM_RANGE_MIN,
+ REG_A8XX_UCHE_CCHE_GC_GMEM_RANGE_MIN + 1,
+ REG_A8XX_UCHE_CCHE_LPAC_GMEM_RANGE_MIN,
+ REG_A8XX_UCHE_CCHE_LPAC_GMEM_RANGE_MIN + 1,
+ REG_A8XX_UCHE_CCHE_TRAP_BASE,
+ REG_A8XX_UCHE_CCHE_TRAP_BASE + 1,
+ REG_A8XX_UCHE_CCHE_WRITE_THRU_BASE,
+ REG_A8XX_UCHE_CCHE_WRITE_THRU_BASE + 1,
+ REG_A8XX_UCHE_CLIENT_PF,
+ REG_A8XX_UCHE_DBG_ECO_CNTL_0,
+ REG_A8XX_UCHE_GBIF_GX_CONFIG,
+ REG_A8XX_UCHE_TRAP_BASE,
+ REG_A8XX_UCHE_TRAP_BASE + 1,
+ REG_A8XX_UCHE_VARB_IDLE_TIMEOUT,
+ REG_A8XX_UCHE_WRITE_THRU_BASE,
+ REG_A8XX_UCHE_WRITE_THRU_BASE + 1,
+ REG_A8XX_VSC_VISIBILITY_FLUSH_CNTL,
+};
+DECLARE_ADRENO_REGLIST_LIST(a850_pwrup_reglist);
+
+static const u32 a850_ifpc_reglist_regs[] = {
+ REG_A8XX_CP_INTERRUPT_STATUS_MASK_GLOBAL,
+ REG_A8XX_RBBM_NC_MODE_CNTL,
+ REG_A8XX_RBBM_SLICE_INTERFACE_HANG_INT_CNTL,
+ REG_A8XX_RBBM_SLICE_NC_MODE_CNTL,
+ REG_A8XX_RBBM_SLICE_PERFCTR_CNTL,
+ REG_A6XX_SP_CHICKEN_BITS,
+ REG_A7XX_SP_CHICKEN_BITS_2,
+ REG_A7XX_SP_CHICKEN_BITS_3,
+ REG_A8XX_SP_CHICKEN_BITS_5,
+ REG_A7XX_SP_HLSQ_DBG_ECO_CNTL,
+ REG_A7XX_SP_HLSQ_DBG_ECO_CNTL_1,
+ REG_A8XX_SP_HLSQ_DBG_ECO_CNTL_3,
+ REG_A8XX_SP_HLSQ_LPAC_GMEM_RANGE_MIN,
+ REG_A8XX_SP_HLSQ_LPAC_GMEM_RANGE_MIN + 1,
+ REG_A6XX_SP_NC_MODE_CNTL,
+ REG_A6XX_SP_PERFCTR_SHADER_MASK,
+ REG_A8XX_SP_L0_PERF_TUNE,
+ REG_A8XX_CP_PROTECT_GLOBAL(0),
+ REG_A8XX_CP_PROTECT_GLOBAL(1),
+ REG_A8XX_CP_PROTECT_GLOBAL(2),
+ REG_A8XX_CP_PROTECT_GLOBAL(3),
+ REG_A8XX_CP_PROTECT_GLOBAL(4),
+ REG_A8XX_CP_PROTECT_GLOBAL(5),
+ REG_A8XX_CP_PROTECT_GLOBAL(6),
+ REG_A8XX_CP_PROTECT_GLOBAL(7),
+ REG_A8XX_CP_PROTECT_GLOBAL(8),
+ REG_A8XX_CP_PROTECT_GLOBAL(9),
+ REG_A8XX_CP_PROTECT_GLOBAL(10),
+ REG_A8XX_CP_PROTECT_GLOBAL(11),
+ REG_A8XX_CP_PROTECT_GLOBAL(12),
+ REG_A8XX_CP_PROTECT_GLOBAL(13),
+ REG_A8XX_CP_PROTECT_GLOBAL(14),
+ REG_A8XX_CP_PROTECT_GLOBAL(15),
+ REG_A8XX_CP_PROTECT_GLOBAL(16),
+ REG_A8XX_CP_PROTECT_GLOBAL(17),
+ REG_A8XX_CP_PROTECT_GLOBAL(18),
+ REG_A8XX_CP_PROTECT_GLOBAL(19),
+ REG_A8XX_CP_PROTECT_GLOBAL(20),
+ REG_A8XX_CP_PROTECT_GLOBAL(21),
+ REG_A8XX_CP_PROTECT_GLOBAL(22),
+ REG_A8XX_CP_PROTECT_GLOBAL(23),
+ REG_A8XX_CP_PROTECT_GLOBAL(24),
+ REG_A8XX_CP_PROTECT_GLOBAL(25),
+ REG_A8XX_CP_PROTECT_GLOBAL(26),
+ REG_A8XX_CP_PROTECT_GLOBAL(27),
+ REG_A8XX_CP_PROTECT_GLOBAL(28),
+ REG_A8XX_CP_PROTECT_GLOBAL(29),
+ REG_A8XX_CP_PROTECT_GLOBAL(30),
+ REG_A8XX_CP_PROTECT_GLOBAL(31),
+ REG_A8XX_CP_PROTECT_GLOBAL(32),
+ REG_A8XX_CP_PROTECT_GLOBAL(33),
+ REG_A8XX_CP_PROTECT_GLOBAL(34),
+ REG_A8XX_CP_PROTECT_GLOBAL(35),
+ REG_A8XX_CP_PROTECT_GLOBAL(36),
+ REG_A8XX_CP_PROTECT_GLOBAL(37),
+ REG_A8XX_CP_PROTECT_GLOBAL(38),
+ REG_A8XX_CP_PROTECT_GLOBAL(39),
+ REG_A8XX_CP_PROTECT_GLOBAL(40),
+ REG_A8XX_CP_PROTECT_GLOBAL(41),
+ REG_A8XX_CP_PROTECT_GLOBAL(42),
+ REG_A8XX_CP_PROTECT_GLOBAL(43),
+ REG_A8XX_CP_PROTECT_GLOBAL(44),
+ REG_A8XX_CP_PROTECT_GLOBAL(45),
+ REG_A8XX_CP_PROTECT_GLOBAL(46),
+ REG_A8XX_CP_PROTECT_GLOBAL(47),
+ REG_A8XX_CP_PROTECT_GLOBAL(48),
+ REG_A8XX_CP_PROTECT_GLOBAL(49),
+ REG_A8XX_CP_PROTECT_GLOBAL(50),
+ REG_A8XX_CP_PROTECT_GLOBAL(51),
+ REG_A8XX_CP_PROTECT_GLOBAL(52),
+ REG_A8XX_CP_PROTECT_GLOBAL(53),
+ REG_A8XX_CP_PROTECT_GLOBAL(54),
+ REG_A8XX_CP_PROTECT_GLOBAL(55),
+ REG_A8XX_CP_PROTECT_GLOBAL(63),
+};
+DECLARE_ADRENO_REGLIST_LIST(a850_ifpc_reglist);
+
+static const struct adreno_reglist a850_gbif[] = {
+ { REG_A6XX_GBIF_QSB_SIDE0, 0x00071e20 },
+ { REG_A6XX_GBIF_QSB_SIDE1, 0x00071e20 },
+ { REG_A6XX_GBIF_QSB_SIDE2, 0x00071e20 },
+ { REG_A6XX_GBIF_QSB_SIDE3, 0x00071e20 },
+ { REG_A6XX_GBIF_CX_CONFIG, 0x20023020 },
+ { },
+};
+
+static const struct adreno_reglist_pipe a850_dyn_pwrup_reglist_regs[] = {
+ { REG_A8XX_GRAS_TSEFE_DBG_ECO_CNTL, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_GRAS_NC_MODE_CNTL, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_GRAS_DBG_ECO_CNTL, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A6XX_PC_AUTO_VERTEX_STRIDE, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_PC_CHICKEN_BITS_1, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_PC_CHICKEN_BITS_2, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_PC_CHICKEN_BITS_3, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_PC_CHICKEN_BITS_4, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_PC_CHICKEN_BITS_5, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_PC_CONTEXT_SWITCH_STABILIZE_CNTL_1, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_PC_VIS_STREAM_CNTL, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A7XX_RB_CCU_CNTL, 0, BIT(PIPE_BR) },
+ { REG_A7XX_RB_CCU_DBG_ECO_CNTL, 0, BIT(PIPE_BR)},
+ { REG_A8XX_RB_CCU_NC_MODE_CNTL, 0, BIT(PIPE_BR) },
+ { REG_A8XX_RB_CMP_NC_MODE_CNTL, 0, BIT(PIPE_BR) },
+ { REG_A6XX_RB_RBP_CNTL, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_RB_RESOLVE_PREFETCH_CNTL, 0, BIT(PIPE_BR) },
+ { REG_A6XX_RB_DBG_ECO_CNTL, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_RB_CMP_DBG_ECO_CNTL, 0, BIT(PIPE_BR) },
+ { REG_A7XX_VFD_DBG_ECO_CNTL, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_VFD_CB_BV_THRESHOLD, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_VFD_CB_BR_THRESHOLD, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_VFD_CB_BUSY_REQ_CNT, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_VFD_CB_LP_REQ_CNT, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_VPC_FLATSHADE_MODE_CNTL, 0, BIT(PIPE_BV) | BIT(PIPE_BR) },
+ { REG_A8XX_CP_HW_FAULT_STATUS_MASK_PIPE, 0, BIT(PIPE_BR) |
+ BIT(PIPE_BV) | BIT(PIPE_LPAC) | BIT(PIPE_AQE0) |
+ BIT(PIPE_AQE1) | BIT(PIPE_DDE_BR) | BIT(PIPE_DDE_BV) },
+ { REG_A8XX_CP_INTERRUPT_STATUS_MASK_PIPE, 0, BIT(PIPE_BR) |
+ BIT(PIPE_BV) | BIT(PIPE_LPAC) | BIT(PIPE_AQE0) |
+ BIT(PIPE_AQE1) | BIT(PIPE_DDE_BR) | BIT(PIPE_DDE_BV) },
+ { REG_A8XX_CP_PROTECT_CNTL_PIPE, 0, BIT(PIPE_BR) | BIT(PIPE_BV) | BIT(PIPE_LPAC) },
+ { REG_A8XX_CP_PROTECT_PIPE(15), 0, BIT(PIPE_BR) | BIT(PIPE_BV) | BIT(PIPE_LPAC) },
+ { REG_A8XX_RB_GC_GMEM_PROTECT, 0, BIT(PIPE_BR) },
+ { REG_A8XX_RB_LPAC_GMEM_PROTECT, 0, BIT(PIPE_BR) },
+ { REG_A6XX_RB_CONTEXT_SWITCH_GMEM_SAVE_RESTORE_ENABLE, 0, BIT(PIPE_BR) },
+};
+DECLARE_ADRENO_REGLIST_PIPE_LIST(a850_dyn_pwrup_reglist);
+
static const struct adreno_info a8xx_gpus[] = {
{
.chip_ids = ADRENO_CHIP_IDS(0x44050001),
@@ -2857,6 +3217,134 @@ static const struct adreno_info a8xx_gpus[] = {
{ 242, 1 },
{ 221, 2 },
),
+ }, {
+ .chip_ids = ADRENO_CHIP_IDS(0x44060000),
+ .family = ADRENO_8XX_GEN2,
+ .fw = {
+ [ADRENO_FW_SQE] = "gen80100_sqe.fw",
+ [ADRENO_FW_GMU] = "gen80100_gmu.bin",
+ [ADRENO_FW_AQE] = "gen80100_aqe.fw",
+ },
+ .gmem = 15 * SZ_1M + SZ_512K + SZ_256K,
+ .inactive_period = DRM_MSM_INACTIVE_PERIOD,
+ .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT |
+ ADRENO_QUIRK_HAS_HW_APRIV |
+ ADRENO_QUIRK_PREEMPTION |
+ ADRENO_QUIRK_SOFTFUSE,
+ .funcs = &a8xx_gpu_funcs,
+ .a6xx = &(const struct a6xx_info) {
+ .protect = &x285_protect,
+ .nonctxt_reglist = x285_nonctxt_regs,
+ .pwrup_reglist = &a840_pwrup_reglist,
+ .dyn_pwrup_reglist = &x285_dyn_pwrup_reglist,
+ .ifpc_reglist = &a840_ifpc_reglist,
+ .gbif_cx = a840_gbif,
+ .max_slices = 3,
+ .gmu_chipid = 0x80a0000,
+ .bcms = (const struct a6xx_bcm[]) {
+ { .name = "SH0", .buswidth = 16 },
+ { .name = "MC0", .buswidth = 4 },
+ {
+ .name = "ACV",
+ .fixed = true,
+ .perfmode = BIT(2),
+ .perfmode_bw = 16500000,
+ },
+ { /* sentinel */ },
+ },
+ },
+ .speedbins = ADRENO_SPEEDBINS(
+ { 0, 0 },
+ { 388, 1 },
+ { 357, 2 },
+ { 284, 3 },
+ ),
+ }, {
+ .chip_ids = ADRENO_CHIP_IDS(0x44051401),
+ .family = ADRENO_8XX_GEN2,
+ .fw = {
+ [ADRENO_FW_SQE] = "gen81100_sqe.fw",
+ [ADRENO_FW_GMU] = "gen81100_gmu.bin",
+ [ADRENO_FW_AQE] = "gen81100_aqe.fw",
+ },
+ .gmem = 18 * SZ_1M,
+ .inactive_period = DRM_MSM_INACTIVE_PERIOD,
+ .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT |
+ ADRENO_QUIRK_HAS_HW_APRIV |
+ ADRENO_QUIRK_PREEMPTION |
+ ADRENO_QUIRK_IFPC,
+ .funcs = &a8xx_gpu_funcs,
+ .a6xx = &(const struct a6xx_info) {
+ .protect = &a850_protect,
+ .nonctxt_reglist = a850_nonctxt_regs,
+ .pwrup_reglist = &a850_pwrup_reglist,
+ .dyn_pwrup_reglist = &a850_dyn_pwrup_reglist,
+ .ifpc_reglist = &a850_ifpc_reglist,
+ .gbif_cx = a850_gbif,
+ .max_slices = 3,
+ .gmu_chipid = 0x80b0100,
+ .thinmem_config = 14,
+ .bcms = (const struct a6xx_bcm[]) {
+ { .name = "SH0", .buswidth = 32 },
+ { .name = "MC0", .buswidth = 4 },
+ {
+ .name = "ACV",
+ .fixed = true,
+ .perfmode = BIT(2),
+ .perfmode_bw = 16500000,
+ },
+ { /* sentinel */ },
+ },
+ },
+ .preempt_record_size = 19708 * SZ_1K,
+ .speedbins = ADRENO_SPEEDBINS(
+ { 0, 0 },
+ { 284, 2 },
+ { 216, 3 },
+ ),
+ }, {
+ .chip_ids = ADRENO_CHIP_IDS(0x44041400),
+ .family = ADRENO_8XX_GEN2,
+ .fw = {
+ [ADRENO_FW_SQE] = "gen81100_sqe.fw",
+ [ADRENO_FW_GMU] = "gen81400_gmu.bin",
+ [ADRENO_FW_AQE] = "gen81100_aqe.fw",
+ },
+ .gmem = 12 * SZ_1M,
+ .inactive_period = DRM_MSM_INACTIVE_PERIOD,
+ .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT |
+ ADRENO_QUIRK_HAS_HW_APRIV |
+ ADRENO_QUIRK_PREEMPTION |
+ ADRENO_QUIRK_IFPC,
+ .funcs = &a8xx_gpu_funcs,
+ .a6xx = &(const struct a6xx_info) {
+ .protect = &a850_protect,
+ .nonctxt_reglist = a845_nonctxt_regs,
+ .pwrup_reglist = &a850_pwrup_reglist,
+ .dyn_pwrup_reglist = &a850_dyn_pwrup_reglist,
+ .ifpc_reglist = &a850_ifpc_reglist,
+ .gbif_cx = a850_gbif,
+ .max_slices = 3,
+ .gmu_chipid = 0x80e0000,
+ .thinmem_config = 14,
+ .bcms = (const struct a6xx_bcm[]) {
+ { .name = "SH0", .buswidth = 32 },
+ { .name = "MC0", .buswidth = 4 },
+ {
+ .name = "ACV",
+ .fixed = true,
+ .perfmode = BIT(2),
+ .perfmode_bw = 16500000,
+ },
+ { /* sentinel */ },
+ },
+ },
+ .preempt_record_size = 13564 * SZ_1K,
+ .speedbins = ADRENO_SPEEDBINS(
+ { 0, 0 },
+ { 0xd8, 0 },
+ { 0x11c, 1 },
+ ),
}
};
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
index 27cac853975f9..261048f482e6d 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
@@ -145,6 +145,19 @@ bool a8xx_gmu_gx_is_on(struct adreno_gpu *adreno_gpu)
if (!gmu->initialized)
return false;
+ /*
+ * Use the CX_MISC_GFX_PWR_CLK_STATUS register instead of the GMUCX
+ * register to ensure correct GDSC and clock status reporting even
+ * when the GMU MX domain is powered off
+ */
+ if (adreno_is_a850_family(adreno_gpu)) {
+ val = a6xx_cx_misc_read(a6xx_gpu, REG_A8XX_CX_MISC_GFX_PWR_CLK_STATUS);
+
+ return !(val &
+ (A8XX_CX_MISC_GFX_PWR_CLK_STATUS_GX_GDSC_POWER_OFF |
+ A8XX_CX_MISC_GFX_PWR_CLK_STATUS_GX_CLK_OFF));
+ }
+
val = gmu_read(gmu, REG_A8XX_GMU_PWR_CLK_STATUS);
return !(val &
@@ -645,7 +658,7 @@ static void a6xx_rpmh_stop(struct a6xx_gmu *gmu)
if (!test_and_clear_bit(GMU_STATUS_FW_START, &gmu->status))
return;
- if (adreno_is_a840(adreno_gpu))
+ if (adreno_is_a840(adreno_gpu) || adreno_is_a850_family(adreno_gpu))
bitmask = BIT(30);
gmu_write(gmu, REG_A6XX_GMU_RSCC_CONTROL_REQ, 1);
@@ -1656,8 +1669,12 @@ static int a6xx_gmu_rpmh_bw_votes_init(struct adreno_gpu *adreno_gpu,
if (bcm->fixed) {
u32 perfmode = 0;
- /* GMU on A6xx votes perfmode on all valid bandwidth */
- if (!adreno_is_a7xx(adreno_gpu) ||
+ /*
+ * GMU on A6xx votes perfmode on all valid
+ * bandwidth. A7xx and A8xx only vote perfmode
+ * above the perfmode_bw threshold.
+ */
+ if (adreno_is_a6xx(adreno_gpu) ||
(bcm->perfmode_bw && bw >= bcm->perfmode_bw))
perfmode = bcm->perfmode;
@@ -1707,70 +1724,85 @@ static unsigned int a6xx_gmu_get_arc_level(struct device *dev,
return val;
}
+static const u16 *a6xx_gmu_rpmh_read_arc(const char *id, size_t *count)
+{
+ const u16 *vals;
+
+ vals = cmd_db_read_aux_data(id, count);
+ if (IS_ERR(vals))
+ return vals;
+
+ *count >>= 1;
+ /* Exclude the trailing zero paddings if there are any */
+ while (*count && !vals[*count - 1])
+ (*count)--;
+
+ if (!*count)
+ return ERR_PTR(-EINVAL);
+
+ return vals;
+}
+
+/*
+ * Find the first index in an arc level array whose level is greater than or
+ * equal to the target. If no level is high enough, either clamp to the
+ * highest available level (@clamp) or fail, dumping the list.
+ */
+static int a6xx_gmu_rpmh_arc_index(struct device *dev, const u16 *arc,
+ size_t arc_count, unsigned int level, bool clamp)
+{
+ int j;
+
+ for (j = 0; j < arc_count; j++) {
+ if (arc[j] >= level)
+ return j;
+ }
+
+ if (clamp)
+ return arc_count - 1;
+
+ DRM_DEV_ERROR(dev, "Level %u not found in the RPMh list\n", level);
+ DRM_DEV_ERROR(dev, "Available levels:\n");
+ for (j = 0; j < arc_count; j++)
+ DRM_DEV_ERROR(dev, " %u\n", arc[j]);
+
+ return -EINVAL;
+}
+
static int a6xx_gmu_rpmh_arc_votes_init(struct device *dev, u32 *votes,
unsigned long *freqs, int freqs_count,
const char *pri_id, const char *sec_id)
{
- int i, j;
+ int i;
const u16 *pri, *sec;
size_t pri_count, sec_count;
- pri = cmd_db_read_aux_data(pri_id, &pri_count);
+ pri = a6xx_gmu_rpmh_read_arc(pri_id, &pri_count);
if (IS_ERR(pri))
return PTR_ERR(pri);
- /*
- * The data comes back as an array of unsigned shorts so adjust the
- * count accordingly
- */
- pri_count >>= 1;
- if (!pri_count)
- return -EINVAL;
- sec = cmd_db_read_aux_data(sec_id, &sec_count);
+ sec = a6xx_gmu_rpmh_read_arc(sec_id, &sec_count);
if (IS_ERR(sec))
return PTR_ERR(sec);
- sec_count >>= 1;
- if (!sec_count)
- return -EINVAL;
-
/* Construct a vote for each frequency */
for (i = 0; i < freqs_count; i++) {
- u8 pindex = 0, sindex = 0;
unsigned int level = a6xx_gmu_get_arc_level(dev, freqs[i]);
+ int pindex, sindex;
- /* Get the primary index that matches the arc level */
- for (j = 0; j < pri_count; j++) {
- if (pri[j] >= level) {
- pindex = j;
- break;
- }
- }
-
- if (j == pri_count) {
- DRM_DEV_ERROR(dev,
- "Level %u not found in the RPMh list\n",
- level);
- DRM_DEV_ERROR(dev, "Available levels:\n");
- for (j = 0; j < pri_count; j++)
- DRM_DEV_ERROR(dev, " %u\n", pri[j]);
-
- return -EINVAL;
- }
+ pindex = a6xx_gmu_rpmh_arc_index(dev, pri, pri_count, level, false);
+ if (pindex < 0)
+ return pindex;
/*
- * Look for a level in in the secondary list that matches. If
- * nothing fits, use the maximum non zero vote
+ * Look for a matching level in the secondary list; if nothing
+ * fits, clamp to the highest available vote. The secondary rail
+ * depends on the primary rail, so match it against the selected
+ * primary voltage (which is >= the requested level), not the
+ * requested level itself.
*/
-
- for (j = 0; j < sec_count; j++) {
- if (sec[j] >= level) {
- sindex = j;
- break;
- } else if (sec[j]) {
- sindex = j;
- }
- }
+ sindex = a6xx_gmu_rpmh_arc_index(dev, sec, sec_count,
+ pri[pindex], true);
/* Construct the vote */
votes[i] = ((pri[pindex] & 0xffff) << 16) |
@@ -1780,22 +1812,33 @@ static int a6xx_gmu_rpmh_arc_votes_init(struct device *dev, u32 *votes,
return 0;
}
+#define GMU_BX_MASK GENMASK(25, 20)
+
static int a6xx_gmu_rpmh_dep_votes_init(struct device *dev, u32 *votes,
unsigned long *freqs, int freqs_count)
{
- const u16 *mx;
- size_t count;
+ const u16 *mx, *gx = NULL, *gbx;
+ size_t count, gx_count = 0, gbx_count = 0;
- mx = cmd_db_read_aux_data("mx.lvl", &count);
+ mx = a6xx_gmu_rpmh_read_arc("mx.lvl", &count);
if (IS_ERR(mx))
return PTR_ERR(mx);
+
/*
- * The data comes back as an array of unsigned shorts so adjust the
- * count accordingly
+ * Targets with a third memory rail (BX), in addition to GX and MX,
+ * expect a per-corner BX vote packed into the dependency vote. Detect
+ * such targets by the presence of the "gbx.lvl" RPMh resource. The BX
+ * corner is matched against the Gx rail level, so the "gfx.lvl" corners
+ * are needed as well.
*/
- count >>= 1;
- if (!count)
- return -EINVAL;
+ gbx = a6xx_gmu_rpmh_read_arc("gbx.lvl", &gbx_count);
+ if (IS_ERR(gbx)) {
+ gbx = NULL;
+ } else {
+ gx = a6xx_gmu_rpmh_read_arc("gfx.lvl", &gx_count);
+ if (IS_ERR(gx))
+ return PTR_ERR(gx);
+ }
/* Fix the vote for zero frequency */
votes[0] = 0xffffffff;
@@ -1803,29 +1846,28 @@ static int a6xx_gmu_rpmh_dep_votes_init(struct device *dev, u32 *votes,
/* Construct a vote for rest of the corners */
for (int i = 1; i < freqs_count; i++) {
unsigned int level = a6xx_gmu_get_arc_level(dev, freqs[i]);
- u8 j, index = 0;
+ int index = a6xx_gmu_rpmh_arc_index(dev, mx, count, level, true);
+ int bx;
- /* Get the primary index that matches the arc level */
- for (j = 0; j < count; j++) {
- if (mx[j] >= level) {
- index = j;
- break;
- }
- }
-
- if (j == count) {
- DRM_DEV_ERROR(dev,
- "Mx Level %u not found in the RPMh list\n",
- level);
- DRM_DEV_ERROR(dev, "Available levels:\n");
- for (j = 0; j < count; j++)
- DRM_DEV_ERROR(dev, " %u\n", mx[j]);
-
- return -EINVAL;
- }
+ if (index < 0)
+ return index;
/* Construct the vote */
votes[i] = (0x3fff << 14) | (index << 8) | (0xff);
+
+ if (!gbx)
+ continue;
+
+ index = a6xx_gmu_rpmh_arc_index(dev, gx, gx_count, level, false);
+ if (index < 0)
+ return index;
+
+ /*
+ * Find the BX corner that satisfies that Gx level, falling
+ * back to the highest BX corner if none is high enough.
+ */
+ bx = a6xx_gmu_rpmh_arc_index(dev, gbx, gbx_count, gx[index], true);
+ FIELD_MODIFY(GMU_BX_MASK, &votes[i], bx);
}
return 0;
@@ -1860,13 +1902,13 @@ static int a6xx_gmu_rpmh_votes_init(struct a6xx_gmu *gmu)
ret = a6xx_gmu_rpmh_arc_votes_init(&gpu->pdev->dev, gmu->gx_arc_votes,
gmu->gpu_freqs, gmu->nr_gpu_freqs, "gfx.lvl", sec_id);
+ ret |= a6xx_gmu_rpmh_dep_votes_init(&gpu->pdev->dev, gmu->dep_arc_votes,
+ gmu->gpu_freqs, gmu->nr_gpu_freqs);
+
/* Build the CX votes */
ret |= a6xx_gmu_rpmh_arc_votes_init(gmu->dev, gmu->cx_arc_votes,
gmu->gmu_freqs, gmu->nr_gmu_freqs, "cx.lvl", "mx.lvl");
- ret |= a6xx_gmu_rpmh_dep_votes_init(gmu->dev, gmu->dep_arc_votes,
- gmu->gpu_freqs, gmu->nr_gpu_freqs);
-
/* Build the interconnect votes */
if (info->bcms && gmu->nr_gpu_bws > 1)
ret |= a6xx_gmu_rpmh_bw_votes_init(adreno_gpu, info, gmu);
@@ -2141,6 +2183,9 @@ void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu)
dev_pm_domain_detach(gmu->gxpd, false);
}
+ if (!IS_ERR_OR_NULL(gmu->gmu_mxpd))
+ dev_pm_domain_detach(gmu->gmu_mxpd, false);
+
if (!IS_ERR_OR_NULL(gmu->qmp))
qmp_put(gmu->qmp);
@@ -2285,7 +2330,8 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
struct msm_gpu *gpu = &adreno_gpu->base;
struct a6xx_gmu *gmu = &a6xx_gpu->gmu;
- struct device_link *link;
+ struct device_link *gmu_mx_link = NULL;
+ struct device_link *cx_link;
resource_size_t start;
struct resource *res;
int ret;
@@ -2432,12 +2478,27 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
goto err_mmio;
}
- link = device_link_add(gmu->dev, gmu->cxpd, DL_FLAG_PM_RUNTIME);
- if (!link) {
+ cx_link = device_link_add(gmu->dev, gmu->cxpd, DL_FLAG_PM_RUNTIME);
+ if (!cx_link) {
ret = -ENODEV;
goto detach_cxpd;
}
+ /* Optionally attach the GMU MX power domain */
+ gmu->gmu_mxpd = dev_pm_domain_attach_by_name(gmu->dev, "gmu_mx");
+ if (IS_ERR(gmu->gmu_mxpd)) {
+ ret = PTR_ERR(gmu->gmu_mxpd);
+ goto detach_cxpd_link;
+ }
+
+ if (gmu->gmu_mxpd) {
+ gmu_mx_link = device_link_add(gmu->dev, gmu->gmu_mxpd, DL_FLAG_PM_RUNTIME);
+ if (!gmu_mx_link) {
+ ret = -ENODEV;
+ goto detach_gmu_mxpd;
+ }
+ }
+
/* Other errors are handled during GPU ACD probe */
gmu->qmp = qmp_get(gmu->dev);
if (PTR_ERR_OR_ZERO(gmu->qmp) == -EPROBE_DEFER) {
@@ -2479,7 +2540,15 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
if (!IS_ERR_OR_NULL(gmu->qmp))
qmp_put(gmu->qmp);
- device_link_del(link);
+ if (!IS_ERR_OR_NULL(gmu_mx_link))
+ device_link_del(gmu_mx_link);
+
+detach_gmu_mxpd:
+ if (gmu->gmu_mxpd)
+ dev_pm_domain_detach(gmu->gmu_mxpd, false);
+
+detach_cxpd_link:
+ device_link_del(cx_link);
detach_cxpd:
dev_pm_domain_detach(gmu->cxpd, false);
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
index 3f96b10b5f61a..d3f6cd8b97413 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
@@ -77,6 +77,7 @@ struct a6xx_gmu {
struct device *gxpd;
struct device *cxpd;
+ struct device *gmu_mxpd;
int idle_level;
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
index b50c57f427b44..43273e5f8b5b2 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
@@ -42,6 +42,7 @@ struct cpu_gpu_lock {
* @hwcg: hw clock gating register sequence
* @protect: CP_PROTECT settings
* @pwrup_reglist pwrup reglist for preemption
+ * @thinmem_config: GMU thinmem configuration
*/
struct a6xx_info {
const struct adreno_reglist *hwcg;
@@ -56,6 +57,7 @@ struct a6xx_info {
u32 gmu_cgc_mode;
u32 prim_fifo_threshold;
const struct a6xx_bcm *bcms;
+ u32 thinmem_config;
};
struct a6xx_gpu {
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_hfi.c b/drivers/gpu/drm/msm/adreno/a6xx_hfi.c
index 186a73c0b99c0..e33a2258e0f9d 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_hfi.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_hfi.c
@@ -888,6 +888,27 @@ static int a6xx_hfi_enable_acd(struct a6xx_gmu *gmu)
return 0;
}
+static int a6xx_hfi_send_thinmem_config(struct a6xx_gmu *gmu)
+{
+ struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu);
+ struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
+ const struct a6xx_info *info = adreno_gpu->info->a6xx;
+ u32 data;
+ int ret;
+
+ if (!info->thinmem_config)
+ return 0;
+
+ /* Bits [7:4] contain the thinmem_cfg data. */
+ data = FIELD_PREP(GENMASK(7, 4), info->thinmem_config);
+
+ ret = a6xx_hfi_feature_ctrl_msg(gmu, HFI_FEATURE_THINMEM_CFG, 1, data);
+ if (ret)
+ DRM_DEV_ERROR(gmu->dev, "Unable to send THINMEM_CFG (%d)\n", ret);
+
+ return ret;
+}
+
static int a6xx_hfi_send_test(struct a6xx_gmu *gmu)
{
struct a6xx_hfi_msg_test msg = { 0 };
@@ -993,6 +1014,10 @@ int a6xx_hfi_start(struct a6xx_gmu *gmu, int boot_state)
if (ret)
return ret;
+ ret = a6xx_hfi_send_thinmem_config(gmu);
+ if (ret)
+ return ret;
+
ret = a6xx_hfi_send_core_fw_start(gmu);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_hfi.h b/drivers/gpu/drm/msm/adreno/a6xx_hfi.h
index e10d32ce93e0c..5123349a3de62 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_hfi.h
+++ b/drivers/gpu/drm/msm/adreno/a6xx_hfi.h
@@ -244,6 +244,7 @@ struct a6xx_hfi_msg_feature_ctrl {
#define HFI_FEATURE_TDCVS 30
#define HFI_FEATURE_DCE 31
#define HFI_FEATURE_IFF_PCLX 32
+#define HFI_FEATURE_THINMEM_CFG 38
#define HFI_FEATURE_SOFT_RESET 0x10000001
#define HFI_FEATURE_DCVS_PROFILE 0x10000002
#define HFI_FEATURE_FAST_CTX_DESTROY 0x10000003
diff --git a/drivers/gpu/drm/msm/adreno/a8xx_gpu.c b/drivers/gpu/drm/msm/adreno/a8xx_gpu.c
index 62df0569c62be..e7d04c8659689 100644
--- a/drivers/gpu/drm/msm/adreno/a8xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a8xx_gpu.c
@@ -200,7 +200,7 @@ static void a8xx_set_hwcg(struct msm_gpu *gpu, bool state)
struct a6xx_gmu *gmu = &a6xx_gpu->gmu;
u32 val;
- if ((adreno_is_x285(adreno_gpu) || adreno_is_a830(adreno_gpu)) && state)
+ if ((adreno_is_x285_family(adreno_gpu) || adreno_is_a830(adreno_gpu)) && state)
gpu_write(gpu, REG_A8XX_RBBM_CGC_0_PC, 0x00000702);
gmu_write(gmu, REG_A6XX_GPU_GMU_AO_GMU_CGC_MODE_CNTL,
@@ -286,10 +286,11 @@ static void a8xx_set_ubwc_config(struct msm_gpu *gpu)
u32 hbb, hbb_hi, hbb_lo, mode;
u8 uavflagprd_inv = 2;
- if (ubwc_version > UBWC_6_0)
+ if (ubwc_version > UBWC_7_0)
dev_err(&gpu->pdev->dev, "Unknown UBWC version: 0x%x\n", ubwc_version);
- if (ubwc_version == UBWC_6_0)
+ if (ubwc_version == UBWC_6_0 ||
+ ubwc_version == UBWC_7_0)
yuvnotcomptofc = true;
if (ubwc_version < UBWC_5_0 &&
@@ -726,6 +727,7 @@ static int hw_init(struct msm_gpu *gpu)
for (pipe_id = PIPE_BR; pipe_id <= PIPE_DDE_BV; pipe_id++) {
u32 apriv_mask = A8XX_APRIV_MASK;
+ u32 int_mask = A8XX_CP_INTERRUPT_STATUS_MASK_PIPE;
unsigned long flags;
if (pipe_id == PIPE_LPAC)
@@ -734,10 +736,16 @@ static int hw_init(struct msm_gpu *gpu)
if (pipe_id == PIPE_BR)
apriv_mask = A8XX_BR_APRIV_MASK;
+ /*
+ * A845/A850's BV pipe raises a spurious RTWROVF fault interrupt;
+ * mask it off to avoid false fault recovery.
+ */
+ if (adreno_is_a850_family(adreno_gpu) && pipe_id == PIPE_BV)
+ int_mask &= ~A8XX_CP_INTERRUPT_STATUS_MASK_PIPE_RTWROVF;
+
a8xx_aperture_acquire(gpu, pipe_id, &flags);
gpu_write(gpu, REG_A8XX_CP_APRIV_CNTL_PIPE, apriv_mask);
- gpu_write(gpu, REG_A8XX_CP_INTERRUPT_STATUS_MASK_PIPE,
- A8XX_CP_INTERRUPT_STATUS_MASK_PIPE);
+ gpu_write(gpu, REG_A8XX_CP_INTERRUPT_STATUS_MASK_PIPE, int_mask);
gpu_write(gpu, REG_A8XX_CP_HW_FAULT_STATUS_MASK_PIPE,
A8XX_CP_HW_FAULT_STATUS_MASK_PIPE);
a8xx_aperture_release(gpu, flags);
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
index 338e02271fcc2..6d6e4c7cf9190 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
@@ -580,6 +580,11 @@ static inline int adreno_is_a750_family(struct adreno_gpu *gpu)
return gpu->info->family == ADRENO_7XX_GEN3;
}
+static inline int adreno_is_a6xx(struct adreno_gpu *gpu)
+{
+ return (gpu->info->family >= ADRENO_6XX_GEN1) && (gpu->info->family < ADRENO_7XX_GEN1);
+}
+
static inline int adreno_is_a7xx(struct adreno_gpu *gpu)
{
/* Update with non-fake (i.e. non-A702) Gen 7 GPUs */
@@ -597,9 +602,12 @@ static inline int adreno_is_a810(struct adreno_gpu *gpu)
return gpu->info->chip_ids[0] == 0x44010000;
}
-static inline int adreno_is_x285(struct adreno_gpu *gpu)
+static inline int adreno_is_x285_family(const struct adreno_gpu *gpu)
{
- return gpu->info->chip_ids[0] == 0x44070001;
+ if (WARN_ON_ONCE(!gpu->info))
+ return false;
+ return gpu->info->chip_ids[0] == 0x44060000 ||
+ gpu->info->chip_ids[0] == 0x44070001;
}
static inline int adreno_is_a830(struct adreno_gpu *gpu)
@@ -612,6 +620,22 @@ static inline int adreno_is_a840(struct adreno_gpu *gpu)
return gpu->info->chip_ids[0] == 0x44050a01;
}
+static inline int adreno_is_a845(struct adreno_gpu *gpu)
+{
+ return gpu->info->chip_ids[0] == 0x44041400;
+}
+
+static inline int adreno_is_a850(struct adreno_gpu *gpu)
+{
+ return gpu->info->chip_ids[0] == 0x44051401;
+}
+
+static inline int adreno_is_a850_family(struct adreno_gpu *gpu)
+{
+ return adreno_is_a845(gpu) ||
+ adreno_is_a850(gpu);
+}
+
/* Put vm_start above 32b to catch issues with not setting xyz_BASE_HI */
#define ADRENO_VM_START 0x100000000ULL
u64 adreno_private_vm_size(struct msm_gpu *gpu);
diff --git a/drivers/gpu/drm/msm/registers/adreno/a6xx.xml b/drivers/gpu/drm/msm/registers/adreno/a6xx.xml
index 69dd0446f8d2d..e6e56969a9b83 100644
--- a/drivers/gpu/drm/msm/registers/adreno/a6xx.xml
+++ b/drivers/gpu/drm/msm/registers/adreno/a6xx.xml
@@ -269,6 +269,7 @@ by a particular renderpass/blit.
+
@@ -1326,6 +1327,7 @@ by a particular renderpass/blit.
+
@@ -4352,6 +4354,7 @@ by a particular renderpass/blit.
+