diff options
Diffstat (limited to 'drivers/gpu/drm/msm/adreno')
-rw-r--r-- | drivers/gpu/drm/msm/adreno/a2xx_gpu.c | 10 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/adreno/a4xx_gpu.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 10 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/adreno/a5xx_power.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/adreno/a6xx.xml.h | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 50 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 219 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/adreno/a6xx_gpu.h | 19 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/adreno/adreno_device.c | 308 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/adreno/adreno_gpu.c | 69 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/adreno/adreno_gpu.h | 156 |
12 files changed, 446 insertions, 404 deletions
diff --git a/drivers/gpu/drm/msm/adreno/a2xx_gpu.c b/drivers/gpu/drm/msm/adreno/a2xx_gpu.c index c67089a7ebc1..0d8133f3174b 100644 --- a/drivers/gpu/drm/msm/adreno/a2xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a2xx_gpu.c @@ -205,7 +205,7 @@ static int a2xx_hw_init(struct msm_gpu *gpu) A2XX_MH_INTERRUPT_MASK_MMU_PAGE_FAULT); for (i = 3; i <= 5; i++) - if ((SZ_16K << i) == adreno_gpu->gmem) + if ((SZ_16K << i) == adreno_gpu->info->gmem) break; gpu_write(gpu, REG_A2XX_RB_EDRAM_INFO, i); @@ -540,6 +540,10 @@ struct msm_gpu *a2xx_gpu_init(struct drm_device *dev) gpu->perfcntrs = perfcntrs; gpu->num_perfcntrs = ARRAY_SIZE(perfcntrs); + ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, 1); + if (ret) + goto fail; + if (adreno_is_a20x(adreno_gpu)) adreno_gpu->registers = a200_registers; else if (adreno_is_a225(adreno_gpu)) @@ -547,10 +551,6 @@ struct msm_gpu *a2xx_gpu_init(struct drm_device *dev) else adreno_gpu->registers = a220_registers; - ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, 1); - if (ret) - goto fail; - if (!gpu->aspace) { dev_err(dev->dev, "No memory protection without MMU\n"); if (!allow_vram_carveout) { diff --git a/drivers/gpu/drm/msm/adreno/a4xx_gpu.c b/drivers/gpu/drm/msm/adreno/a4xx_gpu.c index 715436cb3996..8b4cdf95f445 100644 --- a/drivers/gpu/drm/msm/adreno/a4xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a4xx_gpu.c @@ -145,7 +145,7 @@ static void a4xx_enable_hwcg(struct msm_gpu *gpu) gpu_write(gpu, REG_A4XX_RBBM_CLOCK_DELAY_HLSQ, 0x00220000); /* Early A430's have a timing issue with SP/TP power collapse; disabling HW clock gating prevents it. */ - if (adreno_is_a430(adreno_gpu) && adreno_gpu->rev.patchid < 2) + if (adreno_is_a430(adreno_gpu) && adreno_patchid(adreno_gpu) < 2) gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL, 0); else gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL, 0xAAAAAAAA); diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c index bbb1bf33f98e..e5916c106796 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c @@ -66,7 +66,7 @@ void a5xx_flush(struct msm_gpu *gpu, struct msm_ringbuffer *ring, static void a5xx_submit_in_rb(struct msm_gpu *gpu, struct msm_gem_submit *submit) { struct msm_ringbuffer *ring = submit->ring; - struct msm_gem_object *obj; + struct drm_gem_object *obj; uint32_t *ptr, dwords; unsigned int i; @@ -83,7 +83,7 @@ static void a5xx_submit_in_rb(struct msm_gpu *gpu, struct msm_gem_submit *submit obj = submit->bos[submit->cmd[i].idx].obj; dwords = submit->cmd[i].size; - ptr = msm_gem_get_vaddr(&obj->base); + ptr = msm_gem_get_vaddr(obj); /* _get_vaddr() shouldn't fail at this point, * since we've already mapped it once in @@ -103,7 +103,7 @@ static void a5xx_submit_in_rb(struct msm_gpu *gpu, struct msm_gem_submit *submit OUT_RING(ring, ptr[i]); } - msm_gem_put_vaddr(&obj->base); + msm_gem_put_vaddr(obj); break; } @@ -749,7 +749,7 @@ static int a5xx_hw_init(struct msm_gpu *gpu) gpu_write(gpu, REG_A5XX_UCHE_GMEM_RANGE_MIN_LO, 0x00100000); gpu_write(gpu, REG_A5XX_UCHE_GMEM_RANGE_MIN_HI, 0x00000000); gpu_write(gpu, REG_A5XX_UCHE_GMEM_RANGE_MAX_LO, - 0x00100000 + adreno_gpu->gmem - 1); + 0x00100000 + adreno_gpu->info->gmem - 1); gpu_write(gpu, REG_A5XX_UCHE_GMEM_RANGE_MAX_HI, 0x00000000); if (adreno_is_a506(adreno_gpu) || adreno_is_a508(adreno_gpu) || @@ -1770,7 +1770,7 @@ struct msm_gpu *a5xx_gpu_init(struct drm_device *dev) nr_rings = 4; - if (adreno_cmp_rev(ADRENO_REV(5, 1, 0, ANY_ID), config->rev)) + if (config->info->revn == 510) nr_rings = 1; ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, nr_rings); diff --git a/drivers/gpu/drm/msm/adreno/a5xx_power.c b/drivers/gpu/drm/msm/adreno/a5xx_power.c index 0e63a1429189..7705f8010484 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_power.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_power.c @@ -179,7 +179,7 @@ static void a540_lm_setup(struct msm_gpu *gpu) /* The battery current limiter isn't enabled for A540 */ config = AGC_LM_CONFIG_BCL_DISABLED; - config |= adreno_gpu->rev.patchid << AGC_LM_CONFIG_GPU_VERSION_SHIFT; + config |= adreno_patchid(adreno_gpu) << AGC_LM_CONFIG_GPU_VERSION_SHIFT; /* For now disable GPMU side throttling */ config |= AGC_LM_CONFIG_THROTTLE_DISABLE; diff --git a/drivers/gpu/drm/msm/adreno/a6xx.xml.h b/drivers/gpu/drm/msm/adreno/a6xx.xml.h index 4dc3be6ed45d..1c051535fd4a 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx.xml.h +++ b/drivers/gpu/drm/msm/adreno/a6xx.xml.h @@ -1166,6 +1166,9 @@ static inline uint32_t A6XX_CP_ROQ_THRESHOLDS_2_ROQ_SIZE(uint32_t val) #define REG_A6XX_CP_DBG_ECO_CNTL 0x00000843 #define REG_A6XX_CP_PROTECT_CNTL 0x0000084f +#define A6XX_CP_PROTECT_CNTL_LAST_SPAN_INF_RANGE 0x00000008 +#define A6XX_CP_PROTECT_CNTL_ACCESS_FAULT_ON_VIOL_EN 0x00000002 +#define A6XX_CP_PROTECT_CNTL_ACCESS_PROT_EN 0x00000001 static inline uint32_t REG_A6XX_CP_SCRATCH(uint32_t i0) { return 0x00000883 + 0x1*i0; } diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c index d90011c813b9..7923129363b0 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c @@ -3,6 +3,8 @@ #include <linux/clk.h> #include <linux/interconnect.h> +#include <linux/of_platform.h> +#include <linux/platform_device.h> #include <linux/pm_domain.h> #include <linux/pm_opp.h> #include <soc/qcom/cmd-db.h> @@ -784,10 +786,22 @@ static int a6xx_gmu_fw_start(struct a6xx_gmu *gmu, unsigned int state) gmu_write(gmu, REG_A6XX_GMU_AHB_FENCE_RANGE_0, (1 << 31) | (0xa << 18) | (0xa0)); - chipid = adreno_gpu->rev.core << 24; - chipid |= adreno_gpu->rev.major << 16; - chipid |= adreno_gpu->rev.minor << 12; - chipid |= adreno_gpu->rev.patchid << 8; + /* + * Snapshots toggle the NMI bit which will result in a jump to the NMI + * handler instead of __main. Set the M3 config value to avoid that. + */ + gmu_write(gmu, REG_A6XX_GMU_CM3_CFG, 0x4052); + + /* + * Note that the GMU has a slightly different layout for + * chip_id, for whatever reason, so a bit of massaging + * is needed. The upper 16b are the same, but minor and + * patchid are packed in four bits each with the lower + * 8b unused: + */ + chipid = adreno_gpu->chip_id & 0xffff0000; + chipid |= (adreno_gpu->chip_id << 4) & 0xf000; /* minor */ + chipid |= (adreno_gpu->chip_id << 8) & 0x0f00; /* patchid */ gmu_write(gmu, REG_A6XX_GMU_HFI_SFR_ADDR, chipid); @@ -881,6 +895,13 @@ static void a6xx_gmu_force_off(struct a6xx_gmu *gmu) /* Make sure there are no outstanding RPMh votes */ a6xx_gmu_rpmh_off(gmu); + /* Clear the WRITEDROPPED fields and put fence into allow mode */ + gmu_write(gmu, REG_A6XX_GMU_AHB_FENCE_STATUS_CLR, 0x7); + gmu_write(gmu, REG_A6XX_GMU_AO_AHB_FENCE_CTRL, 0); + + /* Make sure the above writes go through */ + wmb(); + /* Halt the gmu cm3 core */ gmu_write(gmu, REG_A6XX_GMU_CM3_SYSRESET, 1); @@ -1429,8 +1450,15 @@ void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu) struct a6xx_gmu *gmu = &a6xx_gpu->gmu; struct platform_device *pdev = to_platform_device(gmu->dev); - if (!gmu->initialized) + mutex_lock(&gmu->lock); + if (!gmu->initialized) { + mutex_unlock(&gmu->lock); return; + } + + gmu->initialized = false; + + mutex_unlock(&gmu->lock); pm_runtime_force_suspend(gmu->dev); @@ -1460,8 +1488,6 @@ void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu) /* Drop reference taken in of_find_device_by_node */ put_device(gmu->dev); - - gmu->initialized = false; } static int cxpd_notifier_cb(struct notifier_block *nb, @@ -1611,7 +1637,7 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node) SZ_256K - SZ_16K, 0x44000, "dcache"); if (ret) goto err_memory; - } else if (adreno_is_a630(adreno_gpu) || adreno_is_a615_family(adreno_gpu)) { + } else if (adreno_is_a630_family(adreno_gpu)) { /* HFI v1, has sptprac */ gmu->legacy = true; @@ -1621,13 +1647,13 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node) goto err_memory; } - /* Allocate memory for for the HFI queues */ - ret = a6xx_gmu_memory_alloc(gmu, &gmu->hfi, SZ_16K, 0, "hfi"); + /* Allocate memory for the GMU log region */ + ret = a6xx_gmu_memory_alloc(gmu, &gmu->log, SZ_16K, 0, "log"); if (ret) goto err_memory; - /* Allocate memory for the GMU log region */ - ret = a6xx_gmu_memory_alloc(gmu, &gmu->log, SZ_4K, 0, "log"); + /* Allocate memory for for the HFI queues */ + ret = a6xx_gmu_memory_alloc(gmu, &gmu->hfi, SZ_16K, 0, "hfi"); if (ret) goto err_memory; diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h b/drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h index 9ab15d91aced..fcd9eb53baf8 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h @@ -425,6 +425,8 @@ static inline uint32_t A6XX_GMU_GPU_NAP_CTRL_SID(uint32_t val) #define REG_A6XX_GMU_AHB_FENCE_STATUS 0x00009313 +#define REG_A6XX_GMU_AHB_FENCE_STATUS_CLR 0x00009314 + #define REG_A6XX_GMU_RBBM_INT_UNMASKED_STATUS 0x00009315 #define REG_A6XX_GMU_AO_SPARE_CNTL 0x00009316 diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c index b3ada1e7b598..d4e85e24002f 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c @@ -930,10 +930,16 @@ static void a6xx_set_cp_protect(struct msm_gpu *gpu) * protect violation and select the last span to protect from the start * address all the way to the end of the register address space */ - gpu_write(gpu, REG_A6XX_CP_PROTECT_CNTL, BIT(0) | BIT(1) | BIT(3)); - - for (i = 0; i < count - 1; i++) - gpu_write(gpu, REG_A6XX_CP_PROTECT(i), regs[i]); + gpu_write(gpu, REG_A6XX_CP_PROTECT_CNTL, + A6XX_CP_PROTECT_CNTL_ACCESS_PROT_EN | + A6XX_CP_PROTECT_CNTL_ACCESS_FAULT_ON_VIOL_EN | + A6XX_CP_PROTECT_CNTL_LAST_SPAN_INF_RANGE); + + for (i = 0; i < count - 1; i++) { + /* Intentionally skip writing to some registers */ + if (regs[i]) + gpu_write(gpu, REG_A6XX_CP_PROTECT(i), regs[i]); + } /* last CP_PROTECT to have "infinite" length on the last entry */ gpu_write(gpu, REG_A6XX_CP_PROTECT(count_max - 1), regs[i]); } @@ -1195,7 +1201,9 @@ static int hw_init(struct msm_gpu *gpu) if (!adreno_has_gmu_wrapper(adreno_gpu)) { /* Make sure the GMU keeps the GPU on while we set it up */ - a6xx_gmu_set_oob(&a6xx_gpu->gmu, GMU_OOB_GPU_SET); + ret = a6xx_gmu_set_oob(&a6xx_gpu->gmu, GMU_OOB_GPU_SET); + if (ret) + return ret; } /* Clear GBIF halt in case GX domain was not collapsed */ @@ -1270,7 +1278,7 @@ static int hw_init(struct msm_gpu *gpu) gpu_write64(gpu, REG_A6XX_UCHE_GMEM_RANGE_MIN, 0x00100000); gpu_write64(gpu, REG_A6XX_UCHE_GMEM_RANGE_MAX, - 0x00100000 + adreno_gpu->gmem - 1); + 0x00100000 + adreno_gpu->info->gmem - 1); } gpu_write(gpu, REG_A6XX_UCHE_FILTER_CNTL, 0x804); @@ -1729,16 +1737,6 @@ static irqreturn_t a6xx_irq(struct msm_gpu *gpu) return IRQ_HANDLED; } -static void a6xx_llc_rmw(struct a6xx_gpu *a6xx_gpu, u32 reg, u32 mask, u32 or) -{ - return msm_rmw(a6xx_gpu->llc_mmio + (reg << 2), mask, or); -} - -static void a6xx_llc_write(struct a6xx_gpu *a6xx_gpu, u32 reg, u32 value) -{ - msm_writel(value, a6xx_gpu->llc_mmio + (reg << 2)); -} - static void a6xx_llc_deactivate(struct a6xx_gpu *a6xx_gpu) { llcc_slice_deactivate(a6xx_gpu->llc_slice); @@ -2091,9 +2089,7 @@ static void a6xx_destroy(struct msm_gpu *gpu) a6xx_llc_slices_destroy(a6xx_gpu); - mutex_lock(&a6xx_gpu->gmu.lock); a6xx_gmu_remove(a6xx_gpu); - mutex_unlock(&a6xx_gpu->gmu.lock); adreno_gpu_cleanup(adreno_gpu); @@ -2204,159 +2200,19 @@ static bool a6xx_progress(struct msm_gpu *gpu, struct msm_ringbuffer *ring) return progress; } -static u32 a610_get_speed_bin(u32 fuse) -{ - /* - * There are (at least) three SoCs implementing A610: SM6125 (trinket), - * SM6115 (bengal) and SM6225 (khaje). Trinket does not have speedbinning, - * as only a single SKU exists and we don't support khaje upstream yet. - * Hence, this matching table is only valid for bengal and can be easily - * expanded if need be. - */ - - if (fuse == 0) - return 0; - else if (fuse == 206) - return 1; - else if (fuse == 200) - return 2; - else if (fuse == 157) - return 3; - else if (fuse == 127) - return 4; - - return UINT_MAX; -} - -static u32 a618_get_speed_bin(u32 fuse) -{ - if (fuse == 0) - return 0; - else if (fuse == 169) - return 1; - else if (fuse == 174) - return 2; - - return UINT_MAX; -} - -static u32 a619_holi_get_speed_bin(u32 fuse) -{ - /* - * There are (at least) two SoCs implementing A619_holi: SM4350 (holi) - * and SM6375 (blair). Limit the fuse matching to the corresponding - * SoC to prevent bogus frequency setting (as improbable as it may be, - * given unexpected fuse values are.. unexpected! But still possible.) - */ - - if (fuse == 0) - return 0; - - if (of_machine_is_compatible("qcom,sm4350")) { - if (fuse == 138) - return 1; - else if (fuse == 92) - return 2; - } else if (of_machine_is_compatible("qcom,sm6375")) { - if (fuse == 190) - return 1; - else if (fuse == 177) - return 2; - } else - pr_warn("Unknown SoC implementing A619_holi!\n"); - - return UINT_MAX; -} - -static u32 a619_get_speed_bin(u32 fuse) -{ - if (fuse == 0) - return 0; - else if (fuse == 120) - return 4; - else if (fuse == 138) - return 3; - else if (fuse == 169) - return 2; - else if (fuse == 180) - return 1; - - return UINT_MAX; -} - -static u32 a640_get_speed_bin(u32 fuse) +static u32 fuse_to_supp_hw(const struct adreno_info *info, u32 fuse) { - if (fuse == 0) - return 0; - else if (fuse == 1) - return 1; - - return UINT_MAX; -} - -static u32 a650_get_speed_bin(u32 fuse) -{ - if (fuse == 0) - return 0; - else if (fuse == 1) - return 1; - /* Yep, 2 and 3 are swapped! :/ */ - else if (fuse == 2) - return 3; - else if (fuse == 3) - return 2; - - return UINT_MAX; -} + if (!info->speedbins) + return UINT_MAX; -static u32 adreno_7c3_get_speed_bin(u32 fuse) -{ - if (fuse == 0) - return 0; - else if (fuse == 117) - return 0; - else if (fuse == 190) - return 1; + for (int i = 0; info->speedbins[i].fuse != SHRT_MAX; i++) + if (info->speedbins[i].fuse == fuse) + return BIT(info->speedbins[i].speedbin); return UINT_MAX; } -static u32 fuse_to_supp_hw(struct device *dev, struct adreno_gpu *adreno_gpu, u32 fuse) -{ - u32 val = UINT_MAX; - - if (adreno_is_a610(adreno_gpu)) - val = a610_get_speed_bin(fuse); - - if (adreno_is_a618(adreno_gpu)) - val = a618_get_speed_bin(fuse); - - else if (adreno_is_a619_holi(adreno_gpu)) - val = a619_holi_get_speed_bin(fuse); - - else if (adreno_is_a619(adreno_gpu)) - val = a619_get_speed_bin(fuse); - - else if (adreno_is_7c3(adreno_gpu)) - val = adreno_7c3_get_speed_bin(fuse); - - else if (adreno_is_a640(adreno_gpu)) - val = a640_get_speed_bin(fuse); - - else if (adreno_is_a650(adreno_gpu)) - val = a650_get_speed_bin(fuse); - - if (val == UINT_MAX) { - DRM_DEV_ERROR(dev, - "missing support for speed-bin: %u. Some OPPs may not be supported by hardware\n", - fuse); - return UINT_MAX; - } - - return (1 << val); -} - -static int a6xx_set_supported_hw(struct device *dev, struct adreno_gpu *adreno_gpu) +static int a6xx_set_supported_hw(struct device *dev, const struct adreno_info *info) { u32 supp_hw; u32 speedbin; @@ -2375,7 +2231,14 @@ static int a6xx_set_supported_hw(struct device *dev, struct adreno_gpu *adreno_g return ret; } - supp_hw = fuse_to_supp_hw(dev, adreno_gpu, speedbin); + supp_hw = fuse_to_supp_hw(info, speedbin); + + if (supp_hw == UINT_MAX) { + DRM_DEV_ERROR(dev, + "missing support for speed-bin: %u. Some OPPs may not be supported by hardware\n", + speedbin); + return UINT_MAX; + } ret = devm_pm_opp_set_supported_hw(dev, &supp_hw, 1); if (ret) @@ -2449,7 +2312,6 @@ struct msm_gpu *a6xx_gpu_init(struct drm_device *dev) struct msm_drm_private *priv = dev->dev_private; struct platform_device *pdev = priv->gpu_pdev; struct adreno_platform_config *config = pdev->dev.platform_data; - const struct adreno_info *info; struct device_node *node; struct a6xx_gpu *a6xx_gpu; struct adreno_gpu *adreno_gpu; @@ -2474,29 +2336,12 @@ struct msm_gpu *a6xx_gpu_init(struct drm_device *dev) adreno_gpu->gmu_is_wrapper = of_device_is_compatible(node, "qcom,adreno-gmu-wrapper"); - /* - * We need to know the platform type before calling into adreno_gpu_init - * so that the hw_apriv flag can be correctly set. Snoop into the info - * and grab the revision number - */ - info = adreno_info(config->rev); - if (!info) - return ERR_PTR(-EINVAL); - - /* Assign these early so that we can use the is_aXYZ helpers */ - /* Numeric revision IDs (e.g. 630) */ - adreno_gpu->revn = info->revn; - /* New-style ADRENO_REV()-only */ - adreno_gpu->rev = info->rev; - /* Quirk data */ - adreno_gpu->info = info; - - if (adreno_is_a650(adreno_gpu) || adreno_is_a660_family(adreno_gpu)) - adreno_gpu->base.hw_apriv = true; + adreno_gpu->base.hw_apriv = + !!(config->info->quirks & ADRENO_QUIRK_HAS_HW_APRIV); a6xx_llc_slices_init(pdev, a6xx_gpu); - ret = a6xx_set_supported_hw(&pdev->dev, adreno_gpu); + ret = a6xx_set_supported_hw(&pdev->dev, config->info); if (ret) { a6xx_destroy(&(a6xx_gpu->base.base)); return ERR_PTR(ret); diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h index c788b06e72da..34822b080759 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h @@ -39,8 +39,8 @@ struct a6xx_gpu { /* * Given a register and a count, return a value to program into - * REG_CP_PROTECT_REG(n) - this will block both reads and writes for _len - * registers starting at _reg. + * REG_CP_PROTECT_REG(n) - this will block both reads and writes for + * _len + 1 registers starting at _reg. */ #define A6XX_PROTECT_NORDWR(_reg, _len) \ ((1 << 31) | \ @@ -62,6 +62,21 @@ static inline bool a6xx_has_gbif(struct adreno_gpu *gpu) return true; } +static inline void a6xx_llc_rmw(struct a6xx_gpu *a6xx_gpu, u32 reg, u32 mask, u32 or) +{ + return msm_rmw(a6xx_gpu->llc_mmio + (reg << 2), mask, or); +} + +static inline u32 a6xx_llc_read(struct a6xx_gpu *a6xx_gpu, u32 reg) +{ + return msm_readl(a6xx_gpu->llc_mmio + (reg << 2)); +} + +static inline void a6xx_llc_write(struct a6xx_gpu *a6xx_gpu, u32 reg, u32 value) +{ + msm_writel(value, a6xx_gpu->llc_mmio + (reg << 2)); +} + #define shadowptr(_a6xx_gpu, _ring) ((_a6xx_gpu)->shadow_iova + \ ((_ring)->id * sizeof(uint32_t))) diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c index ce8d0b2475bf..575e7c56219f 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_device.c +++ b/drivers/gpu/drm/msm/adreno/adreno_device.c @@ -22,9 +22,9 @@ module_param_named(allow_vram_carveout, allow_vram_carveout, bool, 0600); static const struct adreno_info gpulist[] = { { - .rev = ADRENO_REV(2, 0, 0, 0), + .chip_ids = ADRENO_CHIP_IDS(0x02000000), + .family = ADRENO_2XX_GEN1, .revn = 200, - .name = "A200", .fw = { [ADRENO_FW_PM4] = "yamato_pm4.fw", [ADRENO_FW_PFP] = "yamato_pfp.fw", @@ -33,9 +33,9 @@ static const struct adreno_info gpulist[] = { .inactive_period = DRM_MSM_INACTIVE_PERIOD, .init = a2xx_gpu_init, }, { /* a200 on i.mx51 has only 128kib gmem */ - .rev = ADRENO_REV(2, 0, 0, 1), + .chip_ids = ADRENO_CHIP_IDS(0x02000001), + .family = ADRENO_2XX_GEN1, .revn = 201, - .name = "A200", .fw = { [ADRENO_FW_PM4] = "yamato_pm4.fw", [ADRENO_FW_PFP] = "yamato_pfp.fw", @@ -44,9 +44,9 @@ static const struct adreno_info gpulist[] = { .inactive_period = DRM_MSM_INACTIVE_PERIOD, .init = a2xx_gpu_init, }, { - .rev = ADRENO_REV(2, 2, 0, ANY_ID), + .chip_ids = ADRENO_CHIP_IDS(0x02020000), + .family = ADRENO_2XX_GEN2, .revn = 220, - .name = "A220", .fw = { [ADRENO_FW_PM4] = "leia_pm4_470.fw", [ADRENO_FW_PFP] = "leia_pfp_470.fw", @@ -55,9 +55,12 @@ static const struct adreno_info gpulist[] = { .inactive_period = DRM_MSM_INACTIVE_PERIOD, .init = a2xx_gpu_init, }, { - .rev = ADRENO_REV(3, 0, 5, ANY_ID), + .chip_ids = ADRENO_CHIP_IDS( + 0x03000512, + 0x03000520 + ), + .family = ADRENO_3XX, .revn = 305, - .name = "A305", .fw = { [ADRENO_FW_PM4] = "a300_pm4.fw", [ADRENO_FW_PFP] = "a300_pfp.fw", @@ -66,9 +69,9 @@ static const struct adreno_info gpulist[] = { .inactive_period = DRM_MSM_INACTIVE_PERIOD, .init = a3xx_gpu_init, }, { - .rev = ADRENO_REV(3, 0, 6, 0), + .chip_ids = ADRENO_CHIP_IDS(0x03000600), + .family = ADRENO_3XX, .revn = 307, /* because a305c is revn==306 */ - .name = "A306", .fw = { [ADRENO_FW_PM4] = "a300_pm4.fw", [ADRENO_FW_PFP] = "a300_pfp.fw", @@ -77,9 +80,13 @@ static const struct adreno_info gpulist[] = { .inactive_period = DRM_MSM_INACTIVE_PERIOD, .init = a3xx_gpu_init, }, { - .rev = ADRENO_REV(3, 2, ANY_ID, ANY_ID), + .chip_ids = ADRENO_CHIP_IDS( + 0x03020000, + 0x03020001, + 0x03020002 + ), + .family = ADRENO_3XX, .revn = 320, - .name = "A320", .fw = { [ADRENO_FW_PM4] = "a300_pm4.fw", [ADRENO_FW_PFP] = "a300_pfp.fw", @@ -88,9 +95,13 @@ static const struct adreno_info gpulist[] = { .inactive_period = DRM_MSM_INACTIVE_PERIOD, .init = a3xx_gpu_init, }, { - .rev = ADRENO_REV(3, 3, 0, ANY_ID), + .chip_ids = ADRENO_CHIP_IDS( + 0x03030000, + 0x03030001, + 0x03030002 + ), + .family = ADRENO_3XX, .revn = 330, - .name = "A330", .fw = { [ADRENO_FW_PM4] = "a330_pm4.fw", [ADRENO_FW_PFP] = "a330_pfp.fw", @@ -99,9 +110,9 @@ static const struct adreno_info gpulist[] = { .inactive_period = DRM_MSM_INACTIVE_PERIOD, .init = a3xx_gpu_init, }, { - .rev = ADRENO_REV(4, 0, 5, ANY_ID), + .chip_ids = ADRENO_CHIP_IDS(0x04000500), + .family = ADRENO_4XX, .revn = 405, - .name = "A405", .fw = { [ADRENO_FW_PM4] = "a420_pm4.fw", [ADRENO_FW_PFP] = "a420_pfp.fw", @@ -110,9 +121,9 @@ static const struct adreno_info gpulist[] = { .inactive_period = DRM_MSM_INACTIVE_PERIOD, .init = a4xx_gpu_init, }, { - .rev = ADRENO_REV(4, 2, 0, ANY_ID), + .chip_ids = ADRENO_CHIP_IDS(0x04020000), + .family = ADRENO_4XX, .revn = 420, - .name = "A420", .fw = { [ADRENO_FW_PM4] = "a420_pm4.fw", [ADRENO_FW_PFP] = "a420_pfp.fw", @@ -121,9 +132,9 @@ static const struct adreno_info gpulist[] = { .inactive_period = DRM_MSM_INACTIVE_PERIOD, .init = a4xx_gpu_init, }, { - .rev = ADRENO_REV(4, 3, 0, ANY_ID), + .chip_ids = ADRENO_CHIP_IDS(0x04030002), + .family = ADRENO_4XX, .revn = 430, - .name = "A430", .fw = { [ADRENO_FW_PM4] = "a420_pm4.fw", [ADRENO_FW_PFP] = "a420_pfp.fw", @@ -132,9 +143,9 @@ static const struct adreno_info gpulist[] = { .inactive_period = DRM_MSM_INACTIVE_PERIOD, .init = a4xx_gpu_init, }, { - .rev = ADRENO_REV(5, 0, 6, ANY_ID), + .chip_ids = ADRENO_CHIP_IDS(0x05000600), + .family = ADRENO_5XX, .revn = 506, - .name = "A506", .fw = { [ADRENO_FW_PM4] = "a530_pm4.fw", [ADRENO_FW_PFP] = "a530_pfp.fw", @@ -150,9 +161,9 @@ static const struct adreno_info gpulist[] = { .init = a5xx_gpu_init, .zapfw = "a506_zap.mdt", }, { - .rev = ADRENO_REV(5, 0, 8, ANY_ID), + .chip_ids = ADRENO_CHIP_IDS(0x05000800), + .family = ADRENO_5XX, .revn = 508, - .name = "A508", .fw = { [ADRENO_FW_PM4] = "a530_pm4.fw", [ADRENO_FW_PFP] = "a530_pfp.fw", @@ -167,9 +178,9 @@ static const struct adreno_info gpulist[] = { .init = a5xx_gpu_init, .zapfw = "a508_zap.mdt", }, { - .rev = ADRENO_REV(5, 0, 9, ANY_ID), + .chip_ids = ADRENO_CHIP_IDS(0x05000900), + .family = ADRENO_5XX, .revn = 509, - .name = "A509", .fw = { [ADRENO_FW_PM4] = "a530_pm4.fw", [ADRENO_FW_PFP] = "a530_pfp.fw", @@ -185,9 +196,9 @@ static const struct adreno_info gpulist[] = { /* Adreno 509 uses the same ZAP as 512 */ .zapfw = "a512_zap.mdt", }, { - .rev = ADRENO_REV(5, 1, 0, ANY_ID), + .chip_ids = ADRENO_CHIP_IDS(0x05010000), + .family = ADRENO_5XX, .revn = 510, - .name = "A510", .fw = { [ADRENO_FW_PM4] = "a530_pm4.fw", [ADRENO_FW_PFP] = "a530_pfp.fw", @@ -200,9 +211,9 @@ static const struct adreno_info gpulist[] = { .inactive_period = 250, .init = a5xx_gpu_init, }, { - .rev = ADRENO_REV(5, 1, 2, ANY_ID), + .chip_ids = ADRENO_CHIP_IDS(0x05010200), + .family = ADRENO_5XX, .revn = 512, - .name = "A512", .fw = { [ADRENO_FW_PM4] = "a530_pm4.fw", [ADRENO_FW_PFP] = "a530_pfp.fw", @@ -217,9 +228,12 @@ static const struct adreno_info gpulist[] = { .init = a5xx_gpu_init, .zapfw = "a512_zap.mdt", }, { - .rev = ADRENO_REV(5, 3, 0, 2), + .chip_ids = ADRENO_CHIP_IDS( + 0x05030002, + 0x05030004 + ), + .family = ADRENO_5XX, .revn = 530, - .name = "A530", .fw = { [ADRENO_FW_PM4] = "a530_pm4.fw", [ADRENO_FW_PFP] = "a530_pfp.fw", @@ -236,9 +250,9 @@ static const struct adreno_info gpulist[] = { .init = a5xx_gpu_init, .zapfw = "a530_zap.mdt", }, { - .rev = ADRENO_REV(5, 4, 0, ANY_ID), + .chip_ids = ADRENO_CHIP_IDS(0x05040001), + .family = ADRENO_5XX, .revn = 540, - .name = "A540", .fw = { [ADRENO_FW_PM4] = "a530_pm4.fw", [ADRENO_FW_PFP] = "a530_pfp.fw", @@ -254,9 +268,9 @@ static const struct adreno_info gpulist[] = { .init = a5xx_gpu_init, .zapfw = "a540_zap.mdt", }, { - .rev = ADRENO_REV(6, 1, 0, ANY_ID), + .chip_ids = ADRENO_CHIP_IDS(0x06010000), + .family = ADRENO_6XX_GEN1, .revn = 610, - .name = "A610", .fw = { [ADRENO_FW_SQE] = "a630_sqe.fw", }, @@ -265,21 +279,61 @@ static const struct adreno_info gpulist[] = { .init = a6xx_gpu_init, .zapfw = "a610_zap.mdt", .hwcg = a612_hwcg, + /* + * There are (at least) three SoCs implementing A610: SM6125 + * (trinket), SM6115 (bengal) and SM6225 (khaje). Trinket does + * not have speedbinning, as only a single SKU exists and we + * don't support khaje upstream yet. Hence, this matching + * table is only valid for bengal. + */ + .speedbins = ADRENO_SPEEDBINS( + { 0, 0 }, + { 206, 1 }, + { 200, 2 }, + { 157, 3 }, + { 127, 4 }, + ), }, { - .rev = ADRENO_REV(6, 1, 8, ANY_ID), + .chip_ids = ADRENO_CHIP_IDS(0x06010800), + .family = ADRENO_6XX_GEN1, .revn = 618, - .name = "A618", .fw = { [ADRENO_FW_SQE] = "a630_sqe.fw", [ADRENO_FW_GMU] = "a630_gmu.bin", }, .gmem = SZ_512K, .inactive_period = DRM_MSM_INACTIVE_PERIOD, + .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT, + .init = a6xx_gpu_init, + .speedbins = ADRENO_SPEEDBINS( + { 0, 0 }, + { 169, 1 }, + { 174, 2 }, + ), + }, { + .machine = "qcom,sm4350", + .chip_ids = ADRENO_CHIP_IDS(0x06010900), + .family = ADRENO_6XX_GEN1, + .revn = 619, + .fw = { + [ADRENO_FW_SQE] = "a630_sqe.fw", + [ADRENO_FW_GMU] = "a619_gmu.bin", + }, + .gmem = SZ_512K, + .inactive_period = DRM_MSM_INACTIVE_PERIOD, .init = a6xx_gpu_init, + .zapfw = "a615_zap.mdt", + .hwcg = a615_hwcg, + .speedbins = ADRENO_SPEEDBINS( + { 0, 0 }, + { 138, 1 }, + { 92, 2 }, + ), }, { - .rev = ADRENO_REV(6, 1, 9, ANY_ID), + .machine = "qcom,sm6375", + .chip_ids = ADRENO_CHIP_IDS(0x06010900), + .family = ADRENO_6XX_GEN1, .revn = 619, - .name = "A619", .fw = { [ADRENO_FW_SQE] = "a630_sqe.fw", [ADRENO_FW_GMU] = "a619_gmu.bin", @@ -289,92 +343,149 @@ static const struct adreno_info gpulist[] = { .init = a6xx_gpu_init, .zapfw = "a615_zap.mdt", .hwcg = a615_hwcg, + .speedbins = ADRENO_SPEEDBINS( + { 0, 0 }, + { 190, 1 }, + { 177, 2 }, + ), }, { - .rev = ADRENO_REV(6, 3, 0, ANY_ID), + .chip_ids = ADRENO_CHIP_IDS(0x06010900), + .family = ADRENO_6XX_GEN1, + .revn = 619, + .fw = { + [ADRENO_FW_SQE] = "a630_sqe.fw", + [ADRENO_FW_GMU] = "a619_gmu.bin", + }, + .gmem = SZ_512K, + .inactive_period = DRM_MSM_INACTIVE_PERIOD, + .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT, + .init = a6xx_gpu_init, + .zapfw = "a615_zap.mdt", + .hwcg = a615_hwcg, + .speedbins = ADRENO_SPEEDBINS( + { 0, 0 }, + { 120, 4 }, + { 138, 3 }, + { 169, 2 }, + { 180, 1 }, + ), + }, { + .chip_ids = ADRENO_CHIP_IDS( + 0x06030001, + 0x06030002 + ), + .family = ADRENO_6XX_GEN1, .revn = 630, - .name = "A630", .fw = { [ADRENO_FW_SQE] = "a630_sqe.fw", [ADRENO_FW_GMU] = "a630_gmu.bin", }, .gmem = SZ_1M, .inactive_period = DRM_MSM_INACTIVE_PERIOD, + .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT, .init = a6xx_gpu_init, .zapfw = "a630_zap.mdt", .hwcg = a630_hwcg, }, { - .rev = ADRENO_REV(6, 4, 0, ANY_ID), + .chip_ids = ADRENO_CHIP_IDS(0x06040001), + .family = ADRENO_6XX_GEN2, .revn = 640, - .name = "A640", .fw = { [ADRENO_FW_SQE] = "a630_sqe.fw", [ADRENO_FW_GMU] = "a640_gmu.bin", }, .gmem = SZ_1M, .inactive_period = DRM_MSM_INACTIVE_PERIOD, + .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT, .init = a6xx_gpu_init, .zapfw = "a640_zap.mdt", .hwcg = a640_hwcg, + .speedbins = ADRENO_SPEEDBINS( + { 0, 0 }, + { 1, 1 }, + ), }, { - .rev = ADRENO_REV(6, 5, 0, ANY_ID), + .chip_ids = ADRENO_CHIP_IDS(0x06050002), + .family = ADRENO_6XX_GEN3, .revn = 650, - .name = "A650", .fw = { [ADRENO_FW_SQE] = "a650_sqe.fw", [ADRENO_FW_GMU] = "a650_gmu.bin", }, .gmem = SZ_1M + SZ_128K, .inactive_period = DRM_MSM_INACTIVE_PERIOD, + .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT | + ADRENO_QUIRK_HAS_HW_APRIV, .init = a6xx_gpu_init, .zapfw = "a650_zap.mdt", .hwcg = a650_hwcg, .address_space_size = SZ_16G, + .speedbins = ADRENO_SPEEDBINS( + { 0, 0 }, + { 1, 1 }, + { 2, 3 }, /* Yep, 2 and 3 are swapped! :/ */ + { 3, 2 }, + ), }, { - .rev = ADRENO_REV(6, 6, 0, ANY_ID), + .chip_ids = ADRENO_CHIP_IDS(0x06060001), + .family = ADRENO_6XX_GEN4, .revn = 660, - .name = "A660", .fw = { [ADRENO_FW_SQE] = "a660_sqe.fw", [ADRENO_FW_GMU] = "a660_gmu.bin", }, .gmem = SZ_1M + SZ_512K, .inactive_period = DRM_MSM_INACTIVE_PERIOD, + .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT | + ADRENO_QUIRK_HAS_HW_APRIV, .init = a6xx_gpu_init, .zapfw = "a660_zap.mdt", .hwcg = a660_hwcg, .address_space_size = SZ_16G, }, { - .rev = ADRENO_REV(6, 3, 5, ANY_ID), + .chip_ids = ADRENO_CHIP_IDS(0x06030500), + .family = ADRENO_6XX_GEN4, .fw = { [ADRENO_FW_SQE] = "a660_sqe.fw", [ADRENO_FW_GMU] = "a660_gmu.bin", }, .gmem = SZ_512K, .inactive_period = DRM_MSM_INACTIVE_PERIOD, + .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT | + ADRENO_QUIRK_HAS_HW_APRIV, .init = a6xx_gpu_init, .hwcg = a660_hwcg, .address_space_size = SZ_16G, + .speedbins = ADRENO_SPEEDBINS( + { 0, 0 }, + { 117, 0 }, + { 190, 1 }, + ), }, { - .rev = ADRENO_REV(6, 8, 0, ANY_ID), + .chip_ids = ADRENO_CHIP_IDS(0x06080000), + .family = ADRENO_6XX_GEN2, .revn = 680, - .name = "A680", .fw = { [ADRENO_FW_SQE] = "a630_sqe.fw", [ADRENO_FW_GMU] = "a640_gmu.bin", }, .gmem = SZ_2M, .inactive_period = DRM_MSM_INACTIVE_PERIOD, + .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT, .init = a6xx_gpu_init, .zapfw = "a640_zap.mdt", .hwcg = a640_hwcg, }, { - .rev = ADRENO_REV(6, 9, 0, ANY_ID), + .chip_ids = ADRENO_CHIP_IDS(0x06090000), + .family = ADRENO_6XX_GEN4, .fw = { [ADRENO_FW_SQE] = "a660_sqe.fw", - [ADRENO_FW_GMU] = "a690_gmu.bin", + [ADRENO_FW_GMU] = "a660_gmu.bin", }, .gmem = SZ_4M, .inactive_period = DRM_MSM_INACTIVE_PERIOD, + .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT | + ADRENO_QUIRK_HAS_HW_APRIV, .init = a6xx_gpu_init, .zapfw = "a690_zap.mdt", .hwcg = a690_hwcg, @@ -395,34 +506,31 @@ MODULE_FIRMWARE("qcom/a530_zap.mdt"); MODULE_FIRMWARE("qcom/a530_zap.b00"); MODULE_FIRMWARE("qcom/a530_zap.b01"); MODULE_FIRMWARE("qcom/a530_zap.b02"); +MODULE_FIRMWARE("qcom/a540_gpmu.fw2"); MODULE_FIRMWARE("qcom/a619_gmu.bin"); MODULE_FIRMWARE("qcom/a630_sqe.fw"); MODULE_FIRMWARE("qcom/a630_gmu.bin"); MODULE_FIRMWARE("qcom/a630_zap.mbn"); - -static inline bool _rev_match(uint8_t entry, uint8_t id) -{ - return (entry == ANY_ID) || (entry == id); -} - -bool adreno_cmp_rev(struct adreno_rev rev1, struct adreno_rev rev2) -{ - - return _rev_match(rev1.core, rev2.core) && - _rev_match(rev1.major, rev2.major) && - _rev_match(rev1.minor, rev2.minor) && - _rev_match(rev1.patchid, rev2.patchid); -} - -const struct adreno_info *adreno_info(struct adreno_rev rev) +MODULE_FIRMWARE("qcom/a640_gmu.bin"); +MODULE_FIRMWARE("qcom/a650_gmu.bin"); +MODULE_FIRMWARE("qcom/a650_sqe.fw"); +MODULE_FIRMWARE("qcom/a660_gmu.bin"); +MODULE_FIRMWARE("qcom/a660_sqe.fw"); +MODULE_FIRMWARE("qcom/leia_pfp_470.fw"); +MODULE_FIRMWARE("qcom/leia_pm4_470.fw"); +MODULE_FIRMWARE("qcom/yamato_pfp.fw"); +MODULE_FIRMWARE("qcom/yamato_pm4.fw"); + +static const struct adreno_info *adreno_info(uint32_t chip_id) { - int i; - /* identify gpu: */ - for (i = 0; i < ARRAY_SIZE(gpulist); i++) { + for (int i = 0; i < ARRAY_SIZE(gpulist); i++) { const struct adreno_info *info = &gpulist[i]; - if (adreno_cmp_rev(info->rev, rev)) - return info; + if (info->machine && !of_machine_is_compatible(info->machine)) + continue; + for (int j = 0; info->chip_ids[j]; j++) + if (info->chip_ids[j] == chip_id) + return info; } return NULL; @@ -502,12 +610,11 @@ err_disable_rpm: return NULL; } -static int find_chipid(struct device *dev, struct adreno_rev *rev) +static int find_chipid(struct device *dev, uint32_t *chipid) { struct device_node *node = dev->of_node; const char *compat; int ret; - u32 chipid; /* first search the compat strings for qcom,adreno-XYZ.W: */ ret = of_property_read_string_index(node, "compatible", 0, &compat); @@ -516,32 +623,34 @@ static int find_chipid(struct device *dev, struct adreno_rev *rev) if (sscanf(compat, "qcom,adreno-%u.%u", &r, &patch) == 2 || sscanf(compat, "amd,imageon-%u.%u", &r, &patch) == 2) { - rev->core = r / 100; + uint32_t core, major, minor; + + core = r / 100; r %= 100; - rev->major = r / 10; + major = r / 10; r %= 10; - rev->minor = r; - rev->patchid = patch; + minor = r; + + *chipid = (core << 24) | + (major << 16) | + (minor << 8) | + patch; return 0; } + + if (sscanf(compat, "qcom,adreno-%08x", chipid) == 1) + return 0; } /* and if that fails, fall back to legacy "qcom,chipid" property: */ - ret = of_property_read_u32(node, "qcom,chipid", &chipid); + ret = of_property_read_u32(node, "qcom,chipid", chipid); if (ret) { DRM_DEV_ERROR(dev, "could not parse qcom,chipid: %d\n", ret); return ret; } - rev->core = (chipid >> 24) & 0xff; - rev->major = (chipid >> 16) & 0xff; - rev->minor = (chipid >> 8) & 0xff; - rev->patchid = (chipid & 0xff); - dev_warn(dev, "Using legacy qcom,chipid binding!\n"); - dev_warn(dev, "Use compatible qcom,adreno-%u%u%u.%u instead.\n", - rev->core, rev->major, rev->minor, rev->patchid); return 0; } @@ -555,26 +664,27 @@ static int adreno_bind(struct device *dev, struct device *master, void *data) struct msm_gpu *gpu; int ret; - ret = find_chipid(dev, &config.rev); + ret = find_chipid(dev, &config.chip_id); if (ret) return ret; dev->platform_data = &config; priv->gpu_pdev = to_platform_device(dev); - info = adreno_info(config.rev); - + info = adreno_info(config.chip_id); if (!info) { - dev_warn(drm->dev, "Unknown GPU revision: %u.%u.%u.%u\n", - config.rev.core, config.rev.major, - config.rev.minor, config.rev.patchid); + dev_warn(drm->dev, "Unknown GPU revision: %"ADRENO_CHIPID_FMT"\n", + ADRENO_CHIPID_ARGS(config.chip_id)); return -ENXIO; } - DBG("Found GPU: %u.%u.%u.%u", config.rev.core, config.rev.major, - config.rev.minor, config.rev.patchid); + config.info = info; - priv->is_a2xx = config.rev.core == 2; + DBG("Found GPU: %"ADRENO_CHIPID_FMT, ADRENO_CHIPID_ARGS(config.chip_id)); + + priv->is_a2xx = info->family < ADRENO_3XX; + priv->has_cached_coherent = + !!(info->quirks & ADRENO_QUIRK_HAS_CACHED_COHERENT); gpu = info->init(drm); if (IS_ERR(gpu)) { @@ -586,10 +696,6 @@ static int adreno_bind(struct device *dev, struct device *master, void *data) if (ret) return ret; - if (config.rev.core >= 6) - if (!adreno_has_gmu_wrapper(to_adreno_gpu(gpu))) - priv->has_cached_coherent = true; - return 0; } diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c index 5c5901d65950..8090dde03280 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c @@ -320,16 +320,13 @@ int adreno_get_param(struct msm_gpu *gpu, struct msm_file_private *ctx, *value = adreno_gpu->info->revn; return 0; case MSM_PARAM_GMEM_SIZE: - *value = adreno_gpu->gmem; + *value = adreno_gpu->info->gmem; return 0; case MSM_PARAM_GMEM_BASE: *value = !adreno_is_a650_family(adreno_gpu) ? 0x100000 : 0; return 0; case MSM_PARAM_CHIP_ID: - *value = (uint64_t)adreno_gpu->rev.patchid | - ((uint64_t)adreno_gpu->rev.minor << 8) | - ((uint64_t)adreno_gpu->rev.major << 16) | - ((uint64_t)adreno_gpu->rev.core << 24); + *value = adreno_gpu->chip_id; if (!adreno_gpu->info->revn) *value |= ((uint64_t) adreno_gpu->speedbin) << 32; return 0; @@ -400,17 +397,9 @@ int adreno_set_param(struct msm_gpu *gpu, struct msm_file_private *ctx, case MSM_PARAM_CMDLINE: { char *str, **paramp; - str = kmalloc(len + 1, GFP_KERNEL); - if (!str) - return -ENOMEM; - - if (copy_from_user(str, u64_to_user_ptr(value), len)) { - kfree(str); - return -EFAULT; - } - - /* Ensure string is null terminated: */ - str[len] = '\0'; + str = memdup_user_nul(u64_to_user_ptr(value), len); + if (IS_ERR(str)) + return PTR_ERR(str); mutex_lock(&gpu->lock); @@ -847,10 +836,9 @@ void adreno_show(struct msm_gpu *gpu, struct msm_gpu_state *state, if (IS_ERR_OR_NULL(state)) return; - drm_printf(p, "revision: %d (%d.%d.%d.%d)\n", - adreno_gpu->info->revn, adreno_gpu->rev.core, - adreno_gpu->rev.major, adreno_gpu->rev.minor, - adreno_gpu->rev.patchid); + drm_printf(p, "revision: %u (%"ADRENO_CHIPID_FMT")\n", + adreno_gpu->info->revn, + ADRENO_CHIPID_ARGS(adreno_gpu->chip_id)); /* * If this is state collected due to iova fault, so fault related info * @@ -921,10 +909,9 @@ void adreno_dump_info(struct msm_gpu *gpu) struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); int i; - printk("revision: %d (%d.%d.%d.%d)\n", - adreno_gpu->info->revn, adreno_gpu->rev.core, - adreno_gpu->rev.major, adreno_gpu->rev.minor, - adreno_gpu->rev.patchid); + printk("revision: %u (%"ADRENO_CHIPID_FMT")\n", + adreno_gpu->info->revn, + ADRENO_CHIPID_ARGS(adreno_gpu->chip_id)); for (i = 0; i < gpu->nr_rings; i++) { struct msm_ringbuffer *ring = gpu->rb[i]; @@ -1041,14 +1028,16 @@ int adreno_gpu_ocmem_init(struct device *dev, struct adreno_gpu *adreno_gpu, return PTR_ERR(ocmem); } - ocmem_hdl = ocmem_allocate(ocmem, OCMEM_GRAPHICS, adreno_gpu->gmem); + ocmem_hdl = ocmem_allocate(ocmem, OCMEM_GRAPHICS, adreno_gpu->info->gmem); if (IS_ERR(ocmem_hdl)) return PTR_ERR(ocmem_hdl); adreno_ocmem->ocmem = ocmem; adreno_ocmem->base = ocmem_hdl->addr; adreno_ocmem->hdl = ocmem_hdl; - adreno_gpu->gmem = ocmem_hdl->len; + + if (WARN_ON(ocmem_hdl->len != adreno_gpu->info->gmem)) + return -ENOMEM; return 0; } @@ -1073,13 +1062,19 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev, struct adreno_platform_config *config = dev->platform_data; struct msm_gpu_config adreno_gpu_config = { 0 }; struct msm_gpu *gpu = &adreno_gpu->base; - struct adreno_rev *rev = &config->rev; const char *gpu_name; u32 speedbin; int ret; + adreno_gpu->funcs = funcs; + adreno_gpu->info = config->info; + adreno_gpu->chip_id = config->chip_id; + + gpu->allow_relocs = config->info->family < ADRENO_6XX_GEN1; + /* Only handle the core clock when GMU is not in use (or is absent). */ - if (adreno_has_gmu_wrapper(adreno_gpu) || config->rev.core < 6) { + if (adreno_has_gmu_wrapper(adreno_gpu) || + adreno_gpu->info->family < ADRENO_6XX_GEN1) { /* * This can only be done before devm_pm_opp_of_add_table(), or * dev_pm_opp_set_config() will WARN_ON() @@ -1095,24 +1090,14 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev, devm_pm_opp_set_clkname(dev, "core"); } - adreno_gpu->funcs = funcs; - adreno_gpu->info = adreno_info(config->rev); - adreno_gpu->gmem = adreno_gpu->info->gmem; - adreno_gpu->revn = adreno_gpu->info->revn; - adreno_gpu->rev = *rev; - if (adreno_read_speedbin(dev, &speedbin) || !speedbin) speedbin = 0xffff; adreno_gpu->speedbin = (uint16_t) (0xffff & speedbin); - gpu_name = adreno_gpu->info->name; - if (!gpu_name) { - gpu_name = devm_kasprintf(dev, GFP_KERNEL, "%d.%d.%d.%d", - rev->core, rev->major, rev->minor, - rev->patchid); - if (!gpu_name) - return -ENOMEM; - } + gpu_name = devm_kasprintf(dev, GFP_KERNEL, "%"ADRENO_CHIPID_FMT, + ADRENO_CHIPID_ARGS(config->chip_id)); + if (!gpu_name) + return -ENOMEM; adreno_gpu_config.ioname = "kgsl_3d0_reg_memory"; diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h index 845019891ad1..49f38edf9854 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h @@ -29,21 +29,40 @@ enum { ADRENO_FW_MAX, }; +/** + * @enum adreno_family: identify generation and possibly sub-generation + * + * In some cases there are distinct sub-generations within a major revision + * so it helps to be able to group the GPU devices by generation and if + * necessary sub-generation. + */ +enum adreno_family { + ADRENO_2XX_GEN1, /* a20x */ + ADRENO_2XX_GEN2, /* a22x */ + ADRENO_3XX, + ADRENO_4XX, + ADRENO_5XX, + ADRENO_6XX_GEN1, /* a630 family */ + ADRENO_6XX_GEN2, /* a640 family */ + ADRENO_6XX_GEN3, /* a650 family */ + ADRENO_6XX_GEN4, /* a660 family */ +}; + #define ADRENO_QUIRK_TWO_PASS_USE_WFI BIT(0) #define ADRENO_QUIRK_FAULT_DETECT_MASK BIT(1) #define ADRENO_QUIRK_LMLOADKILL_DISABLE BIT(2) +#define ADRENO_QUIRK_HAS_HW_APRIV BIT(3) +#define ADRENO_QUIRK_HAS_CACHED_COHERENT BIT(4) -struct adreno_rev { - uint8_t core; - uint8_t major; - uint8_t minor; - uint8_t patchid; -}; - -#define ANY_ID 0xff - -#define ADRENO_REV(core, major, minor, patchid) \ - ((struct adreno_rev){ core, major, minor, patchid }) +/* Helper for formating the chip_id in the way that userspace tools like + * crashdec expect. + */ +#define ADRENO_CHIPID_FMT "u.%u.%u.%u" +#define ADRENO_CHIPID_ARGS(_c) \ + (((_c) >> 24) & 0xff), \ + (((_c) >> 16) & 0xff), \ + (((_c) >> 8) & 0xff), \ + ((_c) & 0xff) struct adreno_gpu_funcs { struct msm_gpu_funcs base; @@ -58,10 +77,21 @@ struct adreno_reglist { extern const struct adreno_reglist a612_hwcg[], a615_hwcg[], a630_hwcg[], a640_hwcg[], a650_hwcg[]; extern const struct adreno_reglist a660_hwcg[], a690_hwcg[]; +struct adreno_speedbin { + uint16_t fuse; + uint16_t speedbin; +}; + struct adreno_info { - struct adreno_rev rev; + const char *machine; + /** + * @chipids: Table of matching chip-ids + * + * Terminated with 0 sentinal + */ + uint32_t *chip_ids; + enum adreno_family family; uint32_t revn; - const char *name; const char *fw[ADRENO_FW_MAX]; uint32_t gmem; u64 quirks; @@ -70,16 +100,39 @@ struct adreno_info { u32 inactive_period; const struct adreno_reglist *hwcg; u64 address_space_size; + /** + * @speedbins: Optional table of fuse to speedbin mappings + * + * Consists of pairs of fuse, index mappings, terminated with + * {SHRT_MAX, 0} sentinal. + */ + struct adreno_speedbin *speedbins; }; -const struct adreno_info *adreno_info(struct adreno_rev rev); +#define ADRENO_CHIP_IDS(tbl...) (uint32_t[]) { tbl, 0 } + +/* + * Helper to build a speedbin table, ie. the table: + * fuse | speedbin + * -----+--------- + * 0 | 0 + * 169 | 1 + * 174 | 2 + * + * would be declared as: + * + * .speedbins = ADRENO_SPEEDBINS( + * { 0, 0 }, + * { 169, 1 }, + * { 174, 2 }, + * ), + */ +#define ADRENO_SPEEDBINS(tbl...) (struct adreno_speedbin[]) { tbl {SHRT_MAX, 0} } struct adreno_gpu { struct msm_gpu base; - struct adreno_rev rev; const struct adreno_info *info; - uint32_t gmem; /* actual gmem size */ - uint32_t revn; /* numeric revision name */ + uint32_t chip_id; uint16_t speedbin; const struct adreno_gpu_funcs *funcs; @@ -128,7 +181,8 @@ struct adreno_ocmem { /* platform config data (ie. from DT, or pdata) */ struct adreno_platform_config { - struct adreno_rev rev; + uint32_t chip_id; + const struct adreno_info *info; }; #define ADRENO_IDLE_TIMEOUT msecs_to_jiffies(1000) @@ -145,14 +199,21 @@ struct adreno_platform_config { __ret; \ }) -bool adreno_cmp_rev(struct adreno_rev rev1, struct adreno_rev rev2); +static inline uint8_t adreno_patchid(const struct adreno_gpu *gpu) +{ + /* It is probably ok to assume legacy "adreno_rev" format + * for all a6xx devices, but probably best to limit this + * to older things. + */ + WARN_ON_ONCE(gpu->info->family >= ADRENO_6XX_GEN1); + return gpu->chip_id & 0xff; +} static inline bool adreno_is_revn(const struct adreno_gpu *gpu, uint32_t revn) { - /* revn can be zero, but if not is set at same time as info */ - WARN_ON_ONCE(!gpu->info); - - return gpu->revn == revn; + if (WARN_ON_ONCE(!gpu->info)) + return false; + return gpu->info->revn == revn; } static inline bool adreno_has_gmu_wrapper(const struct adreno_gpu *gpu) @@ -162,18 +223,16 @@ static inline bool adreno_has_gmu_wrapper(const struct adreno_gpu *gpu) static inline bool adreno_is_a2xx(const struct adreno_gpu *gpu) { - /* revn can be zero, but if not is set at same time as info */ - WARN_ON_ONCE(!gpu->info); - - return (gpu->revn < 300); + if (WARN_ON_ONCE(!gpu->info)) + return false; + return gpu->info->family <= ADRENO_2XX_GEN2; } static inline bool adreno_is_a20x(const struct adreno_gpu *gpu) { - /* revn can be zero, but if not is set at same time as info */ - WARN_ON_ONCE(!gpu->info); - - return (gpu->revn < 210); + if (WARN_ON_ONCE(!gpu->info)) + return false; + return gpu->info->family == ADRENO_2XX_GEN1; } static inline bool adreno_is_a225(const struct adreno_gpu *gpu) @@ -204,7 +263,7 @@ static inline bool adreno_is_a330(const struct adreno_gpu *gpu) static inline bool adreno_is_a330v2(const struct adreno_gpu *gpu) { - return adreno_is_a330(gpu) && (gpu->rev.patchid > 0); + return adreno_is_a330(gpu) && (adreno_patchid(gpu) > 0); } static inline int adreno_is_a405(const struct adreno_gpu *gpu) @@ -294,8 +353,7 @@ static inline int adreno_is_a650(const struct adreno_gpu *gpu) static inline int adreno_is_7c3(const struct adreno_gpu *gpu) { - /* The order of args is important here to handle ANY_ID correctly */ - return adreno_cmp_rev(ADRENO_REV(6, 3, 5, ANY_ID), gpu->rev); + return gpu->info->chip_ids[0] == 0x06030500; } static inline int adreno_is_a660(const struct adreno_gpu *gpu) @@ -310,35 +368,37 @@ static inline int adreno_is_a680(const struct adreno_gpu *gpu) static inline int adreno_is_a690(const struct adreno_gpu *gpu) { - /* The order of args is important here to handle ANY_ID correctly */ - return adreno_cmp_rev(ADRENO_REV(6, 9, 0, ANY_ID), gpu->rev); -}; + return gpu->info->chip_ids[0] == 0x06090000; +} -/* check for a615, a616, a618, a619 or any derivatives */ -static inline int adreno_is_a615_family(const struct adreno_gpu *gpu) +/* check for a615, a616, a618, a619 or any a630 derivatives */ +static inline int adreno_is_a630_family(const struct adreno_gpu *gpu) { - return adreno_is_revn(gpu, 615) || - adreno_is_revn(gpu, 616) || - adreno_is_revn(gpu, 618) || - adreno_is_revn(gpu, 619); + if (WARN_ON_ONCE(!gpu->info)) + return false; + return gpu->info->family == ADRENO_6XX_GEN1; } static inline int adreno_is_a660_family(const struct adreno_gpu *gpu) { - return adreno_is_a660(gpu) || adreno_is_a690(gpu) || adreno_is_7c3(gpu); + if (WARN_ON_ONCE(!gpu->info)) + return false; + return gpu->info->family == ADRENO_6XX_GEN4; } /* check for a650, a660, or any derivatives */ static inline int adreno_is_a650_family(const struct adreno_gpu *gpu) { - return adreno_is_revn(gpu, 650) || - adreno_is_revn(gpu, 620) || - adreno_is_a660_family(gpu); + if (WARN_ON_ONCE(!gpu->info)) + return false; + return gpu->info->family >= ADRENO_6XX_GEN3; } static inline int adreno_is_a640_family(const struct adreno_gpu *gpu) { - return adreno_is_a640(gpu) || adreno_is_a680(gpu); + if (WARN_ON_ONCE(!gpu->info)) + return false; + return gpu->info->family == ADRENO_6XX_GEN2; } u64 adreno_private_address_space_size(struct msm_gpu *gpu); |