diff options
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/mes_v10_1.c | 130 | 
1 files changed, 130 insertions, 0 deletions
| diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v10_1.c b/drivers/gpu/drm/amd/amdgpu/mes_v10_1.c index ace82c477f01..36d8314b8d39 100644 --- a/drivers/gpu/drm/amd/amdgpu/mes_v10_1.c +++ b/drivers/gpu/drm/amd/amdgpu/mes_v10_1.c @@ -350,6 +350,136 @@ static int mes_v10_1_allocate_eop_buf(struct amdgpu_device *adev)  	return 0;  } +static int mes_v10_1_mqd_init(struct amdgpu_ring *ring) +{ +	struct amdgpu_device *adev = ring->adev; +	struct v10_compute_mqd *mqd = ring->mqd_ptr; +	uint64_t hqd_gpu_addr, wb_gpu_addr, eop_base_addr; +	uint32_t tmp; + +	mqd->header = 0xC0310800; +	mqd->compute_pipelinestat_enable = 0x00000001; +	mqd->compute_static_thread_mgmt_se0 = 0xffffffff; +	mqd->compute_static_thread_mgmt_se1 = 0xffffffff; +	mqd->compute_static_thread_mgmt_se2 = 0xffffffff; +	mqd->compute_static_thread_mgmt_se3 = 0xffffffff; +	mqd->compute_misc_reserved = 0x00000003; + +	eop_base_addr = ring->eop_gpu_addr >> 8; +	mqd->cp_hqd_eop_base_addr_lo = eop_base_addr; +	mqd->cp_hqd_eop_base_addr_hi = upper_32_bits(eop_base_addr); + +	/* set the EOP size, register value is 2^(EOP_SIZE+1) dwords */ +	tmp = RREG32_SOC15(GC, 0, mmCP_HQD_EOP_CONTROL); +	tmp = REG_SET_FIELD(tmp, CP_HQD_EOP_CONTROL, EOP_SIZE, +			(order_base_2(MES_EOP_SIZE / 4) - 1)); + +	mqd->cp_hqd_eop_control = tmp; + +	/* enable doorbell? */ +	tmp = RREG32_SOC15(GC, 0, mmCP_HQD_PQ_DOORBELL_CONTROL); + +	if (ring->use_doorbell) { +		tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL, +				    DOORBELL_OFFSET, ring->doorbell_index); +		tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL, +				    DOORBELL_EN, 1); +		tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL, +				    DOORBELL_SOURCE, 0); +		tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL, +				    DOORBELL_HIT, 0); +	} +	else +		tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL, +				    DOORBELL_EN, 0); + +	mqd->cp_hqd_pq_doorbell_control = tmp; + +	/* disable the queue if it's active */ +	ring->wptr = 0; +	mqd->cp_hqd_dequeue_request = 0; +	mqd->cp_hqd_pq_rptr = 0; +	mqd->cp_hqd_pq_wptr_lo = 0; +	mqd->cp_hqd_pq_wptr_hi = 0; + +	/* set the pointer to the MQD */ +	mqd->cp_mqd_base_addr_lo = ring->mqd_gpu_addr & 0xfffffffc; +	mqd->cp_mqd_base_addr_hi = upper_32_bits(ring->mqd_gpu_addr); + +	/* set MQD vmid to 0 */ +	tmp = RREG32_SOC15(GC, 0, mmCP_MQD_CONTROL); +	tmp = REG_SET_FIELD(tmp, CP_MQD_CONTROL, VMID, 0); +	mqd->cp_mqd_control = tmp; + +	/* set the pointer to the HQD, this is similar CP_RB0_BASE/_HI */ +	hqd_gpu_addr = ring->gpu_addr >> 8; +	mqd->cp_hqd_pq_base_lo = hqd_gpu_addr; +	mqd->cp_hqd_pq_base_hi = upper_32_bits(hqd_gpu_addr); + +	/* set up the HQD, this is similar to CP_RB0_CNTL */ +	tmp = RREG32_SOC15(GC, 0, mmCP_HQD_PQ_CONTROL); +	tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, QUEUE_SIZE, +			    (order_base_2(ring->ring_size / 4) - 1)); +	tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, RPTR_BLOCK_SIZE, +			    ((order_base_2(AMDGPU_GPU_PAGE_SIZE / 4) - 1) << 8)); +#ifdef __BIG_ENDIAN +	tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, ENDIAN_SWAP, 1); +#endif +	tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, UNORD_DISPATCH, 0); +	tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, TUNNEL_DISPATCH, 0); +	tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, PRIV_STATE, 1); +	tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, KMD_QUEUE, 1); +	mqd->cp_hqd_pq_control = tmp; + +	/* set the wb address whether it's enabled or not */ +	wb_gpu_addr = adev->wb.gpu_addr + (ring->rptr_offs * 4); +	mqd->cp_hqd_pq_rptr_report_addr_lo = wb_gpu_addr & 0xfffffffc; +	mqd->cp_hqd_pq_rptr_report_addr_hi = +		upper_32_bits(wb_gpu_addr) & 0xffff; + +	/* only used if CP_PQ_WPTR_POLL_CNTL.CP_PQ_WPTR_POLL_CNTL__EN_MASK=1 */ +	wb_gpu_addr = adev->wb.gpu_addr + (ring->wptr_offs * 4); +	mqd->cp_hqd_pq_wptr_poll_addr_lo = wb_gpu_addr & 0xfffffff8; +	mqd->cp_hqd_pq_wptr_poll_addr_hi = upper_32_bits(wb_gpu_addr) & 0xffff; + +	tmp = 0; +	/* enable the doorbell if requested */ +	if (ring->use_doorbell) { +		tmp = RREG32_SOC15(GC, 0, mmCP_HQD_PQ_DOORBELL_CONTROL); +		tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL, +				DOORBELL_OFFSET, ring->doorbell_index); + +		tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL, +				    DOORBELL_EN, 1); +		tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL, +				    DOORBELL_SOURCE, 0); +		tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL, +				    DOORBELL_HIT, 0); +	} + +	mqd->cp_hqd_pq_doorbell_control = tmp; + +	/* reset read and write pointers, similar to CP_RB0_WPTR/_RPTR */ +	ring->wptr = 0; +	mqd->cp_hqd_pq_rptr = RREG32_SOC15(GC, 0, mmCP_HQD_PQ_RPTR); + +	/* set the vmid for the queue */ +	mqd->cp_hqd_vmid = 0; + +	tmp = RREG32_SOC15(GC, 0, mmCP_HQD_PERSISTENT_STATE); +	tmp = REG_SET_FIELD(tmp, CP_HQD_PERSISTENT_STATE, PRELOAD_SIZE, 0x53); +	mqd->cp_hqd_persistent_state = tmp; + +	/* set MIN_IB_AVAIL_SIZE */ +	tmp = RREG32_SOC15(GC, 0, mmCP_HQD_IB_CONTROL); +	tmp = REG_SET_FIELD(tmp, CP_HQD_IB_CONTROL, MIN_IB_AVAIL_SIZE, 3); +	mqd->cp_hqd_ib_control = tmp; + +	/* activate the queue */ +	mqd->cp_hqd_active = 1; +	return 0; +} +  static int mes_v10_1_ring_init(struct amdgpu_device *adev)  {  	struct amdgpu_ring *ring; | 
