summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/msm/adreno
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/msm/adreno')
-rw-r--r--drivers/gpu/drm/msm/adreno/a2xx_gpu.c10
-rw-r--r--drivers/gpu/drm/msm/adreno/a4xx_gpu.c2
-rw-r--r--drivers/gpu/drm/msm/adreno/a5xx_gpu.c12
-rw-r--r--drivers/gpu/drm/msm/adreno/a5xx_power.c2
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx.xml.h3
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_gmu.c56
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h2
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_gpu.c219
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_gpu.h19
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_gpu_state.h2
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_device.c310
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_gpu.c69
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_gpu.h152
13 files changed, 448 insertions, 410 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 a99310b68793..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,13 +83,13 @@ 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
* submit_reloc()
*/
- if (WARN_ON(!ptr))
+ if (WARN_ON(IS_ERR_OR_NULL(ptr)))
return;
for (i = 0; i < dwords; i++) {
@@ -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 5deb79924897..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>
@@ -676,12 +678,6 @@ struct block_header {
u32 data[];
};
-/* this should be a general kernel helper */
-static int in_range(u32 addr, u32 start, u32 size)
-{
- return addr >= start && addr < start + size;
-}
-
static bool fw_block_mem(struct a6xx_gmu_bo *bo, const struct block_header *blk)
{
if (!in_range(blk->addr, bo->iova, bo->size))
@@ -790,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);
@@ -887,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);
@@ -1435,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);
@@ -1466,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,
@@ -1617,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;
@@ -1627,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/a6xx_gpu_state.h b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.h
index 790f55e24533..e788ed72eb0d 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.h
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.h
@@ -206,7 +206,7 @@ static const struct a6xx_shader_block {
SHADER(A6XX_SP_LB_3_DATA, 0x800),
SHADER(A6XX_SP_LB_4_DATA, 0x800),
SHADER(A6XX_SP_LB_5_DATA, 0x200),
- SHADER(A6XX_SP_CB_BINDLESS_DATA, 0x2000),
+ SHADER(A6XX_SP_CB_BINDLESS_DATA, 0x800),
SHADER(A6XX_SP_CB_LEGACY_DATA, 0x280),
SHADER(A6XX_SP_UAV_DATA, 0x80),
SHADER(A6XX_SP_INST_TAG, 0x80),
diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c
index cb94cfd137a8..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,94 +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),
- .revn = 690,
- .name = "A690",
+ .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,
@@ -397,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;
@@ -504,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);
@@ -518,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;
}
@@ -557,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)) {
@@ -588,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 d8c9e8cc3753..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,13 +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)
{
- WARN_ON_ONCE(!gpu->revn);
-
- 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)
@@ -161,16 +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)
{
- WARN_ON_ONCE(!gpu->revn);
-
- 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)
{
- WARN_ON_ONCE(!gpu->revn);
-
- 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)
@@ -201,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)
@@ -291,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)
@@ -307,34 +368,37 @@ static inline int adreno_is_a680(const struct adreno_gpu *gpu)
static inline int adreno_is_a690(const struct adreno_gpu *gpu)
{
- return adreno_is_revn(gpu, 690);
-};
+ 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);