Merge tag 'kbuild-v5.11' of git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy...
[linux-2.6-microblaze.git] / drivers / gpu / drm / amd / amdgpu / vega10_ih.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 <linux/pci.h>
25
26 #include "amdgpu.h"
27 #include "amdgpu_ih.h"
28 #include "soc15.h"
29
30 #include "oss/osssys_4_0_offset.h"
31 #include "oss/osssys_4_0_sh_mask.h"
32
33 #include "soc15_common.h"
34 #include "vega10_ih.h"
35
36 #define MAX_REARM_RETRY 10
37
38 static void vega10_ih_set_interrupt_funcs(struct amdgpu_device *adev);
39
40 /**
41  * vega10_ih_enable_interrupts - Enable the interrupt ring buffer
42  *
43  * @adev: amdgpu_device pointer
44  *
45  * Enable the interrupt ring buffer (VEGA10).
46  */
47 static void vega10_ih_enable_interrupts(struct amdgpu_device *adev)
48 {
49         u32 ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL);
50
51         ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, RB_ENABLE, 1);
52         ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, ENABLE_INTR, 1);
53         if (amdgpu_sriov_vf(adev)) {
54                 if (psp_reg_program(&adev->psp, PSP_REG_IH_RB_CNTL, ih_rb_cntl)) {
55                         DRM_ERROR("PSP program IH_RB_CNTL failed!\n");
56                         return;
57                 }
58         } else {
59                 WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL, ih_rb_cntl);
60         }
61         adev->irq.ih.enabled = true;
62
63         if (adev->irq.ih1.ring_size) {
64                 ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1);
65                 ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL_RING1,
66                                            RB_ENABLE, 1);
67                 if (amdgpu_sriov_vf(adev)) {
68                         if (psp_reg_program(&adev->psp, PSP_REG_IH_RB_CNTL_RING1,
69                                                 ih_rb_cntl)) {
70                                 DRM_ERROR("program IH_RB_CNTL_RING1 failed!\n");
71                                 return;
72                         }
73                 } else {
74                         WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1, ih_rb_cntl);
75                 }
76                 adev->irq.ih1.enabled = true;
77         }
78
79         if (adev->irq.ih2.ring_size) {
80                 ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING2);
81                 ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL_RING2,
82                                            RB_ENABLE, 1);
83                 if (amdgpu_sriov_vf(adev)) {
84                         if (psp_reg_program(&adev->psp, PSP_REG_IH_RB_CNTL_RING2,
85                                                 ih_rb_cntl)) {
86                                 DRM_ERROR("program IH_RB_CNTL_RING2 failed!\n");
87                                 return;
88                         }
89                 } else {
90                         WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING2, ih_rb_cntl);
91                 }
92                 adev->irq.ih2.enabled = true;
93         }
94
95         if (adev->irq.ih_soft.ring_size)
96                 adev->irq.ih_soft.enabled = true;
97 }
98
99 /**
100  * vega10_ih_disable_interrupts - Disable the interrupt ring buffer
101  *
102  * @adev: amdgpu_device pointer
103  *
104  * Disable the interrupt ring buffer (VEGA10).
105  */
106 static void vega10_ih_disable_interrupts(struct amdgpu_device *adev)
107 {
108         u32 ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL);
109
110         ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, RB_ENABLE, 0);
111         ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, ENABLE_INTR, 0);
112         if (amdgpu_sriov_vf(adev)) {
113                 if (psp_reg_program(&adev->psp, PSP_REG_IH_RB_CNTL, ih_rb_cntl)) {
114                         DRM_ERROR("PSP program IH_RB_CNTL failed!\n");
115                         return;
116                 }
117         } else {
118                 WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL, ih_rb_cntl);
119         }
120
121         /* set rptr, wptr to 0 */
122         WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR, 0);
123         WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR, 0);
124         adev->irq.ih.enabled = false;
125         adev->irq.ih.rptr = 0;
126
127         if (adev->irq.ih1.ring_size) {
128                 ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1);
129                 ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL_RING1,
130                                            RB_ENABLE, 0);
131                 if (amdgpu_sriov_vf(adev)) {
132                         if (psp_reg_program(&adev->psp, PSP_REG_IH_RB_CNTL_RING1,
133                                                 ih_rb_cntl)) {
134                                 DRM_ERROR("program IH_RB_CNTL_RING1 failed!\n");
135                                 return;
136                         }
137                 } else {
138                         WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1, ih_rb_cntl);
139                 }
140                 /* set rptr, wptr to 0 */
141                 WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR_RING1, 0);
142                 WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_RING1, 0);
143                 adev->irq.ih1.enabled = false;
144                 adev->irq.ih1.rptr = 0;
145         }
146
147         if (adev->irq.ih2.ring_size) {
148                 ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING2);
149                 ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL_RING2,
150                                            RB_ENABLE, 0);
151                 if (amdgpu_sriov_vf(adev)) {
152                         if (psp_reg_program(&adev->psp, PSP_REG_IH_RB_CNTL_RING2,
153                                                 ih_rb_cntl)) {
154                                 DRM_ERROR("program IH_RB_CNTL_RING2 failed!\n");
155                                 return;
156                         }
157                 } else {
158                         WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING2, ih_rb_cntl);
159                 }
160
161                 /* set rptr, wptr to 0 */
162                 WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR_RING2, 0);
163                 WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_RING2, 0);
164                 adev->irq.ih2.enabled = false;
165                 adev->irq.ih2.rptr = 0;
166         }
167 }
168
169 static uint32_t vega10_ih_rb_cntl(struct amdgpu_ih_ring *ih, uint32_t ih_rb_cntl)
170 {
171         int rb_bufsz = order_base_2(ih->ring_size / 4);
172
173         ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
174                                    MC_SPACE, ih->use_bus_addr ? 1 : 4);
175         ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
176                                    WPTR_OVERFLOW_CLEAR, 1);
177         ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
178                                    WPTR_OVERFLOW_ENABLE, 1);
179         ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, RB_SIZE, rb_bufsz);
180         /* Ring Buffer write pointer writeback. If enabled, IH_RB_WPTR register
181          * value is written to memory
182          */
183         ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
184                                    WPTR_WRITEBACK_ENABLE, 1);
185         ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_SNOOP, 1);
186         ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_RO, 0);
187         ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, MC_VMID, 0);
188
189         return ih_rb_cntl;
190 }
191
192 static uint32_t vega10_ih_doorbell_rptr(struct amdgpu_ih_ring *ih)
193 {
194         u32 ih_doorbell_rtpr = 0;
195
196         if (ih->use_doorbell) {
197                 ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr,
198                                                  IH_DOORBELL_RPTR, OFFSET,
199                                                  ih->doorbell_index);
200                 ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr,
201                                                  IH_DOORBELL_RPTR,
202                                                  ENABLE, 1);
203         } else {
204                 ih_doorbell_rtpr = REG_SET_FIELD(ih_doorbell_rtpr,
205                                                  IH_DOORBELL_RPTR,
206                                                  ENABLE, 0);
207         }
208         return ih_doorbell_rtpr;
209 }
210
211 /**
212  * vega10_ih_irq_init - init and enable the interrupt ring
213  *
214  * @adev: amdgpu_device pointer
215  *
216  * Allocate a ring buffer for the interrupt controller,
217  * enable the RLC, disable interrupts, enable the IH
218  * ring buffer and enable it (VI).
219  * Called at device load and reume.
220  * Returns 0 for success, errors for failure.
221  */
222 static int vega10_ih_irq_init(struct amdgpu_device *adev)
223 {
224         struct amdgpu_ih_ring *ih;
225         u32 ih_rb_cntl, ih_chicken;
226         int ret = 0;
227         u32 tmp;
228
229         /* disable irqs */
230         vega10_ih_disable_interrupts(adev);
231
232         adev->nbio.funcs->ih_control(adev);
233
234         ih = &adev->irq.ih;
235         /* Ring Buffer base. [39:8] of 40-bit address of the beginning of the ring buffer*/
236         WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE, ih->gpu_addr >> 8);
237         WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_HI, (ih->gpu_addr >> 40) & 0xff);
238
239         ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL);
240         ih_rb_cntl = vega10_ih_rb_cntl(ih, ih_rb_cntl);
241         ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL, RPTR_REARM,
242                                    !!adev->irq.msi_enabled);
243         if (amdgpu_sriov_vf(adev)) {
244                 if (psp_reg_program(&adev->psp, PSP_REG_IH_RB_CNTL, ih_rb_cntl)) {
245                         DRM_ERROR("PSP program IH_RB_CNTL failed!\n");
246                         return -ETIMEDOUT;
247                 }
248         } else {
249                 WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL, ih_rb_cntl);
250         }
251
252         if ((adev->asic_type == CHIP_ARCTURUS &&
253              adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT) ||
254             adev->asic_type == CHIP_RENOIR) {
255                 ih_chicken = RREG32_SOC15(OSSSYS, 0, mmIH_CHICKEN);
256                 if (adev->irq.ih.use_bus_addr) {
257                         ih_chicken = REG_SET_FIELD(ih_chicken, IH_CHICKEN,
258                                                    MC_SPACE_GPA_ENABLE, 1);
259                 } else {
260                         ih_chicken = REG_SET_FIELD(ih_chicken, IH_CHICKEN,
261                                                    MC_SPACE_FBPA_ENABLE, 1);
262                 }
263                 WREG32_SOC15(OSSSYS, 0, mmIH_CHICKEN, ih_chicken);
264         }
265
266         /* set the writeback address whether it's enabled or not */
267         WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_ADDR_LO,
268                      lower_32_bits(ih->wptr_addr));
269         WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_ADDR_HI,
270                      upper_32_bits(ih->wptr_addr) & 0xFFFF);
271
272         /* set rptr, wptr to 0 */
273         WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR, 0);
274         WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR, 0);
275
276         WREG32_SOC15(OSSSYS, 0, mmIH_DOORBELL_RPTR,
277                      vega10_ih_doorbell_rptr(ih));
278
279         ih = &adev->irq.ih1;
280         if (ih->ring_size) {
281                 WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_RING1, ih->gpu_addr >> 8);
282                 WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_HI_RING1,
283                              (ih->gpu_addr >> 40) & 0xff);
284
285                 ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1);
286                 ih_rb_cntl = vega10_ih_rb_cntl(ih, ih_rb_cntl);
287                 ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
288                                            WPTR_OVERFLOW_ENABLE, 0);
289                 ih_rb_cntl = REG_SET_FIELD(ih_rb_cntl, IH_RB_CNTL,
290                                            RB_FULL_DRAIN_ENABLE, 1);
291                 if (amdgpu_sriov_vf(adev)) {
292                         if (psp_reg_program(&adev->psp, PSP_REG_IH_RB_CNTL_RING1,
293                                                 ih_rb_cntl)) {
294                                 DRM_ERROR("program IH_RB_CNTL_RING1 failed!\n");
295                                 return -ETIMEDOUT;
296                         }
297                 } else {
298                         WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING1, ih_rb_cntl);
299                 }
300
301                 /* set rptr, wptr to 0 */
302                 WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_RING1, 0);
303                 WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR_RING1, 0);
304
305                 WREG32_SOC15(OSSSYS, 0, mmIH_DOORBELL_RPTR_RING1,
306                              vega10_ih_doorbell_rptr(ih));
307         }
308
309         ih = &adev->irq.ih2;
310         if (ih->ring_size) {
311                 WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_RING2, ih->gpu_addr >> 8);
312                 WREG32_SOC15(OSSSYS, 0, mmIH_RB_BASE_HI_RING2,
313                              (ih->gpu_addr >> 40) & 0xff);
314
315                 ih_rb_cntl = RREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING2);
316                 ih_rb_cntl = vega10_ih_rb_cntl(ih, ih_rb_cntl);
317
318                 if (amdgpu_sriov_vf(adev)) {
319                         if (psp_reg_program(&adev->psp, PSP_REG_IH_RB_CNTL_RING2,
320                                                 ih_rb_cntl)) {
321                                 DRM_ERROR("program IH_RB_CNTL_RING2 failed!\n");
322                                 return -ETIMEDOUT;
323                         }
324                 } else {
325                         WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL_RING2, ih_rb_cntl);
326                 }
327
328                 /* set rptr, wptr to 0 */
329                 WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_RING2, 0);
330                 WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR_RING2, 0);
331
332                 WREG32_SOC15(OSSSYS, 0, mmIH_DOORBELL_RPTR_RING2,
333                              vega10_ih_doorbell_rptr(ih));
334         }
335
336         tmp = RREG32_SOC15(OSSSYS, 0, mmIH_STORM_CLIENT_LIST_CNTL);
337         tmp = REG_SET_FIELD(tmp, IH_STORM_CLIENT_LIST_CNTL,
338                             CLIENT18_IS_STORM_CLIENT, 1);
339         WREG32_SOC15(OSSSYS, 0, mmIH_STORM_CLIENT_LIST_CNTL, tmp);
340
341         tmp = RREG32_SOC15(OSSSYS, 0, mmIH_INT_FLOOD_CNTL);
342         tmp = REG_SET_FIELD(tmp, IH_INT_FLOOD_CNTL, FLOOD_CNTL_ENABLE, 1);
343         WREG32_SOC15(OSSSYS, 0, mmIH_INT_FLOOD_CNTL, tmp);
344
345         pci_set_master(adev->pdev);
346
347         /* enable interrupts */
348         vega10_ih_enable_interrupts(adev);
349
350         return ret;
351 }
352
353 /**
354  * vega10_ih_irq_disable - disable interrupts
355  *
356  * @adev: amdgpu_device pointer
357  *
358  * Disable interrupts on the hw (VEGA10).
359  */
360 static void vega10_ih_irq_disable(struct amdgpu_device *adev)
361 {
362         vega10_ih_disable_interrupts(adev);
363
364         /* Wait and acknowledge irq */
365         mdelay(1);
366 }
367
368 /**
369  * vega10_ih_get_wptr - get the IH ring buffer wptr
370  *
371  * @adev: amdgpu_device pointer
372  * @ih: IH ring buffer to fetch wptr
373  *
374  * Get the IH ring buffer wptr from either the register
375  * or the writeback memory buffer (VEGA10).  Also check for
376  * ring buffer overflow and deal with it.
377  * Returns the value of the wptr.
378  */
379 static u32 vega10_ih_get_wptr(struct amdgpu_device *adev,
380                               struct amdgpu_ih_ring *ih)
381 {
382         u32 wptr, reg, tmp;
383
384         wptr = le32_to_cpu(*ih->wptr_cpu);
385
386         if (!REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW))
387                 goto out;
388
389         /* Double check that the overflow wasn't already cleared. */
390
391         if (ih == &adev->irq.ih)
392                 reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_WPTR);
393         else if (ih == &adev->irq.ih1)
394                 reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_WPTR_RING1);
395         else if (ih == &adev->irq.ih2)
396                 reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_WPTR_RING2);
397         else
398                 BUG();
399
400         wptr = RREG32_NO_KIQ(reg);
401         if (!REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW))
402                 goto out;
403
404         wptr = REG_SET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW, 0);
405
406         /* When a ring buffer overflow happen start parsing interrupt
407          * from the last not overwritten vector (wptr + 32). Hopefully
408          * this should allow us to catchup.
409          */
410         tmp = (wptr + 32) & ih->ptr_mask;
411         dev_warn(adev->dev, "IH ring buffer overflow "
412                  "(0x%08X, 0x%08X, 0x%08X)\n",
413                  wptr, ih->rptr, tmp);
414         ih->rptr = tmp;
415
416         if (ih == &adev->irq.ih)
417                 reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_CNTL);
418         else if (ih == &adev->irq.ih1)
419                 reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_CNTL_RING1);
420         else if (ih == &adev->irq.ih2)
421                 reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_CNTL_RING2);
422         else
423                 BUG();
424
425         tmp = RREG32_NO_KIQ(reg);
426         tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1);
427         WREG32_NO_KIQ(reg, tmp);
428
429 out:
430         return (wptr & ih->ptr_mask);
431 }
432
433 /**
434  * vega10_ih_decode_iv - decode an interrupt vector
435  *
436  * @adev: amdgpu_device pointer
437  * @ih: IH ring buffer to decode
438  * @entry: IV entry to place decoded information into
439  *
440  * Decodes the interrupt vector at the current rptr
441  * position and also advance the position.
442  */
443 static void vega10_ih_decode_iv(struct amdgpu_device *adev,
444                                 struct amdgpu_ih_ring *ih,
445                                 struct amdgpu_iv_entry *entry)
446 {
447         /* wptr/rptr are in bytes! */
448         u32 ring_index = ih->rptr >> 2;
449         uint32_t dw[8];
450
451         dw[0] = le32_to_cpu(ih->ring[ring_index + 0]);
452         dw[1] = le32_to_cpu(ih->ring[ring_index + 1]);
453         dw[2] = le32_to_cpu(ih->ring[ring_index + 2]);
454         dw[3] = le32_to_cpu(ih->ring[ring_index + 3]);
455         dw[4] = le32_to_cpu(ih->ring[ring_index + 4]);
456         dw[5] = le32_to_cpu(ih->ring[ring_index + 5]);
457         dw[6] = le32_to_cpu(ih->ring[ring_index + 6]);
458         dw[7] = le32_to_cpu(ih->ring[ring_index + 7]);
459
460         entry->client_id = dw[0] & 0xff;
461         entry->src_id = (dw[0] >> 8) & 0xff;
462         entry->ring_id = (dw[0] >> 16) & 0xff;
463         entry->vmid = (dw[0] >> 24) & 0xf;
464         entry->vmid_src = (dw[0] >> 31);
465         entry->timestamp = dw[1] | ((u64)(dw[2] & 0xffff) << 32);
466         entry->timestamp_src = dw[2] >> 31;
467         entry->pasid = dw[3] & 0xffff;
468         entry->pasid_src = dw[3] >> 31;
469         entry->src_data[0] = dw[4];
470         entry->src_data[1] = dw[5];
471         entry->src_data[2] = dw[6];
472         entry->src_data[3] = dw[7];
473
474         /* wptr/rptr are in bytes! */
475         ih->rptr += 32;
476 }
477
478 /**
479  * vega10_ih_irq_rearm - rearm IRQ if lost
480  *
481  * @adev: amdgpu_device pointer
482  * @ih: IH ring to match
483  *
484  */
485 static void vega10_ih_irq_rearm(struct amdgpu_device *adev,
486                                struct amdgpu_ih_ring *ih)
487 {
488         uint32_t reg_rptr = 0;
489         uint32_t v = 0;
490         uint32_t i = 0;
491
492         if (ih == &adev->irq.ih)
493                 reg_rptr = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_RPTR);
494         else if (ih == &adev->irq.ih1)
495                 reg_rptr = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_RPTR_RING1);
496         else if (ih == &adev->irq.ih2)
497                 reg_rptr = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_RB_RPTR_RING2);
498         else
499                 return;
500
501         /* Rearm IRQ / re-wwrite doorbell if doorbell write is lost */
502         for (i = 0; i < MAX_REARM_RETRY; i++) {
503                 v = RREG32_NO_KIQ(reg_rptr);
504                 if ((v < ih->ring_size) && (v != ih->rptr))
505                         WDOORBELL32(ih->doorbell_index, ih->rptr);
506                 else
507                         break;
508         }
509 }
510
511 /**
512  * vega10_ih_set_rptr - set the IH ring buffer rptr
513  *
514  * @adev: amdgpu_device pointer
515  * @ih: IH ring buffer to set rptr
516  *
517  * Set the IH ring buffer rptr.
518  */
519 static void vega10_ih_set_rptr(struct amdgpu_device *adev,
520                                struct amdgpu_ih_ring *ih)
521 {
522         if (ih->use_doorbell) {
523                 /* XXX check if swapping is necessary on BE */
524                 *ih->rptr_cpu = ih->rptr;
525                 WDOORBELL32(ih->doorbell_index, ih->rptr);
526
527                 if (amdgpu_sriov_vf(adev))
528                         vega10_ih_irq_rearm(adev, ih);
529         } else if (ih == &adev->irq.ih) {
530                 WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR, ih->rptr);
531         } else if (ih == &adev->irq.ih1) {
532                 WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR_RING1, ih->rptr);
533         } else if (ih == &adev->irq.ih2) {
534                 WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR_RING2, ih->rptr);
535         }
536 }
537
538 /**
539  * vega10_ih_self_irq - dispatch work for ring 1 and 2
540  *
541  * @adev: amdgpu_device pointer
542  * @source: irq source
543  * @entry: IV with WPTR update
544  *
545  * Update the WPTR from the IV and schedule work to handle the entries.
546  */
547 static int vega10_ih_self_irq(struct amdgpu_device *adev,
548                               struct amdgpu_irq_src *source,
549                               struct amdgpu_iv_entry *entry)
550 {
551         uint32_t wptr = cpu_to_le32(entry->src_data[0]);
552
553         switch (entry->ring_id) {
554         case 1:
555                 *adev->irq.ih1.wptr_cpu = wptr;
556                 schedule_work(&adev->irq.ih1_work);
557                 break;
558         case 2:
559                 *adev->irq.ih2.wptr_cpu = wptr;
560                 schedule_work(&adev->irq.ih2_work);
561                 break;
562         default: break;
563         }
564         return 0;
565 }
566
567 static const struct amdgpu_irq_src_funcs vega10_ih_self_irq_funcs = {
568         .process = vega10_ih_self_irq,
569 };
570
571 static void vega10_ih_set_self_irq_funcs(struct amdgpu_device *adev)
572 {
573         adev->irq.self_irq.num_types = 0;
574         adev->irq.self_irq.funcs = &vega10_ih_self_irq_funcs;
575 }
576
577 static int vega10_ih_early_init(void *handle)
578 {
579         struct amdgpu_device *adev = (struct amdgpu_device *)handle;
580
581         vega10_ih_set_interrupt_funcs(adev);
582         vega10_ih_set_self_irq_funcs(adev);
583         return 0;
584 }
585
586 static int vega10_ih_sw_init(void *handle)
587 {
588         struct amdgpu_device *adev = (struct amdgpu_device *)handle;
589         int r;
590
591         r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_IH, 0,
592                               &adev->irq.self_irq);
593         if (r)
594                 return r;
595
596         r = amdgpu_ih_ring_init(adev, &adev->irq.ih, 256 * 1024, true);
597         if (r)
598                 return r;
599
600         adev->irq.ih.use_doorbell = true;
601         adev->irq.ih.doorbell_index = adev->doorbell_index.ih << 1;
602
603         r = amdgpu_ih_ring_init(adev, &adev->irq.ih1, PAGE_SIZE, true);
604         if (r)
605                 return r;
606
607         adev->irq.ih1.use_doorbell = true;
608         adev->irq.ih1.doorbell_index = (adev->doorbell_index.ih + 1) << 1;
609
610         r = amdgpu_ih_ring_init(adev, &adev->irq.ih2, PAGE_SIZE, true);
611         if (r)
612                 return r;
613
614         adev->irq.ih2.use_doorbell = true;
615         adev->irq.ih2.doorbell_index = (adev->doorbell_index.ih + 2) << 1;
616
617         r = amdgpu_ih_ring_init(adev, &adev->irq.ih_soft, PAGE_SIZE, true);
618         if (r)
619                 return r;
620
621         r = amdgpu_irq_init(adev);
622
623         return r;
624 }
625
626 static int vega10_ih_sw_fini(void *handle)
627 {
628         struct amdgpu_device *adev = (struct amdgpu_device *)handle;
629
630         amdgpu_irq_fini(adev);
631         amdgpu_ih_ring_fini(adev, &adev->irq.ih2);
632         amdgpu_ih_ring_fini(adev, &adev->irq.ih1);
633         amdgpu_ih_ring_fini(adev, &adev->irq.ih);
634
635         return 0;
636 }
637
638 static int vega10_ih_hw_init(void *handle)
639 {
640         int r;
641         struct amdgpu_device *adev = (struct amdgpu_device *)handle;
642
643         r = vega10_ih_irq_init(adev);
644         if (r)
645                 return r;
646
647         return 0;
648 }
649
650 static int vega10_ih_hw_fini(void *handle)
651 {
652         struct amdgpu_device *adev = (struct amdgpu_device *)handle;
653
654         vega10_ih_irq_disable(adev);
655
656         return 0;
657 }
658
659 static int vega10_ih_suspend(void *handle)
660 {
661         struct amdgpu_device *adev = (struct amdgpu_device *)handle;
662
663         return vega10_ih_hw_fini(adev);
664 }
665
666 static int vega10_ih_resume(void *handle)
667 {
668         struct amdgpu_device *adev = (struct amdgpu_device *)handle;
669
670         return vega10_ih_hw_init(adev);
671 }
672
673 static bool vega10_ih_is_idle(void *handle)
674 {
675         /* todo */
676         return true;
677 }
678
679 static int vega10_ih_wait_for_idle(void *handle)
680 {
681         /* todo */
682         return -ETIMEDOUT;
683 }
684
685 static int vega10_ih_soft_reset(void *handle)
686 {
687         /* todo */
688
689         return 0;
690 }
691
692 static void vega10_ih_update_clockgating_state(struct amdgpu_device *adev,
693                                                bool enable)
694 {
695         uint32_t data, def, field_val;
696
697         if (adev->cg_flags & AMD_CG_SUPPORT_IH_CG) {
698                 def = data = RREG32_SOC15(OSSSYS, 0, mmIH_CLK_CTRL);
699                 field_val = enable ? 0 : 1;
700                 /**
701                  * Vega10 does not have IH_RETRY_INT_CAM_MEM_CLK_SOFT_OVERRIDE
702                  * and IH_BUFFER_MEM_CLK_SOFT_OVERRIDE field.
703                  */
704                 if (adev->asic_type > CHIP_VEGA10) {
705                         data = REG_SET_FIELD(data, IH_CLK_CTRL,
706                                      IH_RETRY_INT_CAM_MEM_CLK_SOFT_OVERRIDE, field_val);
707                         data = REG_SET_FIELD(data, IH_CLK_CTRL,
708                                      IH_BUFFER_MEM_CLK_SOFT_OVERRIDE, field_val);
709                 }
710
711                 data = REG_SET_FIELD(data, IH_CLK_CTRL,
712                                      DBUS_MUX_CLK_SOFT_OVERRIDE, field_val);
713                 data = REG_SET_FIELD(data, IH_CLK_CTRL,
714                                      OSSSYS_SHARE_CLK_SOFT_OVERRIDE, field_val);
715                 data = REG_SET_FIELD(data, IH_CLK_CTRL,
716                                      LIMIT_SMN_CLK_SOFT_OVERRIDE, field_val);
717                 data = REG_SET_FIELD(data, IH_CLK_CTRL,
718                                      DYN_CLK_SOFT_OVERRIDE, field_val);
719                 data = REG_SET_FIELD(data, IH_CLK_CTRL,
720                                      REG_CLK_SOFT_OVERRIDE, field_val);
721                 if (def != data)
722                         WREG32_SOC15(OSSSYS, 0, mmIH_CLK_CTRL, data);
723         }
724 }
725
726 static int vega10_ih_set_clockgating_state(void *handle,
727                                           enum amd_clockgating_state state)
728 {
729         struct amdgpu_device *adev = (struct amdgpu_device *)handle;
730
731         vega10_ih_update_clockgating_state(adev,
732                                 state == AMD_CG_STATE_GATE);
733         return 0;
734
735 }
736
737 static int vega10_ih_set_powergating_state(void *handle,
738                                           enum amd_powergating_state state)
739 {
740         return 0;
741 }
742
743 const struct amd_ip_funcs vega10_ih_ip_funcs = {
744         .name = "vega10_ih",
745         .early_init = vega10_ih_early_init,
746         .late_init = NULL,
747         .sw_init = vega10_ih_sw_init,
748         .sw_fini = vega10_ih_sw_fini,
749         .hw_init = vega10_ih_hw_init,
750         .hw_fini = vega10_ih_hw_fini,
751         .suspend = vega10_ih_suspend,
752         .resume = vega10_ih_resume,
753         .is_idle = vega10_ih_is_idle,
754         .wait_for_idle = vega10_ih_wait_for_idle,
755         .soft_reset = vega10_ih_soft_reset,
756         .set_clockgating_state = vega10_ih_set_clockgating_state,
757         .set_powergating_state = vega10_ih_set_powergating_state,
758 };
759
760 static const struct amdgpu_ih_funcs vega10_ih_funcs = {
761         .get_wptr = vega10_ih_get_wptr,
762         .decode_iv = vega10_ih_decode_iv,
763         .set_rptr = vega10_ih_set_rptr
764 };
765
766 static void vega10_ih_set_interrupt_funcs(struct amdgpu_device *adev)
767 {
768         adev->irq.ih_funcs = &vega10_ih_funcs;
769 }
770
771 const struct amdgpu_ip_block_version vega10_ih_ip_block =
772 {
773         .type = AMD_IP_BLOCK_TYPE_IH,
774         .major = 4,
775         .minor = 0,
776         .rev = 0,
777         .funcs = &vega10_ih_ip_funcs,
778 };