Merge tag 'drm-misc-fixes-2017-11-13' of git://anongit.freedesktop.org/drm/drm-misc...
[sfrench/cifs-2.6.git] / drivers / gpu / drm / amd / powerplay / smumgr / rv_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 "rv_inc.h"
26 #include "pp_soc15.h"
27 #include "rv_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 #include "smu_ucode_xfer_vi.h"
35 #include "smu7_smumgr.h"
36
37 #define VOLTAGE_SCALE 4
38
39 #define BUFFER_SIZE                 80000
40 #define MAX_STRING_SIZE             15
41 #define BUFFER_SIZETWO              131072
42
43 #define MP0_Public                  0x03800000
44 #define MP0_SRAM                    0x03900000
45 #define MP1_Public                  0x03b00000
46 #define MP1_SRAM                    0x03c00004
47
48 #define smnMP1_FIRMWARE_FLAGS       0x3010028
49
50
51 bool rv_is_smc_ram_running(struct pp_hwmgr *hwmgr)
52 {
53         uint32_t mp1_fw_flags, reg;
54
55         reg = soc15_get_register_offset(NBIF_HWID, 0,
56                         mmPCIE_INDEX2_BASE_IDX, mmPCIE_INDEX2);
57
58         cgs_write_register(hwmgr->device, reg,
59                         (MP1_Public | (smnMP1_FIRMWARE_FLAGS & 0xffffffff)));
60
61         reg = soc15_get_register_offset(NBIF_HWID, 0,
62                         mmPCIE_DATA2_BASE_IDX, mmPCIE_DATA2);
63
64         mp1_fw_flags = cgs_read_register(hwmgr->device, reg);
65
66         if (mp1_fw_flags & MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED_MASK)
67                 return true;
68
69         return false;
70 }
71
72 static uint32_t rv_wait_for_response(struct pp_hwmgr *hwmgr)
73 {
74         uint32_t reg;
75
76         if (!rv_is_smc_ram_running(hwmgr))
77                 return -EINVAL;
78
79         reg = soc15_get_register_offset(MP1_HWID, 0,
80                         mmMP1_SMN_C2PMSG_90_BASE_IDX, mmMP1_SMN_C2PMSG_90);
81
82         phm_wait_for_register_unequal(hwmgr, reg,
83                         0, MP1_C2PMSG_90__CONTENT_MASK);
84
85         return cgs_read_register(hwmgr->device, reg);
86 }
87
88 int rv_send_msg_to_smc_without_waiting(struct pp_hwmgr *hwmgr,
89                 uint16_t msg)
90 {
91         uint32_t reg;
92
93         if (!rv_is_smc_ram_running(hwmgr))
94                 return -EINVAL;
95
96         reg = soc15_get_register_offset(MP1_HWID, 0,
97                         mmMP1_SMN_C2PMSG_66_BASE_IDX, mmMP1_SMN_C2PMSG_66);
98         cgs_write_register(hwmgr->device, reg, msg);
99
100         return 0;
101 }
102
103 int rv_read_arg_from_smc(struct pp_hwmgr *hwmgr, uint32_t *arg)
104 {
105         uint32_t reg;
106
107         reg = soc15_get_register_offset(MP1_HWID, 0,
108                         mmMP1_SMN_C2PMSG_82_BASE_IDX, mmMP1_SMN_C2PMSG_82);
109
110         *arg = cgs_read_register(hwmgr->device, reg);
111
112         return 0;
113 }
114
115 int rv_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg)
116 {
117         uint32_t reg;
118
119         rv_wait_for_response(hwmgr);
120
121         reg = soc15_get_register_offset(MP1_HWID, 0,
122                         mmMP1_SMN_C2PMSG_90_BASE_IDX, mmMP1_SMN_C2PMSG_90);
123         cgs_write_register(hwmgr->device, reg, 0);
124
125         rv_send_msg_to_smc_without_waiting(hwmgr, msg);
126
127         if (rv_wait_for_response(hwmgr) == 0)
128                 printk("Failed to send Message %x.\n", msg);
129
130         return 0;
131 }
132
133
134 int rv_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr,
135                 uint16_t msg, uint32_t parameter)
136 {
137         uint32_t reg;
138
139         rv_wait_for_response(hwmgr);
140
141         reg = soc15_get_register_offset(MP1_HWID, 0,
142                         mmMP1_SMN_C2PMSG_90_BASE_IDX, mmMP1_SMN_C2PMSG_90);
143         cgs_write_register(hwmgr->device, reg, 0);
144
145         reg = soc15_get_register_offset(MP1_HWID, 0,
146                         mmMP1_SMN_C2PMSG_82_BASE_IDX, mmMP1_SMN_C2PMSG_82);
147         cgs_write_register(hwmgr->device, reg, parameter);
148
149         rv_send_msg_to_smc_without_waiting(hwmgr, msg);
150
151
152         if (rv_wait_for_response(hwmgr) == 0)
153                 printk("Failed to send Message %x.\n", msg);
154
155         return 0;
156 }
157
158 int rv_copy_table_from_smc(struct pp_hwmgr *hwmgr,
159                 uint8_t *table, int16_t table_id)
160 {
161         struct rv_smumgr *priv =
162                         (struct rv_smumgr *)(hwmgr->smu_backend);
163
164         PP_ASSERT_WITH_CODE(table_id < MAX_SMU_TABLE,
165                         "Invalid SMU Table ID!", return -EINVAL;);
166         PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0,
167                         "Invalid SMU Table version!", return -EINVAL;);
168         PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0,
169                         "Invalid SMU Table Length!", return -EINVAL;);
170         PP_ASSERT_WITH_CODE(rv_send_msg_to_smc_with_parameter(hwmgr,
171                         PPSMC_MSG_SetDriverDramAddrHigh,
172                         priv->smu_tables.entry[table_id].table_addr_high) == 0,
173                         "[CopyTableFromSMC] Attempt to Set Dram Addr High Failed!", return -EINVAL;);
174         PP_ASSERT_WITH_CODE(rv_send_msg_to_smc_with_parameter(hwmgr,
175                         PPSMC_MSG_SetDriverDramAddrLow,
176                         priv->smu_tables.entry[table_id].table_addr_low) == 0,
177                         "[CopyTableFromSMC] Attempt to Set Dram Addr Low Failed!",
178                         return -EINVAL;);
179         PP_ASSERT_WITH_CODE(rv_send_msg_to_smc_with_parameter(hwmgr,
180                         PPSMC_MSG_TransferTableSmu2Dram,
181                         priv->smu_tables.entry[table_id].table_id) == 0,
182                         "[CopyTableFromSMC] Attempt to Transfer Table From SMU Failed!",
183                         return -EINVAL;);
184
185         memcpy(table, priv->smu_tables.entry[table_id].table,
186                         priv->smu_tables.entry[table_id].size);
187
188         return 0;
189 }
190
191 int rv_copy_table_to_smc(struct pp_hwmgr *hwmgr,
192                 uint8_t *table, int16_t table_id)
193 {
194         struct rv_smumgr *priv =
195                         (struct rv_smumgr *)(hwmgr->smu_backend);
196
197         PP_ASSERT_WITH_CODE(table_id < MAX_SMU_TABLE,
198                         "Invalid SMU Table ID!", return -EINVAL;);
199         PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0,
200                         "Invalid SMU Table version!", return -EINVAL;);
201         PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0,
202                         "Invalid SMU Table Length!", return -EINVAL;);
203
204         memcpy(priv->smu_tables.entry[table_id].table, table,
205                         priv->smu_tables.entry[table_id].size);
206
207         PP_ASSERT_WITH_CODE(rv_send_msg_to_smc_with_parameter(hwmgr,
208                         PPSMC_MSG_SetDriverDramAddrHigh,
209                         priv->smu_tables.entry[table_id].table_addr_high) == 0,
210                         "[CopyTableToSMC] Attempt to Set Dram Addr High Failed!",
211                         return -EINVAL;);
212         PP_ASSERT_WITH_CODE(rv_send_msg_to_smc_with_parameter(hwmgr,
213                         PPSMC_MSG_SetDriverDramAddrLow,
214                         priv->smu_tables.entry[table_id].table_addr_low) == 0,
215                         "[CopyTableToSMC] Attempt to Set Dram Addr Low Failed!",
216                         return -EINVAL;);
217         PP_ASSERT_WITH_CODE(rv_send_msg_to_smc_with_parameter(hwmgr,
218                         PPSMC_MSG_TransferTableDram2Smu,
219                         priv->smu_tables.entry[table_id].table_id) == 0,
220                         "[CopyTableToSMC] Attempt to Transfer Table To SMU Failed!",
221                         return -EINVAL;);
222
223         return 0;
224 }
225
226 static int rv_verify_smc_interface(struct pp_hwmgr *hwmgr)
227 {
228         uint32_t smc_driver_if_version;
229
230         PP_ASSERT_WITH_CODE(!rv_send_msg_to_smc(hwmgr,
231                         PPSMC_MSG_GetDriverIfVersion),
232                         "Attempt to get SMC IF Version Number Failed!",
233                         return -EINVAL);
234         PP_ASSERT_WITH_CODE(!rv_read_arg_from_smc(hwmgr,
235                         &smc_driver_if_version),
236                         "Attempt to read SMC IF Version Number Failed!",
237                         return -EINVAL);
238
239         if (smc_driver_if_version != SMU10_DRIVER_IF_VERSION)
240                 return -EINVAL;
241
242         return 0;
243 }
244
245 /* sdma is disabled by default in vbios, need to re-enable in driver */
246 static int rv_smc_enable_sdma(struct pp_hwmgr *hwmgr)
247 {
248         PP_ASSERT_WITH_CODE(!rv_send_msg_to_smc(hwmgr,
249                         PPSMC_MSG_PowerUpSdma),
250                         "Attempt to power up sdma Failed!",
251                         return -EINVAL);
252
253         return 0;
254 }
255
256 static int rv_smc_disable_sdma(struct pp_hwmgr *hwmgr)
257 {
258         PP_ASSERT_WITH_CODE(!rv_send_msg_to_smc(hwmgr,
259                         PPSMC_MSG_PowerDownSdma),
260                         "Attempt to power down sdma Failed!",
261                         return -EINVAL);
262
263         return 0;
264 }
265
266 /* vcn is disabled by default in vbios, need to re-enable in driver */
267 static int rv_smc_enable_vcn(struct pp_hwmgr *hwmgr)
268 {
269         PP_ASSERT_WITH_CODE(!rv_send_msg_to_smc_with_parameter(hwmgr,
270                         PPSMC_MSG_PowerUpVcn, 0),
271                         "Attempt to power up vcn Failed!",
272                         return -EINVAL);
273
274         return 0;
275 }
276
277 static int rv_smc_disable_vcn(struct pp_hwmgr *hwmgr)
278 {
279         PP_ASSERT_WITH_CODE(!rv_send_msg_to_smc_with_parameter(hwmgr,
280                         PPSMC_MSG_PowerDownVcn, 0),
281                         "Attempt to power down vcn Failed!",
282                         return -EINVAL);
283
284         return 0;
285 }
286
287 static int rv_smu_fini(struct pp_hwmgr *hwmgr)
288 {
289         struct rv_smumgr *priv =
290                         (struct rv_smumgr *)(hwmgr->smu_backend);
291
292         if (priv) {
293                 rv_smc_disable_sdma(hwmgr);
294                 rv_smc_disable_vcn(hwmgr);
295                 cgs_free_gpu_mem(hwmgr->device,
296                                 priv->smu_tables.entry[WMTABLE].handle);
297                 cgs_free_gpu_mem(hwmgr->device,
298                                 priv->smu_tables.entry[CLOCKTABLE].handle);
299                 kfree(hwmgr->smu_backend);
300                 hwmgr->smu_backend = NULL;
301         }
302
303         return 0;
304 }
305
306 static int rv_start_smu(struct pp_hwmgr *hwmgr)
307 {
308         if (rv_verify_smc_interface(hwmgr))
309                 return -EINVAL;
310         if (rv_smc_enable_sdma(hwmgr))
311                 return -EINVAL;
312         if (rv_smc_enable_vcn(hwmgr))
313                 return -EINVAL;
314
315         return 0;
316 }
317
318 static int rv_smu_init(struct pp_hwmgr *hwmgr)
319 {
320         struct rv_smumgr *priv;
321         uint64_t mc_addr;
322         void *kaddr = NULL;
323         unsigned long handle;
324
325         priv = kzalloc(sizeof(struct rv_smumgr), GFP_KERNEL);
326
327         if (!priv)
328                 return -ENOMEM;
329
330         hwmgr->smu_backend = priv;
331
332         /* allocate space for watermarks table */
333         smu_allocate_memory(hwmgr->device,
334                         sizeof(Watermarks_t),
335                         CGS_GPU_MEM_TYPE__GART_CACHEABLE,
336                         PAGE_SIZE,
337                         &mc_addr,
338                         &kaddr,
339                         &handle);
340
341         PP_ASSERT_WITH_CODE(kaddr,
342                         "[rv_smu_init] Out of memory for wmtable.",
343                         kfree(hwmgr->smu_backend);
344                         hwmgr->smu_backend = NULL;
345                         return -EINVAL);
346
347         priv->smu_tables.entry[WMTABLE].version = 0x01;
348         priv->smu_tables.entry[WMTABLE].size = sizeof(Watermarks_t);
349         priv->smu_tables.entry[WMTABLE].table_id = TABLE_WATERMARKS;
350         priv->smu_tables.entry[WMTABLE].table_addr_high =
351                         smu_upper_32_bits(mc_addr);
352         priv->smu_tables.entry[WMTABLE].table_addr_low =
353                         smu_lower_32_bits(mc_addr);
354         priv->smu_tables.entry[WMTABLE].table = kaddr;
355         priv->smu_tables.entry[WMTABLE].handle = handle;
356
357         /* allocate space for watermarks table */
358         smu_allocate_memory(hwmgr->device,
359                         sizeof(DpmClocks_t),
360                         CGS_GPU_MEM_TYPE__GART_CACHEABLE,
361                         PAGE_SIZE,
362                         &mc_addr,
363                         &kaddr,
364                         &handle);
365
366         PP_ASSERT_WITH_CODE(kaddr,
367                         "[rv_smu_init] Out of memory for CLOCKTABLE.",
368                         cgs_free_gpu_mem(hwmgr->device,
369                         (cgs_handle_t)priv->smu_tables.entry[WMTABLE].handle);
370                         kfree(hwmgr->smu_backend);
371                         hwmgr->smu_backend = NULL;
372                         return -EINVAL);
373
374         priv->smu_tables.entry[CLOCKTABLE].version = 0x01;
375         priv->smu_tables.entry[CLOCKTABLE].size = sizeof(DpmClocks_t);
376         priv->smu_tables.entry[CLOCKTABLE].table_id = TABLE_DPMCLOCKS;
377         priv->smu_tables.entry[CLOCKTABLE].table_addr_high =
378                         smu_upper_32_bits(mc_addr);
379         priv->smu_tables.entry[CLOCKTABLE].table_addr_low =
380                         smu_lower_32_bits(mc_addr);
381         priv->smu_tables.entry[CLOCKTABLE].table = kaddr;
382         priv->smu_tables.entry[CLOCKTABLE].handle = handle;
383
384         return 0;
385 }
386
387 const struct pp_smumgr_func rv_smu_funcs = {
388         .smu_init = &rv_smu_init,
389         .smu_fini = &rv_smu_fini,
390         .start_smu = &rv_start_smu,
391         .request_smu_load_specific_fw = NULL,
392         .send_msg_to_smc = &rv_send_msg_to_smc,
393         .send_msg_to_smc_with_parameter = &rv_send_msg_to_smc_with_parameter,
394         .download_pptable_settings = NULL,
395         .upload_pptable_settings = NULL,
396 };
397
398