Loading drivers/gpu/msm/adreno.c +132 −10 Original line number Diff line number Diff line Loading @@ -948,7 +948,8 @@ static unsigned int _adreno_iommu_setstate_v1(struct kgsl_device *device, return cmds - cmds_orig; } static unsigned int _adreno_iommu_setstate_v2(struct kgsl_device *device, static unsigned int _adreno_iommu_setstate_v2_a3xx(struct kgsl_device *device, unsigned int *cmds_orig, phys_addr_t pt_val, int num_iommu_units, uint32_t flags) Loading Loading @@ -1046,10 +1047,6 @@ static unsigned int _adreno_iommu_setstate_v2(struct kgsl_device *device, tlbstatus = kgsl_mmu_get_reg_ahbaddr(&device->mmu, i, KGSL_IOMMU_CONTEXT_USER, KGSL_IOMMU_CTX_TLBSTATUS) >> 2; if (adreno_is_a4xx(adreno_dev)) cmds += adreno_wait_reg_mem(cmds, tlbstatus, 0, KGSL_IOMMU_CTX_TLBSTATUS_SACTIVE, 0xF); else cmds += adreno_wait_reg_eq(cmds, tlbstatus, 0, KGSL_IOMMU_CTX_TLBSTATUS_SACTIVE, 0xF); /* release all commands with wait_for_me */ Loading @@ -1062,6 +1059,127 @@ static unsigned int _adreno_iommu_setstate_v2(struct kgsl_device *device, return cmds - cmds_orig; } static unsigned int _adreno_iommu_setstate_v2_a4xx(struct kgsl_device *device, unsigned int *cmds_orig, phys_addr_t pt_val, int num_iommu_units, uint32_t flags) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); uint64_t ttbr0_val; unsigned int reg_pt_val; unsigned int *cmds = cmds_orig; int i; unsigned int ttbr0, tlbiall, tlbstatus, tlbsync; cmds += adreno_add_idle_cmds(adreno_dev, cmds); for (i = 0; i < num_iommu_units; i++) { ttbr0_val = kgsl_mmu_get_default_ttbr0(&device->mmu, i, KGSL_IOMMU_CONTEXT_USER); ttbr0_val &= ~KGSL_IOMMU_CTX_TTBR0_ADDR_MASK; ttbr0_val |= (pt_val & KGSL_IOMMU_CTX_TTBR0_ADDR_MASK); if (flags & KGSL_MMUFLAGS_PTUPDATE) { ttbr0 = kgsl_mmu_get_reg_ahbaddr(&device->mmu, i, KGSL_IOMMU_CONTEXT_USER, KGSL_IOMMU_CTX_TTBR0) >> 2; /* * glue commands together until next * WAIT_FOR_ME */ cmds += adreno_wait_reg_mem(cmds, adreno_getreg(adreno_dev, ADRENO_REG_CP_WFI_PEND_CTR), 1, 0xFFFFFFFF, 0xF); /* MMU-500 VBIF stall */ *cmds++ = cp_type3_packet(CP_REG_RMW, 3); *cmds++ = A3XX_VBIF_DDR_OUTPUT_RECOVERABLE_HALT_CTRL0; /* AND to unmask the HALT bit */ *cmds++ = ~(VBIF_RECOVERABLE_HALT_CTRL); /* OR to set the HALT bit */ *cmds++ = 0x1; /* Wait for acknowledgement */ cmds += adreno_wait_reg_mem(cmds, A3XX_VBIF_DDR_OUTPUT_RECOVERABLE_HALT_CTRL1, 1, 0xFFFFFFFF, 0xF); /* set ttbr0 */ if (sizeof(phys_addr_t) > sizeof(unsigned int)) { reg_pt_val = ttbr0_val & 0xFFFFFFFF; *cmds++ = cp_type3_packet(CP_WIDE_REG_WRITE, 2); *cmds++ = ttbr0; *cmds++ = reg_pt_val; reg_pt_val = (unsigned int) ((ttbr0_val & 0xFFFFFFFF00000000ULL) >> 32); *cmds++ = cp_type3_packet(CP_WIDE_REG_WRITE, 2); *cmds++ = ttbr0+1; *cmds++ = reg_pt_val; } else { reg_pt_val = ttbr0_val; *cmds++ = cp_type3_packet(CP_WIDE_REG_WRITE, 2); *cmds++ = ttbr0; *cmds++ = reg_pt_val; } /* MMU-500 VBIF unstall */ *cmds++ = cp_type3_packet(CP_REG_RMW, 3); *cmds++ = A3XX_VBIF_DDR_OUTPUT_RECOVERABLE_HALT_CTRL0; /* AND to unmask the HALT bit */ *cmds++ = ~(VBIF_RECOVERABLE_HALT_CTRL); /* OR to reset the HALT bit */ *cmds++ = 0; /* release all commands with wait_for_me */ *cmds++ = cp_type3_packet(CP_WAIT_FOR_ME, 1); *cmds++ = 0; } if (flags & KGSL_MMUFLAGS_TLBFLUSH) { tlbiall = kgsl_mmu_get_reg_ahbaddr(&device->mmu, i, KGSL_IOMMU_CONTEXT_USER, KGSL_IOMMU_CTX_TLBIALL) >> 2; *cmds++ = cp_type3_packet(CP_WIDE_REG_WRITE, 2); *cmds++ = tlbiall; *cmds++ = 1; tlbsync = kgsl_mmu_get_reg_ahbaddr(&device->mmu, i, KGSL_IOMMU_CONTEXT_USER, KGSL_IOMMU_CTX_TLBSYNC) >> 2; *cmds++ = cp_type3_packet(CP_WIDE_REG_WRITE, 2); *cmds++ = tlbsync; *cmds++ = 0; tlbstatus = kgsl_mmu_get_reg_ahbaddr(&device->mmu, i, KGSL_IOMMU_CONTEXT_USER, KGSL_IOMMU_CTX_TLBSTATUS) >> 2; cmds += adreno_wait_reg_mem(cmds, tlbstatus, 0, KGSL_IOMMU_CTX_TLBSTATUS_SACTIVE, 0xF); /* release all commands with wait_for_me */ *cmds++ = cp_type3_packet(CP_WAIT_FOR_ME, 1); *cmds++ = 0; } } cmds += adreno_add_idle_cmds(adreno_dev, cmds); return cmds - cmds_orig; } /** * adreno_use_default_setstate() - Use CPU instead of the GPU to manage the mmu? * @adreno_dev: the device Loading Loading @@ -1123,8 +1241,12 @@ static int adreno_iommu_setstate(struct kgsl_device *device, KGSL_IOMMU_SETSTATE_NOP_OFFSET); if (kgsl_msm_supports_iommu_v2()) cmds += _adreno_iommu_setstate_v2(device, cmds, pt_val, num_iommu_units, flags); if (adreno_is_a4xx(adreno_dev)) cmds += _adreno_iommu_setstate_v2_a4xx(device, cmds, pt_val, num_iommu_units, flags); else cmds += _adreno_iommu_setstate_v2_a3xx(device, cmds, pt_val, num_iommu_units, flags); else if (msm_soc_version_supports_iommu_v0()) cmds += _adreno_iommu_setstate_v0(device, cmds, pt_val, num_iommu_units, flags); Loading Loading @@ -1554,6 +1676,9 @@ int adreno_probe(struct platform_device *pdev) return status; } /* Identify the specific GPU */ adreno_identify_gpu(adreno_dev); status = kgsl_device_platform_probe(device); if (status) { device->pdev = NULL; Loading Loading @@ -1640,9 +1765,6 @@ static int adreno_init(struct kgsl_device *device) if (test_bit(ADRENO_DEVICE_INITIALIZED, &adreno_dev->priv)) return 0; /* Identify the specific GPU */ adreno_identify_gpu(adreno_dev); gpudev = ADRENO_GPU_DEVICE(adreno_dev); /* Power up the device */ Loading drivers/gpu/msm/adreno_pm4types.h +7 −0 Original line number Diff line number Diff line Loading @@ -153,6 +153,13 @@ /* Write register, ignoring context state for context sensitive registers */ #define CP_REG_WR_NO_CTXT 0x78 /* * for A4xx * Write to register with address that does not fit into type-0 pkt */ #define CP_WIDE_REG_WRITE 0x74 /* PFP waits until the FIFO between the PFP and the ME is empty */ #define CP_WAIT_FOR_ME 0x13 Loading drivers/gpu/msm/kgsl_iommu.c +16 −3 Original line number Diff line number Diff line Loading @@ -1174,6 +1174,8 @@ static int kgsl_set_register_map(struct kgsl_mmu *mmu) struct kgsl_iommu *iommu = mmu->device->mmu.priv; struct kgsl_iommu_unit *iommu_unit; int i = 0, ret = 0; struct kgsl_device *device = mmu->device; struct adreno_device *adreno_dev = ADRENO_DEVICE(device); for (; i < pdata->iommu_count; i++) { struct kgsl_device_iommu_data data = pdata->iommu_data[i]; Loading Loading @@ -1209,6 +1211,10 @@ static int kgsl_set_register_map(struct kgsl_mmu *mmu) iommu_unit->iommu_halt_enable = 1; if (kgsl_msm_supports_iommu_v2()) if (adreno_is_a405(adreno_dev)) { iommu_unit->ahb_base = KGSL_IOMMU_V2_AHB_BASE_A405; } else iommu_unit->ahb_base = KGSL_IOMMU_V2_AHB_BASE; else iommu_unit->ahb_base = Loading Loading @@ -2146,12 +2152,19 @@ static void kgsl_iommu_set_pagefault(struct kgsl_mmu *mmu) struct kgsl_protected_registers *kgsl_iommu_get_prot_regs(struct kgsl_mmu *mmu) { static struct kgsl_protected_registers iommuv1_regs = { 0x4000, 14 }; static struct kgsl_protected_registers iommuv2_regs = { 0x2800, 10 }; static struct kgsl_protected_registers iommuv2_regs; if (msm_soc_version_supports_iommu_v0()) return NULL; if (kgsl_msm_supports_iommu_v2()) if (kgsl_msm_supports_iommu_v2()) { struct kgsl_iommu *iommu = mmu->priv; /* For V2 there is only one instance of iommu */ iommuv2_regs.base = iommu->iommu_units[0].ahb_base >> 2; iommuv2_regs.range = 10; return &iommuv2_regs; } else return &iommuv1_regs; } Loading drivers/gpu/msm/kgsl_iommu.h +1 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ /* IOMMU V2 AHB base is fixed */ #define KGSL_IOMMU_V2_AHB_BASE 0xA000 #define KGSL_IOMMU_V2_AHB_BASE_A405 0x48000 /* IOMMU_V2 AHB base points to ContextBank1 */ #define KGSL_IOMMU_CTX_AHB_OFFSET_V2 0 Loading Loading
drivers/gpu/msm/adreno.c +132 −10 Original line number Diff line number Diff line Loading @@ -948,7 +948,8 @@ static unsigned int _adreno_iommu_setstate_v1(struct kgsl_device *device, return cmds - cmds_orig; } static unsigned int _adreno_iommu_setstate_v2(struct kgsl_device *device, static unsigned int _adreno_iommu_setstate_v2_a3xx(struct kgsl_device *device, unsigned int *cmds_orig, phys_addr_t pt_val, int num_iommu_units, uint32_t flags) Loading Loading @@ -1046,10 +1047,6 @@ static unsigned int _adreno_iommu_setstate_v2(struct kgsl_device *device, tlbstatus = kgsl_mmu_get_reg_ahbaddr(&device->mmu, i, KGSL_IOMMU_CONTEXT_USER, KGSL_IOMMU_CTX_TLBSTATUS) >> 2; if (adreno_is_a4xx(adreno_dev)) cmds += adreno_wait_reg_mem(cmds, tlbstatus, 0, KGSL_IOMMU_CTX_TLBSTATUS_SACTIVE, 0xF); else cmds += adreno_wait_reg_eq(cmds, tlbstatus, 0, KGSL_IOMMU_CTX_TLBSTATUS_SACTIVE, 0xF); /* release all commands with wait_for_me */ Loading @@ -1062,6 +1059,127 @@ static unsigned int _adreno_iommu_setstate_v2(struct kgsl_device *device, return cmds - cmds_orig; } static unsigned int _adreno_iommu_setstate_v2_a4xx(struct kgsl_device *device, unsigned int *cmds_orig, phys_addr_t pt_val, int num_iommu_units, uint32_t flags) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); uint64_t ttbr0_val; unsigned int reg_pt_val; unsigned int *cmds = cmds_orig; int i; unsigned int ttbr0, tlbiall, tlbstatus, tlbsync; cmds += adreno_add_idle_cmds(adreno_dev, cmds); for (i = 0; i < num_iommu_units; i++) { ttbr0_val = kgsl_mmu_get_default_ttbr0(&device->mmu, i, KGSL_IOMMU_CONTEXT_USER); ttbr0_val &= ~KGSL_IOMMU_CTX_TTBR0_ADDR_MASK; ttbr0_val |= (pt_val & KGSL_IOMMU_CTX_TTBR0_ADDR_MASK); if (flags & KGSL_MMUFLAGS_PTUPDATE) { ttbr0 = kgsl_mmu_get_reg_ahbaddr(&device->mmu, i, KGSL_IOMMU_CONTEXT_USER, KGSL_IOMMU_CTX_TTBR0) >> 2; /* * glue commands together until next * WAIT_FOR_ME */ cmds += adreno_wait_reg_mem(cmds, adreno_getreg(adreno_dev, ADRENO_REG_CP_WFI_PEND_CTR), 1, 0xFFFFFFFF, 0xF); /* MMU-500 VBIF stall */ *cmds++ = cp_type3_packet(CP_REG_RMW, 3); *cmds++ = A3XX_VBIF_DDR_OUTPUT_RECOVERABLE_HALT_CTRL0; /* AND to unmask the HALT bit */ *cmds++ = ~(VBIF_RECOVERABLE_HALT_CTRL); /* OR to set the HALT bit */ *cmds++ = 0x1; /* Wait for acknowledgement */ cmds += adreno_wait_reg_mem(cmds, A3XX_VBIF_DDR_OUTPUT_RECOVERABLE_HALT_CTRL1, 1, 0xFFFFFFFF, 0xF); /* set ttbr0 */ if (sizeof(phys_addr_t) > sizeof(unsigned int)) { reg_pt_val = ttbr0_val & 0xFFFFFFFF; *cmds++ = cp_type3_packet(CP_WIDE_REG_WRITE, 2); *cmds++ = ttbr0; *cmds++ = reg_pt_val; reg_pt_val = (unsigned int) ((ttbr0_val & 0xFFFFFFFF00000000ULL) >> 32); *cmds++ = cp_type3_packet(CP_WIDE_REG_WRITE, 2); *cmds++ = ttbr0+1; *cmds++ = reg_pt_val; } else { reg_pt_val = ttbr0_val; *cmds++ = cp_type3_packet(CP_WIDE_REG_WRITE, 2); *cmds++ = ttbr0; *cmds++ = reg_pt_val; } /* MMU-500 VBIF unstall */ *cmds++ = cp_type3_packet(CP_REG_RMW, 3); *cmds++ = A3XX_VBIF_DDR_OUTPUT_RECOVERABLE_HALT_CTRL0; /* AND to unmask the HALT bit */ *cmds++ = ~(VBIF_RECOVERABLE_HALT_CTRL); /* OR to reset the HALT bit */ *cmds++ = 0; /* release all commands with wait_for_me */ *cmds++ = cp_type3_packet(CP_WAIT_FOR_ME, 1); *cmds++ = 0; } if (flags & KGSL_MMUFLAGS_TLBFLUSH) { tlbiall = kgsl_mmu_get_reg_ahbaddr(&device->mmu, i, KGSL_IOMMU_CONTEXT_USER, KGSL_IOMMU_CTX_TLBIALL) >> 2; *cmds++ = cp_type3_packet(CP_WIDE_REG_WRITE, 2); *cmds++ = tlbiall; *cmds++ = 1; tlbsync = kgsl_mmu_get_reg_ahbaddr(&device->mmu, i, KGSL_IOMMU_CONTEXT_USER, KGSL_IOMMU_CTX_TLBSYNC) >> 2; *cmds++ = cp_type3_packet(CP_WIDE_REG_WRITE, 2); *cmds++ = tlbsync; *cmds++ = 0; tlbstatus = kgsl_mmu_get_reg_ahbaddr(&device->mmu, i, KGSL_IOMMU_CONTEXT_USER, KGSL_IOMMU_CTX_TLBSTATUS) >> 2; cmds += adreno_wait_reg_mem(cmds, tlbstatus, 0, KGSL_IOMMU_CTX_TLBSTATUS_SACTIVE, 0xF); /* release all commands with wait_for_me */ *cmds++ = cp_type3_packet(CP_WAIT_FOR_ME, 1); *cmds++ = 0; } } cmds += adreno_add_idle_cmds(adreno_dev, cmds); return cmds - cmds_orig; } /** * adreno_use_default_setstate() - Use CPU instead of the GPU to manage the mmu? * @adreno_dev: the device Loading Loading @@ -1123,8 +1241,12 @@ static int adreno_iommu_setstate(struct kgsl_device *device, KGSL_IOMMU_SETSTATE_NOP_OFFSET); if (kgsl_msm_supports_iommu_v2()) cmds += _adreno_iommu_setstate_v2(device, cmds, pt_val, num_iommu_units, flags); if (adreno_is_a4xx(adreno_dev)) cmds += _adreno_iommu_setstate_v2_a4xx(device, cmds, pt_val, num_iommu_units, flags); else cmds += _adreno_iommu_setstate_v2_a3xx(device, cmds, pt_val, num_iommu_units, flags); else if (msm_soc_version_supports_iommu_v0()) cmds += _adreno_iommu_setstate_v0(device, cmds, pt_val, num_iommu_units, flags); Loading Loading @@ -1554,6 +1676,9 @@ int adreno_probe(struct platform_device *pdev) return status; } /* Identify the specific GPU */ adreno_identify_gpu(adreno_dev); status = kgsl_device_platform_probe(device); if (status) { device->pdev = NULL; Loading Loading @@ -1640,9 +1765,6 @@ static int adreno_init(struct kgsl_device *device) if (test_bit(ADRENO_DEVICE_INITIALIZED, &adreno_dev->priv)) return 0; /* Identify the specific GPU */ adreno_identify_gpu(adreno_dev); gpudev = ADRENO_GPU_DEVICE(adreno_dev); /* Power up the device */ Loading
drivers/gpu/msm/adreno_pm4types.h +7 −0 Original line number Diff line number Diff line Loading @@ -153,6 +153,13 @@ /* Write register, ignoring context state for context sensitive registers */ #define CP_REG_WR_NO_CTXT 0x78 /* * for A4xx * Write to register with address that does not fit into type-0 pkt */ #define CP_WIDE_REG_WRITE 0x74 /* PFP waits until the FIFO between the PFP and the ME is empty */ #define CP_WAIT_FOR_ME 0x13 Loading
drivers/gpu/msm/kgsl_iommu.c +16 −3 Original line number Diff line number Diff line Loading @@ -1174,6 +1174,8 @@ static int kgsl_set_register_map(struct kgsl_mmu *mmu) struct kgsl_iommu *iommu = mmu->device->mmu.priv; struct kgsl_iommu_unit *iommu_unit; int i = 0, ret = 0; struct kgsl_device *device = mmu->device; struct adreno_device *adreno_dev = ADRENO_DEVICE(device); for (; i < pdata->iommu_count; i++) { struct kgsl_device_iommu_data data = pdata->iommu_data[i]; Loading Loading @@ -1209,6 +1211,10 @@ static int kgsl_set_register_map(struct kgsl_mmu *mmu) iommu_unit->iommu_halt_enable = 1; if (kgsl_msm_supports_iommu_v2()) if (adreno_is_a405(adreno_dev)) { iommu_unit->ahb_base = KGSL_IOMMU_V2_AHB_BASE_A405; } else iommu_unit->ahb_base = KGSL_IOMMU_V2_AHB_BASE; else iommu_unit->ahb_base = Loading Loading @@ -2146,12 +2152,19 @@ static void kgsl_iommu_set_pagefault(struct kgsl_mmu *mmu) struct kgsl_protected_registers *kgsl_iommu_get_prot_regs(struct kgsl_mmu *mmu) { static struct kgsl_protected_registers iommuv1_regs = { 0x4000, 14 }; static struct kgsl_protected_registers iommuv2_regs = { 0x2800, 10 }; static struct kgsl_protected_registers iommuv2_regs; if (msm_soc_version_supports_iommu_v0()) return NULL; if (kgsl_msm_supports_iommu_v2()) if (kgsl_msm_supports_iommu_v2()) { struct kgsl_iommu *iommu = mmu->priv; /* For V2 there is only one instance of iommu */ iommuv2_regs.base = iommu->iommu_units[0].ahb_base >> 2; iommuv2_regs.range = 10; return &iommuv2_regs; } else return &iommuv1_regs; } Loading
drivers/gpu/msm/kgsl_iommu.h +1 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ /* IOMMU V2 AHB base is fixed */ #define KGSL_IOMMU_V2_AHB_BASE 0xA000 #define KGSL_IOMMU_V2_AHB_BASE_A405 0x48000 /* IOMMU_V2 AHB base points to ContextBank1 */ #define KGSL_IOMMU_CTX_AHB_OFFSET_V2 0 Loading