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