/** * cik_sdma_resume - setup and start the async dma engines * * @rdev: radeon_device pointer * * Set up the DMA engines and enable them (CIK). * Returns 0 for success, error for failure. */ int cik_sdma_resume(struct radeon_device *rdev) { int r; /* Reset dma */ WREG32(SRBM_SOFT_RESET, SOFT_RESET_SDMA | SOFT_RESET_SDMA1); RREG32(SRBM_SOFT_RESET); udelay(50); WREG32(SRBM_SOFT_RESET, 0); RREG32(SRBM_SOFT_RESET); r = cik_sdma_load_microcode(rdev); if (r) return r; /* unhalt the MEs */ cik_sdma_enable(rdev, true); /* start the gfx rings and rlc compute queues */ r = cik_sdma_gfx_resume(rdev); if (r) return r; r = cik_sdma_rlc_resume(rdev); if (r) return r; return 0; }
/** * cik_sdma_load_microcode - load the sDMA ME ucode * * @rdev: radeon_device pointer * * Loads the sDMA0/1 ucode. * Returns 0 for success, -EINVAL if the ucode is not available. */ static int cik_sdma_load_microcode(struct radeon_device *rdev) { const __be32 *fw_data; int i; if (!rdev->sdma_fw) return -EINVAL; /* halt the MEs */ cik_sdma_enable(rdev, false); /* sdma0 */ fw_data = (const __be32 *)rdev->sdma_fw->data; WREG32(SDMA0_UCODE_ADDR + SDMA0_REGISTER_OFFSET, 0); for (i = 0; i < CIK_SDMA_UCODE_SIZE; i++) WREG32(SDMA0_UCODE_DATA + SDMA0_REGISTER_OFFSET, be32_to_cpup(fw_data++)); WREG32(SDMA0_UCODE_DATA + SDMA0_REGISTER_OFFSET, CIK_SDMA_UCODE_VERSION); /* sdma1 */ fw_data = (const __be32 *)rdev->sdma_fw->data; WREG32(SDMA0_UCODE_ADDR + SDMA1_REGISTER_OFFSET, 0); for (i = 0; i < CIK_SDMA_UCODE_SIZE; i++) WREG32(SDMA0_UCODE_DATA + SDMA1_REGISTER_OFFSET, be32_to_cpup(fw_data++)); WREG32(SDMA0_UCODE_DATA + SDMA1_REGISTER_OFFSET, CIK_SDMA_UCODE_VERSION); WREG32(SDMA0_UCODE_ADDR + SDMA0_REGISTER_OFFSET, 0); WREG32(SDMA0_UCODE_ADDR + SDMA1_REGISTER_OFFSET, 0); return 0; }
/** * cik_sdma_load_microcode - load the sDMA ME ucode * * @adev: amdgpu_device pointer * * Loads the sDMA0/1 ucode. * Returns 0 for success, -EINVAL if the ucode is not available. */ static int cik_sdma_load_microcode(struct amdgpu_device *adev) { const struct sdma_firmware_header_v1_0 *hdr; const __le32 *fw_data; u32 fw_size; int i, j; /* halt the MEs */ cik_sdma_enable(adev, false); for (i = 0; i < adev->sdma.num_instances; i++) { if (!adev->sdma.instance[i].fw) return -EINVAL; hdr = (const struct sdma_firmware_header_v1_0 *)adev->sdma.instance[i].fw->data; amdgpu_ucode_print_sdma_hdr(&hdr->header); fw_size = le32_to_cpu(hdr->header.ucode_size_bytes) / 4; adev->sdma.instance[i].fw_version = le32_to_cpu(hdr->header.ucode_version); adev->sdma.instance[i].feature_version = le32_to_cpu(hdr->ucode_feature_version); if (adev->sdma.instance[i].feature_version >= 20) adev->sdma.instance[i].burst_nop = true; fw_data = (const __le32 *) (adev->sdma.instance[i].fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes)); WREG32(mmSDMA0_UCODE_ADDR + sdma_offsets[i], 0); for (j = 0; j < fw_size; j++) WREG32(mmSDMA0_UCODE_DATA + sdma_offsets[i], le32_to_cpup(fw_data++)); WREG32(mmSDMA0_UCODE_ADDR + sdma_offsets[i], adev->sdma.instance[i].fw_version); } return 0; }
/** * cik_sdma_fini - tear down the async dma engines * * @rdev: radeon_device pointer * * Stop the async dma engines and free the rings (CIK). */ void cik_sdma_fini(struct radeon_device *rdev) { /* halt the MEs */ cik_sdma_enable(rdev, false); radeon_ring_fini(rdev, &rdev->ring[R600_RING_TYPE_DMA_INDEX]); radeon_ring_fini(rdev, &rdev->ring[CAYMAN_RING_TYPE_DMA1_INDEX]); /* XXX - compute dma queue tear down */ }
static int cik_sdma_hw_fini(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; cik_sdma_enable(adev, false); return 0; }
/** * cik_sdma_load_microcode - load the sDMA ME ucode * * @rdev: radeon_device pointer * * Loads the sDMA0/1 ucode. * Returns 0 for success, -EINVAL if the ucode is not available. */ static int cik_sdma_load_microcode(struct radeon_device *rdev) { int i; if (!rdev->sdma_fw) return -EINVAL; /* halt the MEs */ cik_sdma_enable(rdev, false); if (rdev->new_fw) { const struct sdma_firmware_header_v1_0 *hdr = (const struct sdma_firmware_header_v1_0 *)rdev->sdma_fw->data; const __le32 *fw_data; u32 fw_size; radeon_ucode_print_sdma_hdr(&hdr->header); /* sdma0 */ fw_data = (const __le32 *) (rdev->sdma_fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes)); fw_size = le32_to_cpu(hdr->header.ucode_size_bytes) / 4; WREG32(SDMA0_UCODE_ADDR + SDMA0_REGISTER_OFFSET, 0); for (i = 0; i < fw_size; i++) WREG32(SDMA0_UCODE_DATA + SDMA0_REGISTER_OFFSET, le32_to_cpup(fw_data++)); WREG32(SDMA0_UCODE_DATA + SDMA0_REGISTER_OFFSET, CIK_SDMA_UCODE_VERSION); /* sdma1 */ fw_data = (const __le32 *) (rdev->sdma_fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes)); fw_size = le32_to_cpu(hdr->header.ucode_size_bytes) / 4; WREG32(SDMA0_UCODE_ADDR + SDMA1_REGISTER_OFFSET, 0); for (i = 0; i < fw_size; i++) WREG32(SDMA0_UCODE_DATA + SDMA1_REGISTER_OFFSET, le32_to_cpup(fw_data++)); WREG32(SDMA0_UCODE_DATA + SDMA1_REGISTER_OFFSET, CIK_SDMA_UCODE_VERSION); } else { const __be32 *fw_data; /* sdma0 */ fw_data = (const __be32 *)rdev->sdma_fw->data; WREG32(SDMA0_UCODE_ADDR + SDMA0_REGISTER_OFFSET, 0); for (i = 0; i < CIK_SDMA_UCODE_SIZE; i++) WREG32(SDMA0_UCODE_DATA + SDMA0_REGISTER_OFFSET, be32_to_cpup(fw_data++)); WREG32(SDMA0_UCODE_DATA + SDMA0_REGISTER_OFFSET, CIK_SDMA_UCODE_VERSION); /* sdma1 */ fw_data = (const __be32 *)rdev->sdma_fw->data; WREG32(SDMA0_UCODE_ADDR + SDMA1_REGISTER_OFFSET, 0); for (i = 0; i < CIK_SDMA_UCODE_SIZE; i++) WREG32(SDMA0_UCODE_DATA + SDMA1_REGISTER_OFFSET, be32_to_cpup(fw_data++)); WREG32(SDMA0_UCODE_DATA + SDMA1_REGISTER_OFFSET, CIK_SDMA_UCODE_VERSION); } WREG32(SDMA0_UCODE_ADDR + SDMA0_REGISTER_OFFSET, 0); WREG32(SDMA0_UCODE_ADDR + SDMA1_REGISTER_OFFSET, 0); return 0; }
/** * cik_sdma_resume - setup and start the async dma engines * * @rdev: radeon_device pointer * * Set up the DMA engines and enable them (CIK). * Returns 0 for success, error for failure. */ int cik_sdma_resume(struct radeon_device *rdev) { int r; r = cik_sdma_load_microcode(rdev); if (r) return r; /* unhalt the MEs */ cik_sdma_enable(rdev, true); /* start the gfx rings and rlc compute queues */ r = cik_sdma_gfx_resume(rdev); if (r) return r; r = cik_sdma_rlc_resume(rdev); if (r) return r; return 0; }
/** * cik_sdma_start - setup and start the async dma engines * * @adev: amdgpu_device pointer * * Set up the DMA engines and enable them (CIK). * Returns 0 for success, error for failure. */ static int cik_sdma_start(struct amdgpu_device *adev) { int r; r = cik_sdma_load_microcode(adev); if (r) return r; /* halt the engine before programing */ cik_sdma_enable(adev, false); /* start the gfx rings and rlc compute queues */ r = cik_sdma_gfx_resume(adev); if (r) return r; r = cik_sdma_rlc_resume(adev); if (r) return r; return 0; }
/** * cik_sdma_gfx_resume - setup and start the async dma engines * * @adev: amdgpu_device pointer * * Set up the gfx DMA ring buffers and enable them (CIK). * Returns 0 for success, error for failure. */ static int cik_sdma_gfx_resume(struct amdgpu_device *adev) { struct amdgpu_ring *ring; u32 rb_cntl, ib_cntl; u32 rb_bufsz; u32 wb_offset; int i, j, r; for (i = 0; i < adev->sdma.num_instances; i++) { ring = &adev->sdma.instance[i].ring; wb_offset = (ring->rptr_offs * 4); mutex_lock(&adev->srbm_mutex); for (j = 0; j < 16; j++) { cik_srbm_select(adev, 0, 0, 0, j); /* SDMA GFX */ WREG32(mmSDMA0_GFX_VIRTUAL_ADDR + sdma_offsets[i], 0); WREG32(mmSDMA0_GFX_APE1_CNTL + sdma_offsets[i], 0); /* XXX SDMA RLC - todo */ } cik_srbm_select(adev, 0, 0, 0, 0); mutex_unlock(&adev->srbm_mutex); WREG32(mmSDMA0_TILING_CONFIG + sdma_offsets[i], adev->gfx.config.gb_addr_config & 0x70); WREG32(mmSDMA0_SEM_INCOMPLETE_TIMER_CNTL + sdma_offsets[i], 0); WREG32(mmSDMA0_SEM_WAIT_FAIL_TIMER_CNTL + sdma_offsets[i], 0); /* Set ring buffer size in dwords */ rb_bufsz = order_base_2(ring->ring_size / 4); rb_cntl = rb_bufsz << 1; #ifdef __BIG_ENDIAN rb_cntl |= SDMA0_GFX_RB_CNTL__RB_SWAP_ENABLE_MASK | SDMA0_GFX_RB_CNTL__RPTR_WRITEBACK_SWAP_ENABLE_MASK; #endif WREG32(mmSDMA0_GFX_RB_CNTL + sdma_offsets[i], rb_cntl); /* Initialize the ring buffer's read and write pointers */ WREG32(mmSDMA0_GFX_RB_RPTR + sdma_offsets[i], 0); WREG32(mmSDMA0_GFX_RB_WPTR + sdma_offsets[i], 0); WREG32(mmSDMA0_GFX_IB_RPTR + sdma_offsets[i], 0); WREG32(mmSDMA0_GFX_IB_OFFSET + sdma_offsets[i], 0); /* set the wb address whether it's enabled or not */ WREG32(mmSDMA0_GFX_RB_RPTR_ADDR_HI + sdma_offsets[i], upper_32_bits(adev->wb.gpu_addr + wb_offset) & 0xFFFFFFFF); WREG32(mmSDMA0_GFX_RB_RPTR_ADDR_LO + sdma_offsets[i], ((adev->wb.gpu_addr + wb_offset) & 0xFFFFFFFC)); rb_cntl |= SDMA0_GFX_RB_CNTL__RPTR_WRITEBACK_ENABLE_MASK; WREG32(mmSDMA0_GFX_RB_BASE + sdma_offsets[i], ring->gpu_addr >> 8); WREG32(mmSDMA0_GFX_RB_BASE_HI + sdma_offsets[i], ring->gpu_addr >> 40); ring->wptr = 0; WREG32(mmSDMA0_GFX_RB_WPTR + sdma_offsets[i], lower_32_bits(ring->wptr) << 2); /* enable DMA RB */ WREG32(mmSDMA0_GFX_RB_CNTL + sdma_offsets[i], rb_cntl | SDMA0_GFX_RB_CNTL__RB_ENABLE_MASK); ib_cntl = SDMA0_GFX_IB_CNTL__IB_ENABLE_MASK; #ifdef __BIG_ENDIAN ib_cntl |= SDMA0_GFX_IB_CNTL__IB_SWAP_ENABLE_MASK; #endif /* enable DMA IBs */ WREG32(mmSDMA0_GFX_IB_CNTL + sdma_offsets[i], ib_cntl); ring->ready = true; } cik_sdma_enable(adev, true); for (i = 0; i < adev->sdma.num_instances; i++) { ring = &adev->sdma.instance[i].ring; r = amdgpu_ring_test_ring(ring); if (r) { ring->ready = false; return r; } if (adev->mman.buffer_funcs_ring == ring) amdgpu_ttm_set_active_vram_size(adev, adev->mc.real_vram_size); } return 0; }