188dfc9a3SLikun Gao /*
288dfc9a3SLikun Gao * Copyright 2014 Advanced Micro Devices, Inc.
388dfc9a3SLikun Gao * Copyright 2008 Red Hat Inc.
488dfc9a3SLikun Gao * Copyright 2009 Jerome Glisse.
588dfc9a3SLikun Gao *
688dfc9a3SLikun Gao * Permission is hereby granted, free of charge, to any person obtaining a
788dfc9a3SLikun Gao * copy of this software and associated documentation files (the "Software"),
888dfc9a3SLikun Gao * to deal in the Software without restriction, including without limitation
988dfc9a3SLikun Gao * the rights to use, copy, modify, merge, publish, distribute, sublicense,
1088dfc9a3SLikun Gao * and/or sell copies of the Software, and to permit persons to whom the
1188dfc9a3SLikun Gao * Software is furnished to do so, subject to the following conditions:
1288dfc9a3SLikun Gao *
1388dfc9a3SLikun Gao * The above copyright notice and this permission notice shall be included in
1488dfc9a3SLikun Gao * all copies or substantial portions of the Software.
1588dfc9a3SLikun Gao *
1688dfc9a3SLikun Gao * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1788dfc9a3SLikun Gao * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1888dfc9a3SLikun Gao * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
1988dfc9a3SLikun Gao * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
2088dfc9a3SLikun Gao * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
2188dfc9a3SLikun Gao * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
2288dfc9a3SLikun Gao * OTHER DEALINGS IN THE SOFTWARE.
2388dfc9a3SLikun Gao *
2488dfc9a3SLikun Gao */
25106c7d61SLikun Gao #include <linux/firmware.h>
2688dfc9a3SLikun Gao #include "amdgpu.h"
2788dfc9a3SLikun Gao #include "amdgpu_gfx.h"
2888dfc9a3SLikun Gao #include "amdgpu_rlc.h"
2988dfc9a3SLikun Gao
3088dfc9a3SLikun Gao /**
31106c7d61SLikun Gao * amdgpu_gfx_rlc_enter_safe_mode - Set RLC into safe mode
32106c7d61SLikun Gao *
33106c7d61SLikun Gao * @adev: amdgpu_device pointer
34*ca2943feSSrinivasan Shanmugam * @xcc_id: xcc accelerated compute core id
35106c7d61SLikun Gao *
36106c7d61SLikun Gao * Set RLC enter into safe mode if RLC is enabled and haven't in safe mode.
37106c7d61SLikun Gao */
amdgpu_gfx_rlc_enter_safe_mode(struct amdgpu_device * adev,int xcc_id)3886b20703SLe Ma void amdgpu_gfx_rlc_enter_safe_mode(struct amdgpu_device *adev, int xcc_id)
39106c7d61SLikun Gao {
4086b20703SLe Ma if (adev->gfx.rlc.in_safe_mode[xcc_id])
41106c7d61SLikun Gao return;
42106c7d61SLikun Gao
43106c7d61SLikun Gao /* if RLC is not enabled, do nothing */
44106c7d61SLikun Gao if (!adev->gfx.rlc.funcs->is_rlc_enabled(adev))
45106c7d61SLikun Gao return;
46106c7d61SLikun Gao
47106c7d61SLikun Gao if (adev->cg_flags &
48106c7d61SLikun Gao (AMD_CG_SUPPORT_GFX_CGCG | AMD_CG_SUPPORT_GFX_MGCG |
49106c7d61SLikun Gao AMD_CG_SUPPORT_GFX_3D_CGCG)) {
5086b20703SLe Ma adev->gfx.rlc.funcs->set_safe_mode(adev, xcc_id);
5186b20703SLe Ma adev->gfx.rlc.in_safe_mode[xcc_id] = true;
52106c7d61SLikun Gao }
53106c7d61SLikun Gao }
54106c7d61SLikun Gao
55106c7d61SLikun Gao /**
56106c7d61SLikun Gao * amdgpu_gfx_rlc_exit_safe_mode - Set RLC out of safe mode
57106c7d61SLikun Gao *
58106c7d61SLikun Gao * @adev: amdgpu_device pointer
59*ca2943feSSrinivasan Shanmugam * @xcc_id: xcc accelerated compute core id
60106c7d61SLikun Gao *
61106c7d61SLikun Gao * Set RLC exit safe mode if RLC is enabled and have entered into safe mode.
62106c7d61SLikun Gao */
amdgpu_gfx_rlc_exit_safe_mode(struct amdgpu_device * adev,int xcc_id)6386b20703SLe Ma void amdgpu_gfx_rlc_exit_safe_mode(struct amdgpu_device *adev, int xcc_id)
64106c7d61SLikun Gao {
6586b20703SLe Ma if (!(adev->gfx.rlc.in_safe_mode[xcc_id]))
66106c7d61SLikun Gao return;
67106c7d61SLikun Gao
68106c7d61SLikun Gao /* if RLC is not enabled, do nothing */
69106c7d61SLikun Gao if (!adev->gfx.rlc.funcs->is_rlc_enabled(adev))
70106c7d61SLikun Gao return;
71106c7d61SLikun Gao
72106c7d61SLikun Gao if (adev->cg_flags &
73106c7d61SLikun Gao (AMD_CG_SUPPORT_GFX_CGCG | AMD_CG_SUPPORT_GFX_MGCG |
74106c7d61SLikun Gao AMD_CG_SUPPORT_GFX_3D_CGCG)) {
7586b20703SLe Ma adev->gfx.rlc.funcs->unset_safe_mode(adev, xcc_id);
7686b20703SLe Ma adev->gfx.rlc.in_safe_mode[xcc_id] = false;
77106c7d61SLikun Gao }
78106c7d61SLikun Gao }
79106c7d61SLikun Gao
80106c7d61SLikun Gao /**
81106c7d61SLikun Gao * amdgpu_gfx_rlc_init_sr - Init save restore block
82106c7d61SLikun Gao *
83106c7d61SLikun Gao * @adev: amdgpu_device pointer
84106c7d61SLikun Gao * @dws: the size of save restore block
85106c7d61SLikun Gao *
86106c7d61SLikun Gao * Allocate and setup value to save restore block of rlc.
87106c7d61SLikun Gao * Returns 0 on succeess or negative error code if allocate failed.
88106c7d61SLikun Gao */
amdgpu_gfx_rlc_init_sr(struct amdgpu_device * adev,u32 dws)89106c7d61SLikun Gao int amdgpu_gfx_rlc_init_sr(struct amdgpu_device *adev, u32 dws)
90106c7d61SLikun Gao {
91106c7d61SLikun Gao const u32 *src_ptr;
92106c7d61SLikun Gao volatile u32 *dst_ptr;
93106c7d61SLikun Gao u32 i;
94106c7d61SLikun Gao int r;
95106c7d61SLikun Gao
96106c7d61SLikun Gao /* allocate save restore block */
97106c7d61SLikun Gao r = amdgpu_bo_create_reserved(adev, dws * 4, PAGE_SIZE,
9858ab2c08SChristian König AMDGPU_GEM_DOMAIN_VRAM |
9958ab2c08SChristian König AMDGPU_GEM_DOMAIN_GTT,
100106c7d61SLikun Gao &adev->gfx.rlc.save_restore_obj,
101106c7d61SLikun Gao &adev->gfx.rlc.save_restore_gpu_addr,
102106c7d61SLikun Gao (void **)&adev->gfx.rlc.sr_ptr);
103106c7d61SLikun Gao if (r) {
104106c7d61SLikun Gao dev_warn(adev->dev, "(%d) create RLC sr bo failed\n", r);
105106c7d61SLikun Gao amdgpu_gfx_rlc_fini(adev);
106106c7d61SLikun Gao return r;
107106c7d61SLikun Gao }
108106c7d61SLikun Gao
109106c7d61SLikun Gao /* write the sr buffer */
110106c7d61SLikun Gao src_ptr = adev->gfx.rlc.reg_list;
111106c7d61SLikun Gao dst_ptr = adev->gfx.rlc.sr_ptr;
112106c7d61SLikun Gao for (i = 0; i < adev->gfx.rlc.reg_list_size; i++)
113106c7d61SLikun Gao dst_ptr[i] = cpu_to_le32(src_ptr[i]);
114106c7d61SLikun Gao amdgpu_bo_kunmap(adev->gfx.rlc.save_restore_obj);
115106c7d61SLikun Gao amdgpu_bo_unreserve(adev->gfx.rlc.save_restore_obj);
116106c7d61SLikun Gao
117106c7d61SLikun Gao return 0;
118106c7d61SLikun Gao }
119106c7d61SLikun Gao
120106c7d61SLikun Gao /**
121106c7d61SLikun Gao * amdgpu_gfx_rlc_init_csb - Init clear state block
122106c7d61SLikun Gao *
123106c7d61SLikun Gao * @adev: amdgpu_device pointer
124106c7d61SLikun Gao *
125106c7d61SLikun Gao * Allocate and setup value to clear state block of rlc.
126106c7d61SLikun Gao * Returns 0 on succeess or negative error code if allocate failed.
127106c7d61SLikun Gao */
amdgpu_gfx_rlc_init_csb(struct amdgpu_device * adev)128106c7d61SLikun Gao int amdgpu_gfx_rlc_init_csb(struct amdgpu_device *adev)
129106c7d61SLikun Gao {
130106c7d61SLikun Gao u32 dws;
131106c7d61SLikun Gao int r;
132106c7d61SLikun Gao
133106c7d61SLikun Gao /* allocate clear state block */
134106c7d61SLikun Gao adev->gfx.rlc.clear_state_size = dws = adev->gfx.rlc.funcs->get_csb_size(adev);
135747d4f71SMonk Liu r = amdgpu_bo_create_kernel(adev, dws * 4, PAGE_SIZE,
13658ab2c08SChristian König AMDGPU_GEM_DOMAIN_VRAM |
13758ab2c08SChristian König AMDGPU_GEM_DOMAIN_GTT,
138106c7d61SLikun Gao &adev->gfx.rlc.clear_state_obj,
139106c7d61SLikun Gao &adev->gfx.rlc.clear_state_gpu_addr,
140106c7d61SLikun Gao (void **)&adev->gfx.rlc.cs_ptr);
141106c7d61SLikun Gao if (r) {
142106c7d61SLikun Gao dev_err(adev->dev, "(%d) failed to create rlc csb bo\n", r);
143106c7d61SLikun Gao amdgpu_gfx_rlc_fini(adev);
144106c7d61SLikun Gao return r;
145106c7d61SLikun Gao }
146106c7d61SLikun Gao
147106c7d61SLikun Gao return 0;
148106c7d61SLikun Gao }
149106c7d61SLikun Gao
150106c7d61SLikun Gao /**
151106c7d61SLikun Gao * amdgpu_gfx_rlc_init_cpt - Init cp table
152106c7d61SLikun Gao *
153106c7d61SLikun Gao * @adev: amdgpu_device pointer
154106c7d61SLikun Gao *
155106c7d61SLikun Gao * Allocate and setup value to cp table of rlc.
156106c7d61SLikun Gao * Returns 0 on succeess or negative error code if allocate failed.
157106c7d61SLikun Gao */
amdgpu_gfx_rlc_init_cpt(struct amdgpu_device * adev)158106c7d61SLikun Gao int amdgpu_gfx_rlc_init_cpt(struct amdgpu_device *adev)
159106c7d61SLikun Gao {
160106c7d61SLikun Gao int r;
161106c7d61SLikun Gao
162106c7d61SLikun Gao r = amdgpu_bo_create_reserved(adev, adev->gfx.rlc.cp_table_size,
16358ab2c08SChristian König PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM |
16458ab2c08SChristian König AMDGPU_GEM_DOMAIN_GTT,
165106c7d61SLikun Gao &adev->gfx.rlc.cp_table_obj,
166106c7d61SLikun Gao &adev->gfx.rlc.cp_table_gpu_addr,
167106c7d61SLikun Gao (void **)&adev->gfx.rlc.cp_table_ptr);
168106c7d61SLikun Gao if (r) {
169106c7d61SLikun Gao dev_err(adev->dev, "(%d) failed to create cp table bo\n", r);
170106c7d61SLikun Gao amdgpu_gfx_rlc_fini(adev);
171106c7d61SLikun Gao return r;
172106c7d61SLikun Gao }
173106c7d61SLikun Gao
174106c7d61SLikun Gao /* set up the cp table */
175106c7d61SLikun Gao amdgpu_gfx_rlc_setup_cp_table(adev);
176106c7d61SLikun Gao amdgpu_bo_kunmap(adev->gfx.rlc.cp_table_obj);
177106c7d61SLikun Gao amdgpu_bo_unreserve(adev->gfx.rlc.cp_table_obj);
178106c7d61SLikun Gao
179106c7d61SLikun Gao return 0;
180106c7d61SLikun Gao }
181106c7d61SLikun Gao
182106c7d61SLikun Gao /**
183106c7d61SLikun Gao * amdgpu_gfx_rlc_setup_cp_table - setup cp the buffer of cp table
184106c7d61SLikun Gao *
185106c7d61SLikun Gao * @adev: amdgpu_device pointer
186106c7d61SLikun Gao *
187106c7d61SLikun Gao * Write cp firmware data into cp table.
188106c7d61SLikun Gao */
amdgpu_gfx_rlc_setup_cp_table(struct amdgpu_device * adev)189106c7d61SLikun Gao void amdgpu_gfx_rlc_setup_cp_table(struct amdgpu_device *adev)
190106c7d61SLikun Gao {
191106c7d61SLikun Gao const __le32 *fw_data;
192106c7d61SLikun Gao volatile u32 *dst_ptr;
193106c7d61SLikun Gao int me, i, max_me;
194106c7d61SLikun Gao u32 bo_offset = 0;
195106c7d61SLikun Gao u32 table_offset, table_size;
196106c7d61SLikun Gao
197106c7d61SLikun Gao max_me = adev->gfx.rlc.funcs->get_cp_table_num(adev);
198106c7d61SLikun Gao
199106c7d61SLikun Gao /* write the cp table buffer */
200106c7d61SLikun Gao dst_ptr = adev->gfx.rlc.cp_table_ptr;
201106c7d61SLikun Gao for (me = 0; me < max_me; me++) {
202106c7d61SLikun Gao if (me == 0) {
203106c7d61SLikun Gao const struct gfx_firmware_header_v1_0 *hdr =
204106c7d61SLikun Gao (const struct gfx_firmware_header_v1_0 *)adev->gfx.ce_fw->data;
205106c7d61SLikun Gao fw_data = (const __le32 *)
206106c7d61SLikun Gao (adev->gfx.ce_fw->data +
207106c7d61SLikun Gao le32_to_cpu(hdr->header.ucode_array_offset_bytes));
208106c7d61SLikun Gao table_offset = le32_to_cpu(hdr->jt_offset);
209106c7d61SLikun Gao table_size = le32_to_cpu(hdr->jt_size);
210106c7d61SLikun Gao } else if (me == 1) {
211106c7d61SLikun Gao const struct gfx_firmware_header_v1_0 *hdr =
212106c7d61SLikun Gao (const struct gfx_firmware_header_v1_0 *)adev->gfx.pfp_fw->data;
213106c7d61SLikun Gao fw_data = (const __le32 *)
214106c7d61SLikun Gao (adev->gfx.pfp_fw->data +
215106c7d61SLikun Gao le32_to_cpu(hdr->header.ucode_array_offset_bytes));
216106c7d61SLikun Gao table_offset = le32_to_cpu(hdr->jt_offset);
217106c7d61SLikun Gao table_size = le32_to_cpu(hdr->jt_size);
218106c7d61SLikun Gao } else if (me == 2) {
219106c7d61SLikun Gao const struct gfx_firmware_header_v1_0 *hdr =
220106c7d61SLikun Gao (const struct gfx_firmware_header_v1_0 *)adev->gfx.me_fw->data;
221106c7d61SLikun Gao fw_data = (const __le32 *)
222106c7d61SLikun Gao (adev->gfx.me_fw->data +
223106c7d61SLikun Gao le32_to_cpu(hdr->header.ucode_array_offset_bytes));
224106c7d61SLikun Gao table_offset = le32_to_cpu(hdr->jt_offset);
225106c7d61SLikun Gao table_size = le32_to_cpu(hdr->jt_size);
226106c7d61SLikun Gao } else if (me == 3) {
227106c7d61SLikun Gao const struct gfx_firmware_header_v1_0 *hdr =
228106c7d61SLikun Gao (const struct gfx_firmware_header_v1_0 *)adev->gfx.mec_fw->data;
229106c7d61SLikun Gao fw_data = (const __le32 *)
230106c7d61SLikun Gao (adev->gfx.mec_fw->data +
231106c7d61SLikun Gao le32_to_cpu(hdr->header.ucode_array_offset_bytes));
232106c7d61SLikun Gao table_offset = le32_to_cpu(hdr->jt_offset);
233106c7d61SLikun Gao table_size = le32_to_cpu(hdr->jt_size);
234106c7d61SLikun Gao } else if (me == 4) {
235106c7d61SLikun Gao const struct gfx_firmware_header_v1_0 *hdr =
236106c7d61SLikun Gao (const struct gfx_firmware_header_v1_0 *)adev->gfx.mec2_fw->data;
237106c7d61SLikun Gao fw_data = (const __le32 *)
238106c7d61SLikun Gao (adev->gfx.mec2_fw->data +
239106c7d61SLikun Gao le32_to_cpu(hdr->header.ucode_array_offset_bytes));
240106c7d61SLikun Gao table_offset = le32_to_cpu(hdr->jt_offset);
241106c7d61SLikun Gao table_size = le32_to_cpu(hdr->jt_size);
242106c7d61SLikun Gao }
243106c7d61SLikun Gao
244106c7d61SLikun Gao for (i = 0; i < table_size; i ++) {
245106c7d61SLikun Gao dst_ptr[bo_offset + i] =
246106c7d61SLikun Gao cpu_to_le32(le32_to_cpu(fw_data[table_offset + i]));
247106c7d61SLikun Gao }
248106c7d61SLikun Gao
249106c7d61SLikun Gao bo_offset += table_size;
250106c7d61SLikun Gao }
251106c7d61SLikun Gao }
252106c7d61SLikun Gao
253106c7d61SLikun Gao /**
25488dfc9a3SLikun Gao * amdgpu_gfx_rlc_fini - Free BO which used for RLC
25588dfc9a3SLikun Gao *
25688dfc9a3SLikun Gao * @adev: amdgpu_device pointer
25788dfc9a3SLikun Gao *
25888dfc9a3SLikun Gao * Free three BO which is used for rlc_save_restore_block, rlc_clear_state_block
25988dfc9a3SLikun Gao * and rlc_jump_table_block.
26088dfc9a3SLikun Gao */
amdgpu_gfx_rlc_fini(struct amdgpu_device * adev)26188dfc9a3SLikun Gao void amdgpu_gfx_rlc_fini(struct amdgpu_device *adev)
26288dfc9a3SLikun Gao {
26388dfc9a3SLikun Gao /* save restore block */
26488dfc9a3SLikun Gao if (adev->gfx.rlc.save_restore_obj) {
26588dfc9a3SLikun Gao amdgpu_bo_free_kernel(&adev->gfx.rlc.save_restore_obj,
26688dfc9a3SLikun Gao &adev->gfx.rlc.save_restore_gpu_addr,
26788dfc9a3SLikun Gao (void **)&adev->gfx.rlc.sr_ptr);
26888dfc9a3SLikun Gao }
26988dfc9a3SLikun Gao
27088dfc9a3SLikun Gao /* clear state block */
27188dfc9a3SLikun Gao amdgpu_bo_free_kernel(&adev->gfx.rlc.clear_state_obj,
27288dfc9a3SLikun Gao &adev->gfx.rlc.clear_state_gpu_addr,
27388dfc9a3SLikun Gao (void **)&adev->gfx.rlc.cs_ptr);
27488dfc9a3SLikun Gao
27588dfc9a3SLikun Gao /* jump table block */
27688dfc9a3SLikun Gao amdgpu_bo_free_kernel(&adev->gfx.rlc.cp_table_obj,
27788dfc9a3SLikun Gao &adev->gfx.rlc.cp_table_gpu_addr,
27888dfc9a3SLikun Gao (void **)&adev->gfx.rlc.cp_table_ptr);
27988dfc9a3SLikun Gao }
2800641dbefSHawking Zhang
amdgpu_gfx_rlc_init_microcode_v2_0(struct amdgpu_device * adev)2810641dbefSHawking Zhang static int amdgpu_gfx_rlc_init_microcode_v2_0(struct amdgpu_device *adev)
2820641dbefSHawking Zhang {
2830641dbefSHawking Zhang const struct common_firmware_header *common_hdr;
2840641dbefSHawking Zhang const struct rlc_firmware_header_v2_0 *rlc_hdr;
2850641dbefSHawking Zhang struct amdgpu_firmware_info *info;
2860641dbefSHawking Zhang unsigned int *tmp;
2870641dbefSHawking Zhang unsigned int i;
2880641dbefSHawking Zhang
2890641dbefSHawking Zhang rlc_hdr = (const struct rlc_firmware_header_v2_0 *)adev->gfx.rlc_fw->data;
2900641dbefSHawking Zhang
2910641dbefSHawking Zhang adev->gfx.rlc_fw_version = le32_to_cpu(rlc_hdr->header.ucode_version);
2920641dbefSHawking Zhang adev->gfx.rlc_feature_version = le32_to_cpu(rlc_hdr->ucode_feature_version);
2930641dbefSHawking Zhang adev->gfx.rlc.save_and_restore_offset =
2940641dbefSHawking Zhang le32_to_cpu(rlc_hdr->save_and_restore_offset);
2950641dbefSHawking Zhang adev->gfx.rlc.clear_state_descriptor_offset =
2960641dbefSHawking Zhang le32_to_cpu(rlc_hdr->clear_state_descriptor_offset);
2970641dbefSHawking Zhang adev->gfx.rlc.avail_scratch_ram_locations =
2980641dbefSHawking Zhang le32_to_cpu(rlc_hdr->avail_scratch_ram_locations);
2990641dbefSHawking Zhang adev->gfx.rlc.reg_restore_list_size =
3000641dbefSHawking Zhang le32_to_cpu(rlc_hdr->reg_restore_list_size);
3010641dbefSHawking Zhang adev->gfx.rlc.reg_list_format_start =
3020641dbefSHawking Zhang le32_to_cpu(rlc_hdr->reg_list_format_start);
3030641dbefSHawking Zhang adev->gfx.rlc.reg_list_format_separate_start =
3040641dbefSHawking Zhang le32_to_cpu(rlc_hdr->reg_list_format_separate_start);
3050641dbefSHawking Zhang adev->gfx.rlc.starting_offsets_start =
3060641dbefSHawking Zhang le32_to_cpu(rlc_hdr->starting_offsets_start);
3070641dbefSHawking Zhang adev->gfx.rlc.reg_list_format_size_bytes =
3080641dbefSHawking Zhang le32_to_cpu(rlc_hdr->reg_list_format_size_bytes);
3090641dbefSHawking Zhang adev->gfx.rlc.reg_list_size_bytes =
3100641dbefSHawking Zhang le32_to_cpu(rlc_hdr->reg_list_size_bytes);
3110641dbefSHawking Zhang adev->gfx.rlc.register_list_format =
3120641dbefSHawking Zhang kmalloc(adev->gfx.rlc.reg_list_format_size_bytes +
3130641dbefSHawking Zhang adev->gfx.rlc.reg_list_size_bytes, GFP_KERNEL);
3140641dbefSHawking Zhang if (!adev->gfx.rlc.register_list_format) {
3150641dbefSHawking Zhang dev_err(adev->dev, "failed to allocate memory for rlc register_list_format\n");
3160641dbefSHawking Zhang return -ENOMEM;
3170641dbefSHawking Zhang }
3180641dbefSHawking Zhang
3190641dbefSHawking Zhang tmp = (unsigned int *)((uintptr_t)rlc_hdr +
3200641dbefSHawking Zhang le32_to_cpu(rlc_hdr->reg_list_format_array_offset_bytes));
3210641dbefSHawking Zhang for (i = 0 ; i < (rlc_hdr->reg_list_format_size_bytes >> 2); i++)
3220641dbefSHawking Zhang adev->gfx.rlc.register_list_format[i] = le32_to_cpu(tmp[i]);
3230641dbefSHawking Zhang
3240641dbefSHawking Zhang adev->gfx.rlc.register_restore = adev->gfx.rlc.register_list_format + i;
3250641dbefSHawking Zhang
3260641dbefSHawking Zhang tmp = (unsigned int *)((uintptr_t)rlc_hdr +
3270641dbefSHawking Zhang le32_to_cpu(rlc_hdr->reg_list_array_offset_bytes));
3280641dbefSHawking Zhang for (i = 0 ; i < (rlc_hdr->reg_list_size_bytes >> 2); i++)
3290641dbefSHawking Zhang adev->gfx.rlc.register_restore[i] = le32_to_cpu(tmp[i]);
3300641dbefSHawking Zhang
3310641dbefSHawking Zhang if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
3320641dbefSHawking Zhang info = &adev->firmware.ucode[AMDGPU_UCODE_ID_RLC_G];
3330641dbefSHawking Zhang info->ucode_id = AMDGPU_UCODE_ID_RLC_G;
3340641dbefSHawking Zhang info->fw = adev->gfx.rlc_fw;
3350641dbefSHawking Zhang if (info->fw) {
3360641dbefSHawking Zhang common_hdr = (const struct common_firmware_header *)info->fw->data;
3370641dbefSHawking Zhang adev->firmware.fw_size +=
3380641dbefSHawking Zhang ALIGN(le32_to_cpu(common_hdr->ucode_size_bytes), PAGE_SIZE);
3390641dbefSHawking Zhang }
3400641dbefSHawking Zhang }
3410641dbefSHawking Zhang
3420641dbefSHawking Zhang return 0;
3430641dbefSHawking Zhang }
344f3e6173bSHawking Zhang
amdgpu_gfx_rlc_init_microcode_v2_1(struct amdgpu_device * adev)345f3e6173bSHawking Zhang static void amdgpu_gfx_rlc_init_microcode_v2_1(struct amdgpu_device *adev)
346f3e6173bSHawking Zhang {
347f3e6173bSHawking Zhang const struct rlc_firmware_header_v2_1 *rlc_hdr;
348f3e6173bSHawking Zhang struct amdgpu_firmware_info *info;
349f3e6173bSHawking Zhang
350f3e6173bSHawking Zhang rlc_hdr = (const struct rlc_firmware_header_v2_1 *)adev->gfx.rlc_fw->data;
351f3e6173bSHawking Zhang adev->gfx.rlc_srlc_fw_version = le32_to_cpu(rlc_hdr->save_restore_list_cntl_ucode_ver);
352f3e6173bSHawking Zhang adev->gfx.rlc_srlc_feature_version = le32_to_cpu(rlc_hdr->save_restore_list_cntl_feature_ver);
353f3e6173bSHawking Zhang adev->gfx.rlc.save_restore_list_cntl_size_bytes = le32_to_cpu(rlc_hdr->save_restore_list_cntl_size_bytes);
354f3e6173bSHawking Zhang adev->gfx.rlc.save_restore_list_cntl = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->save_restore_list_cntl_offset_bytes);
355f3e6173bSHawking Zhang adev->gfx.rlc_srlg_fw_version = le32_to_cpu(rlc_hdr->save_restore_list_gpm_ucode_ver);
356f3e6173bSHawking Zhang adev->gfx.rlc_srlg_feature_version = le32_to_cpu(rlc_hdr->save_restore_list_gpm_feature_ver);
357f3e6173bSHawking Zhang adev->gfx.rlc.save_restore_list_gpm_size_bytes = le32_to_cpu(rlc_hdr->save_restore_list_gpm_size_bytes);
358f3e6173bSHawking Zhang adev->gfx.rlc.save_restore_list_gpm = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->save_restore_list_gpm_offset_bytes);
359f3e6173bSHawking Zhang adev->gfx.rlc_srls_fw_version = le32_to_cpu(rlc_hdr->save_restore_list_srm_ucode_ver);
360f3e6173bSHawking Zhang adev->gfx.rlc_srls_feature_version = le32_to_cpu(rlc_hdr->save_restore_list_srm_feature_ver);
361f3e6173bSHawking Zhang adev->gfx.rlc.save_restore_list_srm_size_bytes = le32_to_cpu(rlc_hdr->save_restore_list_srm_size_bytes);
362f3e6173bSHawking Zhang adev->gfx.rlc.save_restore_list_srm = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->save_restore_list_srm_offset_bytes);
363f3e6173bSHawking Zhang adev->gfx.rlc.reg_list_format_direct_reg_list_length =
364f3e6173bSHawking Zhang le32_to_cpu(rlc_hdr->reg_list_format_direct_reg_list_length);
365f3e6173bSHawking Zhang
366f3e6173bSHawking Zhang if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
367940d4dd4SHawking Zhang if (adev->gfx.rlc.save_restore_list_cntl_size_bytes) {
368940d4dd4SHawking Zhang info = &adev->firmware.ucode[AMDGPU_UCODE_ID_RLC_RESTORE_LIST_CNTL];
369940d4dd4SHawking Zhang info->ucode_id = AMDGPU_UCODE_ID_RLC_RESTORE_LIST_CNTL;
370940d4dd4SHawking Zhang info->fw = adev->gfx.rlc_fw;
371940d4dd4SHawking Zhang adev->firmware.fw_size +=
372940d4dd4SHawking Zhang ALIGN(adev->gfx.rlc.save_restore_list_cntl_size_bytes, PAGE_SIZE);
373940d4dd4SHawking Zhang }
374940d4dd4SHawking Zhang
375f3e6173bSHawking Zhang if (adev->gfx.rlc.save_restore_list_gpm_size_bytes) {
376f3e6173bSHawking Zhang info = &adev->firmware.ucode[AMDGPU_UCODE_ID_RLC_RESTORE_LIST_GPM_MEM];
377f3e6173bSHawking Zhang info->ucode_id = AMDGPU_UCODE_ID_RLC_RESTORE_LIST_GPM_MEM;
378f3e6173bSHawking Zhang info->fw = adev->gfx.rlc_fw;
379f3e6173bSHawking Zhang adev->firmware.fw_size +=
380f3e6173bSHawking Zhang ALIGN(adev->gfx.rlc.save_restore_list_gpm_size_bytes, PAGE_SIZE);
381f3e6173bSHawking Zhang }
382f3e6173bSHawking Zhang
383f3e6173bSHawking Zhang if (adev->gfx.rlc.save_restore_list_srm_size_bytes) {
384f3e6173bSHawking Zhang info = &adev->firmware.ucode[AMDGPU_UCODE_ID_RLC_RESTORE_LIST_SRM_MEM];
385f3e6173bSHawking Zhang info->ucode_id = AMDGPU_UCODE_ID_RLC_RESTORE_LIST_SRM_MEM;
386f3e6173bSHawking Zhang info->fw = adev->gfx.rlc_fw;
387f3e6173bSHawking Zhang adev->firmware.fw_size +=
388f3e6173bSHawking Zhang ALIGN(adev->gfx.rlc.save_restore_list_srm_size_bytes, PAGE_SIZE);
389f3e6173bSHawking Zhang }
390f3e6173bSHawking Zhang }
391f3e6173bSHawking Zhang }
392a97d0ec8SHawking Zhang
amdgpu_gfx_rlc_init_microcode_v2_2(struct amdgpu_device * adev)393a97d0ec8SHawking Zhang static void amdgpu_gfx_rlc_init_microcode_v2_2(struct amdgpu_device *adev)
394a97d0ec8SHawking Zhang {
395a97d0ec8SHawking Zhang const struct rlc_firmware_header_v2_2 *rlc_hdr;
396a97d0ec8SHawking Zhang struct amdgpu_firmware_info *info;
397a97d0ec8SHawking Zhang
398a97d0ec8SHawking Zhang rlc_hdr = (const struct rlc_firmware_header_v2_2 *)adev->gfx.rlc_fw->data;
399a97d0ec8SHawking Zhang adev->gfx.rlc.rlc_iram_ucode_size_bytes = le32_to_cpu(rlc_hdr->rlc_iram_ucode_size_bytes);
400a97d0ec8SHawking Zhang adev->gfx.rlc.rlc_iram_ucode = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->rlc_iram_ucode_offset_bytes);
401a97d0ec8SHawking Zhang adev->gfx.rlc.rlc_dram_ucode_size_bytes = le32_to_cpu(rlc_hdr->rlc_dram_ucode_size_bytes);
402a97d0ec8SHawking Zhang adev->gfx.rlc.rlc_dram_ucode = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->rlc_dram_ucode_offset_bytes);
403a97d0ec8SHawking Zhang
404a97d0ec8SHawking Zhang if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
405a97d0ec8SHawking Zhang if (adev->gfx.rlc.rlc_iram_ucode_size_bytes) {
406a97d0ec8SHawking Zhang info = &adev->firmware.ucode[AMDGPU_UCODE_ID_RLC_IRAM];
407a97d0ec8SHawking Zhang info->ucode_id = AMDGPU_UCODE_ID_RLC_IRAM;
408a97d0ec8SHawking Zhang info->fw = adev->gfx.rlc_fw;
409a97d0ec8SHawking Zhang adev->firmware.fw_size +=
410a97d0ec8SHawking Zhang ALIGN(adev->gfx.rlc.rlc_iram_ucode_size_bytes, PAGE_SIZE);
411a97d0ec8SHawking Zhang }
412a97d0ec8SHawking Zhang
413a97d0ec8SHawking Zhang if (adev->gfx.rlc.rlc_dram_ucode_size_bytes) {
414a97d0ec8SHawking Zhang info = &adev->firmware.ucode[AMDGPU_UCODE_ID_RLC_DRAM];
415a97d0ec8SHawking Zhang info->ucode_id = AMDGPU_UCODE_ID_RLC_DRAM;
416a97d0ec8SHawking Zhang info->fw = adev->gfx.rlc_fw;
417a97d0ec8SHawking Zhang adev->firmware.fw_size +=
418a97d0ec8SHawking Zhang ALIGN(adev->gfx.rlc.rlc_dram_ucode_size_bytes, PAGE_SIZE);
419a97d0ec8SHawking Zhang }
420a97d0ec8SHawking Zhang }
421a97d0ec8SHawking Zhang }
422a0d9084dSHawking Zhang
amdgpu_gfx_rlc_init_microcode_v2_3(struct amdgpu_device * adev)423a0d9084dSHawking Zhang static void amdgpu_gfx_rlc_init_microcode_v2_3(struct amdgpu_device *adev)
424a0d9084dSHawking Zhang {
425a0d9084dSHawking Zhang const struct rlc_firmware_header_v2_3 *rlc_hdr;
426a0d9084dSHawking Zhang struct amdgpu_firmware_info *info;
427a0d9084dSHawking Zhang
428a0d9084dSHawking Zhang rlc_hdr = (const struct rlc_firmware_header_v2_3 *)adev->gfx.rlc_fw->data;
429a0d9084dSHawking Zhang adev->gfx.rlcp_ucode_version = le32_to_cpu(rlc_hdr->rlcp_ucode_version);
430a0d9084dSHawking Zhang adev->gfx.rlcp_ucode_feature_version = le32_to_cpu(rlc_hdr->rlcp_ucode_feature_version);
431a0d9084dSHawking Zhang adev->gfx.rlc.rlcp_ucode_size_bytes = le32_to_cpu(rlc_hdr->rlcp_ucode_size_bytes);
432a0d9084dSHawking Zhang adev->gfx.rlc.rlcp_ucode = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->rlcp_ucode_offset_bytes);
433a0d9084dSHawking Zhang
434a0d9084dSHawking Zhang adev->gfx.rlcv_ucode_version = le32_to_cpu(rlc_hdr->rlcv_ucode_version);
435a0d9084dSHawking Zhang adev->gfx.rlcv_ucode_feature_version = le32_to_cpu(rlc_hdr->rlcv_ucode_feature_version);
436a0d9084dSHawking Zhang adev->gfx.rlc.rlcv_ucode_size_bytes = le32_to_cpu(rlc_hdr->rlcv_ucode_size_bytes);
437a0d9084dSHawking Zhang adev->gfx.rlc.rlcv_ucode = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->rlcv_ucode_offset_bytes);
438a0d9084dSHawking Zhang
439a0d9084dSHawking Zhang if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
440a0d9084dSHawking Zhang if (adev->gfx.rlc.rlcp_ucode_size_bytes) {
441a0d9084dSHawking Zhang info = &adev->firmware.ucode[AMDGPU_UCODE_ID_RLC_P];
442a0d9084dSHawking Zhang info->ucode_id = AMDGPU_UCODE_ID_RLC_P;
443a0d9084dSHawking Zhang info->fw = adev->gfx.rlc_fw;
444a0d9084dSHawking Zhang adev->firmware.fw_size +=
445a0d9084dSHawking Zhang ALIGN(adev->gfx.rlc.rlcp_ucode_size_bytes, PAGE_SIZE);
446a0d9084dSHawking Zhang }
447a0d9084dSHawking Zhang
448a0d9084dSHawking Zhang if (adev->gfx.rlc.rlcv_ucode_size_bytes) {
449a0d9084dSHawking Zhang info = &adev->firmware.ucode[AMDGPU_UCODE_ID_RLC_V];
450a0d9084dSHawking Zhang info->ucode_id = AMDGPU_UCODE_ID_RLC_V;
451a0d9084dSHawking Zhang info->fw = adev->gfx.rlc_fw;
452a0d9084dSHawking Zhang adev->firmware.fw_size +=
453a0d9084dSHawking Zhang ALIGN(adev->gfx.rlc.rlcv_ucode_size_bytes, PAGE_SIZE);
454a0d9084dSHawking Zhang }
455a0d9084dSHawking Zhang }
456a0d9084dSHawking Zhang }
457435d6e6fSHawking Zhang
amdgpu_gfx_rlc_init_microcode_v2_4(struct amdgpu_device * adev)458435d6e6fSHawking Zhang static void amdgpu_gfx_rlc_init_microcode_v2_4(struct amdgpu_device *adev)
459435d6e6fSHawking Zhang {
460435d6e6fSHawking Zhang const struct rlc_firmware_header_v2_4 *rlc_hdr;
461435d6e6fSHawking Zhang struct amdgpu_firmware_info *info;
462435d6e6fSHawking Zhang
463435d6e6fSHawking Zhang rlc_hdr = (const struct rlc_firmware_header_v2_4 *)adev->gfx.rlc_fw->data;
464435d6e6fSHawking Zhang adev->gfx.rlc.global_tap_delays_ucode_size_bytes = le32_to_cpu(rlc_hdr->global_tap_delays_ucode_size_bytes);
465435d6e6fSHawking Zhang adev->gfx.rlc.global_tap_delays_ucode = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->global_tap_delays_ucode_offset_bytes);
466435d6e6fSHawking Zhang adev->gfx.rlc.se0_tap_delays_ucode_size_bytes = le32_to_cpu(rlc_hdr->se0_tap_delays_ucode_size_bytes);
467435d6e6fSHawking Zhang adev->gfx.rlc.se0_tap_delays_ucode = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->se0_tap_delays_ucode_offset_bytes);
468435d6e6fSHawking Zhang adev->gfx.rlc.se1_tap_delays_ucode_size_bytes = le32_to_cpu(rlc_hdr->se1_tap_delays_ucode_size_bytes);
469435d6e6fSHawking Zhang adev->gfx.rlc.se1_tap_delays_ucode = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->se1_tap_delays_ucode_offset_bytes);
470435d6e6fSHawking Zhang adev->gfx.rlc.se2_tap_delays_ucode_size_bytes = le32_to_cpu(rlc_hdr->se2_tap_delays_ucode_size_bytes);
471435d6e6fSHawking Zhang adev->gfx.rlc.se2_tap_delays_ucode = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->se2_tap_delays_ucode_offset_bytes);
472435d6e6fSHawking Zhang adev->gfx.rlc.se3_tap_delays_ucode_size_bytes = le32_to_cpu(rlc_hdr->se3_tap_delays_ucode_size_bytes);
473435d6e6fSHawking Zhang adev->gfx.rlc.se3_tap_delays_ucode = (u8 *)rlc_hdr + le32_to_cpu(rlc_hdr->se3_tap_delays_ucode_offset_bytes);
474435d6e6fSHawking Zhang
475435d6e6fSHawking Zhang if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
476435d6e6fSHawking Zhang if (adev->gfx.rlc.global_tap_delays_ucode_size_bytes) {
477435d6e6fSHawking Zhang info = &adev->firmware.ucode[AMDGPU_UCODE_ID_GLOBAL_TAP_DELAYS];
478435d6e6fSHawking Zhang info->ucode_id = AMDGPU_UCODE_ID_GLOBAL_TAP_DELAYS;
479435d6e6fSHawking Zhang info->fw = adev->gfx.rlc_fw;
480435d6e6fSHawking Zhang adev->firmware.fw_size +=
481435d6e6fSHawking Zhang ALIGN(adev->gfx.rlc.global_tap_delays_ucode_size_bytes, PAGE_SIZE);
482435d6e6fSHawking Zhang }
483435d6e6fSHawking Zhang
484435d6e6fSHawking Zhang if (adev->gfx.rlc.se0_tap_delays_ucode_size_bytes) {
485435d6e6fSHawking Zhang info = &adev->firmware.ucode[AMDGPU_UCODE_ID_SE0_TAP_DELAYS];
486435d6e6fSHawking Zhang info->ucode_id = AMDGPU_UCODE_ID_SE0_TAP_DELAYS;
487435d6e6fSHawking Zhang info->fw = adev->gfx.rlc_fw;
488435d6e6fSHawking Zhang adev->firmware.fw_size +=
489435d6e6fSHawking Zhang ALIGN(adev->gfx.rlc.se0_tap_delays_ucode_size_bytes, PAGE_SIZE);
490435d6e6fSHawking Zhang }
491435d6e6fSHawking Zhang
492435d6e6fSHawking Zhang if (adev->gfx.rlc.se1_tap_delays_ucode_size_bytes) {
493435d6e6fSHawking Zhang info = &adev->firmware.ucode[AMDGPU_UCODE_ID_SE1_TAP_DELAYS];
494435d6e6fSHawking Zhang info->ucode_id = AMDGPU_UCODE_ID_SE1_TAP_DELAYS;
495435d6e6fSHawking Zhang info->fw = adev->gfx.rlc_fw;
496435d6e6fSHawking Zhang adev->firmware.fw_size +=
497435d6e6fSHawking Zhang ALIGN(adev->gfx.rlc.se1_tap_delays_ucode_size_bytes, PAGE_SIZE);
498435d6e6fSHawking Zhang }
499435d6e6fSHawking Zhang
500435d6e6fSHawking Zhang if (adev->gfx.rlc.se2_tap_delays_ucode_size_bytes) {
501435d6e6fSHawking Zhang info = &adev->firmware.ucode[AMDGPU_UCODE_ID_SE2_TAP_DELAYS];
502435d6e6fSHawking Zhang info->ucode_id = AMDGPU_UCODE_ID_SE2_TAP_DELAYS;
503435d6e6fSHawking Zhang info->fw = adev->gfx.rlc_fw;
504435d6e6fSHawking Zhang adev->firmware.fw_size +=
505435d6e6fSHawking Zhang ALIGN(adev->gfx.rlc.se2_tap_delays_ucode_size_bytes, PAGE_SIZE);
506435d6e6fSHawking Zhang }
507435d6e6fSHawking Zhang
508435d6e6fSHawking Zhang if (adev->gfx.rlc.se3_tap_delays_ucode_size_bytes) {
509435d6e6fSHawking Zhang info = &adev->firmware.ucode[AMDGPU_UCODE_ID_SE3_TAP_DELAYS];
510435d6e6fSHawking Zhang info->ucode_id = AMDGPU_UCODE_ID_SE3_TAP_DELAYS;
511435d6e6fSHawking Zhang info->fw = adev->gfx.rlc_fw;
512435d6e6fSHawking Zhang adev->firmware.fw_size +=
513435d6e6fSHawking Zhang ALIGN(adev->gfx.rlc.se3_tap_delays_ucode_size_bytes, PAGE_SIZE);
514435d6e6fSHawking Zhang }
515435d6e6fSHawking Zhang }
516435d6e6fSHawking Zhang }
5175b415212SHawking Zhang
amdgpu_gfx_rlc_init_microcode(struct amdgpu_device * adev,uint16_t version_major,uint16_t version_minor)5185b415212SHawking Zhang int amdgpu_gfx_rlc_init_microcode(struct amdgpu_device *adev,
5195b415212SHawking Zhang uint16_t version_major,
5205b415212SHawking Zhang uint16_t version_minor)
5215b415212SHawking Zhang {
5225b415212SHawking Zhang int err;
5235b415212SHawking Zhang
5245b415212SHawking Zhang if (version_major < 2) {
5255b415212SHawking Zhang /* only support rlc_hdr v2.x and onwards */
5265b415212SHawking Zhang dev_err(adev->dev, "unsupported rlc fw hdr\n");
5275b415212SHawking Zhang return -EINVAL;
5285b415212SHawking Zhang }
5295b415212SHawking Zhang
5305b415212SHawking Zhang /* is_rlc_v2_1 is still used in APU code path */
5315b415212SHawking Zhang if (version_major == 2 && version_minor == 1)
5325b415212SHawking Zhang adev->gfx.rlc.is_rlc_v2_1 = true;
5335b415212SHawking Zhang
5345b415212SHawking Zhang if (version_minor >= 0) {
5355b415212SHawking Zhang err = amdgpu_gfx_rlc_init_microcode_v2_0(adev);
5365b415212SHawking Zhang if (err) {
5375b415212SHawking Zhang dev_err(adev->dev, "fail to init rlc v2_0 microcode\n");
5385b415212SHawking Zhang return err;
5395b415212SHawking Zhang }
5405b415212SHawking Zhang }
5415b415212SHawking Zhang if (version_minor >= 1)
5425b415212SHawking Zhang amdgpu_gfx_rlc_init_microcode_v2_1(adev);
5435b415212SHawking Zhang if (version_minor >= 2)
5445b415212SHawking Zhang amdgpu_gfx_rlc_init_microcode_v2_2(adev);
5455b415212SHawking Zhang if (version_minor == 3)
5465b415212SHawking Zhang amdgpu_gfx_rlc_init_microcode_v2_3(adev);
5475b415212SHawking Zhang if (version_minor == 4)
5485b415212SHawking Zhang amdgpu_gfx_rlc_init_microcode_v2_4(adev);
5495b415212SHawking Zhang
5505b415212SHawking Zhang return 0;
5515b415212SHawking Zhang }
552