xref: /netbsd-src/sys/external/bsd/drm2/dist/drm/amd/powerplay/smumgr/amdgpu_smu10_smumgr.c (revision 41ec02673d281bbb3d38e6c78504ce6e30c228c1)
1 /*	$NetBSD: amdgpu_smu10_smumgr.c,v 1.2 2021/12/18 23:45:27 riastradh Exp $	*/
2 
3 /*
4  * Copyright 2016 Advanced Micro Devices, Inc.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22  * OTHER DEALINGS IN THE SOFTWARE.
23  *
24  */
25 
26 #include <sys/cdefs.h>
27 __KERNEL_RCSID(0, "$NetBSD: amdgpu_smu10_smumgr.c,v 1.2 2021/12/18 23:45:27 riastradh Exp $");
28 
29 #include <linux/pci.h>
30 
31 #include "smumgr.h"
32 #include "smu10_inc.h"
33 #include "soc15_common.h"
34 #include "smu10_smumgr.h"
35 #include "ppatomctrl.h"
36 #include "rv_ppsmc.h"
37 #include "smu10_driver_if.h"
38 #include "smu10.h"
39 #include "pp_debug.h"
40 
41 
42 #define BUFFER_SIZE                 80000
43 #define MAX_STRING_SIZE             15
44 #define BUFFER_SIZETWO              131072
45 
46 #define MP0_Public                  0x03800000
47 #define MP0_SRAM                    0x03900000
48 #define MP1_Public                  0x03b00000
49 #define MP1_SRAM                    0x03c00004
50 
51 #define smnMP1_FIRMWARE_FLAGS       0x3010028
52 
53 
smu10_wait_for_response(struct pp_hwmgr * hwmgr)54 static uint32_t smu10_wait_for_response(struct pp_hwmgr *hwmgr)
55 {
56 	struct amdgpu_device *adev = hwmgr->adev;
57 	uint32_t reg;
58 
59 	reg = SOC15_REG_OFFSET(MP1, 0, mmMP1_SMN_C2PMSG_90);
60 
61 	phm_wait_for_register_unequal(hwmgr, reg,
62 			0, MP1_C2PMSG_90__CONTENT_MASK);
63 
64 	return RREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_90);
65 }
66 
smu10_send_msg_to_smc_without_waiting(struct pp_hwmgr * hwmgr,uint16_t msg)67 static int smu10_send_msg_to_smc_without_waiting(struct pp_hwmgr *hwmgr,
68 		uint16_t msg)
69 {
70 	struct amdgpu_device *adev = hwmgr->adev;
71 
72 	WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_66, msg);
73 
74 	return 0;
75 }
76 
smu10_read_arg_from_smc(struct pp_hwmgr * hwmgr)77 static uint32_t smu10_read_arg_from_smc(struct pp_hwmgr *hwmgr)
78 {
79 	struct amdgpu_device *adev = hwmgr->adev;
80 
81 	return RREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_82);
82 }
83 
smu10_send_msg_to_smc(struct pp_hwmgr * hwmgr,uint16_t msg)84 static int smu10_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg)
85 {
86 	struct amdgpu_device *adev = hwmgr->adev;
87 
88 	smu10_wait_for_response(hwmgr);
89 
90 	WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_90, 0);
91 
92 	smu10_send_msg_to_smc_without_waiting(hwmgr, msg);
93 
94 	if (smu10_wait_for_response(hwmgr) == 0)
95 		printk("Failed to send Message %x.\n", msg);
96 
97 	return 0;
98 }
99 
100 
smu10_send_msg_to_smc_with_parameter(struct pp_hwmgr * hwmgr,uint16_t msg,uint32_t parameter)101 static int smu10_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr,
102 		uint16_t msg, uint32_t parameter)
103 {
104 	struct amdgpu_device *adev = hwmgr->adev;
105 
106 	smu10_wait_for_response(hwmgr);
107 
108 	WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_90, 0);
109 
110 	WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_82, parameter);
111 
112 	smu10_send_msg_to_smc_without_waiting(hwmgr, msg);
113 
114 
115 	if (smu10_wait_for_response(hwmgr) == 0)
116 		printk("Failed to send Message %x.\n", msg);
117 
118 	return 0;
119 }
120 
smu10_copy_table_from_smc(struct pp_hwmgr * hwmgr,uint8_t * table,int16_t table_id)121 static int smu10_copy_table_from_smc(struct pp_hwmgr *hwmgr,
122 		uint8_t *table, int16_t table_id)
123 {
124 	struct smu10_smumgr *priv =
125 			(struct smu10_smumgr *)(hwmgr->smu_backend);
126 	struct amdgpu_device *adev = hwmgr->adev;
127 
128 	PP_ASSERT_WITH_CODE(table_id < MAX_SMU_TABLE,
129 			"Invalid SMU Table ID!", return -EINVAL;);
130 	PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0,
131 			"Invalid SMU Table version!", return -EINVAL;);
132 	PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0,
133 			"Invalid SMU Table Length!", return -EINVAL;);
134 	smu10_send_msg_to_smc_with_parameter(hwmgr,
135 			PPSMC_MSG_SetDriverDramAddrHigh,
136 			upper_32_bits(priv->smu_tables.entry[table_id].mc_addr));
137 	smu10_send_msg_to_smc_with_parameter(hwmgr,
138 			PPSMC_MSG_SetDriverDramAddrLow,
139 			lower_32_bits(priv->smu_tables.entry[table_id].mc_addr));
140 	smu10_send_msg_to_smc_with_parameter(hwmgr,
141 			PPSMC_MSG_TransferTableSmu2Dram,
142 			priv->smu_tables.entry[table_id].table_id);
143 
144 	/* flush hdp cache */
145 	amdgpu_asic_flush_hdp(adev, NULL);
146 
147 	memcpy(table, (uint8_t *)priv->smu_tables.entry[table_id].table,
148 			priv->smu_tables.entry[table_id].size);
149 
150 	return 0;
151 }
152 
smu10_copy_table_to_smc(struct pp_hwmgr * hwmgr,uint8_t * table,int16_t table_id)153 static int smu10_copy_table_to_smc(struct pp_hwmgr *hwmgr,
154 		uint8_t *table, int16_t table_id)
155 {
156 	struct smu10_smumgr *priv =
157 			(struct smu10_smumgr *)(hwmgr->smu_backend);
158 	struct amdgpu_device *adev = hwmgr->adev;
159 
160 	PP_ASSERT_WITH_CODE(table_id < MAX_SMU_TABLE,
161 			"Invalid SMU Table ID!", return -EINVAL;);
162 	PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0,
163 			"Invalid SMU Table version!", return -EINVAL;);
164 	PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0,
165 			"Invalid SMU Table Length!", return -EINVAL;);
166 
167 	memcpy(priv->smu_tables.entry[table_id].table, table,
168 			priv->smu_tables.entry[table_id].size);
169 
170 	amdgpu_asic_flush_hdp(adev, NULL);
171 
172 	smu10_send_msg_to_smc_with_parameter(hwmgr,
173 			PPSMC_MSG_SetDriverDramAddrHigh,
174 			upper_32_bits(priv->smu_tables.entry[table_id].mc_addr));
175 	smu10_send_msg_to_smc_with_parameter(hwmgr,
176 			PPSMC_MSG_SetDriverDramAddrLow,
177 			lower_32_bits(priv->smu_tables.entry[table_id].mc_addr));
178 	smu10_send_msg_to_smc_with_parameter(hwmgr,
179 			PPSMC_MSG_TransferTableDram2Smu,
180 			priv->smu_tables.entry[table_id].table_id);
181 
182 	return 0;
183 }
184 
smu10_verify_smc_interface(struct pp_hwmgr * hwmgr)185 static int smu10_verify_smc_interface(struct pp_hwmgr *hwmgr)
186 {
187 	uint32_t smc_driver_if_version;
188 
189 	smu10_send_msg_to_smc(hwmgr,
190 			PPSMC_MSG_GetDriverIfVersion);
191 	smc_driver_if_version = smu10_read_arg_from_smc(hwmgr);
192 
193 	if ((smc_driver_if_version != SMU10_DRIVER_IF_VERSION) &&
194 	    (smc_driver_if_version != SMU10_DRIVER_IF_VERSION + 1)) {
195 		pr_err("Attempt to read SMC IF Version Number Failed!\n");
196 		return -EINVAL;
197 	}
198 
199 	return 0;
200 }
201 
smu10_smu_fini(struct pp_hwmgr * hwmgr)202 static int smu10_smu_fini(struct pp_hwmgr *hwmgr)
203 {
204 	struct smu10_smumgr *priv =
205 			(struct smu10_smumgr *)(hwmgr->smu_backend);
206 
207 	if (priv) {
208 		amdgpu_bo_free_kernel(&priv->smu_tables.entry[SMU10_WMTABLE].handle,
209 					&priv->smu_tables.entry[SMU10_WMTABLE].mc_addr,
210 					&priv->smu_tables.entry[SMU10_WMTABLE].table);
211 		amdgpu_bo_free_kernel(&priv->smu_tables.entry[SMU10_CLOCKTABLE].handle,
212 					&priv->smu_tables.entry[SMU10_CLOCKTABLE].mc_addr,
213 					&priv->smu_tables.entry[SMU10_CLOCKTABLE].table);
214 		kfree(hwmgr->smu_backend);
215 		hwmgr->smu_backend = NULL;
216 	}
217 
218 	return 0;
219 }
220 
smu10_start_smu(struct pp_hwmgr * hwmgr)221 static int smu10_start_smu(struct pp_hwmgr *hwmgr)
222 {
223 	struct amdgpu_device *adev = hwmgr->adev;
224 
225 	smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetSmuVersion);
226 	hwmgr->smu_version = smu10_read_arg_from_smc(hwmgr);
227 	adev->pm.fw_version = hwmgr->smu_version >> 8;
228 
229 	if (adev->rev_id < 0x8 && adev->pdev->device != 0x15d8 &&
230 	    adev->pm.fw_version < 0x1e45)
231 		adev->pm.pp_feature &= ~PP_GFXOFF_MASK;
232 
233 	if (smu10_verify_smc_interface(hwmgr))
234 		return -EINVAL;
235 
236 	return 0;
237 }
238 
smu10_smu_init(struct pp_hwmgr * hwmgr)239 static int smu10_smu_init(struct pp_hwmgr *hwmgr)
240 {
241 	struct smu10_smumgr *priv;
242 	int r;
243 
244 	priv = kzalloc(sizeof(struct smu10_smumgr), GFP_KERNEL);
245 
246 	if (!priv)
247 		return -ENOMEM;
248 
249 	hwmgr->smu_backend = priv;
250 
251 	/* allocate space for watermarks table */
252 	r = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
253 			sizeof(Watermarks_t),
254 			PAGE_SIZE,
255 			AMDGPU_GEM_DOMAIN_VRAM,
256 			&priv->smu_tables.entry[SMU10_WMTABLE].handle,
257 			&priv->smu_tables.entry[SMU10_WMTABLE].mc_addr,
258 			&priv->smu_tables.entry[SMU10_WMTABLE].table);
259 
260 	if (r)
261 		goto err0;
262 
263 	priv->smu_tables.entry[SMU10_WMTABLE].version = 0x01;
264 	priv->smu_tables.entry[SMU10_WMTABLE].size = sizeof(Watermarks_t);
265 	priv->smu_tables.entry[SMU10_WMTABLE].table_id = TABLE_WATERMARKS;
266 
267 	/* allocate space for watermarks table */
268 	r = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
269 			sizeof(DpmClocks_t),
270 			PAGE_SIZE,
271 			AMDGPU_GEM_DOMAIN_VRAM,
272 			&priv->smu_tables.entry[SMU10_CLOCKTABLE].handle,
273 			&priv->smu_tables.entry[SMU10_CLOCKTABLE].mc_addr,
274 			&priv->smu_tables.entry[SMU10_CLOCKTABLE].table);
275 
276 	if (r)
277 		goto err1;
278 
279 	priv->smu_tables.entry[SMU10_CLOCKTABLE].version = 0x01;
280 	priv->smu_tables.entry[SMU10_CLOCKTABLE].size = sizeof(DpmClocks_t);
281 	priv->smu_tables.entry[SMU10_CLOCKTABLE].table_id = TABLE_DPMCLOCKS;
282 
283 	return 0;
284 
285 err1:
286 	amdgpu_bo_free_kernel(&priv->smu_tables.entry[SMU10_WMTABLE].handle,
287 				&priv->smu_tables.entry[SMU10_WMTABLE].mc_addr,
288 				&priv->smu_tables.entry[SMU10_WMTABLE].table);
289 err0:
290 	kfree(priv);
291 	return -EINVAL;
292 }
293 
smu10_smc_table_manager(struct pp_hwmgr * hwmgr,uint8_t * table,uint16_t table_id,bool rw)294 static int smu10_smc_table_manager(struct pp_hwmgr *hwmgr, uint8_t *table, uint16_t table_id, bool rw)
295 {
296 	int ret;
297 
298 	if (rw)
299 		ret = smu10_copy_table_from_smc(hwmgr, table, table_id);
300 	else
301 		ret = smu10_copy_table_to_smc(hwmgr, table, table_id);
302 
303 	return ret;
304 }
305 
306 
307 const struct pp_smumgr_func smu10_smu_funcs = {
308 	.name = "smu10_smu",
309 	.smu_init = &smu10_smu_init,
310 	.smu_fini = &smu10_smu_fini,
311 	.start_smu = &smu10_start_smu,
312 	.request_smu_load_specific_fw = NULL,
313 	.send_msg_to_smc = &smu10_send_msg_to_smc,
314 	.send_msg_to_smc_with_parameter = &smu10_send_msg_to_smc_with_parameter,
315 	.download_pptable_settings = NULL,
316 	.upload_pptable_settings = NULL,
317 	.get_argument = smu10_read_arg_from_smc,
318 	.smc_table_manager = smu10_smc_table_manager,
319 };
320 
321 
322