aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/amdgpu/tonga_smc.c
diff options
context:
space:
mode:
authorAlex Deucher <alexander.deucher@amd.com>2015-04-20 17:31:14 -0400
committerAlex Deucher <alexander.deucher@amd.com>2015-06-03 21:03:17 -0400
commitaaa36a976bbb9b02a54c087ff390c0bad1d18e3e (patch)
tree105be3c06ef33c39e6934801d386847950d4ebf9 /drivers/gpu/drm/amd/amdgpu/tonga_smc.c
parenta2e73f56fa6282481927ec43aa9362c03c2e2104 (diff)
drm/amdgpu: Add initial VI support
This adds initial support for VI asics. This includes Iceland, Tonga, and Carrizo. Our inital focus as been Carrizo, so there are still gaps in support for Tonga and Iceland, notably power management. Acked-by: Christian König <christian.koenig@amd.com> Acked-by: Jammy Zhou <Jammy.Zhou@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/tonga_smc.c')
-rw-r--r--drivers/gpu/drm/amd/amdgpu/tonga_smc.c852
1 files changed, 852 insertions, 0 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/tonga_smc.c b/drivers/gpu/drm/amd/amdgpu/tonga_smc.c
new file mode 100644
index 000000000000..5fc53a40c7ac
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/tonga_smc.c
@@ -0,0 +1,852 @@
1/*
2 * Copyright 2014 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 <linux/firmware.h>
25#include "drmP.h"
26#include "amdgpu.h"
27#include "tonga_ppsmc.h"
28#include "tonga_smumgr.h"
29#include "smu_ucode_xfer_vi.h"
30#include "amdgpu_ucode.h"
31
32#include "smu/smu_7_1_2_d.h"
33#include "smu/smu_7_1_2_sh_mask.h"
34
35#define TONGA_SMC_SIZE 0x20000
36
37static int tonga_set_smc_sram_address(struct amdgpu_device *adev, uint32_t smc_address, uint32_t limit)
38{
39 uint32_t val;
40
41 if (smc_address & 3)
42 return -EINVAL;
43
44 if ((smc_address + 3) > limit)
45 return -EINVAL;
46
47 WREG32(mmSMC_IND_INDEX_0, smc_address);
48
49 val = RREG32(mmSMC_IND_ACCESS_CNTL);
50 val = REG_SET_FIELD(val, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, 0);
51 WREG32(mmSMC_IND_ACCESS_CNTL, val);
52
53 return 0;
54}
55
56static int tonga_copy_bytes_to_smc(struct amdgpu_device *adev, uint32_t smc_start_address, const uint8_t *src, uint32_t byte_count, uint32_t limit)
57{
58 uint32_t addr;
59 uint32_t data, orig_data;
60 int result = 0;
61 uint32_t extra_shift;
62 unsigned long flags;
63
64 if (smc_start_address & 3)
65 return -EINVAL;
66
67 if ((smc_start_address + byte_count) > limit)
68 return -EINVAL;
69
70 addr = smc_start_address;
71
72 spin_lock_irqsave(&adev->smc_idx_lock, flags);
73 while (byte_count >= 4) {
74 /* Bytes are written into the SMC addres space with the MSB first */
75 data = (src[0] << 24) + (src[1] << 16) + (src[2] << 8) + src[3];
76
77 result = tonga_set_smc_sram_address(adev, addr, limit);
78
79 if (result)
80 goto out;
81
82 WREG32(mmSMC_IND_DATA_0, data);
83
84 src += 4;
85 byte_count -= 4;
86 addr += 4;
87 }
88
89 if (0 != byte_count) {
90 /* Now write odd bytes left, do a read modify write cycle */
91 data = 0;
92
93 result = tonga_set_smc_sram_address(adev, addr, limit);
94 if (result)
95 goto out;
96
97 orig_data = RREG32(mmSMC_IND_DATA_0);
98 extra_shift = 8 * (4 - byte_count);
99
100 while (byte_count > 0) {
101 data = (data << 8) + *src++;
102 byte_count--;
103 }
104
105 data <<= extra_shift;
106 data |= (orig_data & ~((~0UL) << extra_shift));
107
108 result = tonga_set_smc_sram_address(adev, addr, limit);
109 if (result)
110 goto out;
111
112 WREG32(mmSMC_IND_DATA_0, data);
113 }
114
115out:
116 spin_unlock_irqrestore(&adev->smc_idx_lock, flags);
117 return result;
118}
119
120static int tonga_program_jump_on_start(struct amdgpu_device *adev)
121{
122 static unsigned char data[] = {0xE0, 0x00, 0x80, 0x40};
123 tonga_copy_bytes_to_smc(adev, 0x0, data, 4, sizeof(data)+1);
124
125 return 0;
126}
127
128static bool tonga_is_smc_ram_running(struct amdgpu_device *adev)
129{
130 uint32_t val = RREG32_SMC(ixSMC_SYSCON_CLOCK_CNTL_0);
131 val = REG_GET_FIELD(val, SMC_SYSCON_CLOCK_CNTL_0, ck_disable);
132
133 return ((0 == val) && (0x20100 <= RREG32_SMC(ixSMC_PC_C)));
134}
135
136static int wait_smu_response(struct amdgpu_device *adev)
137{
138 int i;
139 uint32_t val;
140
141 for (i = 0; i < adev->usec_timeout; i++) {
142 val = RREG32(mmSMC_RESP_0);
143 if (REG_GET_FIELD(val, SMC_RESP_0, SMC_RESP))
144 break;
145 udelay(1);
146 }
147
148 if (i == adev->usec_timeout)
149 return -EINVAL;
150
151 return 0;
152}
153
154static int tonga_send_msg_to_smc_offset(struct amdgpu_device *adev)
155{
156 if (wait_smu_response(adev)) {
157 DRM_ERROR("Failed to send previous message\n");
158 return -EINVAL;
159 }
160
161 WREG32(mmSMC_MSG_ARG_0, 0x20000);
162 WREG32(mmSMC_MESSAGE_0, PPSMC_MSG_Test);
163
164 if (wait_smu_response(adev)) {
165 DRM_ERROR("Failed to send message\n");
166 return -EINVAL;
167 }
168
169 return 0;
170}
171
172static int tonga_send_msg_to_smc(struct amdgpu_device *adev, PPSMC_Msg msg)
173{
174 if (!tonga_is_smc_ram_running(adev))
175 {
176 return -EINVAL;;
177 }
178
179 if (wait_smu_response(adev)) {
180 DRM_ERROR("Failed to send previous message\n");
181 return -EINVAL;
182 }
183
184 WREG32(mmSMC_MESSAGE_0, msg);
185
186 if (wait_smu_response(adev)) {
187 DRM_ERROR("Failed to send message\n");
188 return -EINVAL;
189 }
190
191 return 0;
192}
193
194static int tonga_send_msg_to_smc_without_waiting(struct amdgpu_device *adev,
195 PPSMC_Msg msg)
196{
197 if (wait_smu_response(adev)) {
198 DRM_ERROR("Failed to send previous message\n");
199 return -EINVAL;
200 }
201
202 WREG32(mmSMC_MESSAGE_0, msg);
203
204 return 0;
205}
206
207static int tonga_send_msg_to_smc_with_parameter(struct amdgpu_device *adev,
208 PPSMC_Msg msg,
209 uint32_t parameter)
210{
211 if (!tonga_is_smc_ram_running(adev))
212 return -EINVAL;
213
214 if (wait_smu_response(adev)) {
215 DRM_ERROR("Failed to send previous message\n");
216 return -EINVAL;
217 }
218
219 WREG32(mmSMC_MSG_ARG_0, parameter);
220
221 return tonga_send_msg_to_smc(adev, msg);
222}
223
224static int tonga_send_msg_to_smc_with_parameter_without_waiting(
225 struct amdgpu_device *adev,
226 PPSMC_Msg msg, uint32_t parameter)
227{
228 if (wait_smu_response(adev)) {
229 DRM_ERROR("Failed to send previous message\n");
230 return -EINVAL;
231 }
232
233 WREG32(mmSMC_MSG_ARG_0, parameter);
234
235 return tonga_send_msg_to_smc_without_waiting(adev, msg);
236}
237
238#if 0 /* not used yet */
239static int tonga_wait_for_smc_inactive(struct amdgpu_device *adev)
240{
241 int i;
242 uint32_t val;
243
244 if (!tonga_is_smc_ram_running(adev))
245 return -EINVAL;
246
247 for (i = 0; i < adev->usec_timeout; i++) {
248 val = RREG32_SMC(ixSMC_SYSCON_CLOCK_CNTL_0);
249 if (REG_GET_FIELD(val, SMC_SYSCON_CLOCK_CNTL_0, cken) == 0)
250 break;
251 udelay(1);
252 }
253
254 if (i == adev->usec_timeout)
255 return -EINVAL;
256
257 return 0;
258}
259#endif
260
261static int tonga_smu_upload_firmware_image(struct amdgpu_device *adev)
262{
263 const struct smc_firmware_header_v1_0 *hdr;
264 uint32_t ucode_size;
265 uint32_t ucode_start_address;
266 const uint8_t *src;
267 uint32_t val;
268 uint32_t byte_count;
269 uint32_t *data;
270 unsigned long flags;
271
272 if (!adev->pm.fw)
273 return -EINVAL;
274
275 hdr = (const struct smc_firmware_header_v1_0 *)adev->pm.fw->data;
276 amdgpu_ucode_print_smc_hdr(&hdr->header);
277
278 adev->pm.fw_version = le32_to_cpu(hdr->header.ucode_version);
279 ucode_size = le32_to_cpu(hdr->header.ucode_size_bytes);
280 ucode_start_address = le32_to_cpu(hdr->ucode_start_addr);
281 src = (const uint8_t *)
282 (adev->pm.fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes));
283
284 if (ucode_size & 3) {
285 DRM_ERROR("SMC ucode is not 4 bytes aligned\n");
286 return -EINVAL;
287 }
288
289 if (ucode_size > TONGA_SMC_SIZE) {
290 DRM_ERROR("SMC address is beyond the SMC RAM area\n");
291 return -EINVAL;
292 }
293
294 spin_lock_irqsave(&adev->smc_idx_lock, flags);
295 WREG32(mmSMC_IND_INDEX_0, ucode_start_address);
296
297 val = RREG32(mmSMC_IND_ACCESS_CNTL);
298 val = REG_SET_FIELD(val, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, 1);
299 WREG32(mmSMC_IND_ACCESS_CNTL, val);
300
301 byte_count = ucode_size;
302 data = (uint32_t *)src;
303 for (; byte_count >= 4; data++, byte_count -= 4)
304 WREG32(mmSMC_IND_DATA_0, data[0]);
305
306 val = RREG32(mmSMC_IND_ACCESS_CNTL);
307 val = REG_SET_FIELD(val, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, 0);
308 WREG32(mmSMC_IND_ACCESS_CNTL, val);
309 spin_unlock_irqrestore(&adev->smc_idx_lock, flags);
310
311 return 0;
312}
313
314#if 0 /* not used yet */
315static int tonga_read_smc_sram_dword(struct amdgpu_device *adev,
316 uint32_t smc_address,
317 uint32_t *value,
318 uint32_t limit)
319{
320 int result;
321 unsigned long flags;
322
323 spin_lock_irqsave(&adev->smc_idx_lock, flags);
324 result = tonga_set_smc_sram_address(adev, smc_address, limit);
325 if (result == 0)
326 *value = RREG32(mmSMC_IND_DATA_0);
327 spin_unlock_irqrestore(&adev->smc_idx_lock, flags);
328 return result;
329}
330
331static int tonga_write_smc_sram_dword(struct amdgpu_device *adev,
332 uint32_t smc_address,
333 uint32_t value,
334 uint32_t limit)
335{
336 int result;
337 unsigned long flags;
338
339 spin_lock_irqsave(&adev->smc_idx_lock, flags);
340 result = tonga_set_smc_sram_address(adev, smc_address, limit);
341 if (result == 0)
342 WREG32(mmSMC_IND_DATA_0, value);
343 spin_unlock_irqrestore(&adev->smc_idx_lock, flags);
344 return result;
345}
346
347static int tonga_smu_stop_smc(struct amdgpu_device *adev)
348{
349 uint32_t val = RREG32_SMC(ixSMC_SYSCON_RESET_CNTL);
350 val = REG_SET_FIELD(val, SMC_SYSCON_RESET_CNTL, rst_reg, 1);
351 WREG32_SMC(ixSMC_SYSCON_RESET_CNTL, val);
352
353 val = RREG32_SMC(ixSMC_SYSCON_CLOCK_CNTL_0);
354 val = REG_SET_FIELD(val, SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 1);
355 WREG32_SMC(ixSMC_SYSCON_CLOCK_CNTL_0, val);
356
357 return 0;
358}
359#endif
360
361static enum AMDGPU_UCODE_ID tonga_convert_fw_type(uint32_t fw_type)
362{
363 switch (fw_type) {
364 case UCODE_ID_SDMA0:
365 return AMDGPU_UCODE_ID_SDMA0;
366 case UCODE_ID_SDMA1:
367 return AMDGPU_UCODE_ID_SDMA1;
368 case UCODE_ID_CP_CE:
369 return AMDGPU_UCODE_ID_CP_CE;
370 case UCODE_ID_CP_PFP:
371 return AMDGPU_UCODE_ID_CP_PFP;
372 case UCODE_ID_CP_ME:
373 return AMDGPU_UCODE_ID_CP_ME;
374 case UCODE_ID_CP_MEC:
375 case UCODE_ID_CP_MEC_JT1:
376 return AMDGPU_UCODE_ID_CP_MEC1;
377 case UCODE_ID_CP_MEC_JT2:
378 return AMDGPU_UCODE_ID_CP_MEC2;
379 case UCODE_ID_RLC_G:
380 return AMDGPU_UCODE_ID_RLC_G;
381 default:
382 DRM_ERROR("ucode type is out of range!\n");
383 return AMDGPU_UCODE_ID_MAXIMUM;
384 }
385}
386
387static int tonga_smu_populate_single_firmware_entry(struct amdgpu_device *adev,
388 uint32_t fw_type,
389 struct SMU_Entry *entry)
390{
391 enum AMDGPU_UCODE_ID id = tonga_convert_fw_type(fw_type);
392 struct amdgpu_firmware_info *ucode = &adev->firmware.ucode[id];
393 const struct gfx_firmware_header_v1_0 *header = NULL;
394 uint64_t gpu_addr;
395 uint32_t data_size;
396
397 if (ucode->fw == NULL)
398 return -EINVAL;
399
400 gpu_addr = ucode->mc_addr;
401 header = (const struct gfx_firmware_header_v1_0 *)ucode->fw->data;
402 data_size = le32_to_cpu(header->header.ucode_size_bytes);
403
404 if ((fw_type == UCODE_ID_CP_MEC_JT1) ||
405 (fw_type == UCODE_ID_CP_MEC_JT2)) {
406 gpu_addr += le32_to_cpu(header->jt_offset) << 2;
407 data_size = le32_to_cpu(header->jt_size) << 2;
408 }
409
410 entry->version = (uint16_t)le32_to_cpu(header->header.ucode_version);
411 entry->id = (uint16_t)fw_type;
412 entry->image_addr_high = upper_32_bits(gpu_addr);
413 entry->image_addr_low = lower_32_bits(gpu_addr);
414 entry->meta_data_addr_high = 0;
415 entry->meta_data_addr_low = 0;
416 entry->data_size_byte = data_size;
417 entry->num_register_entries = 0;
418
419 if (fw_type == UCODE_ID_RLC_G)
420 entry->flags = 1;
421 else
422 entry->flags = 0;
423
424 return 0;
425}
426
427static int tonga_smu_request_load_fw(struct amdgpu_device *adev)
428{
429 struct tonga_smu_private_data *private = (struct tonga_smu_private_data *)adev->smu.priv;
430 struct SMU_DRAMData_TOC *toc;
431 uint32_t fw_to_load;
432
433 WREG32_SMC(ixSOFT_REGISTERS_TABLE_28, 0);
434
435 tonga_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_SMU_DRAM_ADDR_HI, private->smu_buffer_addr_high);
436 tonga_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_SMU_DRAM_ADDR_LO, private->smu_buffer_addr_low);
437
438 toc = (struct SMU_DRAMData_TOC *)private->header;
439 toc->num_entries = 0;
440 toc->structure_version = 1;
441
442 if (!adev->firmware.smu_load)
443 return 0;
444
445 if (tonga_smu_populate_single_firmware_entry(adev, UCODE_ID_RLC_G,
446 &toc->entry[toc->num_entries++])) {
447 DRM_ERROR("Failed to get firmware entry for RLC\n");
448 return -EINVAL;
449 }
450
451 if (tonga_smu_populate_single_firmware_entry(adev, UCODE_ID_CP_CE,
452 &toc->entry[toc->num_entries++])) {
453 DRM_ERROR("Failed to get firmware entry for CE\n");
454 return -EINVAL;
455 }
456
457 if (tonga_smu_populate_single_firmware_entry(adev, UCODE_ID_CP_PFP,
458 &toc->entry[toc->num_entries++])) {
459 DRM_ERROR("Failed to get firmware entry for PFP\n");
460 return -EINVAL;
461 }
462
463 if (tonga_smu_populate_single_firmware_entry(adev, UCODE_ID_CP_ME,
464 &toc->entry[toc->num_entries++])) {
465 DRM_ERROR("Failed to get firmware entry for ME\n");
466 return -EINVAL;
467 }
468
469 if (tonga_smu_populate_single_firmware_entry(adev, UCODE_ID_CP_MEC,
470 &toc->entry[toc->num_entries++])) {
471 DRM_ERROR("Failed to get firmware entry for MEC\n");
472 return -EINVAL;
473 }
474
475 if (tonga_smu_populate_single_firmware_entry(adev, UCODE_ID_CP_MEC_JT1,
476 &toc->entry[toc->num_entries++])) {
477 DRM_ERROR("Failed to get firmware entry for MEC_JT1\n");
478 return -EINVAL;
479 }
480
481 if (tonga_smu_populate_single_firmware_entry(adev, UCODE_ID_CP_MEC_JT2,
482 &toc->entry[toc->num_entries++])) {
483 DRM_ERROR("Failed to get firmware entry for MEC_JT2\n");
484 return -EINVAL;
485 }
486
487 if (tonga_smu_populate_single_firmware_entry(adev, UCODE_ID_SDMA0,
488 &toc->entry[toc->num_entries++])) {
489 DRM_ERROR("Failed to get firmware entry for SDMA0\n");
490 return -EINVAL;
491 }
492
493 if (tonga_smu_populate_single_firmware_entry(adev, UCODE_ID_SDMA1,
494 &toc->entry[toc->num_entries++])) {
495 DRM_ERROR("Failed to get firmware entry for SDMA1\n");
496 return -EINVAL;
497 }
498
499 tonga_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_DRV_DRAM_ADDR_HI, private->header_addr_high);
500 tonga_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_DRV_DRAM_ADDR_LO, private->header_addr_low);
501
502 fw_to_load = UCODE_ID_RLC_G_MASK |
503 UCODE_ID_SDMA0_MASK |
504 UCODE_ID_SDMA1_MASK |
505 UCODE_ID_CP_CE_MASK |
506 UCODE_ID_CP_ME_MASK |
507 UCODE_ID_CP_PFP_MASK |
508 UCODE_ID_CP_MEC_MASK;
509
510 if (tonga_send_msg_to_smc_with_parameter_without_waiting(adev, PPSMC_MSG_LoadUcodes, fw_to_load)) {
511 DRM_ERROR("Fail to request SMU load ucode\n");
512 return -EINVAL;
513 }
514
515 return 0;
516}
517
518static uint32_t tonga_smu_get_mask_for_fw_type(uint32_t fw_type)
519{
520 switch (fw_type) {
521 case AMDGPU_UCODE_ID_SDMA0:
522 return UCODE_ID_SDMA0_MASK;
523 case AMDGPU_UCODE_ID_SDMA1:
524 return UCODE_ID_SDMA1_MASK;
525 case AMDGPU_UCODE_ID_CP_CE:
526 return UCODE_ID_CP_CE_MASK;
527 case AMDGPU_UCODE_ID_CP_PFP:
528 return UCODE_ID_CP_PFP_MASK;
529 case AMDGPU_UCODE_ID_CP_ME:
530 return UCODE_ID_CP_ME_MASK;
531 case AMDGPU_UCODE_ID_CP_MEC1:
532 return UCODE_ID_CP_MEC_MASK;
533 case AMDGPU_UCODE_ID_CP_MEC2:
534 return UCODE_ID_CP_MEC_MASK;
535 case AMDGPU_UCODE_ID_RLC_G:
536 return UCODE_ID_RLC_G_MASK;
537 default:
538 DRM_ERROR("ucode type is out of range!\n");
539 return 0;
540 }
541}
542
543static int tonga_smu_check_fw_load_finish(struct amdgpu_device *adev,
544 uint32_t fw_type)
545{
546 uint32_t fw_mask = tonga_smu_get_mask_for_fw_type(fw_type);
547 int i;
548
549 for (i = 0; i < adev->usec_timeout; i++) {
550 if (fw_mask == (RREG32_SMC(ixSOFT_REGISTERS_TABLE_28) & fw_mask))
551 break;
552 udelay(1);
553 }
554
555 if (i == adev->usec_timeout) {
556 DRM_ERROR("check firmware loading failed\n");
557 return -EINVAL;
558 }
559
560 return 0;
561}
562
563static int tonga_smu_start_in_protection_mode(struct amdgpu_device *adev)
564{
565 int result;
566 uint32_t val;
567 int i;
568
569 /* Assert reset */
570 val = RREG32_SMC(ixSMC_SYSCON_RESET_CNTL);
571 val = REG_SET_FIELD(val, SMC_SYSCON_RESET_CNTL, rst_reg, 1);
572 WREG32_SMC(ixSMC_SYSCON_RESET_CNTL, val);
573
574 result = tonga_smu_upload_firmware_image(adev);
575 if (result)
576 return result;
577
578 /* Clear status */
579 WREG32_SMC(ixSMU_STATUS, 0);
580
581 /* Enable clock */
582 val = RREG32_SMC(ixSMC_SYSCON_CLOCK_CNTL_0);
583 val = REG_SET_FIELD(val, SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 0);
584 WREG32_SMC(ixSMC_SYSCON_CLOCK_CNTL_0, val);
585
586 /* De-assert reset */
587 val = RREG32_SMC(ixSMC_SYSCON_RESET_CNTL);
588 val = REG_SET_FIELD(val, SMC_SYSCON_RESET_CNTL, rst_reg, 0);
589 WREG32_SMC(ixSMC_SYSCON_RESET_CNTL, val);
590
591 /* Set SMU Auto Start */
592 val = RREG32_SMC(ixSMU_INPUT_DATA);
593 val = REG_SET_FIELD(val, SMU_INPUT_DATA, AUTO_START, 1);
594 WREG32_SMC(ixSMU_INPUT_DATA, val);
595
596 /* Clear firmware interrupt enable flag */
597 WREG32_SMC(ixFIRMWARE_FLAGS, 0);
598
599 for (i = 0; i < adev->usec_timeout; i++) {
600 val = RREG32_SMC(ixRCU_UC_EVENTS);
601 if (REG_GET_FIELD(val, RCU_UC_EVENTS, INTERRUPTS_ENABLED))
602 break;
603 udelay(1);
604 }
605
606 if (i == adev->usec_timeout) {
607 DRM_ERROR("Interrupt is not enabled by firmware\n");
608 return -EINVAL;
609 }
610
611 /* Call Test SMU message with 0x20000 offset
612 * to trigger SMU start
613 */
614 tonga_send_msg_to_smc_offset(adev);
615
616 /* Wait for done bit to be set */
617 for (i = 0; i < adev->usec_timeout; i++) {
618 val = RREG32_SMC(ixSMU_STATUS);
619 if (REG_GET_FIELD(val, SMU_STATUS, SMU_DONE))
620 break;
621 udelay(1);
622 }
623
624 if (i == adev->usec_timeout) {
625 DRM_ERROR("Timeout for SMU start\n");
626 return -EINVAL;
627 }
628
629 /* Check pass/failed indicator */
630 val = RREG32_SMC(ixSMU_STATUS);
631 if (!REG_GET_FIELD(val, SMU_STATUS, SMU_PASS)) {
632 DRM_ERROR("SMU Firmware start failed\n");
633 return -EINVAL;
634 }
635
636 /* Wait for firmware to initialize */
637 for (i = 0; i < adev->usec_timeout; i++) {
638 val = RREG32_SMC(ixFIRMWARE_FLAGS);
639 if(REG_GET_FIELD(val, FIRMWARE_FLAGS, INTERRUPTS_ENABLED))
640 break;
641 udelay(1);
642 }
643
644 if (i == adev->usec_timeout) {
645 DRM_ERROR("SMU firmware initialization failed\n");
646 return -EINVAL;
647 }
648
649 return 0;
650}
651
652static int tonga_smu_start_in_non_protection_mode(struct amdgpu_device *adev)
653{
654 int i, result;
655 uint32_t val;
656
657 /* wait for smc boot up */
658 for (i = 0; i < adev->usec_timeout; i++) {
659 val = RREG32_SMC(ixRCU_UC_EVENTS);
660 val = REG_GET_FIELD(val, RCU_UC_EVENTS, boot_seq_done);
661 if (val)
662 break;
663 udelay(1);
664 }
665
666 if (i == adev->usec_timeout) {
667 DRM_ERROR("SMC boot sequence is not completed\n");
668 return -EINVAL;
669 }
670
671 /* Clear firmware interrupt enable flag */
672 WREG32_SMC(ixFIRMWARE_FLAGS, 0);
673
674 /* Assert reset */
675 val = RREG32_SMC(ixSMC_SYSCON_RESET_CNTL);
676 val = REG_SET_FIELD(val, SMC_SYSCON_RESET_CNTL, rst_reg, 1);
677 WREG32_SMC(ixSMC_SYSCON_RESET_CNTL, val);
678
679 result = tonga_smu_upload_firmware_image(adev);
680 if (result)
681 return result;
682
683 /* Set smc instruct start point at 0x0 */
684 tonga_program_jump_on_start(adev);
685
686 /* Enable clock */
687 val = RREG32_SMC(ixSMC_SYSCON_CLOCK_CNTL_0);
688 val = REG_SET_FIELD(val, SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 0);
689 WREG32_SMC(ixSMC_SYSCON_CLOCK_CNTL_0, val);
690
691 /* De-assert reset */
692 val = RREG32_SMC(ixSMC_SYSCON_RESET_CNTL);
693 val = REG_SET_FIELD(val, SMC_SYSCON_RESET_CNTL, rst_reg, 0);
694 WREG32_SMC(ixSMC_SYSCON_RESET_CNTL, val);
695
696 /* Wait for firmware to initialize */
697 for (i = 0; i < adev->usec_timeout; i++) {
698 val = RREG32_SMC(ixFIRMWARE_FLAGS);
699 if (REG_GET_FIELD(val, FIRMWARE_FLAGS, INTERRUPTS_ENABLED))
700 break;
701 udelay(1);
702 }
703
704 if (i == adev->usec_timeout) {
705 DRM_ERROR("Timeout for SMC firmware initialization\n");
706 return -EINVAL;
707 }
708
709 return 0;
710}
711
712int tonga_smu_start(struct amdgpu_device *adev)
713{
714 int result;
715 uint32_t val;
716
717 if (!tonga_is_smc_ram_running(adev)) {
718 val = RREG32_SMC(ixSMU_FIRMWARE);
719 if (!REG_GET_FIELD(val, SMU_FIRMWARE, SMU_MODE)) {
720 result = tonga_smu_start_in_non_protection_mode(adev);
721 if (result)
722 return result;
723 } else {
724 result = tonga_smu_start_in_protection_mode(adev);
725 if (result)
726 return result;
727 }
728 }
729
730 return tonga_smu_request_load_fw(adev);
731}
732
733static const struct amdgpu_smumgr_funcs tonga_smumgr_funcs = {
734 .check_fw_load_finish = tonga_smu_check_fw_load_finish,
735 .request_smu_load_fw = NULL,
736 .request_smu_specific_fw = NULL,
737};
738
739int tonga_smu_init(struct amdgpu_device *adev)
740{
741 struct tonga_smu_private_data *private;
742 uint32_t image_size = ((sizeof(struct SMU_DRAMData_TOC) / 4096) + 1) * 4096;
743 uint32_t smu_internal_buffer_size = 200*4096;
744 struct amdgpu_bo **toc_buf = &adev->smu.toc_buf;
745 struct amdgpu_bo **smu_buf = &adev->smu.smu_buf;
746 uint64_t mc_addr;
747 void *toc_buf_ptr;
748 void *smu_buf_ptr;
749 int ret;
750
751 private = kzalloc(sizeof(struct tonga_smu_private_data), GFP_KERNEL);
752 if (NULL == private)
753 return -ENOMEM;
754
755 /* allocate firmware buffers */
756 if (adev->firmware.smu_load)
757 amdgpu_ucode_init_bo(adev);
758
759 adev->smu.priv = private;
760 adev->smu.fw_flags = 0;
761
762 /* Allocate FW image data structure and header buffer */
763 ret = amdgpu_bo_create(adev, image_size, PAGE_SIZE,
764 true, AMDGPU_GEM_DOMAIN_VRAM, 0, NULL, toc_buf);
765 if (ret) {
766 DRM_ERROR("Failed to allocate memory for TOC buffer\n");
767 return -ENOMEM;
768 }
769
770 /* Allocate buffer for SMU internal buffer */
771 ret = amdgpu_bo_create(adev, smu_internal_buffer_size, PAGE_SIZE,
772 true, AMDGPU_GEM_DOMAIN_VRAM, 0, NULL, smu_buf);
773 if (ret) {
774 DRM_ERROR("Failed to allocate memory for SMU internal buffer\n");
775 return -ENOMEM;
776 }
777
778 /* Retrieve GPU address for header buffer and internal buffer */
779 ret = amdgpu_bo_reserve(adev->smu.toc_buf, false);
780 if (ret) {
781 amdgpu_bo_unref(&adev->smu.toc_buf);
782 DRM_ERROR("Failed to reserve the TOC buffer\n");
783 return -EINVAL;
784 }
785
786 ret = amdgpu_bo_pin(adev->smu.toc_buf, AMDGPU_GEM_DOMAIN_VRAM, &mc_addr);
787 if (ret) {
788 amdgpu_bo_unreserve(adev->smu.toc_buf);
789 amdgpu_bo_unref(&adev->smu.toc_buf);
790 DRM_ERROR("Failed to pin the TOC buffer\n");
791 return -EINVAL;
792 }
793
794 ret = amdgpu_bo_kmap(*toc_buf, &toc_buf_ptr);
795 if (ret) {
796 amdgpu_bo_unreserve(adev->smu.toc_buf);
797 amdgpu_bo_unref(&adev->smu.toc_buf);
798 DRM_ERROR("Failed to map the TOC buffer\n");
799 return -EINVAL;
800 }
801
802 amdgpu_bo_unreserve(adev->smu.toc_buf);
803 private->header_addr_low = lower_32_bits(mc_addr);
804 private->header_addr_high = upper_32_bits(mc_addr);
805 private->header = toc_buf_ptr;
806
807 ret = amdgpu_bo_reserve(adev->smu.smu_buf, false);
808 if (ret) {
809 amdgpu_bo_unref(&adev->smu.smu_buf);
810 amdgpu_bo_unref(&adev->smu.toc_buf);
811 DRM_ERROR("Failed to reserve the SMU internal buffer\n");
812 return -EINVAL;
813 }
814
815 ret = amdgpu_bo_pin(adev->smu.smu_buf, AMDGPU_GEM_DOMAIN_VRAM, &mc_addr);
816 if (ret) {
817 amdgpu_bo_unreserve(adev->smu.smu_buf);
818 amdgpu_bo_unref(&adev->smu.smu_buf);
819 amdgpu_bo_unref(&adev->smu.toc_buf);
820 DRM_ERROR("Failed to pin the SMU internal buffer\n");
821 return -EINVAL;
822 }
823
824 ret = amdgpu_bo_kmap(*smu_buf, &smu_buf_ptr);
825 if (ret) {
826 amdgpu_bo_unreserve(adev->smu.smu_buf);
827 amdgpu_bo_unref(&adev->smu.smu_buf);
828 amdgpu_bo_unref(&adev->smu.toc_buf);
829 DRM_ERROR("Failed to map the SMU internal buffer\n");
830 return -EINVAL;
831 }
832
833 amdgpu_bo_unreserve(adev->smu.smu_buf);
834 private->smu_buffer_addr_low = lower_32_bits(mc_addr);
835 private->smu_buffer_addr_high = upper_32_bits(mc_addr);
836
837 adev->smu.smumgr_funcs = &tonga_smumgr_funcs;
838
839 return 0;
840}
841
842int tonga_smu_fini(struct amdgpu_device *adev)
843{
844 amdgpu_bo_unref(&adev->smu.toc_buf);
845 amdgpu_bo_unref(&adev->smu.smu_buf);
846 kfree(adev->smu.priv);
847 adev->smu.priv = NULL;
848 if (adev->firmware.fw_buf)
849 amdgpu_ucode_fini_bo(adev);
850
851 return 0;
852}