xref: /dragonfly/sys/dev/drm/amd/amdgpu/sdma_v4_0.c (revision 809f3802)
1b843c749SSergey Zigachev /*
2b843c749SSergey Zigachev  * Copyright 2016 Advanced Micro Devices, Inc.
3b843c749SSergey Zigachev  *
4b843c749SSergey Zigachev  * Permission is hereby granted, free of charge, to any person obtaining a
5b843c749SSergey Zigachev  * copy of this software and associated documentation files (the "Software"),
6b843c749SSergey Zigachev  * to deal in the Software without restriction, including without limitation
7b843c749SSergey Zigachev  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8b843c749SSergey Zigachev  * and/or sell copies of the Software, and to permit persons to whom the
9b843c749SSergey Zigachev  * Software is furnished to do so, subject to the following conditions:
10b843c749SSergey Zigachev  *
11b843c749SSergey Zigachev  * The above copyright notice and this permission notice shall be included in
12b843c749SSergey Zigachev  * all copies or substantial portions of the Software.
13b843c749SSergey Zigachev  *
14b843c749SSergey Zigachev  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15b843c749SSergey Zigachev  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16b843c749SSergey Zigachev  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17b843c749SSergey Zigachev  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18b843c749SSergey Zigachev  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19b843c749SSergey Zigachev  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20b843c749SSergey Zigachev  * OTHER DEALINGS IN THE SOFTWARE.
21b843c749SSergey Zigachev  *
22b843c749SSergey Zigachev  */
23b843c749SSergey Zigachev 
24b843c749SSergey Zigachev #include <linux/firmware.h>
25b843c749SSergey Zigachev #include <drm/drmP.h>
26b843c749SSergey Zigachev #include "amdgpu.h"
27b843c749SSergey Zigachev #include "amdgpu_ucode.h"
28b843c749SSergey Zigachev #include "amdgpu_trace.h"
29b843c749SSergey Zigachev 
30b843c749SSergey Zigachev #include "sdma0/sdma0_4_0_offset.h"
31b843c749SSergey Zigachev #include "sdma0/sdma0_4_0_sh_mask.h"
32b843c749SSergey Zigachev #include "sdma1/sdma1_4_0_offset.h"
33b843c749SSergey Zigachev #include "sdma1/sdma1_4_0_sh_mask.h"
34b843c749SSergey Zigachev #include "hdp/hdp_4_0_offset.h"
35b843c749SSergey Zigachev #include "sdma0/sdma0_4_1_default.h"
36b843c749SSergey Zigachev 
37b843c749SSergey Zigachev #include "soc15_common.h"
38b843c749SSergey Zigachev #include "soc15.h"
39b843c749SSergey Zigachev #include "vega10_sdma_pkt_open.h"
40b843c749SSergey Zigachev 
41b843c749SSergey Zigachev #include "ivsrcid/sdma0/irqsrcs_sdma0_4_0.h"
42b843c749SSergey Zigachev #include "ivsrcid/sdma1/irqsrcs_sdma1_4_0.h"
43b843c749SSergey Zigachev 
44*809f3802SSergey Zigachev MODULE_FIRMWARE("amdgpufw_vega10_sdma");
45*809f3802SSergey Zigachev MODULE_FIRMWARE("amdgpufw_vega10_sdma1");
46*809f3802SSergey Zigachev MODULE_FIRMWARE("amdgpufw_vega12_sdma");
47*809f3802SSergey Zigachev MODULE_FIRMWARE("amdgpufw_vega12_sdma1");
48*809f3802SSergey Zigachev MODULE_FIRMWARE("amdgpufw_vega20_sdma");
49*809f3802SSergey Zigachev MODULE_FIRMWARE("amdgpufw_vega20_sdma1");
50*809f3802SSergey Zigachev MODULE_FIRMWARE("amdgpufw_raven_sdma");
51b843c749SSergey Zigachev 
52b843c749SSergey Zigachev #define SDMA0_POWER_CNTL__ON_OFF_CONDITION_HOLD_TIME_MASK  0x000000F8L
53b843c749SSergey Zigachev #define SDMA0_POWER_CNTL__ON_OFF_STATUS_DURATION_TIME_MASK 0xFC000000L
54b843c749SSergey Zigachev 
55b843c749SSergey Zigachev static void sdma_v4_0_set_ring_funcs(struct amdgpu_device *adev);
56b843c749SSergey Zigachev static void sdma_v4_0_set_buffer_funcs(struct amdgpu_device *adev);
57b843c749SSergey Zigachev static void sdma_v4_0_set_vm_pte_funcs(struct amdgpu_device *adev);
58b843c749SSergey Zigachev static void sdma_v4_0_set_irq_funcs(struct amdgpu_device *adev);
59b843c749SSergey Zigachev 
60b843c749SSergey Zigachev static const struct soc15_reg_golden golden_settings_sdma_4[] = {
61b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_CHICKEN_BITS, 0xfe931f07, 0x02831d07),
62b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_CLK_CTRL, 0xff000ff0, 0x3f000100),
63b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GFX_IB_CNTL, 0x800f0100, 0x00000100),
64b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GFX_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
65b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_PAGE_IB_CNTL, 0x800f0100, 0x00000100),
66b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_PAGE_RB_WPTR_POLL_CNTL, 0x0000fff0, 0x00403000),
67b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_POWER_CNTL, 0x003ff006, 0x0003c000),
68b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_RLC0_IB_CNTL, 0x800f0100, 0x00000100),
69b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_RLC0_RB_WPTR_POLL_CNTL, 0x0000fff0, 0x00403000),
70b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_RLC1_IB_CNTL, 0x800f0100, 0x00000100),
71b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_RLC1_RB_WPTR_POLL_CNTL, 0x0000fff0, 0x00403000),
72b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_PAGE, 0x000003ff, 0x000003c0),
73b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_WATERMK, 0xfc000000, 0x00000000),
74b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_CLK_CTRL, 0xffffffff, 0x3f000100),
75b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GFX_IB_CNTL, 0x800f0100, 0x00000100),
76b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GFX_RB_WPTR_POLL_CNTL, 0x0000fff0, 0x00403000),
77b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_PAGE_IB_CNTL, 0x800f0100, 0x00000100),
78b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_PAGE_RB_WPTR_POLL_CNTL, 0x0000fff0, 0x00403000),
79b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_POWER_CNTL, 0x003ff000, 0x0003c000),
80b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_RLC0_IB_CNTL, 0x800f0100, 0x00000100),
81b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_RLC0_RB_WPTR_POLL_CNTL, 0x0000fff0, 0x00403000),
82b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_RLC1_IB_CNTL, 0x800f0100, 0x00000100),
83b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_RLC1_RB_WPTR_POLL_CNTL, 0x0000fff0, 0x00403000),
84b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_UTCL1_PAGE, 0x000003ff, 0x000003c0),
85b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_UTCL1_WATERMK, 0xfc000000, 0x00000000)
86b843c749SSergey Zigachev };
87b843c749SSergey Zigachev 
88b843c749SSergey Zigachev static const struct soc15_reg_golden golden_settings_sdma_vg10[] = {
89b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GB_ADDR_CONFIG, 0x0018773f, 0x00104002),
90b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GB_ADDR_CONFIG_READ, 0x0018773f, 0x00104002),
91b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_CHICKEN_BITS, 0xfe931f07, 0x02831d07),
92b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GB_ADDR_CONFIG, 0x0018773f, 0x00104002),
93b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GB_ADDR_CONFIG_READ, 0x0018773f, 0x00104002)
94b843c749SSergey Zigachev };
95b843c749SSergey Zigachev 
96b843c749SSergey Zigachev static const struct soc15_reg_golden golden_settings_sdma_vg12[] = {
97b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GB_ADDR_CONFIG, 0x0018773f, 0x00104001),
98b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GB_ADDR_CONFIG_READ, 0x0018773f, 0x00104001),
99b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_CHICKEN_BITS, 0xfe931f07, 0x02831d07),
100b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GB_ADDR_CONFIG, 0x0018773f, 0x00104001),
101b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GB_ADDR_CONFIG_READ, 0x0018773f, 0x00104001)
102b843c749SSergey Zigachev };
103b843c749SSergey Zigachev 
104b843c749SSergey Zigachev static const struct soc15_reg_golden golden_settings_sdma_4_1[] =
105b843c749SSergey Zigachev {
106b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_CHICKEN_BITS, 0xfe931f07, 0x02831d07),
107b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_CLK_CTRL, 0xffffffff, 0x3f000100),
108b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GFX_IB_CNTL, 0x800f0111, 0x00000100),
109b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GFX_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
110b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_POWER_CNTL, 0xfc3fffff, 0x40000051),
111b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_RLC0_IB_CNTL, 0x800f0111, 0x00000100),
112b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_RLC0_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
113b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_RLC1_IB_CNTL, 0x800f0111, 0x00000100),
114b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_RLC1_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
115b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_PAGE, 0x000003ff, 0x000003c0),
116b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_WATERMK, 0xfc000000, 0x00000000)
117b843c749SSergey Zigachev };
118b843c749SSergey Zigachev 
119b843c749SSergey Zigachev static const struct soc15_reg_golden golden_settings_sdma_4_2[] =
120b843c749SSergey Zigachev {
121b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_CHICKEN_BITS, 0xfe931f07, 0x02831d07),
122b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_CLK_CTRL, 0xffffffff, 0x3f000100),
123b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GB_ADDR_CONFIG, 0x0000773f, 0x00004002),
124b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GB_ADDR_CONFIG_READ, 0x0000773f, 0x00004002),
125b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GFX_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
126b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_PAGE_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
127b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_RLC0_RB_WPTR_POLL_CNTL, 0xfffffff0, 0x00403000),
128b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_RLC1_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
129b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_PAGE, 0x000003ff, 0x000003c0),
130b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_CHICKEN_BITS, 0xfe931f07, 0x02831d07),
131b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_CLK_CTRL, 0xffffffff, 0x3f000100),
132b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GB_ADDR_CONFIG, 0x0000773f, 0x00004002),
133b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GB_ADDR_CONFIG_READ, 0x0000773f, 0x00004002),
134b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GFX_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
135b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_PAGE_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
136b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_RLC0_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
137b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_RLC1_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
138b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_UTCL1_PAGE, 0x000003ff, 0x000003c0)
139b843c749SSergey Zigachev };
140b843c749SSergey Zigachev 
141b843c749SSergey Zigachev static const struct soc15_reg_golden golden_settings_sdma_rv1[] =
142b843c749SSergey Zigachev {
143b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GB_ADDR_CONFIG, 0x0018773f, 0x00000002),
144b843c749SSergey Zigachev 	SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GB_ADDR_CONFIG_READ, 0x0018773f, 0x00000002)
145b843c749SSergey Zigachev };
146b843c749SSergey Zigachev 
sdma_v4_0_get_reg_offset(struct amdgpu_device * adev,u32 instance,u32 offset)147b843c749SSergey Zigachev static u32 sdma_v4_0_get_reg_offset(struct amdgpu_device *adev,
148b843c749SSergey Zigachev 		u32 instance, u32 offset)
149b843c749SSergey Zigachev {
150b843c749SSergey Zigachev 	return ( 0 == instance ? (adev->reg_offset[SDMA0_HWIP][0][0] + offset) :
151b843c749SSergey Zigachev 			(adev->reg_offset[SDMA1_HWIP][0][0] + offset));
152b843c749SSergey Zigachev }
153b843c749SSergey Zigachev 
sdma_v4_0_init_golden_registers(struct amdgpu_device * adev)154b843c749SSergey Zigachev static void sdma_v4_0_init_golden_registers(struct amdgpu_device *adev)
155b843c749SSergey Zigachev {
156b843c749SSergey Zigachev 	switch (adev->asic_type) {
157b843c749SSergey Zigachev 	case CHIP_VEGA10:
158b843c749SSergey Zigachev 		soc15_program_register_sequence(adev,
159b843c749SSergey Zigachev 						 golden_settings_sdma_4,
160b843c749SSergey Zigachev 						 ARRAY_SIZE(golden_settings_sdma_4));
161b843c749SSergey Zigachev 		soc15_program_register_sequence(adev,
162b843c749SSergey Zigachev 						 golden_settings_sdma_vg10,
163b843c749SSergey Zigachev 						 ARRAY_SIZE(golden_settings_sdma_vg10));
164b843c749SSergey Zigachev 		break;
165b843c749SSergey Zigachev 	case CHIP_VEGA12:
166b843c749SSergey Zigachev 		soc15_program_register_sequence(adev,
167b843c749SSergey Zigachev 						golden_settings_sdma_4,
168b843c749SSergey Zigachev 						ARRAY_SIZE(golden_settings_sdma_4));
169b843c749SSergey Zigachev 		soc15_program_register_sequence(adev,
170b843c749SSergey Zigachev 						golden_settings_sdma_vg12,
171b843c749SSergey Zigachev 						ARRAY_SIZE(golden_settings_sdma_vg12));
172b843c749SSergey Zigachev 		break;
173b843c749SSergey Zigachev 	case CHIP_VEGA20:
174b843c749SSergey Zigachev 		soc15_program_register_sequence(adev,
175b843c749SSergey Zigachev 						golden_settings_sdma_4_2,
176b843c749SSergey Zigachev 						ARRAY_SIZE(golden_settings_sdma_4_2));
177b843c749SSergey Zigachev 		break;
178b843c749SSergey Zigachev 	case CHIP_RAVEN:
179b843c749SSergey Zigachev 		soc15_program_register_sequence(adev,
180b843c749SSergey Zigachev 						 golden_settings_sdma_4_1,
181b843c749SSergey Zigachev 						 ARRAY_SIZE(golden_settings_sdma_4_1));
182b843c749SSergey Zigachev 		soc15_program_register_sequence(adev,
183b843c749SSergey Zigachev 						 golden_settings_sdma_rv1,
184b843c749SSergey Zigachev 						 ARRAY_SIZE(golden_settings_sdma_rv1));
185b843c749SSergey Zigachev 		break;
186b843c749SSergey Zigachev 	default:
187b843c749SSergey Zigachev 		break;
188b843c749SSergey Zigachev 	}
189b843c749SSergey Zigachev }
190b843c749SSergey Zigachev 
191b843c749SSergey Zigachev /**
192b843c749SSergey Zigachev  * sdma_v4_0_init_microcode - load ucode images from disk
193b843c749SSergey Zigachev  *
194b843c749SSergey Zigachev  * @adev: amdgpu_device pointer
195b843c749SSergey Zigachev  *
196b843c749SSergey Zigachev  * Use the firmware interface to load the ucode images into
197b843c749SSergey Zigachev  * the driver (not loaded into hw).
198b843c749SSergey Zigachev  * Returns 0 on success, error on failure.
199b843c749SSergey Zigachev  */
200b843c749SSergey Zigachev 
201b843c749SSergey Zigachev // emulation only, won't work on real chip
202b843c749SSergey Zigachev // vega10 real chip need to use PSP to load firmware
sdma_v4_0_init_microcode(struct amdgpu_device * adev)203b843c749SSergey Zigachev static int sdma_v4_0_init_microcode(struct amdgpu_device *adev)
204b843c749SSergey Zigachev {
205b843c749SSergey Zigachev 	const char *chip_name;
206b843c749SSergey Zigachev 	char fw_name[30];
207b843c749SSergey Zigachev 	int err = 0, i;
208b843c749SSergey Zigachev 	struct amdgpu_firmware_info *info = NULL;
209b843c749SSergey Zigachev 	const struct common_firmware_header *header = NULL;
210b843c749SSergey Zigachev 	const struct sdma_firmware_header_v1_0 *hdr;
211b843c749SSergey Zigachev 
212b843c749SSergey Zigachev 	DRM_DEBUG("\n");
213b843c749SSergey Zigachev 
214b843c749SSergey Zigachev 	switch (adev->asic_type) {
215b843c749SSergey Zigachev 	case CHIP_VEGA10:
216b843c749SSergey Zigachev 		chip_name = "vega10";
217b843c749SSergey Zigachev 		break;
218b843c749SSergey Zigachev 	case CHIP_VEGA12:
219b843c749SSergey Zigachev 		chip_name = "vega12";
220b843c749SSergey Zigachev 		break;
221b843c749SSergey Zigachev 	case CHIP_VEGA20:
222b843c749SSergey Zigachev 		chip_name = "vega20";
223b843c749SSergey Zigachev 		break;
224b843c749SSergey Zigachev 	case CHIP_RAVEN:
225b843c749SSergey Zigachev 		chip_name = "raven";
226b843c749SSergey Zigachev 		break;
227b843c749SSergey Zigachev 	default:
228b843c749SSergey Zigachev 		BUG();
229b843c749SSergey Zigachev 	}
230b843c749SSergey Zigachev 
231b843c749SSergey Zigachev 	for (i = 0; i < adev->sdma.num_instances; i++) {
232b843c749SSergey Zigachev 		if (i == 0)
233*809f3802SSergey Zigachev 			snprintf(fw_name, sizeof(fw_name), "amdgpufw_%s_sdma", chip_name);
234b843c749SSergey Zigachev 		else
235*809f3802SSergey Zigachev 			snprintf(fw_name, sizeof(fw_name), "amdgpufw_%s_sdma1", chip_name);
236b843c749SSergey Zigachev 		err = request_firmware(&adev->sdma.instance[i].fw, fw_name, adev->dev);
237b843c749SSergey Zigachev 		if (err)
238b843c749SSergey Zigachev 			goto out;
239b843c749SSergey Zigachev 		err = amdgpu_ucode_validate(adev->sdma.instance[i].fw);
240b843c749SSergey Zigachev 		if (err)
241b843c749SSergey Zigachev 			goto out;
242b843c749SSergey Zigachev 		hdr = (const struct sdma_firmware_header_v1_0 *)adev->sdma.instance[i].fw->data;
243b843c749SSergey Zigachev 		adev->sdma.instance[i].fw_version = le32_to_cpu(hdr->header.ucode_version);
244b843c749SSergey Zigachev 		adev->sdma.instance[i].feature_version = le32_to_cpu(hdr->ucode_feature_version);
245b843c749SSergey Zigachev 		if (adev->sdma.instance[i].feature_version >= 20)
246b843c749SSergey Zigachev 			adev->sdma.instance[i].burst_nop = true;
247b843c749SSergey Zigachev 		DRM_DEBUG("psp_load == '%s'\n",
248b843c749SSergey Zigachev 				adev->firmware.load_type == AMDGPU_FW_LOAD_PSP ? "true" : "false");
249b843c749SSergey Zigachev 
250b843c749SSergey Zigachev 		if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
251b843c749SSergey Zigachev 			info = &adev->firmware.ucode[AMDGPU_UCODE_ID_SDMA0 + i];
252b843c749SSergey Zigachev 			info->ucode_id = AMDGPU_UCODE_ID_SDMA0 + i;
253b843c749SSergey Zigachev 			info->fw = adev->sdma.instance[i].fw;
254b843c749SSergey Zigachev 			header = (const struct common_firmware_header *)info->fw->data;
255b843c749SSergey Zigachev 			adev->firmware.fw_size +=
256b843c749SSergey Zigachev 				ALIGN(le32_to_cpu(header->ucode_size_bytes), PAGE_SIZE);
257b843c749SSergey Zigachev 		}
258b843c749SSergey Zigachev 	}
259b843c749SSergey Zigachev out:
260b843c749SSergey Zigachev 	if (err) {
261b843c749SSergey Zigachev 		DRM_ERROR("sdma_v4_0: Failed to load firmware \"%s\"\n", fw_name);
262b843c749SSergey Zigachev 		for (i = 0; i < adev->sdma.num_instances; i++) {
263b843c749SSergey Zigachev 			release_firmware(adev->sdma.instance[i].fw);
264b843c749SSergey Zigachev 			adev->sdma.instance[i].fw = NULL;
265b843c749SSergey Zigachev 		}
266b843c749SSergey Zigachev 	}
267b843c749SSergey Zigachev 	return err;
268b843c749SSergey Zigachev }
269b843c749SSergey Zigachev 
270b843c749SSergey Zigachev /**
271b843c749SSergey Zigachev  * sdma_v4_0_ring_get_rptr - get the current read pointer
272b843c749SSergey Zigachev  *
273b843c749SSergey Zigachev  * @ring: amdgpu ring pointer
274b843c749SSergey Zigachev  *
275b843c749SSergey Zigachev  * Get the current rptr from the hardware (VEGA10+).
276b843c749SSergey Zigachev  */
sdma_v4_0_ring_get_rptr(struct amdgpu_ring * ring)277b843c749SSergey Zigachev static uint64_t sdma_v4_0_ring_get_rptr(struct amdgpu_ring *ring)
278b843c749SSergey Zigachev {
279b843c749SSergey Zigachev 	u64 *rptr;
280b843c749SSergey Zigachev 
281b843c749SSergey Zigachev 	/* XXX check if swapping is necessary on BE */
282b843c749SSergey Zigachev 	rptr = ((u64 *)&ring->adev->wb.wb[ring->rptr_offs]);
283b843c749SSergey Zigachev 
284b843c749SSergey Zigachev 	DRM_DEBUG("rptr before shift == 0x%016llx\n", *rptr);
285b843c749SSergey Zigachev 	return ((*rptr) >> 2);
286b843c749SSergey Zigachev }
287b843c749SSergey Zigachev 
288b843c749SSergey Zigachev /**
289b843c749SSergey Zigachev  * sdma_v4_0_ring_get_wptr - get the current write pointer
290b843c749SSergey Zigachev  *
291b843c749SSergey Zigachev  * @ring: amdgpu ring pointer
292b843c749SSergey Zigachev  *
293b843c749SSergey Zigachev  * Get the current wptr from the hardware (VEGA10+).
294b843c749SSergey Zigachev  */
sdma_v4_0_ring_get_wptr(struct amdgpu_ring * ring)295b843c749SSergey Zigachev static uint64_t sdma_v4_0_ring_get_wptr(struct amdgpu_ring *ring)
296b843c749SSergey Zigachev {
297b843c749SSergey Zigachev 	struct amdgpu_device *adev = ring->adev;
298b843c749SSergey Zigachev 	u64 wptr;
299b843c749SSergey Zigachev 
300b843c749SSergey Zigachev 	if (ring->use_doorbell) {
301b843c749SSergey Zigachev 		/* XXX check if swapping is necessary on BE */
302b843c749SSergey Zigachev 		wptr = READ_ONCE(*((u64 *)&adev->wb.wb[ring->wptr_offs]));
303b843c749SSergey Zigachev 		DRM_DEBUG("wptr/doorbell before shift == 0x%016llx\n", wptr);
304b843c749SSergey Zigachev 	} else {
305b843c749SSergey Zigachev 		u32 lowbit, highbit;
306b843c749SSergey Zigachev 
307b843c749SSergey Zigachev 		lowbit = RREG32(sdma_v4_0_get_reg_offset(adev, ring->me, mmSDMA0_GFX_RB_WPTR)) >> 2;
308b843c749SSergey Zigachev 		highbit = RREG32(sdma_v4_0_get_reg_offset(adev, ring->me, mmSDMA0_GFX_RB_WPTR_HI)) >> 2;
309b843c749SSergey Zigachev 
310b843c749SSergey Zigachev 		DRM_DEBUG("wptr [%i]high== 0x%08x low==0x%08x\n",
311b843c749SSergey Zigachev 				ring->me, highbit, lowbit);
312b843c749SSergey Zigachev 		wptr = highbit;
313b843c749SSergey Zigachev 		wptr = wptr << 32;
314b843c749SSergey Zigachev 		wptr |= lowbit;
315b843c749SSergey Zigachev 	}
316b843c749SSergey Zigachev 
317b843c749SSergey Zigachev 	return wptr >> 2;
318b843c749SSergey Zigachev }
319b843c749SSergey Zigachev 
320b843c749SSergey Zigachev /**
321b843c749SSergey Zigachev  * sdma_v4_0_ring_set_wptr - commit the write pointer
322b843c749SSergey Zigachev  *
323b843c749SSergey Zigachev  * @ring: amdgpu ring pointer
324b843c749SSergey Zigachev  *
325b843c749SSergey Zigachev  * Write the wptr back to the hardware (VEGA10+).
326b843c749SSergey Zigachev  */
sdma_v4_0_ring_set_wptr(struct amdgpu_ring * ring)327b843c749SSergey Zigachev static void sdma_v4_0_ring_set_wptr(struct amdgpu_ring *ring)
328b843c749SSergey Zigachev {
329b843c749SSergey Zigachev 	struct amdgpu_device *adev = ring->adev;
330b843c749SSergey Zigachev 
331b843c749SSergey Zigachev 	DRM_DEBUG("Setting write pointer\n");
332b843c749SSergey Zigachev 	if (ring->use_doorbell) {
333b843c749SSergey Zigachev 		u64 *wb = (u64 *)&adev->wb.wb[ring->wptr_offs];
334b843c749SSergey Zigachev 
335b843c749SSergey Zigachev 		DRM_DEBUG("Using doorbell -- "
336b843c749SSergey Zigachev 				"wptr_offs == 0x%08x "
337b843c749SSergey Zigachev 				"lower_32_bits(ring->wptr) << 2 == 0x%08x "
338b843c749SSergey Zigachev 				"upper_32_bits(ring->wptr) << 2 == 0x%08x\n",
339b843c749SSergey Zigachev 				ring->wptr_offs,
340b843c749SSergey Zigachev 				lower_32_bits(ring->wptr << 2),
341b843c749SSergey Zigachev 				upper_32_bits(ring->wptr << 2));
342b843c749SSergey Zigachev 		/* XXX check if swapping is necessary on BE */
343b843c749SSergey Zigachev 		WRITE_ONCE(*wb, (ring->wptr << 2));
344b843c749SSergey Zigachev 		DRM_DEBUG("calling WDOORBELL64(0x%08x, 0x%016llx)\n",
345b843c749SSergey Zigachev 				ring->doorbell_index, ring->wptr << 2);
346b843c749SSergey Zigachev 		WDOORBELL64(ring->doorbell_index, ring->wptr << 2);
347b843c749SSergey Zigachev 	} else {
348b843c749SSergey Zigachev 		DRM_DEBUG("Not using doorbell -- "
349b843c749SSergey Zigachev 				"mmSDMA%i_GFX_RB_WPTR == 0x%08x "
350b843c749SSergey Zigachev 				"mmSDMA%i_GFX_RB_WPTR_HI == 0x%08x\n",
351b843c749SSergey Zigachev 				ring->me,
352b843c749SSergey Zigachev 				lower_32_bits(ring->wptr << 2),
353b843c749SSergey Zigachev 				ring->me,
354b843c749SSergey Zigachev 				upper_32_bits(ring->wptr << 2));
355b843c749SSergey Zigachev 		WREG32(sdma_v4_0_get_reg_offset(adev, ring->me, mmSDMA0_GFX_RB_WPTR), lower_32_bits(ring->wptr << 2));
356b843c749SSergey Zigachev 		WREG32(sdma_v4_0_get_reg_offset(adev, ring->me, mmSDMA0_GFX_RB_WPTR_HI), upper_32_bits(ring->wptr << 2));
357b843c749SSergey Zigachev 	}
358b843c749SSergey Zigachev }
359b843c749SSergey Zigachev 
sdma_v4_0_ring_insert_nop(struct amdgpu_ring * ring,uint32_t count)360b843c749SSergey Zigachev static void sdma_v4_0_ring_insert_nop(struct amdgpu_ring *ring, uint32_t count)
361b843c749SSergey Zigachev {
362b843c749SSergey Zigachev 	struct amdgpu_sdma_instance *sdma = amdgpu_get_sdma_instance(ring);
363b843c749SSergey Zigachev 	int i;
364b843c749SSergey Zigachev 
365b843c749SSergey Zigachev 	for (i = 0; i < count; i++)
366b843c749SSergey Zigachev 		if (sdma && sdma->burst_nop && (i == 0))
367b843c749SSergey Zigachev 			amdgpu_ring_write(ring, ring->funcs->nop |
368b843c749SSergey Zigachev 				SDMA_PKT_NOP_HEADER_COUNT(count - 1));
369b843c749SSergey Zigachev 		else
370b843c749SSergey Zigachev 			amdgpu_ring_write(ring, ring->funcs->nop);
371b843c749SSergey Zigachev }
372b843c749SSergey Zigachev 
373b843c749SSergey Zigachev /**
374b843c749SSergey Zigachev  * sdma_v4_0_ring_emit_ib - Schedule an IB on the DMA engine
375b843c749SSergey Zigachev  *
376b843c749SSergey Zigachev  * @ring: amdgpu ring pointer
377b843c749SSergey Zigachev  * @ib: IB object to schedule
378b843c749SSergey Zigachev  *
379b843c749SSergey Zigachev  * Schedule an IB in the DMA ring (VEGA10).
380b843c749SSergey Zigachev  */
sdma_v4_0_ring_emit_ib(struct amdgpu_ring * ring,struct amdgpu_ib * ib,unsigned vmid,bool ctx_switch)381b843c749SSergey Zigachev static void sdma_v4_0_ring_emit_ib(struct amdgpu_ring *ring,
382b843c749SSergey Zigachev 					struct amdgpu_ib *ib,
383b843c749SSergey Zigachev 					unsigned vmid, bool ctx_switch)
384b843c749SSergey Zigachev {
385b843c749SSergey Zigachev 	/* IB packet must end on a 8 DW boundary */
386b843c749SSergey Zigachev 	sdma_v4_0_ring_insert_nop(ring, (10 - (lower_32_bits(ring->wptr) & 7)) % 8);
387b843c749SSergey Zigachev 
388b843c749SSergey Zigachev 	amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_INDIRECT) |
389b843c749SSergey Zigachev 			  SDMA_PKT_INDIRECT_HEADER_VMID(vmid & 0xf));
390b843c749SSergey Zigachev 	/* base must be 32 byte aligned */
391b843c749SSergey Zigachev 	amdgpu_ring_write(ring, lower_32_bits(ib->gpu_addr) & 0xffffffe0);
392b843c749SSergey Zigachev 	amdgpu_ring_write(ring, upper_32_bits(ib->gpu_addr));
393b843c749SSergey Zigachev 	amdgpu_ring_write(ring, ib->length_dw);
394b843c749SSergey Zigachev 	amdgpu_ring_write(ring, 0);
395b843c749SSergey Zigachev 	amdgpu_ring_write(ring, 0);
396b843c749SSergey Zigachev 
397b843c749SSergey Zigachev }
398b843c749SSergey Zigachev 
sdma_v4_0_wait_reg_mem(struct amdgpu_ring * ring,int mem_space,int hdp,uint32_t addr0,uint32_t addr1,uint32_t ref,uint32_t mask,uint32_t inv)399b843c749SSergey Zigachev static void sdma_v4_0_wait_reg_mem(struct amdgpu_ring *ring,
400b843c749SSergey Zigachev 				   int mem_space, int hdp,
401b843c749SSergey Zigachev 				   uint32_t addr0, uint32_t addr1,
402b843c749SSergey Zigachev 				   uint32_t ref, uint32_t mask,
403b843c749SSergey Zigachev 				   uint32_t inv)
404b843c749SSergey Zigachev {
405b843c749SSergey Zigachev 	amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_POLL_REGMEM) |
406b843c749SSergey Zigachev 			  SDMA_PKT_POLL_REGMEM_HEADER_HDP_FLUSH(hdp) |
407b843c749SSergey Zigachev 			  SDMA_PKT_POLL_REGMEM_HEADER_MEM_POLL(mem_space) |
408b843c749SSergey Zigachev 			  SDMA_PKT_POLL_REGMEM_HEADER_FUNC(3)); /* == */
409b843c749SSergey Zigachev 	if (mem_space) {
410b843c749SSergey Zigachev 		/* memory */
411b843c749SSergey Zigachev 		amdgpu_ring_write(ring, addr0);
412b843c749SSergey Zigachev 		amdgpu_ring_write(ring, addr1);
413b843c749SSergey Zigachev 	} else {
414b843c749SSergey Zigachev 		/* registers */
415b843c749SSergey Zigachev 		amdgpu_ring_write(ring, addr0 << 2);
416b843c749SSergey Zigachev 		amdgpu_ring_write(ring, addr1 << 2);
417b843c749SSergey Zigachev 	}
418b843c749SSergey Zigachev 	amdgpu_ring_write(ring, ref); /* reference */
419b843c749SSergey Zigachev 	amdgpu_ring_write(ring, mask); /* mask */
420b843c749SSergey Zigachev 	amdgpu_ring_write(ring, SDMA_PKT_POLL_REGMEM_DW5_RETRY_COUNT(0xfff) |
421b843c749SSergey Zigachev 			  SDMA_PKT_POLL_REGMEM_DW5_INTERVAL(inv)); /* retry count, poll interval */
422b843c749SSergey Zigachev }
423b843c749SSergey Zigachev 
424b843c749SSergey Zigachev /**
425b843c749SSergey Zigachev  * sdma_v4_0_ring_emit_hdp_flush - emit an hdp flush on the DMA ring
426b843c749SSergey Zigachev  *
427b843c749SSergey Zigachev  * @ring: amdgpu ring pointer
428b843c749SSergey Zigachev  *
429b843c749SSergey Zigachev  * Emit an hdp flush packet on the requested DMA ring.
430b843c749SSergey Zigachev  */
sdma_v4_0_ring_emit_hdp_flush(struct amdgpu_ring * ring)431b843c749SSergey Zigachev static void sdma_v4_0_ring_emit_hdp_flush(struct amdgpu_ring *ring)
432b843c749SSergey Zigachev {
433b843c749SSergey Zigachev 	struct amdgpu_device *adev = ring->adev;
434b843c749SSergey Zigachev 	u32 ref_and_mask = 0;
435b843c749SSergey Zigachev 	const struct nbio_hdp_flush_reg *nbio_hf_reg = adev->nbio_funcs->hdp_flush_reg;
436b843c749SSergey Zigachev 
437b843c749SSergey Zigachev 	if (ring->me == 0)
438b843c749SSergey Zigachev 		ref_and_mask = nbio_hf_reg->ref_and_mask_sdma0;
439b843c749SSergey Zigachev 	else
440b843c749SSergey Zigachev 		ref_and_mask = nbio_hf_reg->ref_and_mask_sdma1;
441b843c749SSergey Zigachev 
442b843c749SSergey Zigachev 	sdma_v4_0_wait_reg_mem(ring, 0, 1,
443b843c749SSergey Zigachev 			       adev->nbio_funcs->get_hdp_flush_done_offset(adev),
444b843c749SSergey Zigachev 			       adev->nbio_funcs->get_hdp_flush_req_offset(adev),
445b843c749SSergey Zigachev 			       ref_and_mask, ref_and_mask, 10);
446b843c749SSergey Zigachev }
447b843c749SSergey Zigachev 
448b843c749SSergey Zigachev /**
449b843c749SSergey Zigachev  * sdma_v4_0_ring_emit_fence - emit a fence on the DMA ring
450b843c749SSergey Zigachev  *
451b843c749SSergey Zigachev  * @ring: amdgpu ring pointer
452b843c749SSergey Zigachev  * @fence: amdgpu fence object
453b843c749SSergey Zigachev  *
454b843c749SSergey Zigachev  * Add a DMA fence packet to the ring to write
455b843c749SSergey Zigachev  * the fence seq number and DMA trap packet to generate
456b843c749SSergey Zigachev  * an interrupt if needed (VEGA10).
457b843c749SSergey Zigachev  */
sdma_v4_0_ring_emit_fence(struct amdgpu_ring * ring,uint64_t addr,uint64_t seq,unsigned flags)45878973132SSergey Zigachev static void sdma_v4_0_ring_emit_fence(struct amdgpu_ring *ring, uint64_t addr, uint64_t seq,
459b843c749SSergey Zigachev 				      unsigned flags)
460b843c749SSergey Zigachev {
461b843c749SSergey Zigachev 	bool write64bit = flags & AMDGPU_FENCE_FLAG_64BIT;
462b843c749SSergey Zigachev 	/* write the fence */
463b843c749SSergey Zigachev 	amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_FENCE));
464b843c749SSergey Zigachev 	/* zero in first two bits */
465b843c749SSergey Zigachev 	BUG_ON(addr & 0x3);
466b843c749SSergey Zigachev 	amdgpu_ring_write(ring, lower_32_bits(addr));
467b843c749SSergey Zigachev 	amdgpu_ring_write(ring, upper_32_bits(addr));
468b843c749SSergey Zigachev 	amdgpu_ring_write(ring, lower_32_bits(seq));
469b843c749SSergey Zigachev 
470b843c749SSergey Zigachev 	/* optionally write high bits as well */
471b843c749SSergey Zigachev 	if (write64bit) {
472b843c749SSergey Zigachev 		addr += 4;
473b843c749SSergey Zigachev 		amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_FENCE));
474b843c749SSergey Zigachev 		/* zero in first two bits */
475b843c749SSergey Zigachev 		BUG_ON(addr & 0x3);
476b843c749SSergey Zigachev 		amdgpu_ring_write(ring, lower_32_bits(addr));
477b843c749SSergey Zigachev 		amdgpu_ring_write(ring, upper_32_bits(addr));
478b843c749SSergey Zigachev 		amdgpu_ring_write(ring, upper_32_bits(seq));
479b843c749SSergey Zigachev 	}
480b843c749SSergey Zigachev 
481b843c749SSergey Zigachev 	/* generate an interrupt */
482b843c749SSergey Zigachev 	amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_TRAP));
483b843c749SSergey Zigachev 	amdgpu_ring_write(ring, SDMA_PKT_TRAP_INT_CONTEXT_INT_CONTEXT(0));
484b843c749SSergey Zigachev }
485b843c749SSergey Zigachev 
486b843c749SSergey Zigachev 
487b843c749SSergey Zigachev /**
488b843c749SSergey Zigachev  * sdma_v4_0_gfx_stop - stop the gfx async dma engines
489b843c749SSergey Zigachev  *
490b843c749SSergey Zigachev  * @adev: amdgpu_device pointer
491b843c749SSergey Zigachev  *
492b843c749SSergey Zigachev  * Stop the gfx async dma ring buffers (VEGA10).
493b843c749SSergey Zigachev  */
sdma_v4_0_gfx_stop(struct amdgpu_device * adev)494b843c749SSergey Zigachev static void sdma_v4_0_gfx_stop(struct amdgpu_device *adev)
495b843c749SSergey Zigachev {
496b843c749SSergey Zigachev 	struct amdgpu_ring *sdma0 = &adev->sdma.instance[0].ring;
497b843c749SSergey Zigachev 	struct amdgpu_ring *sdma1 = &adev->sdma.instance[1].ring;
498b843c749SSergey Zigachev 	u32 rb_cntl, ib_cntl;
499b843c749SSergey Zigachev 	int i;
500b843c749SSergey Zigachev 
501b843c749SSergey Zigachev 	if ((adev->mman.buffer_funcs_ring == sdma0) ||
502b843c749SSergey Zigachev 	    (adev->mman.buffer_funcs_ring == sdma1))
503b843c749SSergey Zigachev 			amdgpu_ttm_set_buffer_funcs_status(adev, false);
504b843c749SSergey Zigachev 
505b843c749SSergey Zigachev 	for (i = 0; i < adev->sdma.num_instances; i++) {
506b843c749SSergey Zigachev 		rb_cntl = RREG32(sdma_v4_0_get_reg_offset(adev, i, mmSDMA0_GFX_RB_CNTL));
507b843c749SSergey Zigachev 		rb_cntl = REG_SET_FIELD(rb_cntl, SDMA0_GFX_RB_CNTL, RB_ENABLE, 0);
508b843c749SSergey Zigachev 		WREG32(sdma_v4_0_get_reg_offset(adev, i, mmSDMA0_GFX_RB_CNTL), rb_cntl);
509b843c749SSergey Zigachev 		ib_cntl = RREG32(sdma_v4_0_get_reg_offset(adev, i, mmSDMA0_GFX_IB_CNTL));
510b843c749SSergey Zigachev 		ib_cntl = REG_SET_FIELD(ib_cntl, SDMA0_GFX_IB_CNTL, IB_ENABLE, 0);
511b843c749SSergey Zigachev 		WREG32(sdma_v4_0_get_reg_offset(adev, i, mmSDMA0_GFX_IB_CNTL), ib_cntl);
512b843c749SSergey Zigachev 	}
513b843c749SSergey Zigachev 
514b843c749SSergey Zigachev 	sdma0->ready = false;
515b843c749SSergey Zigachev 	sdma1->ready = false;
516b843c749SSergey Zigachev }
517b843c749SSergey Zigachev 
518b843c749SSergey Zigachev /**
519b843c749SSergey Zigachev  * sdma_v4_0_rlc_stop - stop the compute async dma engines
520b843c749SSergey Zigachev  *
521b843c749SSergey Zigachev  * @adev: amdgpu_device pointer
522b843c749SSergey Zigachev  *
523b843c749SSergey Zigachev  * Stop the compute async dma queues (VEGA10).
524b843c749SSergey Zigachev  */
sdma_v4_0_rlc_stop(struct amdgpu_device * adev)525b843c749SSergey Zigachev static void sdma_v4_0_rlc_stop(struct amdgpu_device *adev)
526b843c749SSergey Zigachev {
527b843c749SSergey Zigachev 	/* XXX todo */
528b843c749SSergey Zigachev }
529b843c749SSergey Zigachev 
530b843c749SSergey Zigachev /**
531b843c749SSergey Zigachev  * sdma_v_0_ctx_switch_enable - stop the async dma engines context switch
532b843c749SSergey Zigachev  *
533b843c749SSergey Zigachev  * @adev: amdgpu_device pointer
534b843c749SSergey Zigachev  * @enable: enable/disable the DMA MEs context switch.
535b843c749SSergey Zigachev  *
536b843c749SSergey Zigachev  * Halt or unhalt the async dma engines context switch (VEGA10).
537b843c749SSergey Zigachev  */
sdma_v4_0_ctx_switch_enable(struct amdgpu_device * adev,bool enable)538b843c749SSergey Zigachev static void sdma_v4_0_ctx_switch_enable(struct amdgpu_device *adev, bool enable)
539b843c749SSergey Zigachev {
540b843c749SSergey Zigachev 	u32 f32_cntl, phase_quantum = 0;
541b843c749SSergey Zigachev 	int i;
542b843c749SSergey Zigachev 
543b843c749SSergey Zigachev 	if (amdgpu_sdma_phase_quantum) {
544b843c749SSergey Zigachev 		unsigned value = amdgpu_sdma_phase_quantum;
545b843c749SSergey Zigachev 		unsigned unit = 0;
546b843c749SSergey Zigachev 
547b843c749SSergey Zigachev 		while (value > (SDMA0_PHASE0_QUANTUM__VALUE_MASK >>
548b843c749SSergey Zigachev 				SDMA0_PHASE0_QUANTUM__VALUE__SHIFT)) {
549b843c749SSergey Zigachev 			value = (value + 1) >> 1;
550b843c749SSergey Zigachev 			unit++;
551b843c749SSergey Zigachev 		}
552b843c749SSergey Zigachev 		if (unit > (SDMA0_PHASE0_QUANTUM__UNIT_MASK >>
553b843c749SSergey Zigachev 			    SDMA0_PHASE0_QUANTUM__UNIT__SHIFT)) {
554b843c749SSergey Zigachev 			value = (SDMA0_PHASE0_QUANTUM__VALUE_MASK >>
555b843c749SSergey Zigachev 				 SDMA0_PHASE0_QUANTUM__VALUE__SHIFT);
556b843c749SSergey Zigachev 			unit = (SDMA0_PHASE0_QUANTUM__UNIT_MASK >>
557b843c749SSergey Zigachev 				SDMA0_PHASE0_QUANTUM__UNIT__SHIFT);
558b843c749SSergey Zigachev 			WARN_ONCE(1,
559b843c749SSergey Zigachev 			"clamping sdma_phase_quantum to %uK clock cycles\n",
560b843c749SSergey Zigachev 				  value << unit);
561b843c749SSergey Zigachev 		}
562b843c749SSergey Zigachev 		phase_quantum =
563b843c749SSergey Zigachev 			value << SDMA0_PHASE0_QUANTUM__VALUE__SHIFT |
564b843c749SSergey Zigachev 			unit  << SDMA0_PHASE0_QUANTUM__UNIT__SHIFT;
565b843c749SSergey Zigachev 	}
566b843c749SSergey Zigachev 
567b843c749SSergey Zigachev 	for (i = 0; i < adev->sdma.num_instances; i++) {
568b843c749SSergey Zigachev 		f32_cntl = RREG32(sdma_v4_0_get_reg_offset(adev, i, mmSDMA0_CNTL));
569b843c749SSergey Zigachev 		f32_cntl = REG_SET_FIELD(f32_cntl, SDMA0_CNTL,
570b843c749SSergey Zigachev 				AUTO_CTXSW_ENABLE, enable ? 1 : 0);
571b843c749SSergey Zigachev 		if (enable && amdgpu_sdma_phase_quantum) {
572b843c749SSergey Zigachev 			WREG32(sdma_v4_0_get_reg_offset(adev, i, mmSDMA0_PHASE0_QUANTUM),
573b843c749SSergey Zigachev 			       phase_quantum);
574b843c749SSergey Zigachev 			WREG32(sdma_v4_0_get_reg_offset(adev, i, mmSDMA0_PHASE1_QUANTUM),
575b843c749SSergey Zigachev 			       phase_quantum);
576b843c749SSergey Zigachev 			WREG32(sdma_v4_0_get_reg_offset(adev, i, mmSDMA0_PHASE2_QUANTUM),
577b843c749SSergey Zigachev 			       phase_quantum);
578b843c749SSergey Zigachev 		}
579b843c749SSergey Zigachev 		WREG32(sdma_v4_0_get_reg_offset(adev, i, mmSDMA0_CNTL), f32_cntl);
580b843c749SSergey Zigachev 	}
581b843c749SSergey Zigachev 
582b843c749SSergey Zigachev }
583b843c749SSergey Zigachev 
584b843c749SSergey Zigachev /**
585b843c749SSergey Zigachev  * sdma_v4_0_enable - stop the async dma engines
586b843c749SSergey Zigachev  *
587b843c749SSergey Zigachev  * @adev: amdgpu_device pointer
588b843c749SSergey Zigachev  * @enable: enable/disable the DMA MEs.
589b843c749SSergey Zigachev  *
590b843c749SSergey Zigachev  * Halt or unhalt the async dma engines (VEGA10).
591b843c749SSergey Zigachev  */
sdma_v4_0_enable(struct amdgpu_device * adev,bool enable)592b843c749SSergey Zigachev static void sdma_v4_0_enable(struct amdgpu_device *adev, bool enable)
593b843c749SSergey Zigachev {
594b843c749SSergey Zigachev 	u32 f32_cntl;
595b843c749SSergey Zigachev 	int i;
596b843c749SSergey Zigachev 
597b843c749SSergey Zigachev 	if (enable == false) {
598b843c749SSergey Zigachev 		sdma_v4_0_gfx_stop(adev);
599b843c749SSergey Zigachev 		sdma_v4_0_rlc_stop(adev);
600b843c749SSergey Zigachev 	}
601b843c749SSergey Zigachev 
602b843c749SSergey Zigachev 	for (i = 0; i < adev->sdma.num_instances; i++) {
603b843c749SSergey Zigachev 		f32_cntl = RREG32(sdma_v4_0_get_reg_offset(adev, i, mmSDMA0_F32_CNTL));
604b843c749SSergey Zigachev 		f32_cntl = REG_SET_FIELD(f32_cntl, SDMA0_F32_CNTL, HALT, enable ? 0 : 1);
605b843c749SSergey Zigachev 		WREG32(sdma_v4_0_get_reg_offset(adev, i, mmSDMA0_F32_CNTL), f32_cntl);
606b843c749SSergey Zigachev 	}
607b843c749SSergey Zigachev }
608b843c749SSergey Zigachev 
609b843c749SSergey Zigachev /**
610b843c749SSergey Zigachev  * sdma_v4_0_gfx_resume - setup and start the async dma engines
611b843c749SSergey Zigachev  *
612b843c749SSergey Zigachev  * @adev: amdgpu_device pointer
613b843c749SSergey Zigachev  *
614b843c749SSergey Zigachev  * Set up the gfx DMA ring buffers and enable them (VEGA10).
615b843c749SSergey Zigachev  * Returns 0 for success, error for failure.
616b843c749SSergey Zigachev  */
sdma_v4_0_gfx_resume(struct amdgpu_device * adev)617b843c749SSergey Zigachev static int sdma_v4_0_gfx_resume(struct amdgpu_device *adev)
618b843c749SSergey Zigachev {
619b843c749SSergey Zigachev 	struct amdgpu_ring *ring;
620b843c749SSergey Zigachev 	u32 rb_cntl, ib_cntl, wptr_poll_cntl;
621b843c749SSergey Zigachev 	u32 rb_bufsz;
622b843c749SSergey Zigachev 	u32 wb_offset;
623b843c749SSergey Zigachev 	u32 doorbell;
624b843c749SSergey Zigachev 	u32 doorbell_offset;
625b843c749SSergey Zigachev 	u32 temp;
626b843c749SSergey Zigachev 	u64 wptr_gpu_addr;
627b843c749SSergey Zigachev 	int i, r;
628b843c749SSergey Zigachev 
629b843c749SSergey Zigachev 	for (i = 0; i < adev->sdma.num_instances; i++) {
630b843c749SSergey Zigachev 		ring = &adev->sdma.instance[i].ring;
631b843c749SSergey Zigachev 		wb_offset = (ring->rptr_offs * 4);
632b843c749SSergey Zigachev 
633b843c749SSergey Zigachev 		WREG32(sdma_v4_0_get_reg_offset(adev, i, mmSDMA0_SEM_WAIT_FAIL_TIMER_CNTL), 0);
634b843c749SSergey Zigachev 
635b843c749SSergey Zigachev 		/* Set ring buffer size in dwords */
636b843c749SSergey Zigachev 		rb_bufsz = order_base_2(ring->ring_size / 4);
637b843c749SSergey Zigachev 		rb_cntl = RREG32(sdma_v4_0_get_reg_offset(adev, i, mmSDMA0_GFX_RB_CNTL));
638b843c749SSergey Zigachev 		rb_cntl = REG_SET_FIELD(rb_cntl, SDMA0_GFX_RB_CNTL, RB_SIZE, rb_bufsz);
639b843c749SSergey Zigachev #ifdef __BIG_ENDIAN
640b843c749SSergey Zigachev 		rb_cntl = REG_SET_FIELD(rb_cntl, SDMA0_GFX_RB_CNTL, RB_SWAP_ENABLE, 1);
641b843c749SSergey Zigachev 		rb_cntl = REG_SET_FIELD(rb_cntl, SDMA0_GFX_RB_CNTL,
642b843c749SSergey Zigachev 					RPTR_WRITEBACK_SWAP_ENABLE, 1);
643b843c749SSergey Zigachev #endif
644b843c749SSergey Zigachev 		WREG32(sdma_v4_0_get_reg_offset(adev, i, mmSDMA0_GFX_RB_CNTL), rb_cntl);
645b843c749SSergey Zigachev 
646b843c749SSergey Zigachev 		/* Initialize the ring buffer's read and write pointers */
647b843c749SSergey Zigachev 		WREG32(sdma_v4_0_get_reg_offset(adev, i, mmSDMA0_GFX_RB_RPTR), 0);
648b843c749SSergey Zigachev 		WREG32(sdma_v4_0_get_reg_offset(adev, i, mmSDMA0_GFX_RB_RPTR_HI), 0);
649b843c749SSergey Zigachev 		WREG32(sdma_v4_0_get_reg_offset(adev, i, mmSDMA0_GFX_RB_WPTR), 0);
650b843c749SSergey Zigachev 		WREG32(sdma_v4_0_get_reg_offset(adev, i, mmSDMA0_GFX_RB_WPTR_HI), 0);
651b843c749SSergey Zigachev 
652b843c749SSergey Zigachev 		/* set the wb address whether it's enabled or not */
653b843c749SSergey Zigachev 		WREG32(sdma_v4_0_get_reg_offset(adev, i, mmSDMA0_GFX_RB_RPTR_ADDR_HI),
654b843c749SSergey Zigachev 		       upper_32_bits(adev->wb.gpu_addr + wb_offset) & 0xFFFFFFFF);
655b843c749SSergey Zigachev 		WREG32(sdma_v4_0_get_reg_offset(adev, i, mmSDMA0_GFX_RB_RPTR_ADDR_LO),
656b843c749SSergey Zigachev 		       lower_32_bits(adev->wb.gpu_addr + wb_offset) & 0xFFFFFFFC);
657b843c749SSergey Zigachev 
658b843c749SSergey Zigachev 		rb_cntl = REG_SET_FIELD(rb_cntl, SDMA0_GFX_RB_CNTL, RPTR_WRITEBACK_ENABLE, 1);
659b843c749SSergey Zigachev 
660b843c749SSergey Zigachev 		WREG32(sdma_v4_0_get_reg_offset(adev, i, mmSDMA0_GFX_RB_BASE), ring->gpu_addr >> 8);
661b843c749SSergey Zigachev 		WREG32(sdma_v4_0_get_reg_offset(adev, i, mmSDMA0_GFX_RB_BASE_HI), ring->gpu_addr >> 40);
662b843c749SSergey Zigachev 
663b843c749SSergey Zigachev 		ring->wptr = 0;
664b843c749SSergey Zigachev 
665b843c749SSergey Zigachev 		/* before programing wptr to a less value, need set minor_ptr_update first */
666b843c749SSergey Zigachev 		WREG32(sdma_v4_0_get_reg_offset(adev, i, mmSDMA0_GFX_MINOR_PTR_UPDATE), 1);
667b843c749SSergey Zigachev 
668b843c749SSergey Zigachev 		if (!amdgpu_sriov_vf(adev)) { /* only bare-metal use register write for wptr */
669b843c749SSergey Zigachev 			WREG32(sdma_v4_0_get_reg_offset(adev, i, mmSDMA0_GFX_RB_WPTR), lower_32_bits(ring->wptr) << 2);
670b843c749SSergey Zigachev 			WREG32(sdma_v4_0_get_reg_offset(adev, i, mmSDMA0_GFX_RB_WPTR_HI), upper_32_bits(ring->wptr) << 2);
671b843c749SSergey Zigachev 		}
672b843c749SSergey Zigachev 
673b843c749SSergey Zigachev 		doorbell = RREG32(sdma_v4_0_get_reg_offset(adev, i, mmSDMA0_GFX_DOORBELL));
674b843c749SSergey Zigachev 		doorbell_offset = RREG32(sdma_v4_0_get_reg_offset(adev, i, mmSDMA0_GFX_DOORBELL_OFFSET));
675b843c749SSergey Zigachev 
676b843c749SSergey Zigachev 		if (ring->use_doorbell) {
677b843c749SSergey Zigachev 			doorbell = REG_SET_FIELD(doorbell, SDMA0_GFX_DOORBELL, ENABLE, 1);
678b843c749SSergey Zigachev 			doorbell_offset = REG_SET_FIELD(doorbell_offset, SDMA0_GFX_DOORBELL_OFFSET,
679b843c749SSergey Zigachev 					OFFSET, ring->doorbell_index);
680b843c749SSergey Zigachev 		} else {
681b843c749SSergey Zigachev 			doorbell = REG_SET_FIELD(doorbell, SDMA0_GFX_DOORBELL, ENABLE, 0);
682b843c749SSergey Zigachev 		}
683b843c749SSergey Zigachev 		WREG32(sdma_v4_0_get_reg_offset(adev, i, mmSDMA0_GFX_DOORBELL), doorbell);
684b843c749SSergey Zigachev 		WREG32(sdma_v4_0_get_reg_offset(adev, i, mmSDMA0_GFX_DOORBELL_OFFSET), doorbell_offset);
685b843c749SSergey Zigachev 		adev->nbio_funcs->sdma_doorbell_range(adev, i, ring->use_doorbell,
686b843c749SSergey Zigachev 						      ring->doorbell_index);
687b843c749SSergey Zigachev 
688b843c749SSergey Zigachev 		if (amdgpu_sriov_vf(adev))
689b843c749SSergey Zigachev 			sdma_v4_0_ring_set_wptr(ring);
690b843c749SSergey Zigachev 
691b843c749SSergey Zigachev 		/* set minor_ptr_update to 0 after wptr programed */
692b843c749SSergey Zigachev 		WREG32(sdma_v4_0_get_reg_offset(adev, i, mmSDMA0_GFX_MINOR_PTR_UPDATE), 0);
693b843c749SSergey Zigachev 
694b843c749SSergey Zigachev 		/* set utc l1 enable flag always to 1 */
695b843c749SSergey Zigachev 		temp = RREG32(sdma_v4_0_get_reg_offset(adev, i, mmSDMA0_CNTL));
696b843c749SSergey Zigachev 		temp = REG_SET_FIELD(temp, SDMA0_CNTL, UTC_L1_ENABLE, 1);
697b843c749SSergey Zigachev 		WREG32(sdma_v4_0_get_reg_offset(adev, i, mmSDMA0_CNTL), temp);
698b843c749SSergey Zigachev 
699b843c749SSergey Zigachev 		if (!amdgpu_sriov_vf(adev)) {
700b843c749SSergey Zigachev 			/* unhalt engine */
701b843c749SSergey Zigachev 			temp = RREG32(sdma_v4_0_get_reg_offset(adev, i, mmSDMA0_F32_CNTL));
702b843c749SSergey Zigachev 			temp = REG_SET_FIELD(temp, SDMA0_F32_CNTL, HALT, 0);
703b843c749SSergey Zigachev 			WREG32(sdma_v4_0_get_reg_offset(adev, i, mmSDMA0_F32_CNTL), temp);
704b843c749SSergey Zigachev 		}
705b843c749SSergey Zigachev 
706b843c749SSergey Zigachev 		/* setup the wptr shadow polling */
707b843c749SSergey Zigachev 		wptr_gpu_addr = adev->wb.gpu_addr + (ring->wptr_offs * 4);
708b843c749SSergey Zigachev 		WREG32(sdma_v4_0_get_reg_offset(adev, i, mmSDMA0_GFX_RB_WPTR_POLL_ADDR_LO),
709b843c749SSergey Zigachev 		       lower_32_bits(wptr_gpu_addr));
710b843c749SSergey Zigachev 		WREG32(sdma_v4_0_get_reg_offset(adev, i, mmSDMA0_GFX_RB_WPTR_POLL_ADDR_HI),
711b843c749SSergey Zigachev 		       upper_32_bits(wptr_gpu_addr));
712b843c749SSergey Zigachev 		wptr_poll_cntl = RREG32(sdma_v4_0_get_reg_offset(adev, i, mmSDMA0_GFX_RB_WPTR_POLL_CNTL));
713b843c749SSergey Zigachev 		if (amdgpu_sriov_vf(adev))
714b843c749SSergey Zigachev 			wptr_poll_cntl = REG_SET_FIELD(wptr_poll_cntl, SDMA0_GFX_RB_WPTR_POLL_CNTL, F32_POLL_ENABLE, 1);
715b843c749SSergey Zigachev 		else
716b843c749SSergey Zigachev 			wptr_poll_cntl = REG_SET_FIELD(wptr_poll_cntl, SDMA0_GFX_RB_WPTR_POLL_CNTL, F32_POLL_ENABLE, 0);
717b843c749SSergey Zigachev 		WREG32(sdma_v4_0_get_reg_offset(adev, i, mmSDMA0_GFX_RB_WPTR_POLL_CNTL), wptr_poll_cntl);
718b843c749SSergey Zigachev 
719b843c749SSergey Zigachev 		/* enable DMA RB */
720b843c749SSergey Zigachev 		rb_cntl = REG_SET_FIELD(rb_cntl, SDMA0_GFX_RB_CNTL, RB_ENABLE, 1);
721b843c749SSergey Zigachev 		WREG32(sdma_v4_0_get_reg_offset(adev, i, mmSDMA0_GFX_RB_CNTL), rb_cntl);
722b843c749SSergey Zigachev 
723b843c749SSergey Zigachev 		ib_cntl = RREG32(sdma_v4_0_get_reg_offset(adev, i, mmSDMA0_GFX_IB_CNTL));
724b843c749SSergey Zigachev 		ib_cntl = REG_SET_FIELD(ib_cntl, SDMA0_GFX_IB_CNTL, IB_ENABLE, 1);
725b843c749SSergey Zigachev #ifdef __BIG_ENDIAN
726b843c749SSergey Zigachev 		ib_cntl = REG_SET_FIELD(ib_cntl, SDMA0_GFX_IB_CNTL, IB_SWAP_ENABLE, 1);
727b843c749SSergey Zigachev #endif
728b843c749SSergey Zigachev 		/* enable DMA IBs */
729b843c749SSergey Zigachev 		WREG32(sdma_v4_0_get_reg_offset(adev, i, mmSDMA0_GFX_IB_CNTL), ib_cntl);
730b843c749SSergey Zigachev 
731b843c749SSergey Zigachev 		ring->ready = true;
732b843c749SSergey Zigachev 
733b843c749SSergey Zigachev 		if (amdgpu_sriov_vf(adev)) { /* bare-metal sequence doesn't need below to lines */
734b843c749SSergey Zigachev 			sdma_v4_0_ctx_switch_enable(adev, true);
735b843c749SSergey Zigachev 			sdma_v4_0_enable(adev, true);
736b843c749SSergey Zigachev 		}
737b843c749SSergey Zigachev 
738b843c749SSergey Zigachev 		r = amdgpu_ring_test_ring(ring);
739b843c749SSergey Zigachev 		if (r) {
740b843c749SSergey Zigachev 			ring->ready = false;
741b843c749SSergey Zigachev 			return r;
742b843c749SSergey Zigachev 		}
743b843c749SSergey Zigachev 
744b843c749SSergey Zigachev 		if (adev->mman.buffer_funcs_ring == ring)
745b843c749SSergey Zigachev 			amdgpu_ttm_set_buffer_funcs_status(adev, true);
746b843c749SSergey Zigachev 
747b843c749SSergey Zigachev 	}
748b843c749SSergey Zigachev 
749b843c749SSergey Zigachev 	return 0;
750b843c749SSergey Zigachev }
751b843c749SSergey Zigachev 
752b843c749SSergey Zigachev static void
sdma_v4_1_update_power_gating(struct amdgpu_device * adev,bool enable)753b843c749SSergey Zigachev sdma_v4_1_update_power_gating(struct amdgpu_device *adev, bool enable)
754b843c749SSergey Zigachev {
755b843c749SSergey Zigachev 	uint32_t def, data;
756b843c749SSergey Zigachev 
757b843c749SSergey Zigachev 	if (enable && (adev->pg_flags & AMD_PG_SUPPORT_SDMA)) {
758b843c749SSergey Zigachev 		/* disable idle interrupt */
759b843c749SSergey Zigachev 		def = data = RREG32(SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_CNTL));
760b843c749SSergey Zigachev 		data |= SDMA0_CNTL__CTXEMPTY_INT_ENABLE_MASK;
761b843c749SSergey Zigachev 
762b843c749SSergey Zigachev 		if (data != def)
763b843c749SSergey Zigachev 			WREG32(SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_CNTL), data);
764b843c749SSergey Zigachev 	} else {
765b843c749SSergey Zigachev 		/* disable idle interrupt */
766b843c749SSergey Zigachev 		def = data = RREG32(SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_CNTL));
767b843c749SSergey Zigachev 		data &= ~SDMA0_CNTL__CTXEMPTY_INT_ENABLE_MASK;
768b843c749SSergey Zigachev 		if (data != def)
769b843c749SSergey Zigachev 			WREG32(SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_CNTL), data);
770b843c749SSergey Zigachev 	}
771b843c749SSergey Zigachev }
772b843c749SSergey Zigachev 
sdma_v4_1_init_power_gating(struct amdgpu_device * adev)773b843c749SSergey Zigachev static void sdma_v4_1_init_power_gating(struct amdgpu_device *adev)
774b843c749SSergey Zigachev {
775b843c749SSergey Zigachev 	uint32_t def, data;
776b843c749SSergey Zigachev 
777b843c749SSergey Zigachev 	/* Enable HW based PG. */
778b843c749SSergey Zigachev 	def = data = RREG32(SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_POWER_CNTL));
779b843c749SSergey Zigachev 	data |= SDMA0_POWER_CNTL__PG_CNTL_ENABLE_MASK;
780b843c749SSergey Zigachev 	if (data != def)
781b843c749SSergey Zigachev 		WREG32(SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_POWER_CNTL), data);
782b843c749SSergey Zigachev 
783b843c749SSergey Zigachev 	/* enable interrupt */
784b843c749SSergey Zigachev 	def = data = RREG32(SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_CNTL));
785b843c749SSergey Zigachev 	data |= SDMA0_CNTL__CTXEMPTY_INT_ENABLE_MASK;
786b843c749SSergey Zigachev 	if (data != def)
787b843c749SSergey Zigachev 		WREG32(SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_CNTL), data);
788b843c749SSergey Zigachev 
789b843c749SSergey Zigachev 	/* Configure hold time to filter in-valid power on/off request. Use default right now */
790b843c749SSergey Zigachev 	def = data = RREG32(SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_POWER_CNTL));
791b843c749SSergey Zigachev 	data &= ~SDMA0_POWER_CNTL__ON_OFF_CONDITION_HOLD_TIME_MASK;
792b843c749SSergey Zigachev 	data |= (mmSDMA0_POWER_CNTL_DEFAULT & SDMA0_POWER_CNTL__ON_OFF_CONDITION_HOLD_TIME_MASK);
793b843c749SSergey Zigachev 	/* Configure switch time for hysteresis purpose. Use default right now */
794b843c749SSergey Zigachev 	data &= ~SDMA0_POWER_CNTL__ON_OFF_STATUS_DURATION_TIME_MASK;
795b843c749SSergey Zigachev 	data |= (mmSDMA0_POWER_CNTL_DEFAULT & SDMA0_POWER_CNTL__ON_OFF_STATUS_DURATION_TIME_MASK);
796b843c749SSergey Zigachev 	if(data != def)
797b843c749SSergey Zigachev 		WREG32(SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_POWER_CNTL), data);
798b843c749SSergey Zigachev }
799b843c749SSergey Zigachev 
sdma_v4_0_init_pg(struct amdgpu_device * adev)800b843c749SSergey Zigachev static void sdma_v4_0_init_pg(struct amdgpu_device *adev)
801b843c749SSergey Zigachev {
802b843c749SSergey Zigachev 	if (!(adev->pg_flags & AMD_PG_SUPPORT_SDMA))
803b843c749SSergey Zigachev 		return;
804b843c749SSergey Zigachev 
805b843c749SSergey Zigachev 	switch (adev->asic_type) {
806b843c749SSergey Zigachev 	case CHIP_RAVEN:
807b843c749SSergey Zigachev 		sdma_v4_1_init_power_gating(adev);
808b843c749SSergey Zigachev 		sdma_v4_1_update_power_gating(adev, true);
809b843c749SSergey Zigachev 		break;
810b843c749SSergey Zigachev 	default:
811b843c749SSergey Zigachev 		break;
812b843c749SSergey Zigachev 	}
813b843c749SSergey Zigachev }
814b843c749SSergey Zigachev 
815b843c749SSergey Zigachev /**
816b843c749SSergey Zigachev  * sdma_v4_0_rlc_resume - setup and start the async dma engines
817b843c749SSergey Zigachev  *
818b843c749SSergey Zigachev  * @adev: amdgpu_device pointer
819b843c749SSergey Zigachev  *
820b843c749SSergey Zigachev  * Set up the compute DMA queues and enable them (VEGA10).
821b843c749SSergey Zigachev  * Returns 0 for success, error for failure.
822b843c749SSergey Zigachev  */
sdma_v4_0_rlc_resume(struct amdgpu_device * adev)823b843c749SSergey Zigachev static int sdma_v4_0_rlc_resume(struct amdgpu_device *adev)
824b843c749SSergey Zigachev {
825b843c749SSergey Zigachev 	sdma_v4_0_init_pg(adev);
826b843c749SSergey Zigachev 
827b843c749SSergey Zigachev 	return 0;
828b843c749SSergey Zigachev }
829b843c749SSergey Zigachev 
830b843c749SSergey Zigachev /**
831b843c749SSergey Zigachev  * sdma_v4_0_load_microcode - load the sDMA ME ucode
832b843c749SSergey Zigachev  *
833b843c749SSergey Zigachev  * @adev: amdgpu_device pointer
834b843c749SSergey Zigachev  *
835b843c749SSergey Zigachev  * Loads the sDMA0/1 ucode.
836b843c749SSergey Zigachev  * Returns 0 for success, -EINVAL if the ucode is not available.
837b843c749SSergey Zigachev  */
sdma_v4_0_load_microcode(struct amdgpu_device * adev)838b843c749SSergey Zigachev static int sdma_v4_0_load_microcode(struct amdgpu_device *adev)
839b843c749SSergey Zigachev {
840b843c749SSergey Zigachev 	const struct sdma_firmware_header_v1_0 *hdr;
841b843c749SSergey Zigachev 	const __le32 *fw_data;
842b843c749SSergey Zigachev 	u32 fw_size;
843b843c749SSergey Zigachev 	int i, j;
844b843c749SSergey Zigachev 
845b843c749SSergey Zigachev 	/* halt the MEs */
846b843c749SSergey Zigachev 	sdma_v4_0_enable(adev, false);
847b843c749SSergey Zigachev 
848b843c749SSergey Zigachev 	for (i = 0; i < adev->sdma.num_instances; i++) {
849b843c749SSergey Zigachev 		if (!adev->sdma.instance[i].fw)
850b843c749SSergey Zigachev 			return -EINVAL;
851b843c749SSergey Zigachev 
852b843c749SSergey Zigachev 		hdr = (const struct sdma_firmware_header_v1_0 *)adev->sdma.instance[i].fw->data;
853b843c749SSergey Zigachev 		amdgpu_ucode_print_sdma_hdr(&hdr->header);
854b843c749SSergey Zigachev 		fw_size = le32_to_cpu(hdr->header.ucode_size_bytes) / 4;
855b843c749SSergey Zigachev 
856b843c749SSergey Zigachev 		fw_data = (const __le32 *)
857b843c749SSergey Zigachev 			(adev->sdma.instance[i].fw->data +
858b843c749SSergey Zigachev 				le32_to_cpu(hdr->header.ucode_array_offset_bytes));
859b843c749SSergey Zigachev 
860b843c749SSergey Zigachev 		WREG32(sdma_v4_0_get_reg_offset(adev, i, mmSDMA0_UCODE_ADDR), 0);
861b843c749SSergey Zigachev 
862b843c749SSergey Zigachev 		for (j = 0; j < fw_size; j++)
863b843c749SSergey Zigachev 			WREG32(sdma_v4_0_get_reg_offset(adev, i, mmSDMA0_UCODE_DATA), le32_to_cpup(fw_data++));
864b843c749SSergey Zigachev 
865b843c749SSergey Zigachev 		WREG32(sdma_v4_0_get_reg_offset(adev, i, mmSDMA0_UCODE_ADDR), adev->sdma.instance[i].fw_version);
866b843c749SSergey Zigachev 	}
867b843c749SSergey Zigachev 
868b843c749SSergey Zigachev 	return 0;
869b843c749SSergey Zigachev }
870b843c749SSergey Zigachev 
871b843c749SSergey Zigachev /**
872b843c749SSergey Zigachev  * sdma_v4_0_start - setup and start the async dma engines
873b843c749SSergey Zigachev  *
874b843c749SSergey Zigachev  * @adev: amdgpu_device pointer
875b843c749SSergey Zigachev  *
876b843c749SSergey Zigachev  * Set up the DMA engines and enable them (VEGA10).
877b843c749SSergey Zigachev  * Returns 0 for success, error for failure.
878b843c749SSergey Zigachev  */
sdma_v4_0_start(struct amdgpu_device * adev)879b843c749SSergey Zigachev static int sdma_v4_0_start(struct amdgpu_device *adev)
880b843c749SSergey Zigachev {
881b843c749SSergey Zigachev 	int r = 0;
882b843c749SSergey Zigachev 
883b843c749SSergey Zigachev 	if (amdgpu_sriov_vf(adev)) {
884b843c749SSergey Zigachev 		sdma_v4_0_ctx_switch_enable(adev, false);
885b843c749SSergey Zigachev 		sdma_v4_0_enable(adev, false);
886b843c749SSergey Zigachev 
887b843c749SSergey Zigachev 		/* set RB registers */
888b843c749SSergey Zigachev 		r = sdma_v4_0_gfx_resume(adev);
889b843c749SSergey Zigachev 		return r;
890b843c749SSergey Zigachev 	}
891b843c749SSergey Zigachev 
892b843c749SSergey Zigachev 	if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) {
893b843c749SSergey Zigachev 		r = sdma_v4_0_load_microcode(adev);
894b843c749SSergey Zigachev 		if (r)
895b843c749SSergey Zigachev 			return r;
896b843c749SSergey Zigachev 	}
897b843c749SSergey Zigachev 
898b843c749SSergey Zigachev 	/* unhalt the MEs */
899b843c749SSergey Zigachev 	sdma_v4_0_enable(adev, true);
900b843c749SSergey Zigachev 	/* enable sdma ring preemption */
901b843c749SSergey Zigachev 	sdma_v4_0_ctx_switch_enable(adev, true);
902b843c749SSergey Zigachev 
903b843c749SSergey Zigachev 	/* start the gfx rings and rlc compute queues */
904b843c749SSergey Zigachev 	r = sdma_v4_0_gfx_resume(adev);
905b843c749SSergey Zigachev 	if (r)
906b843c749SSergey Zigachev 		return r;
907b843c749SSergey Zigachev 	r = sdma_v4_0_rlc_resume(adev);
908b843c749SSergey Zigachev 
909b843c749SSergey Zigachev 	return r;
910b843c749SSergey Zigachev }
911b843c749SSergey Zigachev 
912b843c749SSergey Zigachev /**
913b843c749SSergey Zigachev  * sdma_v4_0_ring_test_ring - simple async dma engine test
914b843c749SSergey Zigachev  *
915b843c749SSergey Zigachev  * @ring: amdgpu_ring structure holding ring information
916b843c749SSergey Zigachev  *
917b843c749SSergey Zigachev  * Test the DMA engine by writing using it to write an
918b843c749SSergey Zigachev  * value to memory. (VEGA10).
919b843c749SSergey Zigachev  * Returns 0 for success, error for failure.
920b843c749SSergey Zigachev  */
sdma_v4_0_ring_test_ring(struct amdgpu_ring * ring)921b843c749SSergey Zigachev static int sdma_v4_0_ring_test_ring(struct amdgpu_ring *ring)
922b843c749SSergey Zigachev {
923b843c749SSergey Zigachev 	struct amdgpu_device *adev = ring->adev;
924b843c749SSergey Zigachev 	unsigned i;
925b843c749SSergey Zigachev 	unsigned index;
926b843c749SSergey Zigachev 	int r;
927b843c749SSergey Zigachev 	u32 tmp;
928b843c749SSergey Zigachev 	u64 gpu_addr;
929b843c749SSergey Zigachev 
930b843c749SSergey Zigachev 	r = amdgpu_device_wb_get(adev, &index);
931b843c749SSergey Zigachev 	if (r) {
932b843c749SSergey Zigachev 		dev_err(adev->dev, "(%d) failed to allocate wb slot\n", r);
933b843c749SSergey Zigachev 		return r;
934b843c749SSergey Zigachev 	}
935b843c749SSergey Zigachev 
936b843c749SSergey Zigachev 	gpu_addr = adev->wb.gpu_addr + (index * 4);
937b843c749SSergey Zigachev 	tmp = 0xCAFEDEAD;
938b843c749SSergey Zigachev 	adev->wb.wb[index] = cpu_to_le32(tmp);
939b843c749SSergey Zigachev 
940b843c749SSergey Zigachev 	r = amdgpu_ring_alloc(ring, 5);
941b843c749SSergey Zigachev 	if (r) {
942b843c749SSergey Zigachev 		DRM_ERROR("amdgpu: dma failed to lock ring %d (%d).\n", ring->idx, r);
943b843c749SSergey Zigachev 		amdgpu_device_wb_free(adev, index);
944b843c749SSergey Zigachev 		return r;
945b843c749SSergey Zigachev 	}
946b843c749SSergey Zigachev 
947b843c749SSergey Zigachev 	amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_WRITE) |
948b843c749SSergey Zigachev 			  SDMA_PKT_HEADER_SUB_OP(SDMA_SUBOP_WRITE_LINEAR));
949b843c749SSergey Zigachev 	amdgpu_ring_write(ring, lower_32_bits(gpu_addr));
950b843c749SSergey Zigachev 	amdgpu_ring_write(ring, upper_32_bits(gpu_addr));
951b843c749SSergey Zigachev 	amdgpu_ring_write(ring, SDMA_PKT_WRITE_UNTILED_DW_3_COUNT(0));
952b843c749SSergey Zigachev 	amdgpu_ring_write(ring, 0xDEADBEEF);
953b843c749SSergey Zigachev 	amdgpu_ring_commit(ring);
954b843c749SSergey Zigachev 
955b843c749SSergey Zigachev 	for (i = 0; i < adev->usec_timeout; i++) {
956b843c749SSergey Zigachev 		tmp = le32_to_cpu(adev->wb.wb[index]);
957b843c749SSergey Zigachev 		if (tmp == 0xDEADBEEF)
958b843c749SSergey Zigachev 			break;
959b843c749SSergey Zigachev 		DRM_UDELAY(1);
960b843c749SSergey Zigachev 	}
961b843c749SSergey Zigachev 
962b843c749SSergey Zigachev 	if (i < adev->usec_timeout) {
963b843c749SSergey Zigachev 		DRM_DEBUG("ring test on %d succeeded in %d usecs\n", ring->idx, i);
964b843c749SSergey Zigachev 	} else {
965b843c749SSergey Zigachev 		DRM_ERROR("amdgpu: ring %d test failed (0x%08X)\n",
966b843c749SSergey Zigachev 			  ring->idx, tmp);
967b843c749SSergey Zigachev 		r = -EINVAL;
968b843c749SSergey Zigachev 	}
969b843c749SSergey Zigachev 	amdgpu_device_wb_free(adev, index);
970b843c749SSergey Zigachev 
971b843c749SSergey Zigachev 	return r;
972b843c749SSergey Zigachev }
973b843c749SSergey Zigachev 
974b843c749SSergey Zigachev /**
975b843c749SSergey Zigachev  * sdma_v4_0_ring_test_ib - test an IB on the DMA engine
976b843c749SSergey Zigachev  *
977b843c749SSergey Zigachev  * @ring: amdgpu_ring structure holding ring information
978b843c749SSergey Zigachev  *
979b843c749SSergey Zigachev  * Test a simple IB in the DMA ring (VEGA10).
980b843c749SSergey Zigachev  * Returns 0 on success, error on failure.
981b843c749SSergey Zigachev  */
sdma_v4_0_ring_test_ib(struct amdgpu_ring * ring,long timeout)982b843c749SSergey Zigachev static int sdma_v4_0_ring_test_ib(struct amdgpu_ring *ring, long timeout)
983b843c749SSergey Zigachev {
984b843c749SSergey Zigachev 	struct amdgpu_device *adev = ring->adev;
985b843c749SSergey Zigachev 	struct amdgpu_ib ib;
986b843c749SSergey Zigachev 	struct dma_fence *f = NULL;
987b843c749SSergey Zigachev 	unsigned index;
988b843c749SSergey Zigachev 	long r;
989b843c749SSergey Zigachev 	u32 tmp = 0;
990b843c749SSergey Zigachev 	u64 gpu_addr;
991b843c749SSergey Zigachev 
992b843c749SSergey Zigachev 	r = amdgpu_device_wb_get(adev, &index);
993b843c749SSergey Zigachev 	if (r) {
994b843c749SSergey Zigachev 		dev_err(adev->dev, "(%ld) failed to allocate wb slot\n", r);
995b843c749SSergey Zigachev 		return r;
996b843c749SSergey Zigachev 	}
997b843c749SSergey Zigachev 
998b843c749SSergey Zigachev 	gpu_addr = adev->wb.gpu_addr + (index * 4);
999b843c749SSergey Zigachev 	tmp = 0xCAFEDEAD;
1000b843c749SSergey Zigachev 	adev->wb.wb[index] = cpu_to_le32(tmp);
1001b843c749SSergey Zigachev 	memset(&ib, 0, sizeof(ib));
1002b843c749SSergey Zigachev 	r = amdgpu_ib_get(adev, NULL, 256, &ib);
1003b843c749SSergey Zigachev 	if (r) {
1004b843c749SSergey Zigachev 		DRM_ERROR("amdgpu: failed to get ib (%ld).\n", r);
1005b843c749SSergey Zigachev 		goto err0;
1006b843c749SSergey Zigachev 	}
1007b843c749SSergey Zigachev 
1008b843c749SSergey Zigachev 	ib.ptr[0] = SDMA_PKT_HEADER_OP(SDMA_OP_WRITE) |
1009b843c749SSergey Zigachev 		SDMA_PKT_HEADER_SUB_OP(SDMA_SUBOP_WRITE_LINEAR);
1010b843c749SSergey Zigachev 	ib.ptr[1] = lower_32_bits(gpu_addr);
1011b843c749SSergey Zigachev 	ib.ptr[2] = upper_32_bits(gpu_addr);
1012b843c749SSergey Zigachev 	ib.ptr[3] = SDMA_PKT_WRITE_UNTILED_DW_3_COUNT(0);
1013b843c749SSergey Zigachev 	ib.ptr[4] = 0xDEADBEEF;
1014b843c749SSergey Zigachev 	ib.ptr[5] = SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP);
1015b843c749SSergey Zigachev 	ib.ptr[6] = SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP);
1016b843c749SSergey Zigachev 	ib.ptr[7] = SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP);
1017b843c749SSergey Zigachev 	ib.length_dw = 8;
1018b843c749SSergey Zigachev 
1019b843c749SSergey Zigachev 	r = amdgpu_ib_schedule(ring, 1, &ib, NULL, &f);
1020b843c749SSergey Zigachev 	if (r)
1021b843c749SSergey Zigachev 		goto err1;
1022b843c749SSergey Zigachev 
1023b843c749SSergey Zigachev 	r = dma_fence_wait_timeout(f, false, timeout);
1024b843c749SSergey Zigachev 	if (r == 0) {
1025b843c749SSergey Zigachev 		DRM_ERROR("amdgpu: IB test timed out\n");
1026b843c749SSergey Zigachev 		r = -ETIMEDOUT;
1027b843c749SSergey Zigachev 		goto err1;
1028b843c749SSergey Zigachev 	} else if (r < 0) {
1029b843c749SSergey Zigachev 		DRM_ERROR("amdgpu: fence wait failed (%ld).\n", r);
1030b843c749SSergey Zigachev 		goto err1;
1031b843c749SSergey Zigachev 	}
1032b843c749SSergey Zigachev 	tmp = le32_to_cpu(adev->wb.wb[index]);
1033b843c749SSergey Zigachev 	if (tmp == 0xDEADBEEF) {
1034b843c749SSergey Zigachev 		DRM_DEBUG("ib test on ring %d succeeded\n", ring->idx);
1035b843c749SSergey Zigachev 		r = 0;
1036b843c749SSergey Zigachev 	} else {
1037b843c749SSergey Zigachev 		DRM_ERROR("amdgpu: ib test failed (0x%08X)\n", tmp);
1038b843c749SSergey Zigachev 		r = -EINVAL;
1039b843c749SSergey Zigachev 	}
1040b843c749SSergey Zigachev err1:
1041b843c749SSergey Zigachev 	amdgpu_ib_free(adev, &ib, NULL);
1042b843c749SSergey Zigachev 	dma_fence_put(f);
1043b843c749SSergey Zigachev err0:
1044b843c749SSergey Zigachev 	amdgpu_device_wb_free(adev, index);
1045b843c749SSergey Zigachev 	return r;
1046b843c749SSergey Zigachev }
1047b843c749SSergey Zigachev 
1048b843c749SSergey Zigachev 
1049b843c749SSergey Zigachev /**
1050b843c749SSergey Zigachev  * sdma_v4_0_vm_copy_pte - update PTEs by copying them from the GART
1051b843c749SSergey Zigachev  *
1052b843c749SSergey Zigachev  * @ib: indirect buffer to fill with commands
1053b843c749SSergey Zigachev  * @pe: addr of the page entry
1054b843c749SSergey Zigachev  * @src: src addr to copy from
1055b843c749SSergey Zigachev  * @count: number of page entries to update
1056b843c749SSergey Zigachev  *
1057b843c749SSergey Zigachev  * Update PTEs by copying them from the GART using sDMA (VEGA10).
1058b843c749SSergey Zigachev  */
sdma_v4_0_vm_copy_pte(struct amdgpu_ib * ib,uint64_t pe,uint64_t src,unsigned count)1059b843c749SSergey Zigachev static void sdma_v4_0_vm_copy_pte(struct amdgpu_ib *ib,
1060b843c749SSergey Zigachev 				  uint64_t pe, uint64_t src,
1061b843c749SSergey Zigachev 				  unsigned count)
1062b843c749SSergey Zigachev {
1063b843c749SSergey Zigachev 	unsigned bytes = count * 8;
1064b843c749SSergey Zigachev 
1065b843c749SSergey Zigachev 	ib->ptr[ib->length_dw++] = SDMA_PKT_HEADER_OP(SDMA_OP_COPY) |
1066b843c749SSergey Zigachev 		SDMA_PKT_HEADER_SUB_OP(SDMA_SUBOP_COPY_LINEAR);
1067b843c749SSergey Zigachev 	ib->ptr[ib->length_dw++] = bytes - 1;
1068b843c749SSergey Zigachev 	ib->ptr[ib->length_dw++] = 0; /* src/dst endian swap */
1069b843c749SSergey Zigachev 	ib->ptr[ib->length_dw++] = lower_32_bits(src);
1070b843c749SSergey Zigachev 	ib->ptr[ib->length_dw++] = upper_32_bits(src);
1071b843c749SSergey Zigachev 	ib->ptr[ib->length_dw++] = lower_32_bits(pe);
1072b843c749SSergey Zigachev 	ib->ptr[ib->length_dw++] = upper_32_bits(pe);
1073b843c749SSergey Zigachev 
1074b843c749SSergey Zigachev }
1075b843c749SSergey Zigachev 
1076b843c749SSergey Zigachev /**
1077b843c749SSergey Zigachev  * sdma_v4_0_vm_write_pte - update PTEs by writing them manually
1078b843c749SSergey Zigachev  *
1079b843c749SSergey Zigachev  * @ib: indirect buffer to fill with commands
1080b843c749SSergey Zigachev  * @pe: addr of the page entry
1081b843c749SSergey Zigachev  * @addr: dst addr to write into pe
1082b843c749SSergey Zigachev  * @count: number of page entries to update
1083b843c749SSergey Zigachev  * @incr: increase next addr by incr bytes
1084b843c749SSergey Zigachev  * @flags: access flags
1085b843c749SSergey Zigachev  *
1086b843c749SSergey Zigachev  * Update PTEs by writing them manually using sDMA (VEGA10).
1087b843c749SSergey Zigachev  */
sdma_v4_0_vm_write_pte(struct amdgpu_ib * ib,uint64_t pe,uint64_t value,unsigned count,uint32_t incr)1088b843c749SSergey Zigachev static void sdma_v4_0_vm_write_pte(struct amdgpu_ib *ib, uint64_t pe,
1089b843c749SSergey Zigachev 				   uint64_t value, unsigned count,
1090b843c749SSergey Zigachev 				   uint32_t incr)
1091b843c749SSergey Zigachev {
1092b843c749SSergey Zigachev 	unsigned ndw = count * 2;
1093b843c749SSergey Zigachev 
1094b843c749SSergey Zigachev 	ib->ptr[ib->length_dw++] = SDMA_PKT_HEADER_OP(SDMA_OP_WRITE) |
1095b843c749SSergey Zigachev 		SDMA_PKT_HEADER_SUB_OP(SDMA_SUBOP_WRITE_LINEAR);
1096b843c749SSergey Zigachev 	ib->ptr[ib->length_dw++] = lower_32_bits(pe);
1097b843c749SSergey Zigachev 	ib->ptr[ib->length_dw++] = upper_32_bits(pe);
1098b843c749SSergey Zigachev 	ib->ptr[ib->length_dw++] = ndw - 1;
1099b843c749SSergey Zigachev 	for (; ndw > 0; ndw -= 2) {
1100b843c749SSergey Zigachev 		ib->ptr[ib->length_dw++] = lower_32_bits(value);
1101b843c749SSergey Zigachev 		ib->ptr[ib->length_dw++] = upper_32_bits(value);
1102b843c749SSergey Zigachev 		value += incr;
1103b843c749SSergey Zigachev 	}
1104b843c749SSergey Zigachev }
1105b843c749SSergey Zigachev 
1106b843c749SSergey Zigachev /**
1107b843c749SSergey Zigachev  * sdma_v4_0_vm_set_pte_pde - update the page tables using sDMA
1108b843c749SSergey Zigachev  *
1109b843c749SSergey Zigachev  * @ib: indirect buffer to fill with commands
1110b843c749SSergey Zigachev  * @pe: addr of the page entry
1111b843c749SSergey Zigachev  * @addr: dst addr to write into pe
1112b843c749SSergey Zigachev  * @count: number of page entries to update
1113b843c749SSergey Zigachev  * @incr: increase next addr by incr bytes
1114b843c749SSergey Zigachev  * @flags: access flags
1115b843c749SSergey Zigachev  *
1116b843c749SSergey Zigachev  * Update the page tables using sDMA (VEGA10).
1117b843c749SSergey Zigachev  */
sdma_v4_0_vm_set_pte_pde(struct amdgpu_ib * ib,uint64_t pe,uint64_t addr,unsigned count,uint32_t incr,uint64_t flags)1118b843c749SSergey Zigachev static void sdma_v4_0_vm_set_pte_pde(struct amdgpu_ib *ib,
1119b843c749SSergey Zigachev 				     uint64_t pe,
1120b843c749SSergey Zigachev 				     uint64_t addr, unsigned count,
1121b843c749SSergey Zigachev 				     uint32_t incr, uint64_t flags)
1122b843c749SSergey Zigachev {
1123b843c749SSergey Zigachev 	/* for physically contiguous pages (vram) */
1124b843c749SSergey Zigachev 	ib->ptr[ib->length_dw++] = SDMA_PKT_HEADER_OP(SDMA_OP_PTEPDE);
1125b843c749SSergey Zigachev 	ib->ptr[ib->length_dw++] = lower_32_bits(pe); /* dst addr */
1126b843c749SSergey Zigachev 	ib->ptr[ib->length_dw++] = upper_32_bits(pe);
1127b843c749SSergey Zigachev 	ib->ptr[ib->length_dw++] = lower_32_bits(flags); /* mask */
1128b843c749SSergey Zigachev 	ib->ptr[ib->length_dw++] = upper_32_bits(flags);
1129b843c749SSergey Zigachev 	ib->ptr[ib->length_dw++] = lower_32_bits(addr); /* value */
1130b843c749SSergey Zigachev 	ib->ptr[ib->length_dw++] = upper_32_bits(addr);
1131b843c749SSergey Zigachev 	ib->ptr[ib->length_dw++] = incr; /* increment size */
1132b843c749SSergey Zigachev 	ib->ptr[ib->length_dw++] = 0;
1133b843c749SSergey Zigachev 	ib->ptr[ib->length_dw++] = count - 1; /* number of entries */
1134b843c749SSergey Zigachev }
1135b843c749SSergey Zigachev 
1136b843c749SSergey Zigachev /**
1137b843c749SSergey Zigachev  * sdma_v4_0_ring_pad_ib - pad the IB to the required number of dw
1138b843c749SSergey Zigachev  *
1139b843c749SSergey Zigachev  * @ib: indirect buffer to fill with padding
1140b843c749SSergey Zigachev  *
1141b843c749SSergey Zigachev  */
sdma_v4_0_ring_pad_ib(struct amdgpu_ring * ring,struct amdgpu_ib * ib)1142b843c749SSergey Zigachev static void sdma_v4_0_ring_pad_ib(struct amdgpu_ring *ring, struct amdgpu_ib *ib)
1143b843c749SSergey Zigachev {
1144b843c749SSergey Zigachev 	struct amdgpu_sdma_instance *sdma = amdgpu_get_sdma_instance(ring);
1145b843c749SSergey Zigachev 	u32 pad_count;
1146b843c749SSergey Zigachev 	int i;
1147b843c749SSergey Zigachev 
1148b843c749SSergey Zigachev 	pad_count = (8 - (ib->length_dw & 0x7)) % 8;
1149b843c749SSergey Zigachev 	for (i = 0; i < pad_count; i++)
1150b843c749SSergey Zigachev 		if (sdma && sdma->burst_nop && (i == 0))
1151b843c749SSergey Zigachev 			ib->ptr[ib->length_dw++] =
1152b843c749SSergey Zigachev 				SDMA_PKT_HEADER_OP(SDMA_OP_NOP) |
1153b843c749SSergey Zigachev 				SDMA_PKT_NOP_HEADER_COUNT(pad_count - 1);
1154b843c749SSergey Zigachev 		else
1155b843c749SSergey Zigachev 			ib->ptr[ib->length_dw++] =
1156b843c749SSergey Zigachev 				SDMA_PKT_HEADER_OP(SDMA_OP_NOP);
1157b843c749SSergey Zigachev }
1158b843c749SSergey Zigachev 
1159b843c749SSergey Zigachev 
1160b843c749SSergey Zigachev /**
1161b843c749SSergey Zigachev  * sdma_v4_0_ring_emit_pipeline_sync - sync the pipeline
1162b843c749SSergey Zigachev  *
1163b843c749SSergey Zigachev  * @ring: amdgpu_ring pointer
1164b843c749SSergey Zigachev  *
1165b843c749SSergey Zigachev  * Make sure all previous operations are completed (CIK).
1166b843c749SSergey Zigachev  */
sdma_v4_0_ring_emit_pipeline_sync(struct amdgpu_ring * ring)1167b843c749SSergey Zigachev static void sdma_v4_0_ring_emit_pipeline_sync(struct amdgpu_ring *ring)
1168b843c749SSergey Zigachev {
1169b843c749SSergey Zigachev 	uint32_t seq = ring->fence_drv.sync_seq;
1170b843c749SSergey Zigachev 	uint64_t addr = ring->fence_drv.gpu_addr;
1171b843c749SSergey Zigachev 
1172b843c749SSergey Zigachev 	/* wait for idle */
1173b843c749SSergey Zigachev 	sdma_v4_0_wait_reg_mem(ring, 1, 0,
1174b843c749SSergey Zigachev 			       addr & 0xfffffffc,
1175b843c749SSergey Zigachev 			       upper_32_bits(addr) & 0xffffffff,
1176b843c749SSergey Zigachev 			       seq, 0xffffffff, 4);
1177b843c749SSergey Zigachev }
1178b843c749SSergey Zigachev 
1179b843c749SSergey Zigachev 
1180b843c749SSergey Zigachev /**
1181b843c749SSergey Zigachev  * sdma_v4_0_ring_emit_vm_flush - vm flush using sDMA
1182b843c749SSergey Zigachev  *
1183b843c749SSergey Zigachev  * @ring: amdgpu_ring pointer
1184b843c749SSergey Zigachev  * @vm: amdgpu_vm pointer
1185b843c749SSergey Zigachev  *
1186b843c749SSergey Zigachev  * Update the page table base and flush the VM TLB
1187b843c749SSergey Zigachev  * using sDMA (VEGA10).
1188b843c749SSergey Zigachev  */
sdma_v4_0_ring_emit_vm_flush(struct amdgpu_ring * ring,unsigned vmid,uint64_t pd_addr)1189b843c749SSergey Zigachev static void sdma_v4_0_ring_emit_vm_flush(struct amdgpu_ring *ring,
1190b843c749SSergey Zigachev 					 unsigned vmid, uint64_t pd_addr)
1191b843c749SSergey Zigachev {
1192b843c749SSergey Zigachev 	amdgpu_gmc_emit_flush_gpu_tlb(ring, vmid, pd_addr);
1193b843c749SSergey Zigachev }
1194b843c749SSergey Zigachev 
sdma_v4_0_ring_emit_wreg(struct amdgpu_ring * ring,uint32_t reg,uint32_t val)1195b843c749SSergey Zigachev static void sdma_v4_0_ring_emit_wreg(struct amdgpu_ring *ring,
1196b843c749SSergey Zigachev 				     uint32_t reg, uint32_t val)
1197b843c749SSergey Zigachev {
1198b843c749SSergey Zigachev 	amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_SRBM_WRITE) |
1199b843c749SSergey Zigachev 			  SDMA_PKT_SRBM_WRITE_HEADER_BYTE_EN(0xf));
1200b843c749SSergey Zigachev 	amdgpu_ring_write(ring, reg);
1201b843c749SSergey Zigachev 	amdgpu_ring_write(ring, val);
1202b843c749SSergey Zigachev }
1203b843c749SSergey Zigachev 
sdma_v4_0_ring_emit_reg_wait(struct amdgpu_ring * ring,uint32_t reg,uint32_t val,uint32_t mask)1204b843c749SSergey Zigachev static void sdma_v4_0_ring_emit_reg_wait(struct amdgpu_ring *ring, uint32_t reg,
1205b843c749SSergey Zigachev 					 uint32_t val, uint32_t mask)
1206b843c749SSergey Zigachev {
1207b843c749SSergey Zigachev 	sdma_v4_0_wait_reg_mem(ring, 0, 0, reg, 0, val, mask, 10);
1208b843c749SSergey Zigachev }
1209b843c749SSergey Zigachev 
sdma_v4_0_early_init(void * handle)1210b843c749SSergey Zigachev static int sdma_v4_0_early_init(void *handle)
1211b843c749SSergey Zigachev {
1212b843c749SSergey Zigachev 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
1213b843c749SSergey Zigachev 
1214b843c749SSergey Zigachev 	if (adev->asic_type == CHIP_RAVEN)
1215b843c749SSergey Zigachev 		adev->sdma.num_instances = 1;
1216b843c749SSergey Zigachev 	else
1217b843c749SSergey Zigachev 		adev->sdma.num_instances = 2;
1218b843c749SSergey Zigachev 
1219b843c749SSergey Zigachev 	sdma_v4_0_set_ring_funcs(adev);
1220b843c749SSergey Zigachev 	sdma_v4_0_set_buffer_funcs(adev);
1221b843c749SSergey Zigachev 	sdma_v4_0_set_vm_pte_funcs(adev);
1222b843c749SSergey Zigachev 	sdma_v4_0_set_irq_funcs(adev);
1223b843c749SSergey Zigachev 
1224b843c749SSergey Zigachev 	return 0;
1225b843c749SSergey Zigachev }
1226b843c749SSergey Zigachev 
1227b843c749SSergey Zigachev 
sdma_v4_0_sw_init(void * handle)1228b843c749SSergey Zigachev static int sdma_v4_0_sw_init(void *handle)
1229b843c749SSergey Zigachev {
1230b843c749SSergey Zigachev 	struct amdgpu_ring *ring;
1231b843c749SSergey Zigachev 	int r, i;
1232b843c749SSergey Zigachev 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
1233b843c749SSergey Zigachev 
1234b843c749SSergey Zigachev 	/* SDMA trap event */
1235b843c749SSergey Zigachev 	r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_SDMA0, SDMA0_4_0__SRCID__SDMA_TRAP,
1236b843c749SSergey Zigachev 			      &adev->sdma.trap_irq);
1237b843c749SSergey Zigachev 	if (r)
1238b843c749SSergey Zigachev 		return r;
1239b843c749SSergey Zigachev 
1240b843c749SSergey Zigachev 	/* SDMA trap event */
1241b843c749SSergey Zigachev 	r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_SDMA1, SDMA1_4_0__SRCID__SDMA_TRAP,
1242b843c749SSergey Zigachev 			      &adev->sdma.trap_irq);
1243b843c749SSergey Zigachev 	if (r)
1244b843c749SSergey Zigachev 		return r;
1245b843c749SSergey Zigachev 
1246b843c749SSergey Zigachev 	r = sdma_v4_0_init_microcode(adev);
1247b843c749SSergey Zigachev 	if (r) {
1248b843c749SSergey Zigachev 		DRM_ERROR("Failed to load sdma firmware!\n");
1249b843c749SSergey Zigachev 		return r;
1250b843c749SSergey Zigachev 	}
1251b843c749SSergey Zigachev 
1252b843c749SSergey Zigachev 	for (i = 0; i < adev->sdma.num_instances; i++) {
1253b843c749SSergey Zigachev 		ring = &adev->sdma.instance[i].ring;
1254b843c749SSergey Zigachev 		ring->ring_obj = NULL;
1255b843c749SSergey Zigachev 		ring->use_doorbell = true;
1256b843c749SSergey Zigachev 
1257b843c749SSergey Zigachev 		DRM_INFO("use_doorbell being set to: [%s]\n",
1258b843c749SSergey Zigachev 				ring->use_doorbell?"true":"false");
1259b843c749SSergey Zigachev 
1260b843c749SSergey Zigachev 		ring->doorbell_index = (i == 0) ?
1261b843c749SSergey Zigachev 			(AMDGPU_DOORBELL64_sDMA_ENGINE0 << 1) //get DWORD offset
1262b843c749SSergey Zigachev 			: (AMDGPU_DOORBELL64_sDMA_ENGINE1 << 1); // get DWORD offset
1263b843c749SSergey Zigachev 
126478973132SSergey Zigachev 		ksprintf(ring->name, "sdma%d", i);
1265b843c749SSergey Zigachev 		r = amdgpu_ring_init(adev, ring, 1024,
1266b843c749SSergey Zigachev 				     &adev->sdma.trap_irq,
1267b843c749SSergey Zigachev 				     (i == 0) ?
1268b843c749SSergey Zigachev 				     AMDGPU_SDMA_IRQ_TRAP0 :
1269b843c749SSergey Zigachev 				     AMDGPU_SDMA_IRQ_TRAP1);
1270b843c749SSergey Zigachev 		if (r)
1271b843c749SSergey Zigachev 			return r;
1272b843c749SSergey Zigachev 	}
1273b843c749SSergey Zigachev 
1274b843c749SSergey Zigachev 	return r;
1275b843c749SSergey Zigachev }
1276b843c749SSergey Zigachev 
sdma_v4_0_sw_fini(void * handle)1277b843c749SSergey Zigachev static int sdma_v4_0_sw_fini(void *handle)
1278b843c749SSergey Zigachev {
1279b843c749SSergey Zigachev 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
1280b843c749SSergey Zigachev 	int i;
1281b843c749SSergey Zigachev 
1282b843c749SSergey Zigachev 	for (i = 0; i < adev->sdma.num_instances; i++)
1283b843c749SSergey Zigachev 		amdgpu_ring_fini(&adev->sdma.instance[i].ring);
1284b843c749SSergey Zigachev 
1285b843c749SSergey Zigachev 	for (i = 0; i < adev->sdma.num_instances; i++) {
1286b843c749SSergey Zigachev 		release_firmware(adev->sdma.instance[i].fw);
1287b843c749SSergey Zigachev 		adev->sdma.instance[i].fw = NULL;
1288b843c749SSergey Zigachev 	}
1289b843c749SSergey Zigachev 
1290b843c749SSergey Zigachev 	return 0;
1291b843c749SSergey Zigachev }
1292b843c749SSergey Zigachev 
sdma_v4_0_hw_init(void * handle)1293b843c749SSergey Zigachev static int sdma_v4_0_hw_init(void *handle)
1294b843c749SSergey Zigachev {
1295b843c749SSergey Zigachev 	int r;
1296b843c749SSergey Zigachev 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
1297b843c749SSergey Zigachev 
1298b843c749SSergey Zigachev 	sdma_v4_0_init_golden_registers(adev);
1299b843c749SSergey Zigachev 
1300b843c749SSergey Zigachev 	r = sdma_v4_0_start(adev);
1301b843c749SSergey Zigachev 
1302b843c749SSergey Zigachev 	return r;
1303b843c749SSergey Zigachev }
1304b843c749SSergey Zigachev 
sdma_v4_0_hw_fini(void * handle)1305b843c749SSergey Zigachev static int sdma_v4_0_hw_fini(void *handle)
1306b843c749SSergey Zigachev {
1307b843c749SSergey Zigachev 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
1308b843c749SSergey Zigachev 
1309b843c749SSergey Zigachev 	if (amdgpu_sriov_vf(adev))
1310b843c749SSergey Zigachev 		return 0;
1311b843c749SSergey Zigachev 
1312b843c749SSergey Zigachev 	sdma_v4_0_ctx_switch_enable(adev, false);
1313b843c749SSergey Zigachev 	sdma_v4_0_enable(adev, false);
1314b843c749SSergey Zigachev 
1315b843c749SSergey Zigachev 	return 0;
1316b843c749SSergey Zigachev }
1317b843c749SSergey Zigachev 
sdma_v4_0_suspend(void * handle)1318b843c749SSergey Zigachev static int sdma_v4_0_suspend(void *handle)
1319b843c749SSergey Zigachev {
1320b843c749SSergey Zigachev 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
1321b843c749SSergey Zigachev 
1322b843c749SSergey Zigachev 	return sdma_v4_0_hw_fini(adev);
1323b843c749SSergey Zigachev }
1324b843c749SSergey Zigachev 
sdma_v4_0_resume(void * handle)1325b843c749SSergey Zigachev static int sdma_v4_0_resume(void *handle)
1326b843c749SSergey Zigachev {
1327b843c749SSergey Zigachev 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
1328b843c749SSergey Zigachev 
1329b843c749SSergey Zigachev 	return sdma_v4_0_hw_init(adev);
1330b843c749SSergey Zigachev }
1331b843c749SSergey Zigachev 
sdma_v4_0_is_idle(void * handle)1332b843c749SSergey Zigachev static bool sdma_v4_0_is_idle(void *handle)
1333b843c749SSergey Zigachev {
1334b843c749SSergey Zigachev 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
1335b843c749SSergey Zigachev 	u32 i;
1336b843c749SSergey Zigachev 
1337b843c749SSergey Zigachev 	for (i = 0; i < adev->sdma.num_instances; i++) {
1338b843c749SSergey Zigachev 		u32 tmp = RREG32(sdma_v4_0_get_reg_offset(adev, i, mmSDMA0_STATUS_REG));
1339b843c749SSergey Zigachev 
1340b843c749SSergey Zigachev 		if (!(tmp & SDMA0_STATUS_REG__IDLE_MASK))
1341b843c749SSergey Zigachev 			return false;
1342b843c749SSergey Zigachev 	}
1343b843c749SSergey Zigachev 
1344b843c749SSergey Zigachev 	return true;
1345b843c749SSergey Zigachev }
1346b843c749SSergey Zigachev 
sdma_v4_0_wait_for_idle(void * handle)1347b843c749SSergey Zigachev static int sdma_v4_0_wait_for_idle(void *handle)
1348b843c749SSergey Zigachev {
1349b843c749SSergey Zigachev 	unsigned i;
1350b843c749SSergey Zigachev 	u32 sdma0, sdma1;
1351b843c749SSergey Zigachev 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
1352b843c749SSergey Zigachev 
1353b843c749SSergey Zigachev 	for (i = 0; i < adev->usec_timeout; i++) {
1354b843c749SSergey Zigachev 		sdma0 = RREG32(sdma_v4_0_get_reg_offset(adev, 0, mmSDMA0_STATUS_REG));
1355b843c749SSergey Zigachev 		sdma1 = RREG32(sdma_v4_0_get_reg_offset(adev, 1, mmSDMA0_STATUS_REG));
1356b843c749SSergey Zigachev 
1357b843c749SSergey Zigachev 		if (sdma0 & sdma1 & SDMA0_STATUS_REG__IDLE_MASK)
1358b843c749SSergey Zigachev 			return 0;
1359b843c749SSergey Zigachev 		udelay(1);
1360b843c749SSergey Zigachev 	}
1361b843c749SSergey Zigachev 	return -ETIMEDOUT;
1362b843c749SSergey Zigachev }
1363b843c749SSergey Zigachev 
sdma_v4_0_soft_reset(void * handle)1364b843c749SSergey Zigachev static int sdma_v4_0_soft_reset(void *handle)
1365b843c749SSergey Zigachev {
1366b843c749SSergey Zigachev 	/* todo */
1367b843c749SSergey Zigachev 
1368b843c749SSergey Zigachev 	return 0;
1369b843c749SSergey Zigachev }
1370b843c749SSergey Zigachev 
sdma_v4_0_set_trap_irq_state(struct amdgpu_device * adev,struct amdgpu_irq_src * source,unsigned type,enum amdgpu_interrupt_state state)1371b843c749SSergey Zigachev static int sdma_v4_0_set_trap_irq_state(struct amdgpu_device *adev,
1372b843c749SSergey Zigachev 					struct amdgpu_irq_src *source,
1373b843c749SSergey Zigachev 					unsigned type,
1374b843c749SSergey Zigachev 					enum amdgpu_interrupt_state state)
1375b843c749SSergey Zigachev {
1376b843c749SSergey Zigachev 	u32 sdma_cntl;
1377b843c749SSergey Zigachev 
1378b843c749SSergey Zigachev 	u32 reg_offset = (type == AMDGPU_SDMA_IRQ_TRAP0) ?
1379b843c749SSergey Zigachev 		sdma_v4_0_get_reg_offset(adev, 0, mmSDMA0_CNTL) :
1380b843c749SSergey Zigachev 		sdma_v4_0_get_reg_offset(adev, 1, mmSDMA0_CNTL);
1381b843c749SSergey Zigachev 
1382b843c749SSergey Zigachev 	sdma_cntl = RREG32(reg_offset);
1383b843c749SSergey Zigachev 	sdma_cntl = REG_SET_FIELD(sdma_cntl, SDMA0_CNTL, TRAP_ENABLE,
1384b843c749SSergey Zigachev 		       state == AMDGPU_IRQ_STATE_ENABLE ? 1 : 0);
1385b843c749SSergey Zigachev 	WREG32(reg_offset, sdma_cntl);
1386b843c749SSergey Zigachev 
1387b843c749SSergey Zigachev 	return 0;
1388b843c749SSergey Zigachev }
1389b843c749SSergey Zigachev 
sdma_v4_0_process_trap_irq(struct amdgpu_device * adev,struct amdgpu_irq_src * source,struct amdgpu_iv_entry * entry)1390b843c749SSergey Zigachev static int sdma_v4_0_process_trap_irq(struct amdgpu_device *adev,
1391b843c749SSergey Zigachev 				      struct amdgpu_irq_src *source,
1392b843c749SSergey Zigachev 				      struct amdgpu_iv_entry *entry)
1393b843c749SSergey Zigachev {
1394b843c749SSergey Zigachev 	DRM_DEBUG("IH: SDMA trap\n");
1395b843c749SSergey Zigachev 	switch (entry->client_id) {
1396b843c749SSergey Zigachev 	case SOC15_IH_CLIENTID_SDMA0:
1397b843c749SSergey Zigachev 		switch (entry->ring_id) {
1398b843c749SSergey Zigachev 		case 0:
1399b843c749SSergey Zigachev 			amdgpu_fence_process(&adev->sdma.instance[0].ring);
1400b843c749SSergey Zigachev 			break;
1401b843c749SSergey Zigachev 		case 1:
1402b843c749SSergey Zigachev 			/* XXX compute */
1403b843c749SSergey Zigachev 			break;
1404b843c749SSergey Zigachev 		case 2:
1405b843c749SSergey Zigachev 			/* XXX compute */
1406b843c749SSergey Zigachev 			break;
1407b843c749SSergey Zigachev 		case 3:
1408b843c749SSergey Zigachev 			/* XXX page queue*/
1409b843c749SSergey Zigachev 			break;
1410b843c749SSergey Zigachev 		}
1411b843c749SSergey Zigachev 		break;
1412b843c749SSergey Zigachev 	case SOC15_IH_CLIENTID_SDMA1:
1413b843c749SSergey Zigachev 		switch (entry->ring_id) {
1414b843c749SSergey Zigachev 		case 0:
1415b843c749SSergey Zigachev 			amdgpu_fence_process(&adev->sdma.instance[1].ring);
1416b843c749SSergey Zigachev 			break;
1417b843c749SSergey Zigachev 		case 1:
1418b843c749SSergey Zigachev 			/* XXX compute */
1419b843c749SSergey Zigachev 			break;
1420b843c749SSergey Zigachev 		case 2:
1421b843c749SSergey Zigachev 			/* XXX compute */
1422b843c749SSergey Zigachev 			break;
1423b843c749SSergey Zigachev 		case 3:
1424b843c749SSergey Zigachev 			/* XXX page queue*/
1425b843c749SSergey Zigachev 			break;
1426b843c749SSergey Zigachev 		}
1427b843c749SSergey Zigachev 		break;
1428b843c749SSergey Zigachev 	}
1429b843c749SSergey Zigachev 	return 0;
1430b843c749SSergey Zigachev }
1431b843c749SSergey Zigachev 
sdma_v4_0_process_illegal_inst_irq(struct amdgpu_device * adev,struct amdgpu_irq_src * source,struct amdgpu_iv_entry * entry)1432b843c749SSergey Zigachev static int sdma_v4_0_process_illegal_inst_irq(struct amdgpu_device *adev,
1433b843c749SSergey Zigachev 					      struct amdgpu_irq_src *source,
1434b843c749SSergey Zigachev 					      struct amdgpu_iv_entry *entry)
1435b843c749SSergey Zigachev {
1436b843c749SSergey Zigachev 	DRM_ERROR("Illegal instruction in SDMA command stream\n");
1437b843c749SSergey Zigachev 	schedule_work(&adev->reset_work);
1438b843c749SSergey Zigachev 	return 0;
1439b843c749SSergey Zigachev }
1440b843c749SSergey Zigachev 
1441b843c749SSergey Zigachev 
sdma_v4_0_update_medium_grain_clock_gating(struct amdgpu_device * adev,bool enable)1442b843c749SSergey Zigachev static void sdma_v4_0_update_medium_grain_clock_gating(
1443b843c749SSergey Zigachev 		struct amdgpu_device *adev,
1444b843c749SSergey Zigachev 		bool enable)
1445b843c749SSergey Zigachev {
1446b843c749SSergey Zigachev 	uint32_t data, def;
1447b843c749SSergey Zigachev 
1448b843c749SSergey Zigachev 	if (enable && (adev->cg_flags & AMD_CG_SUPPORT_SDMA_MGCG)) {
1449b843c749SSergey Zigachev 		/* enable sdma0 clock gating */
1450b843c749SSergey Zigachev 		def = data = RREG32(SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_CLK_CTRL));
1451b843c749SSergey Zigachev 		data &= ~(SDMA0_CLK_CTRL__SOFT_OVERRIDE7_MASK |
1452b843c749SSergey Zigachev 			  SDMA0_CLK_CTRL__SOFT_OVERRIDE6_MASK |
1453b843c749SSergey Zigachev 			  SDMA0_CLK_CTRL__SOFT_OVERRIDE5_MASK |
1454b843c749SSergey Zigachev 			  SDMA0_CLK_CTRL__SOFT_OVERRIDE4_MASK |
1455b843c749SSergey Zigachev 			  SDMA0_CLK_CTRL__SOFT_OVERRIDE3_MASK |
1456b843c749SSergey Zigachev 			  SDMA0_CLK_CTRL__SOFT_OVERRIDE2_MASK |
1457b843c749SSergey Zigachev 			  SDMA0_CLK_CTRL__SOFT_OVERRIDE1_MASK |
1458b843c749SSergey Zigachev 			  SDMA0_CLK_CTRL__SOFT_OVERRIDE0_MASK);
1459b843c749SSergey Zigachev 		if (def != data)
1460b843c749SSergey Zigachev 			WREG32(SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_CLK_CTRL), data);
1461b843c749SSergey Zigachev 
1462b843c749SSergey Zigachev 		if (adev->sdma.num_instances > 1) {
1463b843c749SSergey Zigachev 			def = data = RREG32(SOC15_REG_OFFSET(SDMA1, 0, mmSDMA1_CLK_CTRL));
1464b843c749SSergey Zigachev 			data &= ~(SDMA1_CLK_CTRL__SOFT_OVERRIDE7_MASK |
1465b843c749SSergey Zigachev 				  SDMA1_CLK_CTRL__SOFT_OVERRIDE6_MASK |
1466b843c749SSergey Zigachev 				  SDMA1_CLK_CTRL__SOFT_OVERRIDE5_MASK |
1467b843c749SSergey Zigachev 				  SDMA1_CLK_CTRL__SOFT_OVERRIDE4_MASK |
1468b843c749SSergey Zigachev 				  SDMA1_CLK_CTRL__SOFT_OVERRIDE3_MASK |
1469b843c749SSergey Zigachev 				  SDMA1_CLK_CTRL__SOFT_OVERRIDE2_MASK |
1470b843c749SSergey Zigachev 				  SDMA1_CLK_CTRL__SOFT_OVERRIDE1_MASK |
1471b843c749SSergey Zigachev 				  SDMA1_CLK_CTRL__SOFT_OVERRIDE0_MASK);
1472b843c749SSergey Zigachev 			if (def != data)
1473b843c749SSergey Zigachev 				WREG32(SOC15_REG_OFFSET(SDMA1, 0, mmSDMA1_CLK_CTRL), data);
1474b843c749SSergey Zigachev 		}
1475b843c749SSergey Zigachev 	} else {
1476b843c749SSergey Zigachev 		/* disable sdma0 clock gating */
1477b843c749SSergey Zigachev 		def = data = RREG32(SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_CLK_CTRL));
1478b843c749SSergey Zigachev 		data |= (SDMA0_CLK_CTRL__SOFT_OVERRIDE7_MASK |
1479b843c749SSergey Zigachev 			 SDMA0_CLK_CTRL__SOFT_OVERRIDE6_MASK |
1480b843c749SSergey Zigachev 			 SDMA0_CLK_CTRL__SOFT_OVERRIDE5_MASK |
1481b843c749SSergey Zigachev 			 SDMA0_CLK_CTRL__SOFT_OVERRIDE4_MASK |
1482b843c749SSergey Zigachev 			 SDMA0_CLK_CTRL__SOFT_OVERRIDE3_MASK |
1483b843c749SSergey Zigachev 			 SDMA0_CLK_CTRL__SOFT_OVERRIDE2_MASK |
1484b843c749SSergey Zigachev 			 SDMA0_CLK_CTRL__SOFT_OVERRIDE1_MASK |
1485b843c749SSergey Zigachev 			 SDMA0_CLK_CTRL__SOFT_OVERRIDE0_MASK);
1486b843c749SSergey Zigachev 
1487b843c749SSergey Zigachev 		if (def != data)
1488b843c749SSergey Zigachev 			WREG32(SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_CLK_CTRL), data);
1489b843c749SSergey Zigachev 
1490b843c749SSergey Zigachev 		if (adev->sdma.num_instances > 1) {
1491b843c749SSergey Zigachev 			def = data = RREG32(SOC15_REG_OFFSET(SDMA1, 0, mmSDMA1_CLK_CTRL));
1492b843c749SSergey Zigachev 			data |= (SDMA1_CLK_CTRL__SOFT_OVERRIDE7_MASK |
1493b843c749SSergey Zigachev 				 SDMA1_CLK_CTRL__SOFT_OVERRIDE6_MASK |
1494b843c749SSergey Zigachev 				 SDMA1_CLK_CTRL__SOFT_OVERRIDE5_MASK |
1495b843c749SSergey Zigachev 				 SDMA1_CLK_CTRL__SOFT_OVERRIDE4_MASK |
1496b843c749SSergey Zigachev 				 SDMA1_CLK_CTRL__SOFT_OVERRIDE3_MASK |
1497b843c749SSergey Zigachev 				 SDMA1_CLK_CTRL__SOFT_OVERRIDE2_MASK |
1498b843c749SSergey Zigachev 				 SDMA1_CLK_CTRL__SOFT_OVERRIDE1_MASK |
1499b843c749SSergey Zigachev 				 SDMA1_CLK_CTRL__SOFT_OVERRIDE0_MASK);
1500b843c749SSergey Zigachev 			if (def != data)
1501b843c749SSergey Zigachev 				WREG32(SOC15_REG_OFFSET(SDMA1, 0, mmSDMA1_CLK_CTRL), data);
1502b843c749SSergey Zigachev 		}
1503b843c749SSergey Zigachev 	}
1504b843c749SSergey Zigachev }
1505b843c749SSergey Zigachev 
1506b843c749SSergey Zigachev 
sdma_v4_0_update_medium_grain_light_sleep(struct amdgpu_device * adev,bool enable)1507b843c749SSergey Zigachev static void sdma_v4_0_update_medium_grain_light_sleep(
1508b843c749SSergey Zigachev 		struct amdgpu_device *adev,
1509b843c749SSergey Zigachev 		bool enable)
1510b843c749SSergey Zigachev {
1511b843c749SSergey Zigachev 	uint32_t data, def;
1512b843c749SSergey Zigachev 
1513b843c749SSergey Zigachev 	if (enable && (adev->cg_flags & AMD_CG_SUPPORT_SDMA_LS)) {
1514b843c749SSergey Zigachev 		/* 1-not override: enable sdma0 mem light sleep */
1515b843c749SSergey Zigachev 		def = data = RREG32(SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_POWER_CNTL));
1516b843c749SSergey Zigachev 		data |= SDMA0_POWER_CNTL__MEM_POWER_OVERRIDE_MASK;
1517b843c749SSergey Zigachev 		if (def != data)
1518b843c749SSergey Zigachev 			WREG32(SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_POWER_CNTL), data);
1519b843c749SSergey Zigachev 
1520b843c749SSergey Zigachev 		/* 1-not override: enable sdma1 mem light sleep */
1521b843c749SSergey Zigachev 		if (adev->sdma.num_instances > 1) {
1522b843c749SSergey Zigachev 			def = data = RREG32(SOC15_REG_OFFSET(SDMA1, 0, mmSDMA1_POWER_CNTL));
1523b843c749SSergey Zigachev 			data |= SDMA1_POWER_CNTL__MEM_POWER_OVERRIDE_MASK;
1524b843c749SSergey Zigachev 			if (def != data)
1525b843c749SSergey Zigachev 				WREG32(SOC15_REG_OFFSET(SDMA1, 0, mmSDMA1_POWER_CNTL), data);
1526b843c749SSergey Zigachev 		}
1527b843c749SSergey Zigachev 	} else {
1528b843c749SSergey Zigachev 		/* 0-override:disable sdma0 mem light sleep */
1529b843c749SSergey Zigachev 		def = data = RREG32(SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_POWER_CNTL));
1530b843c749SSergey Zigachev 		data &= ~SDMA0_POWER_CNTL__MEM_POWER_OVERRIDE_MASK;
1531b843c749SSergey Zigachev 		if (def != data)
1532b843c749SSergey Zigachev 			WREG32(SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_POWER_CNTL), data);
1533b843c749SSergey Zigachev 
1534b843c749SSergey Zigachev 		/* 0-override:disable sdma1 mem light sleep */
1535b843c749SSergey Zigachev 		if (adev->sdma.num_instances > 1) {
1536b843c749SSergey Zigachev 			def = data = RREG32(SOC15_REG_OFFSET(SDMA1, 0, mmSDMA1_POWER_CNTL));
1537b843c749SSergey Zigachev 			data &= ~SDMA1_POWER_CNTL__MEM_POWER_OVERRIDE_MASK;
1538b843c749SSergey Zigachev 			if (def != data)
1539b843c749SSergey Zigachev 				WREG32(SOC15_REG_OFFSET(SDMA1, 0, mmSDMA1_POWER_CNTL), data);
1540b843c749SSergey Zigachev 		}
1541b843c749SSergey Zigachev 	}
1542b843c749SSergey Zigachev }
1543b843c749SSergey Zigachev 
sdma_v4_0_set_clockgating_state(void * handle,enum amd_clockgating_state state)1544b843c749SSergey Zigachev static int sdma_v4_0_set_clockgating_state(void *handle,
1545b843c749SSergey Zigachev 					  enum amd_clockgating_state state)
1546b843c749SSergey Zigachev {
1547b843c749SSergey Zigachev 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
1548b843c749SSergey Zigachev 
1549b843c749SSergey Zigachev 	if (amdgpu_sriov_vf(adev))
1550b843c749SSergey Zigachev 		return 0;
1551b843c749SSergey Zigachev 
1552b843c749SSergey Zigachev 	switch (adev->asic_type) {
1553b843c749SSergey Zigachev 	case CHIP_VEGA10:
1554b843c749SSergey Zigachev 	case CHIP_VEGA12:
1555b843c749SSergey Zigachev 	case CHIP_VEGA20:
1556b843c749SSergey Zigachev 	case CHIP_RAVEN:
1557b843c749SSergey Zigachev 		sdma_v4_0_update_medium_grain_clock_gating(adev,
1558b843c749SSergey Zigachev 				state == AMD_CG_STATE_GATE ? true : false);
1559b843c749SSergey Zigachev 		sdma_v4_0_update_medium_grain_light_sleep(adev,
1560b843c749SSergey Zigachev 				state == AMD_CG_STATE_GATE ? true : false);
1561b843c749SSergey Zigachev 		break;
1562b843c749SSergey Zigachev 	default:
1563b843c749SSergey Zigachev 		break;
1564b843c749SSergey Zigachev 	}
1565b843c749SSergey Zigachev 	return 0;
1566b843c749SSergey Zigachev }
1567b843c749SSergey Zigachev 
sdma_v4_0_set_powergating_state(void * handle,enum amd_powergating_state state)1568b843c749SSergey Zigachev static int sdma_v4_0_set_powergating_state(void *handle,
1569b843c749SSergey Zigachev 					  enum amd_powergating_state state)
1570b843c749SSergey Zigachev {
1571b843c749SSergey Zigachev 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
1572b843c749SSergey Zigachev 
1573b843c749SSergey Zigachev 	switch (adev->asic_type) {
1574b843c749SSergey Zigachev 	case CHIP_RAVEN:
1575b843c749SSergey Zigachev 		sdma_v4_1_update_power_gating(adev,
1576b843c749SSergey Zigachev 				state == AMD_PG_STATE_GATE ? true : false);
1577b843c749SSergey Zigachev 		break;
1578b843c749SSergey Zigachev 	default:
1579b843c749SSergey Zigachev 		break;
1580b843c749SSergey Zigachev 	}
1581b843c749SSergey Zigachev 
1582b843c749SSergey Zigachev 	return 0;
1583b843c749SSergey Zigachev }
1584b843c749SSergey Zigachev 
sdma_v4_0_get_clockgating_state(void * handle,u32 * flags)1585b843c749SSergey Zigachev static void sdma_v4_0_get_clockgating_state(void *handle, u32 *flags)
1586b843c749SSergey Zigachev {
1587b843c749SSergey Zigachev 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
1588b843c749SSergey Zigachev 	int data;
1589b843c749SSergey Zigachev 
1590b843c749SSergey Zigachev 	if (amdgpu_sriov_vf(adev))
1591b843c749SSergey Zigachev 		*flags = 0;
1592b843c749SSergey Zigachev 
1593b843c749SSergey Zigachev 	/* AMD_CG_SUPPORT_SDMA_MGCG */
1594b843c749SSergey Zigachev 	data = RREG32(SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_CLK_CTRL));
1595b843c749SSergey Zigachev 	if (!(data & SDMA0_CLK_CTRL__SOFT_OVERRIDE7_MASK))
1596b843c749SSergey Zigachev 		*flags |= AMD_CG_SUPPORT_SDMA_MGCG;
1597b843c749SSergey Zigachev 
1598b843c749SSergey Zigachev 	/* AMD_CG_SUPPORT_SDMA_LS */
1599b843c749SSergey Zigachev 	data = RREG32(SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_POWER_CNTL));
1600b843c749SSergey Zigachev 	if (data & SDMA0_POWER_CNTL__MEM_POWER_OVERRIDE_MASK)
1601b843c749SSergey Zigachev 		*flags |= AMD_CG_SUPPORT_SDMA_LS;
1602b843c749SSergey Zigachev }
1603b843c749SSergey Zigachev 
1604b843c749SSergey Zigachev const struct amd_ip_funcs sdma_v4_0_ip_funcs = {
1605b843c749SSergey Zigachev 	.name = "sdma_v4_0",
1606b843c749SSergey Zigachev 	.early_init = sdma_v4_0_early_init,
1607b843c749SSergey Zigachev 	.late_init = NULL,
1608b843c749SSergey Zigachev 	.sw_init = sdma_v4_0_sw_init,
1609b843c749SSergey Zigachev 	.sw_fini = sdma_v4_0_sw_fini,
1610b843c749SSergey Zigachev 	.hw_init = sdma_v4_0_hw_init,
1611b843c749SSergey Zigachev 	.hw_fini = sdma_v4_0_hw_fini,
1612b843c749SSergey Zigachev 	.suspend = sdma_v4_0_suspend,
1613b843c749SSergey Zigachev 	.resume = sdma_v4_0_resume,
1614b843c749SSergey Zigachev 	.is_idle = sdma_v4_0_is_idle,
1615b843c749SSergey Zigachev 	.wait_for_idle = sdma_v4_0_wait_for_idle,
1616b843c749SSergey Zigachev 	.soft_reset = sdma_v4_0_soft_reset,
1617b843c749SSergey Zigachev 	.set_clockgating_state = sdma_v4_0_set_clockgating_state,
1618b843c749SSergey Zigachev 	.set_powergating_state = sdma_v4_0_set_powergating_state,
1619b843c749SSergey Zigachev 	.get_clockgating_state = sdma_v4_0_get_clockgating_state,
1620b843c749SSergey Zigachev };
1621b843c749SSergey Zigachev 
1622b843c749SSergey Zigachev static const struct amdgpu_ring_funcs sdma_v4_0_ring_funcs = {
1623b843c749SSergey Zigachev 	.type = AMDGPU_RING_TYPE_SDMA,
1624b843c749SSergey Zigachev 	.align_mask = 0xf,
1625b843c749SSergey Zigachev 	.nop = SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP),
1626b843c749SSergey Zigachev 	.support_64bit_ptrs = true,
1627b843c749SSergey Zigachev 	.vmhub = AMDGPU_MMHUB,
1628b843c749SSergey Zigachev 	.get_rptr = sdma_v4_0_ring_get_rptr,
1629b843c749SSergey Zigachev 	.get_wptr = sdma_v4_0_ring_get_wptr,
1630b843c749SSergey Zigachev 	.set_wptr = sdma_v4_0_ring_set_wptr,
1631b843c749SSergey Zigachev 	.emit_frame_size =
1632b843c749SSergey Zigachev 		6 + /* sdma_v4_0_ring_emit_hdp_flush */
1633b843c749SSergey Zigachev 		3 + /* hdp invalidate */
1634b843c749SSergey Zigachev 		6 + /* sdma_v4_0_ring_emit_pipeline_sync */
1635b843c749SSergey Zigachev 		/* sdma_v4_0_ring_emit_vm_flush */
1636b843c749SSergey Zigachev 		SOC15_FLUSH_GPU_TLB_NUM_WREG * 3 +
1637b843c749SSergey Zigachev 		SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 6 +
1638b843c749SSergey Zigachev 		10 + 10 + 10, /* sdma_v4_0_ring_emit_fence x3 for user fence, vm fence */
1639b843c749SSergey Zigachev 	.emit_ib_size = 7 + 6, /* sdma_v4_0_ring_emit_ib */
1640b843c749SSergey Zigachev 	.emit_ib = sdma_v4_0_ring_emit_ib,
1641b843c749SSergey Zigachev 	.emit_fence = sdma_v4_0_ring_emit_fence,
1642b843c749SSergey Zigachev 	.emit_pipeline_sync = sdma_v4_0_ring_emit_pipeline_sync,
1643b843c749SSergey Zigachev 	.emit_vm_flush = sdma_v4_0_ring_emit_vm_flush,
1644b843c749SSergey Zigachev 	.emit_hdp_flush = sdma_v4_0_ring_emit_hdp_flush,
1645b843c749SSergey Zigachev 	.test_ring = sdma_v4_0_ring_test_ring,
1646b843c749SSergey Zigachev 	.test_ib = sdma_v4_0_ring_test_ib,
1647b843c749SSergey Zigachev 	.insert_nop = sdma_v4_0_ring_insert_nop,
1648b843c749SSergey Zigachev 	.pad_ib = sdma_v4_0_ring_pad_ib,
1649b843c749SSergey Zigachev 	.emit_wreg = sdma_v4_0_ring_emit_wreg,
1650b843c749SSergey Zigachev 	.emit_reg_wait = sdma_v4_0_ring_emit_reg_wait,
1651b843c749SSergey Zigachev 	.emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,
1652b843c749SSergey Zigachev };
1653b843c749SSergey Zigachev 
sdma_v4_0_set_ring_funcs(struct amdgpu_device * adev)1654b843c749SSergey Zigachev static void sdma_v4_0_set_ring_funcs(struct amdgpu_device *adev)
1655b843c749SSergey Zigachev {
1656b843c749SSergey Zigachev 	int i;
1657b843c749SSergey Zigachev 
1658b843c749SSergey Zigachev 	for (i = 0; i < adev->sdma.num_instances; i++) {
1659b843c749SSergey Zigachev 		adev->sdma.instance[i].ring.funcs = &sdma_v4_0_ring_funcs;
1660b843c749SSergey Zigachev 		adev->sdma.instance[i].ring.me = i;
1661b843c749SSergey Zigachev 	}
1662b843c749SSergey Zigachev }
1663b843c749SSergey Zigachev 
1664b843c749SSergey Zigachev static const struct amdgpu_irq_src_funcs sdma_v4_0_trap_irq_funcs = {
1665b843c749SSergey Zigachev 	.set = sdma_v4_0_set_trap_irq_state,
1666b843c749SSergey Zigachev 	.process = sdma_v4_0_process_trap_irq,
1667b843c749SSergey Zigachev };
1668b843c749SSergey Zigachev 
1669b843c749SSergey Zigachev static const struct amdgpu_irq_src_funcs sdma_v4_0_illegal_inst_irq_funcs = {
1670b843c749SSergey Zigachev 	.process = sdma_v4_0_process_illegal_inst_irq,
1671b843c749SSergey Zigachev };
1672b843c749SSergey Zigachev 
sdma_v4_0_set_irq_funcs(struct amdgpu_device * adev)1673b843c749SSergey Zigachev static void sdma_v4_0_set_irq_funcs(struct amdgpu_device *adev)
1674b843c749SSergey Zigachev {
1675b843c749SSergey Zigachev 	adev->sdma.trap_irq.num_types = AMDGPU_SDMA_IRQ_LAST;
1676b843c749SSergey Zigachev 	adev->sdma.trap_irq.funcs = &sdma_v4_0_trap_irq_funcs;
1677b843c749SSergey Zigachev 	adev->sdma.illegal_inst_irq.funcs = &sdma_v4_0_illegal_inst_irq_funcs;
1678b843c749SSergey Zigachev }
1679b843c749SSergey Zigachev 
1680b843c749SSergey Zigachev /**
1681b843c749SSergey Zigachev  * sdma_v4_0_emit_copy_buffer - copy buffer using the sDMA engine
1682b843c749SSergey Zigachev  *
1683b843c749SSergey Zigachev  * @ring: amdgpu_ring structure holding ring information
1684b843c749SSergey Zigachev  * @src_offset: src GPU address
1685b843c749SSergey Zigachev  * @dst_offset: dst GPU address
1686b843c749SSergey Zigachev  * @byte_count: number of bytes to xfer
1687b843c749SSergey Zigachev  *
1688b843c749SSergey Zigachev  * Copy GPU buffers using the DMA engine (VEGA10/12).
1689b843c749SSergey Zigachev  * Used by the amdgpu ttm implementation to move pages if
1690b843c749SSergey Zigachev  * registered as the asic copy callback.
1691b843c749SSergey Zigachev  */
sdma_v4_0_emit_copy_buffer(struct amdgpu_ib * ib,uint64_t src_offset,uint64_t dst_offset,uint32_t byte_count)1692b843c749SSergey Zigachev static void sdma_v4_0_emit_copy_buffer(struct amdgpu_ib *ib,
1693b843c749SSergey Zigachev 				       uint64_t src_offset,
1694b843c749SSergey Zigachev 				       uint64_t dst_offset,
1695b843c749SSergey Zigachev 				       uint32_t byte_count)
1696b843c749SSergey Zigachev {
1697b843c749SSergey Zigachev 	ib->ptr[ib->length_dw++] = SDMA_PKT_HEADER_OP(SDMA_OP_COPY) |
1698b843c749SSergey Zigachev 		SDMA_PKT_HEADER_SUB_OP(SDMA_SUBOP_COPY_LINEAR);
1699b843c749SSergey Zigachev 	ib->ptr[ib->length_dw++] = byte_count - 1;
1700b843c749SSergey Zigachev 	ib->ptr[ib->length_dw++] = 0; /* src/dst endian swap */
1701b843c749SSergey Zigachev 	ib->ptr[ib->length_dw++] = lower_32_bits(src_offset);
1702b843c749SSergey Zigachev 	ib->ptr[ib->length_dw++] = upper_32_bits(src_offset);
1703b843c749SSergey Zigachev 	ib->ptr[ib->length_dw++] = lower_32_bits(dst_offset);
1704b843c749SSergey Zigachev 	ib->ptr[ib->length_dw++] = upper_32_bits(dst_offset);
1705b843c749SSergey Zigachev }
1706b843c749SSergey Zigachev 
1707b843c749SSergey Zigachev /**
1708b843c749SSergey Zigachev  * sdma_v4_0_emit_fill_buffer - fill buffer using the sDMA engine
1709b843c749SSergey Zigachev  *
1710b843c749SSergey Zigachev  * @ring: amdgpu_ring structure holding ring information
1711b843c749SSergey Zigachev  * @src_data: value to write to buffer
1712b843c749SSergey Zigachev  * @dst_offset: dst GPU address
1713b843c749SSergey Zigachev  * @byte_count: number of bytes to xfer
1714b843c749SSergey Zigachev  *
1715b843c749SSergey Zigachev  * Fill GPU buffers using the DMA engine (VEGA10/12).
1716b843c749SSergey Zigachev  */
sdma_v4_0_emit_fill_buffer(struct amdgpu_ib * ib,uint32_t src_data,uint64_t dst_offset,uint32_t byte_count)1717b843c749SSergey Zigachev static void sdma_v4_0_emit_fill_buffer(struct amdgpu_ib *ib,
1718b843c749SSergey Zigachev 				       uint32_t src_data,
1719b843c749SSergey Zigachev 				       uint64_t dst_offset,
1720b843c749SSergey Zigachev 				       uint32_t byte_count)
1721b843c749SSergey Zigachev {
1722b843c749SSergey Zigachev 	ib->ptr[ib->length_dw++] = SDMA_PKT_HEADER_OP(SDMA_OP_CONST_FILL);
1723b843c749SSergey Zigachev 	ib->ptr[ib->length_dw++] = lower_32_bits(dst_offset);
1724b843c749SSergey Zigachev 	ib->ptr[ib->length_dw++] = upper_32_bits(dst_offset);
1725b843c749SSergey Zigachev 	ib->ptr[ib->length_dw++] = src_data;
1726b843c749SSergey Zigachev 	ib->ptr[ib->length_dw++] = byte_count - 1;
1727b843c749SSergey Zigachev }
1728b843c749SSergey Zigachev 
1729b843c749SSergey Zigachev static const struct amdgpu_buffer_funcs sdma_v4_0_buffer_funcs = {
1730b843c749SSergey Zigachev 	.copy_max_bytes = 0x400000,
1731b843c749SSergey Zigachev 	.copy_num_dw = 7,
1732b843c749SSergey Zigachev 	.emit_copy_buffer = sdma_v4_0_emit_copy_buffer,
1733b843c749SSergey Zigachev 
1734b843c749SSergey Zigachev 	.fill_max_bytes = 0x400000,
1735b843c749SSergey Zigachev 	.fill_num_dw = 5,
1736b843c749SSergey Zigachev 	.emit_fill_buffer = sdma_v4_0_emit_fill_buffer,
1737b843c749SSergey Zigachev };
1738b843c749SSergey Zigachev 
sdma_v4_0_set_buffer_funcs(struct amdgpu_device * adev)1739b843c749SSergey Zigachev static void sdma_v4_0_set_buffer_funcs(struct amdgpu_device *adev)
1740b843c749SSergey Zigachev {
1741b843c749SSergey Zigachev 	if (adev->mman.buffer_funcs == NULL) {
1742b843c749SSergey Zigachev 		adev->mman.buffer_funcs = &sdma_v4_0_buffer_funcs;
1743b843c749SSergey Zigachev 		adev->mman.buffer_funcs_ring = &adev->sdma.instance[0].ring;
1744b843c749SSergey Zigachev 	}
1745b843c749SSergey Zigachev }
1746b843c749SSergey Zigachev 
1747b843c749SSergey Zigachev static const struct amdgpu_vm_pte_funcs sdma_v4_0_vm_pte_funcs = {
1748b843c749SSergey Zigachev 	.copy_pte_num_dw = 7,
1749b843c749SSergey Zigachev 	.copy_pte = sdma_v4_0_vm_copy_pte,
1750b843c749SSergey Zigachev 
1751b843c749SSergey Zigachev 	.write_pte = sdma_v4_0_vm_write_pte,
1752b843c749SSergey Zigachev 	.set_pte_pde = sdma_v4_0_vm_set_pte_pde,
1753b843c749SSergey Zigachev };
1754b843c749SSergey Zigachev 
sdma_v4_0_set_vm_pte_funcs(struct amdgpu_device * adev)1755b843c749SSergey Zigachev static void sdma_v4_0_set_vm_pte_funcs(struct amdgpu_device *adev)
1756b843c749SSergey Zigachev {
1757b843c749SSergey Zigachev 	unsigned i;
1758b843c749SSergey Zigachev 
1759b843c749SSergey Zigachev 	if (adev->vm_manager.vm_pte_funcs == NULL) {
1760b843c749SSergey Zigachev 		adev->vm_manager.vm_pte_funcs = &sdma_v4_0_vm_pte_funcs;
1761b843c749SSergey Zigachev 		for (i = 0; i < adev->sdma.num_instances; i++)
1762b843c749SSergey Zigachev 			adev->vm_manager.vm_pte_rings[i] =
1763b843c749SSergey Zigachev 				&adev->sdma.instance[i].ring;
1764b843c749SSergey Zigachev 
1765b843c749SSergey Zigachev 		adev->vm_manager.vm_pte_num_rings = adev->sdma.num_instances;
1766b843c749SSergey Zigachev 	}
1767b843c749SSergey Zigachev }
1768b843c749SSergey Zigachev 
1769b843c749SSergey Zigachev const struct amdgpu_ip_block_version sdma_v4_0_ip_block = {
1770b843c749SSergey Zigachev 	.type = AMD_IP_BLOCK_TYPE_SDMA,
1771b843c749SSergey Zigachev 	.major = 4,
1772b843c749SSergey Zigachev 	.minor = 0,
1773b843c749SSergey Zigachev 	.rev = 0,
1774b843c749SSergey Zigachev 	.funcs = &sdma_v4_0_ip_funcs,
1775b843c749SSergey Zigachev };
1776