/* * Copyright 2014 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. *
*/
/** * gmc_v7_0_init_microcode - load ucode images from disk * * @adev: amdgpu_device pointer * * Use the firmware interface to load the ucode images into * the driver (not loaded into hw). * Returns 0 on success, error on failure.
*/ staticint gmc_v7_0_init_microcode(struct amdgpu_device *adev)
{ constchar *chip_name; int err;
DRM_DEBUG("\n");
switch (adev->asic_type) { case CHIP_BONAIRE:
chip_name = "bonaire"; break; case CHIP_HAWAII:
chip_name = "hawaii"; break; case CHIP_TOPAZ:
chip_name = "topaz"; break; case CHIP_KAVERI: case CHIP_KABINI: case CHIP_MULLINS: return 0; default: return -EINVAL;
}
if (running == 0) { /* reset the engine and set to writable */
WREG32(mmMC_SEQ_SUP_CNTL, 0x00000008);
WREG32(mmMC_SEQ_SUP_CNTL, 0x00000010);
/* load mc io regs */ for (i = 0; i < regs_size; i++) {
WREG32(mmMC_SEQ_IO_DEBUG_INDEX, le32_to_cpup(io_mc_regs++));
WREG32(mmMC_SEQ_IO_DEBUG_DATA, le32_to_cpup(io_mc_regs++));
} /* load the MC ucode */ for (i = 0; i < ucode_size; i++)
WREG32(mmMC_SEQ_SUP_PGM, le32_to_cpup(fw_data++));
/* put the engine back into the active state */
WREG32(mmMC_SEQ_SUP_CNTL, 0x00000008);
WREG32(mmMC_SEQ_SUP_CNTL, 0x00000004);
WREG32(mmMC_SEQ_SUP_CNTL, 0x00000001);
/* wait for training to complete */ for (i = 0; i < adev->usec_timeout; i++) { if (REG_GET_FIELD(RREG32(mmMC_SEQ_TRAIN_WAKEUP_CNTL),
MC_SEQ_TRAIN_WAKEUP_CNTL, TRAIN_DONE_D0)) break;
udelay(1);
} for (i = 0; i < adev->usec_timeout; i++) { if (REG_GET_FIELD(RREG32(mmMC_SEQ_TRAIN_WAKEUP_CNTL),
MC_SEQ_TRAIN_WAKEUP_CNTL, TRAIN_DONE_D1)) break;
udelay(1);
}
}
/** * gmc_v7_0_mc_program - program the GPU memory controller * * @adev: amdgpu_device pointer * * Set the location of vram, gart, and AGP in the GPU's * physical address space (CIK).
*/ staticvoid gmc_v7_0_mc_program(struct amdgpu_device *adev)
{ struct amdgpu_ip_block *ip_block;
u32 tmp; int i, j;
ip_block = amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_GMC); if (!ip_block) return;
/** * gmc_v7_0_mc_init - initialize the memory controller driver params * * @adev: amdgpu_device pointer * * Look up the amount of vram, vram width, and decide how to place * vram and gart within the GPU's physical address space (CIK). * Returns 0 for success.
*/ staticint gmc_v7_0_mc_init(struct amdgpu_device *adev)
{ int r;
adev->gmc.vram_width = amdgpu_atombios_get_vram_width(adev); if (!adev->gmc.vram_width) {
u32 tmp; int chansize, numchan;
/* Get VRAM informations */
tmp = RREG32(mmMC_ARB_RAMCFG); if (REG_GET_FIELD(tmp, MC_ARB_RAMCFG, CHANSIZE))
chansize = 64; else
chansize = 32;
tmp = RREG32(mmMC_SHARED_CHMAP); switch (REG_GET_FIELD(tmp, MC_SHARED_CHMAP, NOOFCHAN)) { case 0: default:
numchan = 1; break; case 1:
numchan = 2; break; case 2:
numchan = 4; break; case 3:
numchan = 8; break; case 4:
numchan = 3; break; case 5:
numchan = 6; break; case 6:
numchan = 10; break; case 7:
numchan = 12; break; case 8:
numchan = 16; break;
}
adev->gmc.vram_width = numchan * chansize;
} /* size in MB on si */
adev->gmc.mc_vram_size = RREG32(mmCONFIG_MEMSIZE) * 1024ULL * 1024ULL;
adev->gmc.real_vram_size = RREG32(mmCONFIG_MEMSIZE) * 1024ULL * 1024ULL;
if (!(adev->flags & AMD_IS_APU)) {
r = amdgpu_device_resize_fb_bar(adev); if (r) return r;
}
adev->gmc.aper_base = pci_resource_start(adev->pdev, 0);
adev->gmc.aper_size = pci_resource_len(adev->pdev, 0);
/* set the gart size */ if (amdgpu_gart_size == -1) { switch (adev->asic_type) { case CHIP_TOPAZ: /* no MM engines */ default:
adev->gmc.gart_size = 256ULL << 20; break; #ifdef CONFIG_DRM_AMDGPU_CIK case CHIP_BONAIRE: /* UVD, VCE do not support GPUVM */ case CHIP_HAWAII: /* UVD, VCE do not support GPUVM */ case CHIP_KAVERI: /* UVD, VCE do not support GPUVM */ case CHIP_KABINI: /* UVD, VCE do not support GPUVM */ case CHIP_MULLINS: /* UVD, VCE do not support GPUVM */
adev->gmc.gart_size = 1024ULL << 20; break; #endif
}
} else {
adev->gmc.gart_size = (u64)amdgpu_gart_size << 20;
}
/** * gmc_v7_0_flush_gpu_tlb_pasid - tlb flush via pasid * * @adev: amdgpu_device pointer * @pasid: pasid to be flush * @flush_type: type of flush * @all_hub: flush all hubs * @inst: is used to select which instance of KIQ to use for the invalidation * * Flush the TLB for the requested pasid.
*/ staticvoid gmc_v7_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev,
uint16_t pasid, uint32_t flush_type, bool all_hub, uint32_t inst)
{
u32 mask = 0x0; int vmid;
/* * GART * VMID 0 is the physical GPU addresses as used by the kernel. * VMIDs 1-15 are used for userspace clients and are handled * by the amdgpu vm/hsa code.
*/
/** * gmc_v7_0_flush_gpu_tlb - gart tlb flush callback * * @adev: amdgpu_device pointer * @vmid: vm instance to flush * @vmhub: which hub to flush * @flush_type: type of flush * * * Flush the TLB for the requested page table (CIK).
*/ staticvoid gmc_v7_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
uint32_t vmhub, uint32_t flush_type)
{ /* bits 0-15 are the VM contexts0-15 */
WREG32(mmVM_INVALIDATE_REQUEST, 1 << vmid);
}
/** * gmc_v7_0_gart_enable - gart enable * * @adev: amdgpu_device pointer * * This sets up the TLBs, programs the page tables for VMID0, * sets up the hw for VMIDs 1-15 which are allocated on * demand, and sets up the global locations for the LDS, GDS, * and GPUVM for FSA64 clients (CIK). * Returns 0 for success, errors for failure.
*/ staticint gmc_v7_0_gart_enable(struct amdgpu_device *adev)
{
uint64_t table_addr;
u32 tmp, field; int i;
if (adev->gart.bo == NULL) {
dev_err(adev->dev, "No VRAM object for PCIE GART.\n"); return -EINVAL;
}
amdgpu_gtt_mgr_recover(&adev->mman.gtt_mgr);
table_addr = amdgpu_bo_gpu_offset(adev->gart.bo);
/* empty context1-15 */ /* FIXME start with 4G, once using 2 level pt switch to full * vm size space
*/ /* set vm size, must be a multiple of 4 */
WREG32(mmVM_CONTEXT1_PAGE_TABLE_START_ADDR, 0);
WREG32(mmVM_CONTEXT1_PAGE_TABLE_END_ADDR, adev->vm_manager.max_pfn - 1); for (i = 1; i < AMDGPU_NUM_VMID; i++) { if (i < 8)
WREG32(mmVM_CONTEXT0_PAGE_TABLE_BASE_ADDR + i,
table_addr >> 12); else
WREG32(mmVM_CONTEXT8_PAGE_TABLE_BASE_ADDR + i - 8,
table_addr >> 12);
}
for (i = 0; i < ARRAY_SIZE(mc_cg_registers); i++) {
orig = data = RREG32(mc_cg_registers[i]); if (enable && (adev->cg_flags & AMD_CG_SUPPORT_MC_LS))
data |= mc_cg_ls_en[i]; else
data &= ~mc_cg_ls_en[i]; if (data != orig)
WREG32(mc_cg_registers[i], data);
}
}
for (i = 0; i < ARRAY_SIZE(mc_cg_registers); i++) {
orig = data = RREG32(mc_cg_registers[i]); if (enable && (adev->cg_flags & AMD_CG_SUPPORT_MC_MGCG))
data |= mc_cg_en[i]; else
data &= ~mc_cg_en[i]; if (data != orig)
WREG32(mc_cg_registers[i], data);
}
}
r = amdgpu_irq_add_id(adev, AMDGPU_IRQ_CLIENTID_LEGACY, VISLANDS30_IV_SRCID_GFX_PAGE_INV_FAULT, &adev->gmc.vm_fault); if (r) return r;
r = amdgpu_irq_add_id(adev, AMDGPU_IRQ_CLIENTID_LEGACY, VISLANDS30_IV_SRCID_GFX_MEM_PROT_FAULT, &adev->gmc.vm_fault); if (r) return r;
/* Adjust VM size here. * Currently set to 4GB ((1 << 20) 4k pages). * Max GPUVM size for cayman and SI is 40 bits.
*/
amdgpu_vm_adjust_size(adev, 64, 9, 1, 40);
/* Set the internal MC address mask * This is the max address of the GPU's * internal address space.
*/
adev->gmc.mc_mask = 0xffffffffffULL; /* 40 bit MC */
r = dma_set_mask_and_coherent(adev->dev, DMA_BIT_MASK(40)); if (r) {
pr_warn("No suitable DMA available\n"); return r;
}
adev->need_swiotlb = drm_need_swiotlb(40);
r = gmc_v7_0_init_microcode(adev); if (r) {
DRM_ERROR("Failed to load mc firmware!\n"); return r;
}
r = gmc_v7_0_mc_init(adev); if (r) return r;
amdgpu_gmc_get_vbios_allocations(adev);
/* Memory manager */
r = amdgpu_bo_init(adev); if (r) return r;
r = gmc_v7_0_gart_init(adev); if (r) return r;
/* * number of VMs * VMID 0 is reserved for System * amdgpu graphics/compute will use VMIDs 1-7 * amdkfd will use VMIDs 8-15
*/
adev->vm_manager.first_kfd_vmid = 8;
amdgpu_vm_manager_init(adev);
/* base offset of vram pages */ if (adev->flags & AMD_IS_APU) {
u64 tmp = RREG32(mmMC_VM_FB_OFFSET);
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.6Bemerkung:
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.