Loading drivers/gpu/msm/a6xx_reg.h +25 −18 Original line number Diff line number Diff line Loading @@ -1029,7 +1029,6 @@ #define A6XX_GMU_AO_RGMU_GLM_HW_CRC_DISABLE 0x23B82 /* GMU RSC control registers */ #define A6XX_GPU_RSCC_RSC_STATUS0_DRV0 0x23404 #define A6XX_GMU_RSCC_CONTROL_REQ 0x23B07 #define A6XX_GMU_RSCC_CONTROL_ACK 0x23B08 Loading @@ -1042,23 +1041,24 @@ #define A6XX_GPU_CC_GX_DOMAIN_MISC 0x24542 /* GPU RSC sequencer registers */ #define A6XX_RSCC_PDC_SEQ_START_ADDR 0x23408 #define A6XX_RSCC_PDC_MATCH_VALUE_LO 0x23409 #define A6XX_RSCC_PDC_MATCH_VALUE_HI 0x2340A #define A6XX_RSCC_PDC_SLAVE_ID_DRV0 0x2340B #define A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR 0x2340D #define A6XX_RSCC_HIDDEN_TCS_CMD0_DATA 0x2340E #define A6XX_RSCC_TIMESTAMP_UNIT0_TIMESTAMP_L_DRV0 0x23482 #define A6XX_RSCC_TIMESTAMP_UNIT0_TIMESTAMP_H_DRV0 0x23483 #define A6XX_RSCC_TIMESTAMP_UNIT1_EN_DRV0 0x23489 #define A6XX_RSCC_TIMESTAMP_UNIT1_OUTPUT_DRV0 0x2348C #define A6XX_RSCC_OVERRIDE_START_ADDR 0x23500 #define A6XX_RSCC_SEQ_BUSY_DRV0 0x23501 #define A6XX_RSCC_SEQ_MEM_0_DRV0 0x23580 #define A6XX_RSCC_TCS0_DRV0_STATUS 0x23746 #define A6XX_RSCC_TCS1_DRV0_STATUS 0x237EE #define A6XX_RSCC_TCS2_DRV0_STATUS 0x23896 #define A6XX_RSCC_TCS3_DRV0_STATUS 0x2393E #define A6XX_GPU_RSCC_RSC_STATUS0_DRV0 0x00004 #define A6XX_RSCC_PDC_SEQ_START_ADDR 0x00008 #define A6XX_RSCC_PDC_MATCH_VALUE_LO 0x00009 #define A6XX_RSCC_PDC_MATCH_VALUE_HI 0x0000A #define A6XX_RSCC_PDC_SLAVE_ID_DRV0 0x0000B #define A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR 0x0000D #define A6XX_RSCC_HIDDEN_TCS_CMD0_DATA 0x0000E #define A6XX_RSCC_TIMESTAMP_UNIT0_TIMESTAMP_L_DRV0 0x00082 #define A6XX_RSCC_TIMESTAMP_UNIT0_TIMESTAMP_H_DRV0 0x00083 #define A6XX_RSCC_TIMESTAMP_UNIT1_EN_DRV0 0x00089 #define A6XX_RSCC_TIMESTAMP_UNIT1_OUTPUT_DRV0 0x0008C #define A6XX_RSCC_OVERRIDE_START_ADDR 0x00100 #define A6XX_RSCC_SEQ_BUSY_DRV0 0x00101 #define A6XX_RSCC_SEQ_MEM_0_DRV0 0x00180 #define A6XX_RSCC_TCS0_DRV0_STATUS 0x00346 #define A6XX_RSCC_TCS1_DRV0_STATUS 0x003EE #define A6XX_RSCC_TCS2_DRV0_STATUS 0x00496 #define A6XX_RSCC_TCS3_DRV0_STATUS 0x0053E /* GPU PDC sequencer registers in AOSS.RPMh domain */ #define PDC_GPU_ENABLE_PDC 0x1140 Loading Loading @@ -1095,6 +1095,13 @@ */ #define PDC_GPU_SEQ_MEM_0 0x0 /* * Legacy RSCC register range was a part of the GMU register space * now we are using a separate section for RSCC regsiters. Add the * offset for backward compatibility. */ #define RSCC_OFFSET_LEGACY 0x23400 /* RGMU(PCC) registers in A6X_GMU_CX_0_NON_CONTEXT_DEC domain */ #define A6XX_RGMU_CX_INTR_GEN_EN 0x1F80F #define A6XX_RGMU_CX_RGMU_TIMER0 0x1F834 Loading drivers/gpu/msm/adreno.c +38 −0 Original line number Diff line number Diff line Loading @@ -1210,6 +1210,25 @@ static void adreno_cx_misc_probe(struct kgsl_device *device) res->start, adreno_dev->cx_misc_len); } static void adreno_rscc_probe(struct kgsl_device *device) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); struct resource *res; res = platform_get_resource_byname(device->pdev, IORESOURCE_MEM, "rscc"); if (res == NULL) return; adreno_dev->rscc_base = res->start - device->reg_phys; adreno_dev->rscc_len = resource_size(res); adreno_dev->rscc_virt = devm_ioremap(device->dev, res->start, adreno_dev->rscc_len); if (adreno_dev->rscc_virt == NULL) dev_warn(device->dev, "rscc ioremap failed\n"); } static void adreno_efuse_read_soc_hw_rev(struct adreno_device *adreno_dev) { unsigned int val; Loading Loading @@ -1335,6 +1354,7 @@ static int adreno_probe(struct platform_device *pdev) /* Probe for the optional CX_MISC block */ adreno_cx_misc_probe(device); adreno_rscc_probe(device); /* * qcom,iommu-secure-id is used to identify MMUs that can handle secure * content but that is only part of the story - the GPU also has to be Loading Loading @@ -3205,6 +3225,24 @@ void adreno_cx_misc_regread(struct adreno_device *adreno_dev, */ rmb(); } void adreno_rscc_regread(struct adreno_device *adreno_dev, unsigned int offsetwords, unsigned int *value) { unsigned int rscc_offset; rscc_offset = (offsetwords << 2); if (!adreno_dev->rscc_virt || (rscc_offset >= adreno_dev->rscc_len)) return; *value = __raw_readl(adreno_dev->rscc_virt + rscc_offset); /* * ensure this read finishes before the next one. * i.e. act like normal readl() */ rmb(); } void adreno_cx_misc_regwrite(struct adreno_device *adreno_dev, unsigned int offsetwords, unsigned int value) Loading drivers/gpu/msm/adreno.h +8 −0 Original line number Diff line number Diff line Loading @@ -441,6 +441,9 @@ enum gpu_coresight_sources { * @gmem_size: GMEM size * @cx_misc_len: Length of the CX MISC register block * @cx_misc_virt: Pointer where the CX MISC block is mapped * @rscc_base: Base physical address of the RSCC * @rscc_len: Length of the RSCC register block * @rscc_virt: Pointer where RSCC block is mapped * @gpucore: Pointer to the adreno_gpu_core structure * @pfp_fw: Buffer which holds the pfp ucode * @pfp_fw_size: Size of pfp ucode buffer Loading Loading @@ -523,6 +526,9 @@ struct adreno_device { void __iomem *cx_dbgc_virt; unsigned int cx_misc_len; void __iomem *cx_misc_virt; unsigned long rscc_base; unsigned int rscc_len; void __iomem *rscc_virt; const struct adreno_gpu_core *gpucore; struct adreno_firmware fw[2]; size_t gpmu_cmds_size; Loading Loading @@ -1182,6 +1188,8 @@ void adreno_cx_misc_regwrite(struct adreno_device *adreno_dev, void adreno_cx_misc_regrmw(struct adreno_device *adreno_dev, unsigned int offsetwords, unsigned int mask, unsigned int bits); void adreno_rscc_regread(struct adreno_device *adreno_dev, unsigned int offsetwords, unsigned int *value); #define ADRENO_TARGET(_name, _id) \ Loading drivers/gpu/msm/adreno_a6xx.h +33 −0 Original line number Diff line number Diff line Loading @@ -135,6 +135,39 @@ static inline int timed_poll_check(struct kgsl_device *device, return -ETIMEDOUT; } static inline int timed_poll_check_rscc(struct kgsl_device *device, unsigned int offset, unsigned int expected_ret, unsigned int timeout, unsigned int mask) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); unsigned long t; unsigned int value; t = jiffies + msecs_to_jiffies(timeout); do { if (adreno_is_a650(adreno_dev)) adreno_rscc_regread(adreno_dev, offset, &value); else gmu_core_regread(device, offset + RSCC_OFFSET_LEGACY, &value); if ((value & mask) == expected_ret) return 0; /* Wait 100us to reduce unnecessary AHB bus traffic */ usleep_range(10, 100); } while (!time_after(jiffies, t)); /* Double check one last time */ if (adreno_is_a650(adreno_dev)) adreno_rscc_regread(adreno_dev, offset, &value); else gmu_core_regread(device, offset + RSCC_OFFSET_LEGACY, &value); if ((value & mask) == expected_ret) return 0; return -ETIMEDOUT; } /* * read_AO_counter() - Returns the 64bit always on counter value * Loading drivers/gpu/msm/adreno_a6xx_gmu.c +41 −41 Original line number Diff line number Diff line Loading @@ -81,8 +81,8 @@ static int _load_gmu_rpmh_ucode(struct kgsl_device *device) struct gmu_device *gmu = KGSL_GMU_DEVICE(device); struct adreno_device *adreno_dev = ADRENO_DEVICE(device); struct resource *res_pdc, *res_cfg, *res_seq; void __iomem *cfg = NULL, *seq = NULL; unsigned int cfg_offset, seq_offset; void __iomem *cfg = NULL, *seq = NULL, *rscc; unsigned int cfg_offset, seq_offset, rscc_offset; /* Offsets from the base PDC (if no PDC subsections in the DTSI) */ if (adreno_is_a640v2(adreno_dev)) { Loading @@ -93,6 +93,10 @@ static int _load_gmu_rpmh_ucode(struct kgsl_device *device) seq_offset = 0x280000; } if (adreno_is_a650(adreno_dev)) rscc = adreno_dev->rscc_virt; else rscc = device->gmu_core.reg_virt + 0x23000; /* * Older A6x platforms specified PDC registers in the DT using a * single base pointer that encompassed the entire PDC range. Current Loading @@ -111,7 +115,6 @@ static int _load_gmu_rpmh_ucode(struct kgsl_device *device) "kgsl_gmu_pdc_cfg"); res_seq = platform_get_resource_byname(gmu->pdev, IORESOURCE_MEM, "kgsl_gmu_pdc_seq"); /* * Map the starting address for pdc_cfg programming. If the pdc_cfg * resource is not available use an offset from the base PDC resource. Loading Loading @@ -142,37 +145,33 @@ static int _load_gmu_rpmh_ucode(struct kgsl_device *device) } /* Disable SDE clock gating */ gmu_core_regwrite(device, A6XX_GPU_RSCC_RSC_STATUS0_DRV0, BIT(24)); _regwrite(rscc, A6XX_GPU_RSCC_RSC_STATUS0_DRV0, BIT(24)); /* Setup RSC PDC handshake for sleep and wakeup */ gmu_core_regwrite(device, A6XX_RSCC_PDC_SLAVE_ID_DRV0, 1); gmu_core_regwrite(device, A6XX_RSCC_HIDDEN_TCS_CMD0_DATA, 0); gmu_core_regwrite(device, A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR, 0); gmu_core_regwrite(device, A6XX_RSCC_HIDDEN_TCS_CMD0_DATA + RSC_CMD_OFFSET, 0); gmu_core_regwrite(device, A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR + RSC_CMD_OFFSET, 0); gmu_core_regwrite(device, A6XX_RSCC_HIDDEN_TCS_CMD0_DATA + RSC_CMD_OFFSET * 2, _regwrite(rscc, A6XX_RSCC_PDC_SLAVE_ID_DRV0, 1); _regwrite(rscc, A6XX_RSCC_HIDDEN_TCS_CMD0_DATA, 0); _regwrite(rscc, A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR, 0); _regwrite(rscc, A6XX_RSCC_HIDDEN_TCS_CMD0_DATA + RSC_CMD_OFFSET, 0); _regwrite(rscc, A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR + RSC_CMD_OFFSET, 0); _regwrite(rscc, A6XX_RSCC_HIDDEN_TCS_CMD0_DATA + RSC_CMD_OFFSET * 2, 0x80000000); gmu_core_regwrite(device, A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR + RSC_CMD_OFFSET * 2, _regwrite(rscc, A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR + RSC_CMD_OFFSET * 2, 0); gmu_core_regwrite(device, A6XX_RSCC_OVERRIDE_START_ADDR, 0); gmu_core_regwrite(device, A6XX_RSCC_PDC_SEQ_START_ADDR, 0x4520); gmu_core_regwrite(device, A6XX_RSCC_PDC_MATCH_VALUE_LO, 0x4510); gmu_core_regwrite(device, A6XX_RSCC_PDC_MATCH_VALUE_HI, 0x4514); _regwrite(rscc, A6XX_RSCC_OVERRIDE_START_ADDR, 0); _regwrite(rscc, A6XX_RSCC_PDC_SEQ_START_ADDR, 0x4520); _regwrite(rscc, A6XX_RSCC_PDC_MATCH_VALUE_LO, 0x4510); _regwrite(rscc, A6XX_RSCC_PDC_MATCH_VALUE_HI, 0x4514); /* Enable timestamp event for v1 only */ if (adreno_is_a630v1(adreno_dev)) gmu_core_regwrite(device, A6XX_RSCC_TIMESTAMP_UNIT1_EN_DRV0, 1); _regwrite(rscc, A6XX_RSCC_TIMESTAMP_UNIT1_EN_DRV0, 1); /* Load RSC sequencer uCode for sleep and wakeup */ gmu_core_regwrite(device, A6XX_RSCC_SEQ_MEM_0_DRV0, 0xA7A506A0); gmu_core_regwrite(device, A6XX_RSCC_SEQ_MEM_0_DRV0 + 1, 0xA1E6A6E7); gmu_core_regwrite(device, A6XX_RSCC_SEQ_MEM_0_DRV0 + 2, 0xA2E081E1); gmu_core_regwrite(device, A6XX_RSCC_SEQ_MEM_0_DRV0 + 3, 0xE9A982E2); gmu_core_regwrite(device, A6XX_RSCC_SEQ_MEM_0_DRV0 + 4, 0x0020E8A8); _regwrite(rscc, A6XX_RSCC_SEQ_MEM_0_DRV0, 0xA7A506A0); _regwrite(rscc, A6XX_RSCC_SEQ_MEM_0_DRV0 + 1, 0xA1E6A6E7); _regwrite(rscc, A6XX_RSCC_SEQ_MEM_0_DRV0 + 2, 0xA2E081E1); _regwrite(rscc, A6XX_RSCC_SEQ_MEM_0_DRV0 + 3, 0xE9A982E2); _regwrite(rscc, A6XX_RSCC_SEQ_MEM_0_DRV0 + 4, 0x0020E8A8); /* Load PDC sequencer uCode for power up and power down sequence */ _regwrite(seq, PDC_GPU_SEQ_MEM_0, 0xFEBEA1E1); Loading Loading @@ -389,7 +388,7 @@ static int a6xx_rpmh_power_on_gpu(struct kgsl_device *device) return -EINVAL; } if (timed_poll_check(device, if (timed_poll_check_rscc(device, A6XX_RSCC_SEQ_BUSY_DRV0, 0, GPU_START_TIMEOUT, Loading Loading @@ -425,20 +424,21 @@ static int a6xx_rpmh_power_off_gpu(struct kgsl_device *device) /* RSC sleep sequence is different on v1 */ if (adreno_is_a630v1(adreno_dev)) gmu_core_regwrite(device, A6XX_RSCC_TIMESTAMP_UNIT1_EN_DRV0, 1); gmu_core_regwrite(device, A6XX_RSCC_TIMESTAMP_UNIT1_EN_DRV0 + RSCC_OFFSET_LEGACY, 1); gmu_core_regwrite(device, A6XX_GMU_RSCC_CONTROL_REQ, 1); /* Make sure the request completes before continuing */ wmb(); if (adreno_is_a630v1(adreno_dev)) ret = timed_poll_check(device, ret = timed_poll_check_rscc(device, A6XX_RSCC_TIMESTAMP_UNIT1_OUTPUT_DRV0, BIT(0), GPU_START_TIMEOUT, BIT(0)); else ret = timed_poll_check(device, ret = timed_poll_check_rscc(device, A6XX_GPU_RSCC_RSC_STATUS0_DRV0, BIT(16), GPU_START_TIMEOUT, Loading @@ -452,11 +452,11 @@ static int a6xx_rpmh_power_off_gpu(struct kgsl_device *device) /* Read to clear the timestamp valid signal. Don't care what we read. */ if (adreno_is_a630v1(adreno_dev)) { gmu_core_regread(device, A6XX_RSCC_TIMESTAMP_UNIT0_TIMESTAMP_L_DRV0, &ret); A6XX_RSCC_TIMESTAMP_UNIT0_TIMESTAMP_L_DRV0 + RSCC_OFFSET_LEGACY, &ret); gmu_core_regread(device, A6XX_RSCC_TIMESTAMP_UNIT0_TIMESTAMP_H_DRV0, &ret); A6XX_RSCC_TIMESTAMP_UNIT0_TIMESTAMP_H_DRV0 + RSCC_OFFSET_LEGACY, &ret); } gmu_core_regwrite(device, A6XX_GMU_RSCC_CONTROL_REQ, 0); Loading Loading @@ -700,14 +700,14 @@ static int a6xx_complete_rpmh_votes(struct kgsl_device *device) if (!gmu_core_isenabled(device)) return ret; ret |= timed_poll_check(device, A6XX_RSCC_TCS0_DRV0_STATUS, BIT(0), GPU_RESET_TIMEOUT, BIT(0)); ret |= timed_poll_check(device, A6XX_RSCC_TCS1_DRV0_STATUS, BIT(0), GPU_RESET_TIMEOUT, BIT(0)); ret |= timed_poll_check(device, A6XX_RSCC_TCS2_DRV0_STATUS, BIT(0), GPU_RESET_TIMEOUT, BIT(0)); ret |= timed_poll_check(device, A6XX_RSCC_TCS3_DRV0_STATUS, BIT(0), GPU_RESET_TIMEOUT, BIT(0)); ret |= timed_poll_check_rscc(device, A6XX_RSCC_TCS0_DRV0_STATUS, BIT(0), GPU_RESET_TIMEOUT, BIT(0)); ret |= timed_poll_check_rscc(device, A6XX_RSCC_TCS1_DRV0_STATUS, BIT(0), GPU_RESET_TIMEOUT, BIT(0)); ret |= timed_poll_check_rscc(device, A6XX_RSCC_TCS2_DRV0_STATUS, BIT(0), GPU_RESET_TIMEOUT, BIT(0)); ret |= timed_poll_check_rscc(device, A6XX_RSCC_TCS3_DRV0_STATUS, BIT(0), GPU_RESET_TIMEOUT, BIT(0)); return ret; } Loading Loading
drivers/gpu/msm/a6xx_reg.h +25 −18 Original line number Diff line number Diff line Loading @@ -1029,7 +1029,6 @@ #define A6XX_GMU_AO_RGMU_GLM_HW_CRC_DISABLE 0x23B82 /* GMU RSC control registers */ #define A6XX_GPU_RSCC_RSC_STATUS0_DRV0 0x23404 #define A6XX_GMU_RSCC_CONTROL_REQ 0x23B07 #define A6XX_GMU_RSCC_CONTROL_ACK 0x23B08 Loading @@ -1042,23 +1041,24 @@ #define A6XX_GPU_CC_GX_DOMAIN_MISC 0x24542 /* GPU RSC sequencer registers */ #define A6XX_RSCC_PDC_SEQ_START_ADDR 0x23408 #define A6XX_RSCC_PDC_MATCH_VALUE_LO 0x23409 #define A6XX_RSCC_PDC_MATCH_VALUE_HI 0x2340A #define A6XX_RSCC_PDC_SLAVE_ID_DRV0 0x2340B #define A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR 0x2340D #define A6XX_RSCC_HIDDEN_TCS_CMD0_DATA 0x2340E #define A6XX_RSCC_TIMESTAMP_UNIT0_TIMESTAMP_L_DRV0 0x23482 #define A6XX_RSCC_TIMESTAMP_UNIT0_TIMESTAMP_H_DRV0 0x23483 #define A6XX_RSCC_TIMESTAMP_UNIT1_EN_DRV0 0x23489 #define A6XX_RSCC_TIMESTAMP_UNIT1_OUTPUT_DRV0 0x2348C #define A6XX_RSCC_OVERRIDE_START_ADDR 0x23500 #define A6XX_RSCC_SEQ_BUSY_DRV0 0x23501 #define A6XX_RSCC_SEQ_MEM_0_DRV0 0x23580 #define A6XX_RSCC_TCS0_DRV0_STATUS 0x23746 #define A6XX_RSCC_TCS1_DRV0_STATUS 0x237EE #define A6XX_RSCC_TCS2_DRV0_STATUS 0x23896 #define A6XX_RSCC_TCS3_DRV0_STATUS 0x2393E #define A6XX_GPU_RSCC_RSC_STATUS0_DRV0 0x00004 #define A6XX_RSCC_PDC_SEQ_START_ADDR 0x00008 #define A6XX_RSCC_PDC_MATCH_VALUE_LO 0x00009 #define A6XX_RSCC_PDC_MATCH_VALUE_HI 0x0000A #define A6XX_RSCC_PDC_SLAVE_ID_DRV0 0x0000B #define A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR 0x0000D #define A6XX_RSCC_HIDDEN_TCS_CMD0_DATA 0x0000E #define A6XX_RSCC_TIMESTAMP_UNIT0_TIMESTAMP_L_DRV0 0x00082 #define A6XX_RSCC_TIMESTAMP_UNIT0_TIMESTAMP_H_DRV0 0x00083 #define A6XX_RSCC_TIMESTAMP_UNIT1_EN_DRV0 0x00089 #define A6XX_RSCC_TIMESTAMP_UNIT1_OUTPUT_DRV0 0x0008C #define A6XX_RSCC_OVERRIDE_START_ADDR 0x00100 #define A6XX_RSCC_SEQ_BUSY_DRV0 0x00101 #define A6XX_RSCC_SEQ_MEM_0_DRV0 0x00180 #define A6XX_RSCC_TCS0_DRV0_STATUS 0x00346 #define A6XX_RSCC_TCS1_DRV0_STATUS 0x003EE #define A6XX_RSCC_TCS2_DRV0_STATUS 0x00496 #define A6XX_RSCC_TCS3_DRV0_STATUS 0x0053E /* GPU PDC sequencer registers in AOSS.RPMh domain */ #define PDC_GPU_ENABLE_PDC 0x1140 Loading Loading @@ -1095,6 +1095,13 @@ */ #define PDC_GPU_SEQ_MEM_0 0x0 /* * Legacy RSCC register range was a part of the GMU register space * now we are using a separate section for RSCC regsiters. Add the * offset for backward compatibility. */ #define RSCC_OFFSET_LEGACY 0x23400 /* RGMU(PCC) registers in A6X_GMU_CX_0_NON_CONTEXT_DEC domain */ #define A6XX_RGMU_CX_INTR_GEN_EN 0x1F80F #define A6XX_RGMU_CX_RGMU_TIMER0 0x1F834 Loading
drivers/gpu/msm/adreno.c +38 −0 Original line number Diff line number Diff line Loading @@ -1210,6 +1210,25 @@ static void adreno_cx_misc_probe(struct kgsl_device *device) res->start, adreno_dev->cx_misc_len); } static void adreno_rscc_probe(struct kgsl_device *device) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); struct resource *res; res = platform_get_resource_byname(device->pdev, IORESOURCE_MEM, "rscc"); if (res == NULL) return; adreno_dev->rscc_base = res->start - device->reg_phys; adreno_dev->rscc_len = resource_size(res); adreno_dev->rscc_virt = devm_ioremap(device->dev, res->start, adreno_dev->rscc_len); if (adreno_dev->rscc_virt == NULL) dev_warn(device->dev, "rscc ioremap failed\n"); } static void adreno_efuse_read_soc_hw_rev(struct adreno_device *adreno_dev) { unsigned int val; Loading Loading @@ -1335,6 +1354,7 @@ static int adreno_probe(struct platform_device *pdev) /* Probe for the optional CX_MISC block */ adreno_cx_misc_probe(device); adreno_rscc_probe(device); /* * qcom,iommu-secure-id is used to identify MMUs that can handle secure * content but that is only part of the story - the GPU also has to be Loading Loading @@ -3205,6 +3225,24 @@ void adreno_cx_misc_regread(struct adreno_device *adreno_dev, */ rmb(); } void adreno_rscc_regread(struct adreno_device *adreno_dev, unsigned int offsetwords, unsigned int *value) { unsigned int rscc_offset; rscc_offset = (offsetwords << 2); if (!adreno_dev->rscc_virt || (rscc_offset >= adreno_dev->rscc_len)) return; *value = __raw_readl(adreno_dev->rscc_virt + rscc_offset); /* * ensure this read finishes before the next one. * i.e. act like normal readl() */ rmb(); } void adreno_cx_misc_regwrite(struct adreno_device *adreno_dev, unsigned int offsetwords, unsigned int value) Loading
drivers/gpu/msm/adreno.h +8 −0 Original line number Diff line number Diff line Loading @@ -441,6 +441,9 @@ enum gpu_coresight_sources { * @gmem_size: GMEM size * @cx_misc_len: Length of the CX MISC register block * @cx_misc_virt: Pointer where the CX MISC block is mapped * @rscc_base: Base physical address of the RSCC * @rscc_len: Length of the RSCC register block * @rscc_virt: Pointer where RSCC block is mapped * @gpucore: Pointer to the adreno_gpu_core structure * @pfp_fw: Buffer which holds the pfp ucode * @pfp_fw_size: Size of pfp ucode buffer Loading Loading @@ -523,6 +526,9 @@ struct adreno_device { void __iomem *cx_dbgc_virt; unsigned int cx_misc_len; void __iomem *cx_misc_virt; unsigned long rscc_base; unsigned int rscc_len; void __iomem *rscc_virt; const struct adreno_gpu_core *gpucore; struct adreno_firmware fw[2]; size_t gpmu_cmds_size; Loading Loading @@ -1182,6 +1188,8 @@ void adreno_cx_misc_regwrite(struct adreno_device *adreno_dev, void adreno_cx_misc_regrmw(struct adreno_device *adreno_dev, unsigned int offsetwords, unsigned int mask, unsigned int bits); void adreno_rscc_regread(struct adreno_device *adreno_dev, unsigned int offsetwords, unsigned int *value); #define ADRENO_TARGET(_name, _id) \ Loading
drivers/gpu/msm/adreno_a6xx.h +33 −0 Original line number Diff line number Diff line Loading @@ -135,6 +135,39 @@ static inline int timed_poll_check(struct kgsl_device *device, return -ETIMEDOUT; } static inline int timed_poll_check_rscc(struct kgsl_device *device, unsigned int offset, unsigned int expected_ret, unsigned int timeout, unsigned int mask) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); unsigned long t; unsigned int value; t = jiffies + msecs_to_jiffies(timeout); do { if (adreno_is_a650(adreno_dev)) adreno_rscc_regread(adreno_dev, offset, &value); else gmu_core_regread(device, offset + RSCC_OFFSET_LEGACY, &value); if ((value & mask) == expected_ret) return 0; /* Wait 100us to reduce unnecessary AHB bus traffic */ usleep_range(10, 100); } while (!time_after(jiffies, t)); /* Double check one last time */ if (adreno_is_a650(adreno_dev)) adreno_rscc_regread(adreno_dev, offset, &value); else gmu_core_regread(device, offset + RSCC_OFFSET_LEGACY, &value); if ((value & mask) == expected_ret) return 0; return -ETIMEDOUT; } /* * read_AO_counter() - Returns the 64bit always on counter value * Loading
drivers/gpu/msm/adreno_a6xx_gmu.c +41 −41 Original line number Diff line number Diff line Loading @@ -81,8 +81,8 @@ static int _load_gmu_rpmh_ucode(struct kgsl_device *device) struct gmu_device *gmu = KGSL_GMU_DEVICE(device); struct adreno_device *adreno_dev = ADRENO_DEVICE(device); struct resource *res_pdc, *res_cfg, *res_seq; void __iomem *cfg = NULL, *seq = NULL; unsigned int cfg_offset, seq_offset; void __iomem *cfg = NULL, *seq = NULL, *rscc; unsigned int cfg_offset, seq_offset, rscc_offset; /* Offsets from the base PDC (if no PDC subsections in the DTSI) */ if (adreno_is_a640v2(adreno_dev)) { Loading @@ -93,6 +93,10 @@ static int _load_gmu_rpmh_ucode(struct kgsl_device *device) seq_offset = 0x280000; } if (adreno_is_a650(adreno_dev)) rscc = adreno_dev->rscc_virt; else rscc = device->gmu_core.reg_virt + 0x23000; /* * Older A6x platforms specified PDC registers in the DT using a * single base pointer that encompassed the entire PDC range. Current Loading @@ -111,7 +115,6 @@ static int _load_gmu_rpmh_ucode(struct kgsl_device *device) "kgsl_gmu_pdc_cfg"); res_seq = platform_get_resource_byname(gmu->pdev, IORESOURCE_MEM, "kgsl_gmu_pdc_seq"); /* * Map the starting address for pdc_cfg programming. If the pdc_cfg * resource is not available use an offset from the base PDC resource. Loading Loading @@ -142,37 +145,33 @@ static int _load_gmu_rpmh_ucode(struct kgsl_device *device) } /* Disable SDE clock gating */ gmu_core_regwrite(device, A6XX_GPU_RSCC_RSC_STATUS0_DRV0, BIT(24)); _regwrite(rscc, A6XX_GPU_RSCC_RSC_STATUS0_DRV0, BIT(24)); /* Setup RSC PDC handshake for sleep and wakeup */ gmu_core_regwrite(device, A6XX_RSCC_PDC_SLAVE_ID_DRV0, 1); gmu_core_regwrite(device, A6XX_RSCC_HIDDEN_TCS_CMD0_DATA, 0); gmu_core_regwrite(device, A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR, 0); gmu_core_regwrite(device, A6XX_RSCC_HIDDEN_TCS_CMD0_DATA + RSC_CMD_OFFSET, 0); gmu_core_regwrite(device, A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR + RSC_CMD_OFFSET, 0); gmu_core_regwrite(device, A6XX_RSCC_HIDDEN_TCS_CMD0_DATA + RSC_CMD_OFFSET * 2, _regwrite(rscc, A6XX_RSCC_PDC_SLAVE_ID_DRV0, 1); _regwrite(rscc, A6XX_RSCC_HIDDEN_TCS_CMD0_DATA, 0); _regwrite(rscc, A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR, 0); _regwrite(rscc, A6XX_RSCC_HIDDEN_TCS_CMD0_DATA + RSC_CMD_OFFSET, 0); _regwrite(rscc, A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR + RSC_CMD_OFFSET, 0); _regwrite(rscc, A6XX_RSCC_HIDDEN_TCS_CMD0_DATA + RSC_CMD_OFFSET * 2, 0x80000000); gmu_core_regwrite(device, A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR + RSC_CMD_OFFSET * 2, _regwrite(rscc, A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR + RSC_CMD_OFFSET * 2, 0); gmu_core_regwrite(device, A6XX_RSCC_OVERRIDE_START_ADDR, 0); gmu_core_regwrite(device, A6XX_RSCC_PDC_SEQ_START_ADDR, 0x4520); gmu_core_regwrite(device, A6XX_RSCC_PDC_MATCH_VALUE_LO, 0x4510); gmu_core_regwrite(device, A6XX_RSCC_PDC_MATCH_VALUE_HI, 0x4514); _regwrite(rscc, A6XX_RSCC_OVERRIDE_START_ADDR, 0); _regwrite(rscc, A6XX_RSCC_PDC_SEQ_START_ADDR, 0x4520); _regwrite(rscc, A6XX_RSCC_PDC_MATCH_VALUE_LO, 0x4510); _regwrite(rscc, A6XX_RSCC_PDC_MATCH_VALUE_HI, 0x4514); /* Enable timestamp event for v1 only */ if (adreno_is_a630v1(adreno_dev)) gmu_core_regwrite(device, A6XX_RSCC_TIMESTAMP_UNIT1_EN_DRV0, 1); _regwrite(rscc, A6XX_RSCC_TIMESTAMP_UNIT1_EN_DRV0, 1); /* Load RSC sequencer uCode for sleep and wakeup */ gmu_core_regwrite(device, A6XX_RSCC_SEQ_MEM_0_DRV0, 0xA7A506A0); gmu_core_regwrite(device, A6XX_RSCC_SEQ_MEM_0_DRV0 + 1, 0xA1E6A6E7); gmu_core_regwrite(device, A6XX_RSCC_SEQ_MEM_0_DRV0 + 2, 0xA2E081E1); gmu_core_regwrite(device, A6XX_RSCC_SEQ_MEM_0_DRV0 + 3, 0xE9A982E2); gmu_core_regwrite(device, A6XX_RSCC_SEQ_MEM_0_DRV0 + 4, 0x0020E8A8); _regwrite(rscc, A6XX_RSCC_SEQ_MEM_0_DRV0, 0xA7A506A0); _regwrite(rscc, A6XX_RSCC_SEQ_MEM_0_DRV0 + 1, 0xA1E6A6E7); _regwrite(rscc, A6XX_RSCC_SEQ_MEM_0_DRV0 + 2, 0xA2E081E1); _regwrite(rscc, A6XX_RSCC_SEQ_MEM_0_DRV0 + 3, 0xE9A982E2); _regwrite(rscc, A6XX_RSCC_SEQ_MEM_0_DRV0 + 4, 0x0020E8A8); /* Load PDC sequencer uCode for power up and power down sequence */ _regwrite(seq, PDC_GPU_SEQ_MEM_0, 0xFEBEA1E1); Loading Loading @@ -389,7 +388,7 @@ static int a6xx_rpmh_power_on_gpu(struct kgsl_device *device) return -EINVAL; } if (timed_poll_check(device, if (timed_poll_check_rscc(device, A6XX_RSCC_SEQ_BUSY_DRV0, 0, GPU_START_TIMEOUT, Loading Loading @@ -425,20 +424,21 @@ static int a6xx_rpmh_power_off_gpu(struct kgsl_device *device) /* RSC sleep sequence is different on v1 */ if (adreno_is_a630v1(adreno_dev)) gmu_core_regwrite(device, A6XX_RSCC_TIMESTAMP_UNIT1_EN_DRV0, 1); gmu_core_regwrite(device, A6XX_RSCC_TIMESTAMP_UNIT1_EN_DRV0 + RSCC_OFFSET_LEGACY, 1); gmu_core_regwrite(device, A6XX_GMU_RSCC_CONTROL_REQ, 1); /* Make sure the request completes before continuing */ wmb(); if (adreno_is_a630v1(adreno_dev)) ret = timed_poll_check(device, ret = timed_poll_check_rscc(device, A6XX_RSCC_TIMESTAMP_UNIT1_OUTPUT_DRV0, BIT(0), GPU_START_TIMEOUT, BIT(0)); else ret = timed_poll_check(device, ret = timed_poll_check_rscc(device, A6XX_GPU_RSCC_RSC_STATUS0_DRV0, BIT(16), GPU_START_TIMEOUT, Loading @@ -452,11 +452,11 @@ static int a6xx_rpmh_power_off_gpu(struct kgsl_device *device) /* Read to clear the timestamp valid signal. Don't care what we read. */ if (adreno_is_a630v1(adreno_dev)) { gmu_core_regread(device, A6XX_RSCC_TIMESTAMP_UNIT0_TIMESTAMP_L_DRV0, &ret); A6XX_RSCC_TIMESTAMP_UNIT0_TIMESTAMP_L_DRV0 + RSCC_OFFSET_LEGACY, &ret); gmu_core_regread(device, A6XX_RSCC_TIMESTAMP_UNIT0_TIMESTAMP_H_DRV0, &ret); A6XX_RSCC_TIMESTAMP_UNIT0_TIMESTAMP_H_DRV0 + RSCC_OFFSET_LEGACY, &ret); } gmu_core_regwrite(device, A6XX_GMU_RSCC_CONTROL_REQ, 0); Loading Loading @@ -700,14 +700,14 @@ static int a6xx_complete_rpmh_votes(struct kgsl_device *device) if (!gmu_core_isenabled(device)) return ret; ret |= timed_poll_check(device, A6XX_RSCC_TCS0_DRV0_STATUS, BIT(0), GPU_RESET_TIMEOUT, BIT(0)); ret |= timed_poll_check(device, A6XX_RSCC_TCS1_DRV0_STATUS, BIT(0), GPU_RESET_TIMEOUT, BIT(0)); ret |= timed_poll_check(device, A6XX_RSCC_TCS2_DRV0_STATUS, BIT(0), GPU_RESET_TIMEOUT, BIT(0)); ret |= timed_poll_check(device, A6XX_RSCC_TCS3_DRV0_STATUS, BIT(0), GPU_RESET_TIMEOUT, BIT(0)); ret |= timed_poll_check_rscc(device, A6XX_RSCC_TCS0_DRV0_STATUS, BIT(0), GPU_RESET_TIMEOUT, BIT(0)); ret |= timed_poll_check_rscc(device, A6XX_RSCC_TCS1_DRV0_STATUS, BIT(0), GPU_RESET_TIMEOUT, BIT(0)); ret |= timed_poll_check_rscc(device, A6XX_RSCC_TCS2_DRV0_STATUS, BIT(0), GPU_RESET_TIMEOUT, BIT(0)); ret |= timed_poll_check_rscc(device, A6XX_RSCC_TCS3_DRV0_STATUS, BIT(0), GPU_RESET_TIMEOUT, BIT(0)); return ret; } Loading