diff --git a/arch/riscv/boot/dts/thead/th1520.dtsi b/arch/riscv/boot/dts/thead/th1520.dtsi index 42724bf7e90e08..f33601dbf3d92a 100644 --- a/arch/riscv/boot/dts/thead/th1520.dtsi +++ b/arch/riscv/boot/dts/thead/th1520.dtsi @@ -225,6 +225,13 @@ #clock-cells = <0>; }; + gc620_cclk: clk-gc620-fake { + compatible = "fixed-clock"; + clock-frequency = <264000000>; + clock-output-names = "gc620_cclk"; + #clock-cells = <0>; + }; + stmmac_axi_config: stmmac-axi-config { snps,wr_osr_lmt = <15>; snps,rd_osr_lmt = <15>; @@ -493,6 +500,18 @@ status = "disabled"; }; + /* Vivante GC620, 2D only */ + g2d: gpu@ffecc80000 { + compatible = "vivante,gc"; + reg = <0xff 0xecc80000 0x0 0x40000>; + interrupt-parent = <&plic>; + interrupts = <101 IRQ_TYPE_LEVEL_HIGH>; + + clocks = <&gc620_cclk>; + clock-names = "core"; + status = "okay"; + }; + clk: clock-controller@ffef010000 { compatible = "thead,th1520-clk-ap"; reg = <0xff 0xef010000 0x0 0x1000>; diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c index cf0d9049bcf1e3..a8d4394c8f6375 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c @@ -559,7 +559,11 @@ static int etnaviv_hw_reset(struct etnaviv_gpu *gpu) control |= VIVS_HI_CLOCK_CONTROL_ISOLATE_GPU; gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, control); - if (gpu->sec_mode == ETNA_SEC_KERNEL) { + if (etnaviv_is_model_rev(gpu, 0x620, 0x5552)) { + gpu_write(gpu, VIVS_DEC400EX_UNK00800, 0x10); + } + + if (gpu->identity.minor_features7 & chipMinorFeatures7_BIT_SECURITY) { gpu_write(gpu, VIVS_MMUv2_AHB_CONTROL, VIVS_MMUv2_AHB_CONTROL_RESET); } else { @@ -797,7 +801,16 @@ static void etnaviv_gpu_hw_init(struct etnaviv_gpu *gpu) gpu_write(gpu, VIVS_MC_BUS_CONFIG, bus_config); } - if (gpu->sec_mode == ETNA_SEC_KERNEL) { + /* + * FIXME: Required by GC620 r5552 as a bug workaround, but might be + * useful on other GPUs with G2D_DEC400EX feature too. + */ + if (etnaviv_is_model_rev(gpu, 0x620, 0x5552)) { + gpu_write(gpu, VIVS_DEC400EX_UNK00800, 0x2010188); + gpu_write(gpu, VIVS_DEC400EX_UNK00808, 0x3fc104); + } + + if (gpu->identity.minor_features7 & chipMinorFeatures7_BIT_SECURITY) { u32 val = gpu_read(gpu, VIVS_MMUv2_AHB_CONTROL); val |= VIVS_MMUv2_AHB_CONTROL_NONSEC_ACCESS; gpu_write(gpu, VIVS_MMUv2_AHB_CONTROL, val); @@ -853,7 +866,7 @@ int etnaviv_gpu_init(struct etnaviv_gpu *gpu) * On cores with security features supported, we claim control over the * security states. */ - if ((gpu->identity.minor_features7 & chipMinorFeatures7_BIT_SECURITY) && + if ((gpu->identity.minor_features7 & chipMinorFeatures7_BIT_SECURITY) || (gpu->identity.minor_features10 & chipMinorFeatures10_SECURITY_AHB)) gpu->sec_mode = ETNA_SEC_KERNEL; diff --git a/drivers/gpu/drm/etnaviv/etnaviv_hwdb.c b/drivers/gpu/drm/etnaviv/etnaviv_hwdb.c index 8665f2658d51b3..6a56f1ab444498 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_hwdb.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_hwdb.c @@ -69,6 +69,37 @@ static const struct etnaviv_chip_identity etnaviv_chip_identities[] = { .minor_features10 = 0x00000000, .minor_features11 = 0x00000000, }, + { + .model = 0x620, + .revision = 0x5552, + .product_id = 0x6200, + .customer_id = 0x20b, + .eco_id = 0, + .stream_count = 1, + .register_max = 64, + .thread_count = 256, + .shader_core_count = 1, + .vertex_cache_size = 8, + .vertex_output_buffer_size = 512, + .pixel_pipes = 1, + .instruction_count = 256, + .num_constants = 168, + .buffer_size = 0, + .varyings_count = 8, + .features = 0x001b4a40, + .minor_features0 = 0xa0600080, + .minor_features1 = 0x18050000, + .minor_features2 = 0x04f30000, + .minor_features3 = 0x00060005, + .minor_features4 = 0x20629000, + .minor_features5 = 0x0003380c, + .minor_features6 = 0x00000000, + .minor_features7 = 0x00001000, + .minor_features8 = 0x00000000, + .minor_features9 = 0x00000180, + .minor_features10 = 0x00004000, + .minor_features11 = 0x00000000, + }, { .model = 0x7000, .revision = 0x6202, diff --git a/drivers/gpu/drm/etnaviv/etnaviv_iommu.c b/drivers/gpu/drm/etnaviv/etnaviv_iommu.c index afe5dd6a9925bf..6fdce63b9971a2 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_iommu.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_iommu.c @@ -39,7 +39,7 @@ static void etnaviv_iommuv1_free(struct etnaviv_iommu_context *context) dma_free_wc(context->global->dev, PT_SIZE, v1_context->pgtable_cpu, v1_context->pgtable_dma); - context->global->v1.shared_context = NULL; + context->global->shared_context = NULL; kfree(v1_context); } @@ -136,8 +136,8 @@ etnaviv_iommuv1_context_alloc(struct etnaviv_iommu_global *global) * a stop the world operation, so we only support a single shared * context with this version. */ - if (global->v1.shared_context) { - context = global->v1.shared_context; + if (global->shared_context) { + context = global->shared_context; etnaviv_iommu_context_get(context); mutex_unlock(&global->lock); return context; @@ -163,7 +163,7 @@ etnaviv_iommuv1_context_alloc(struct etnaviv_iommu_global *global) mutex_init(&context->lock); INIT_LIST_HEAD(&context->mappings); drm_mm_init(&context->mm, GPU_MEM_START, PT_ENTRIES * SZ_4K); - context->global->v1.shared_context = context; + context->global->shared_context = context; mutex_unlock(&global->lock); diff --git a/drivers/gpu/drm/etnaviv/etnaviv_iommu_v2.c b/drivers/gpu/drm/etnaviv/etnaviv_iommu_v2.c index d664ae29ae2096..960ba3d659dc50 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_iommu_v2.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_iommu_v2.c @@ -272,20 +272,24 @@ etnaviv_iommuv2_context_alloc(struct etnaviv_iommu_global *global) struct etnaviv_iommuv2_context *v2_context; struct etnaviv_iommu_context *context; + mutex_lock(&global->lock); + if (global->shared_context) { + context = global->shared_context; + etnaviv_iommu_context_get(context); + mutex_unlock(&global->lock); + return context; + } + v2_context = vzalloc(sizeof(*v2_context)); if (!v2_context) - return NULL; + goto out_mutex_unlock; - mutex_lock(&global->lock); v2_context->id = find_first_zero_bit(global->v2.pta_alloc, ETNAVIV_PTA_ENTRIES); - if (v2_context->id < ETNAVIV_PTA_ENTRIES) { + if (v2_context->id < ETNAVIV_PTA_ENTRIES) set_bit(v2_context->id, global->v2.pta_alloc); - } else { - mutex_unlock(&global->lock); + else goto out_free; - } - mutex_unlock(&global->lock); v2_context->mtlb_cpu = dma_alloc_wc(global->dev, SZ_4K, &v2_context->mtlb_dma, GFP_KERNEL); @@ -303,12 +307,17 @@ etnaviv_iommuv2_context_alloc(struct etnaviv_iommu_global *global) mutex_init(&context->lock); INIT_LIST_HEAD(&context->mappings); drm_mm_init(&context->mm, SZ_4K, (u64)SZ_1G * 4 - SZ_4K); + if (global->v2.broken_pta) + global->shared_context = context; + mutex_unlock(&global->lock); return context; out_free_id: clear_bit(v2_context->id, global->v2.pta_alloc); out_free: vfree(v2_context); +out_mutex_unlock: + mutex_unlock(&global->lock); return NULL; } diff --git a/drivers/gpu/drm/etnaviv/etnaviv_mmu.c b/drivers/gpu/drm/etnaviv/etnaviv_mmu.c index df5192083b2019..a0f9c950504e0b 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_mmu.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_mmu.c @@ -504,6 +504,7 @@ int etnaviv_iommu_global_init(struct etnaviv_gpu *gpu) memset32(global->bad_page_cpu, 0xdead55aa, SZ_4K / sizeof(u32)); if (version == ETNAVIV_IOMMU_V2) { + global->v2.broken_pta = gpu->identity.model == chipModel_GC620; global->v2.pta_cpu = dma_alloc_wc(dev, ETNAVIV_PTA_SIZE, &global->v2.pta_dma, GFP_KERNEL); if (!global->v2.pta_cpu) diff --git a/drivers/gpu/drm/etnaviv/etnaviv_mmu.h b/drivers/gpu/drm/etnaviv/etnaviv_mmu.h index 7f8ac017854748..5627d2a0d02377 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_mmu.h +++ b/drivers/gpu/drm/etnaviv/etnaviv_mmu.h @@ -49,21 +49,15 @@ struct etnaviv_iommu_global { u32 memory_base; - /* - * This union holds members needed by either MMUv1 or MMUv2, which - * can not exist at the same time. - */ - union { - struct { - struct etnaviv_iommu_context *shared_context; - } v1; - struct { - /* P(age) T(able) A(rray) */ - u64 *pta_cpu; - dma_addr_t pta_dma; - DECLARE_BITMAP(pta_alloc, ETNAVIV_PTA_ENTRIES); - } v2; - }; + struct etnaviv_iommu_context *shared_context; + struct { + /* P(age) T(able) A(rray) */ + u64 *pta_cpu; + dma_addr_t pta_dma; + DECLARE_BITMAP(pta_alloc, ETNAVIV_PTA_ENTRIES); + /* Whether runtime switching page table ID will fail */ + bool broken_pta; + } v2; }; struct etnaviv_iommu_context {