Revert "Update drm/radeon to Linux 4.7.10 as much as possible..."
[dragonfly.git] / sys / dev / drm / radeon / si_smc.c
1 /*
2  * Copyright 2011 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  * Authors: Alex Deucher
23  */
24
25 #include <linux/firmware.h>
26 #include <drm/drmP.h>
27 #include "radeon.h"
28 #include "sid.h"
29 #include "ppsmc.h"
30 #include "radeon_ucode.h"
31 #include "sislands_smc.h"
32
33 static int si_set_smc_sram_address(struct radeon_device *rdev,
34                                    u32 smc_address, u32 limit)
35 {
36         if (smc_address & 3)
37                 return -EINVAL;
38         if ((smc_address + 3) > limit)
39                 return -EINVAL;
40
41         WREG32(SMC_IND_INDEX_0, smc_address);
42         WREG32_P(SMC_IND_ACCESS_CNTL, 0, ~AUTO_INCREMENT_IND_0);
43
44         return 0;
45 }
46
47 int si_copy_bytes_to_smc(struct radeon_device *rdev,
48                          u32 smc_start_address,
49                          const u8 *src, u32 byte_count, u32 limit)
50 {
51         int ret = 0;
52         u32 data, original_data, addr, extra_shift;
53
54         if (smc_start_address & 3)
55                 return -EINVAL;
56         if ((smc_start_address + byte_count) > limit)
57                 return -EINVAL;
58
59         addr = smc_start_address;
60
61         spin_lock(&rdev->smc_idx_lock);
62         while (byte_count >= 4) {
63                 /* SMC address space is BE */
64                 data = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3];
65
66                 ret = si_set_smc_sram_address(rdev, addr, limit);
67                 if (ret)
68                         goto done;
69
70                 WREG32(SMC_IND_DATA_0, data);
71
72                 src += 4;
73                 byte_count -= 4;
74                 addr += 4;
75         }
76
77         /* RMW for the final bytes */
78         if (byte_count > 0) {
79                 data = 0;
80
81                 ret = si_set_smc_sram_address(rdev, addr, limit);
82                 if (ret)
83                         goto done;
84
85                 original_data = RREG32(SMC_IND_DATA_0);
86
87                 extra_shift = 8 * (4 - byte_count);
88
89                 while (byte_count > 0) {
90                         /* SMC address space is BE */
91                         data = (data << 8) + *src++;
92                         byte_count--;
93                 }
94
95                 data <<= extra_shift;
96
97                 data |= (original_data & ~((~0UL) << extra_shift));
98
99                 ret = si_set_smc_sram_address(rdev, addr, limit);
100                 if (ret)
101                         goto done;
102
103                 WREG32(SMC_IND_DATA_0, data);
104         }
105
106 done:
107         spin_unlock(&rdev->smc_idx_lock);
108
109         return ret;
110 }
111
112 void si_start_smc(struct radeon_device *rdev)
113 {
114         u32 tmp = RREG32_SMC(SMC_SYSCON_RESET_CNTL);
115
116         tmp &= ~RST_REG;
117
118         WREG32_SMC(SMC_SYSCON_RESET_CNTL, tmp);
119 }
120
121 void si_reset_smc(struct radeon_device *rdev)
122 {
123         u32 tmp;
124
125         RREG32(CB_CGTT_SCLK_CTRL);
126         RREG32(CB_CGTT_SCLK_CTRL);
127         RREG32(CB_CGTT_SCLK_CTRL);
128         RREG32(CB_CGTT_SCLK_CTRL);
129
130         tmp = RREG32_SMC(SMC_SYSCON_RESET_CNTL);
131         tmp |= RST_REG;
132         WREG32_SMC(SMC_SYSCON_RESET_CNTL, tmp);
133 }
134
135 int si_program_jump_on_start(struct radeon_device *rdev)
136 {
137         static u8 data[] = { 0x0E, 0x00, 0x40, 0x40 };
138
139         return si_copy_bytes_to_smc(rdev, 0x0, data, 4, sizeof(data)+1);
140 }
141
142 void si_stop_smc_clock(struct radeon_device *rdev)
143 {
144         u32 tmp = RREG32_SMC(SMC_SYSCON_CLOCK_CNTL_0);
145
146         tmp |= CK_DISABLE;
147
148         WREG32_SMC(SMC_SYSCON_CLOCK_CNTL_0, tmp);
149 }
150
151 void si_start_smc_clock(struct radeon_device *rdev)
152 {
153         u32 tmp = RREG32_SMC(SMC_SYSCON_CLOCK_CNTL_0);
154
155         tmp &= ~CK_DISABLE;
156
157         WREG32_SMC(SMC_SYSCON_CLOCK_CNTL_0, tmp);
158 }
159
160 bool si_is_smc_running(struct radeon_device *rdev)
161 {
162         u32 rst = RREG32_SMC(SMC_SYSCON_RESET_CNTL);
163         u32 clk = RREG32_SMC(SMC_SYSCON_CLOCK_CNTL_0);
164
165         if (!(rst & RST_REG) && !(clk & CK_DISABLE))
166                 return true;
167
168         return false;
169 }
170
171 PPSMC_Result si_send_msg_to_smc(struct radeon_device *rdev, PPSMC_Msg msg)
172 {
173         u32 tmp;
174         int i;
175
176         if (!si_is_smc_running(rdev))
177                 return PPSMC_Result_Failed;
178
179         WREG32(SMC_MESSAGE_0, msg);
180
181         for (i = 0; i < rdev->usec_timeout; i++) {
182                 tmp = RREG32(SMC_RESP_0);
183                 if (tmp != 0)
184                         break;
185                 udelay(1);
186         }
187         tmp = RREG32(SMC_RESP_0);
188
189         return (PPSMC_Result)tmp;
190 }
191
192 PPSMC_Result si_wait_for_smc_inactive(struct radeon_device *rdev)
193 {
194         u32 tmp;
195         int i;
196
197         if (!si_is_smc_running(rdev))
198                 return PPSMC_Result_OK;
199
200         for (i = 0; i < rdev->usec_timeout; i++) {
201                 tmp = RREG32_SMC(SMC_SYSCON_CLOCK_CNTL_0);
202                 if ((tmp & CKEN) == 0)
203                         break;
204                 udelay(1);
205         }
206
207         return PPSMC_Result_OK;
208 }
209
210 int si_load_smc_ucode(struct radeon_device *rdev, u32 limit)
211 {
212         u32 ucode_start_address;
213         u32 ucode_size;
214         const u8 *src;
215         u32 data;
216
217         if (!rdev->smc_fw)
218                 return -EINVAL;
219
220         if (rdev->new_fw) {
221                 const struct smc_firmware_header_v1_0 *hdr =
222                         (const struct smc_firmware_header_v1_0 *)rdev->smc_fw->data;
223
224                 radeon_ucode_print_smc_hdr(&hdr->header);
225
226                 ucode_start_address = le32_to_cpu(hdr->ucode_start_addr);
227                 ucode_size = le32_to_cpu(hdr->header.ucode_size_bytes);
228                 src = (const u8 *)
229                         ((const char *)rdev->smc_fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes));
230         } else {
231                 switch (rdev->family) {
232                 case CHIP_TAHITI:
233                         ucode_start_address = TAHITI_SMC_UCODE_START;
234                         ucode_size = TAHITI_SMC_UCODE_SIZE;
235                         break;
236                 case CHIP_PITCAIRN:
237                         ucode_start_address = PITCAIRN_SMC_UCODE_START;
238                         ucode_size = PITCAIRN_SMC_UCODE_SIZE;
239                         break;
240                 case CHIP_VERDE:
241                         ucode_start_address = VERDE_SMC_UCODE_START;
242                         ucode_size = VERDE_SMC_UCODE_SIZE;
243                         break;
244                 case CHIP_OLAND:
245                         ucode_start_address = OLAND_SMC_UCODE_START;
246                         ucode_size = OLAND_SMC_UCODE_SIZE;
247                         break;
248                 case CHIP_HAINAN:
249                         ucode_start_address = HAINAN_SMC_UCODE_START;
250                         ucode_size = HAINAN_SMC_UCODE_SIZE;
251                         break;
252                 default:
253                         DRM_ERROR("unknown asic in smc ucode loader\n");
254                         BUG();
255                 }
256                 src = (const u8 *)rdev->smc_fw->data;
257         }
258
259         if (ucode_size & 3)
260                 return -EINVAL;
261
262         spin_lock(&rdev->smc_idx_lock);
263         WREG32(SMC_IND_INDEX_0, ucode_start_address);
264         WREG32_P(SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, ~AUTO_INCREMENT_IND_0);
265         while (ucode_size >= 4) {
266                 /* SMC address space is BE */
267                 data = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3];
268
269                 WREG32(SMC_IND_DATA_0, data);
270
271                 src += 4;
272                 ucode_size -= 4;
273         }
274         WREG32_P(SMC_IND_ACCESS_CNTL, 0, ~AUTO_INCREMENT_IND_0);
275         spin_unlock(&rdev->smc_idx_lock);
276
277         return 0;
278 }
279
280 int si_read_smc_sram_dword(struct radeon_device *rdev, u32 smc_address,
281                            u32 *value, u32 limit)
282 {
283         int ret;
284
285         spin_lock(&rdev->smc_idx_lock);
286         ret = si_set_smc_sram_address(rdev, smc_address, limit);
287         if (ret == 0)
288                 *value = RREG32(SMC_IND_DATA_0);
289         spin_unlock(&rdev->smc_idx_lock);
290
291         return ret;
292 }
293
294 int si_write_smc_sram_dword(struct radeon_device *rdev, u32 smc_address,
295                             u32 value, u32 limit)
296 {
297         int ret;
298
299         spin_lock(&rdev->smc_idx_lock);
300         ret = si_set_smc_sram_address(rdev, smc_address, limit);
301         if (ret == 0)
302                 WREG32(SMC_IND_DATA_0, value);
303         spin_unlock(&rdev->smc_idx_lock);
304
305         return ret;
306 }