xref: /openbmc/linux/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c (revision 352b919c)
1e60f8db5SAlex Xie /*
2e60f8db5SAlex Xie  * Copyright 2016 Advanced Micro Devices, Inc.
3e60f8db5SAlex Xie  *
4e60f8db5SAlex Xie  * Permission is hereby granted, free of charge, to any person obtaining a
5e60f8db5SAlex Xie  * copy of this software and associated documentation files (the "Software"),
6e60f8db5SAlex Xie  * to deal in the Software without restriction, including without limitation
7e60f8db5SAlex Xie  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8e60f8db5SAlex Xie  * and/or sell copies of the Software, and to permit persons to whom the
9e60f8db5SAlex Xie  * Software is furnished to do so, subject to the following conditions:
10e60f8db5SAlex Xie  *
11e60f8db5SAlex Xie  * The above copyright notice and this permission notice shall be included in
12e60f8db5SAlex Xie  * all copies or substantial portions of the Software.
13e60f8db5SAlex Xie  *
14e60f8db5SAlex Xie  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15e60f8db5SAlex Xie  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16e60f8db5SAlex Xie  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17e60f8db5SAlex Xie  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18e60f8db5SAlex Xie  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19e60f8db5SAlex Xie  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20e60f8db5SAlex Xie  * OTHER DEALINGS IN THE SOFTWARE.
21e60f8db5SAlex Xie  *
22e60f8db5SAlex Xie  */
23f867723bSSam Ravnborg 
24e60f8db5SAlex Xie #include <linux/firmware.h>
25f867723bSSam Ravnborg #include <linux/pci.h>
26f867723bSSam Ravnborg 
27fd5fd480SChunming Zhou #include <drm/drm_cache.h>
28f867723bSSam Ravnborg 
29e60f8db5SAlex Xie #include "amdgpu.h"
30e60f8db5SAlex Xie #include "gmc_v9_0.h"
318d6a5230SAlex Deucher #include "amdgpu_atomfirmware.h"
322cddc50eSHuang Rui #include "amdgpu_gem.h"
33e60f8db5SAlex Xie 
34cde5c34fSFeifei Xu #include "gc/gc_9_0_sh_mask.h"
35135d4b10SFeifei Xu #include "dce/dce_12_0_offset.h"
36135d4b10SFeifei Xu #include "dce/dce_12_0_sh_mask.h"
37fb960bd2SFeifei Xu #include "vega10_enum.h"
3865417d9fSFeifei Xu #include "mmhub/mmhub_1_0_offset.h"
39ea930000SAlex Sierra #include "athub/athub_1_0_sh_mask.h"
406ce68225SFeifei Xu #include "athub/athub_1_0_offset.h"
41250b4228SChristian König #include "oss/osssys_4_0_offset.h"
42e60f8db5SAlex Xie 
43946a4d5bSShaoyun Liu #include "soc15.h"
44ea930000SAlex Sierra #include "soc15d.h"
45e60f8db5SAlex Xie #include "soc15_common.h"
4690c7a935SFeifei Xu #include "umc/umc_6_0_sh_mask.h"
47e60f8db5SAlex Xie 
48e60f8db5SAlex Xie #include "gfxhub_v1_0.h"
49e60f8db5SAlex Xie #include "mmhub_v1_0.h"
50bee7b51aSLe Ma #include "athub_v1_0.h"
51bf0a60b7SAlex Deucher #include "gfxhub_v1_1.h"
52018f7300SLe Ma #include "gfxhub_v1_2.h"
5351cce480SLe Ma #include "mmhub_v9_4.h"
5485e39550SLe Ma #include "mmhub_v1_7.h"
55018f7300SLe Ma #include "mmhub_v1_8.h"
565b6b35aaSHawking Zhang #include "umc_v6_1.h"
57e7da754bSMonk Liu #include "umc_v6_0.h"
58186c8a85SJohn Clements #include "umc_v6_7.h"
596f12507fSHawking Zhang #include "hdp_v4_0.h"
603907c492SJohn Clements #include "mca_v3_0.h"
61e60f8db5SAlex Xie 
6244a99b65SAndrey Grodzovsky #include "ivsrcid/vmc/irqsrcs_vmc_1_0.h"
6344a99b65SAndrey Grodzovsky 
64791c4769Sxinhui pan #include "amdgpu_ras.h"
65029fbd43SHawking Zhang #include "amdgpu_xgmi.h"
66791c4769Sxinhui pan 
67d0fb18b5SAndrey Grodzovsky #include "amdgpu_reset.h"
68d0fb18b5SAndrey Grodzovsky 
69ebdef28eSAlex Deucher /* add these here since we already include dce12 headers and these are for DCN */
70ebdef28eSAlex Deucher #define mmHUBP0_DCSURF_PRI_VIEWPORT_DIMENSION                                                          0x055d
71ebdef28eSAlex Deucher #define mmHUBP0_DCSURF_PRI_VIEWPORT_DIMENSION_BASE_IDX                                                 2
72ebdef28eSAlex Deucher #define HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION__PRI_VIEWPORT_WIDTH__SHIFT                                        0x0
73ebdef28eSAlex Deucher #define HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION__PRI_VIEWPORT_HEIGHT__SHIFT                                       0x10
74ebdef28eSAlex Deucher #define HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION__PRI_VIEWPORT_WIDTH_MASK                                          0x00003FFFL
75ebdef28eSAlex Deucher #define HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION__PRI_VIEWPORT_HEIGHT_MASK                                         0x3FFF0000L
76f8646661SAlex Deucher #define mmDCHUBBUB_SDPIF_MMIO_CNTRL_0                                                                  0x049d
77f8646661SAlex Deucher #define mmDCHUBBUB_SDPIF_MMIO_CNTRL_0_BASE_IDX                                                         2
78f8646661SAlex Deucher 
79dc5d4affSHarry Wentland #define mmHUBP0_DCSURF_PRI_VIEWPORT_DIMENSION_DCN2                                                          0x05ea
80dc5d4affSHarry Wentland #define mmHUBP0_DCSURF_PRI_VIEWPORT_DIMENSION_DCN2_BASE_IDX                                                 2
81dc5d4affSHarry Wentland 
82a433f1f5SLijo Lazar #define MAX_MEM_RANGES 8
83ebdef28eSAlex Deucher 
84be99ecbfSAlex Deucher static const char *gfxhub_client_ids[] = {
85be99ecbfSAlex Deucher 	"CB",
86be99ecbfSAlex Deucher 	"DB",
87be99ecbfSAlex Deucher 	"IA",
88be99ecbfSAlex Deucher 	"WD",
89be99ecbfSAlex Deucher 	"CPF",
90be99ecbfSAlex Deucher 	"CPC",
91be99ecbfSAlex Deucher 	"CPG",
92be99ecbfSAlex Deucher 	"RLC",
93be99ecbfSAlex Deucher 	"TCP",
94be99ecbfSAlex Deucher 	"SQC (inst)",
95be99ecbfSAlex Deucher 	"SQC (data)",
96be99ecbfSAlex Deucher 	"SQG",
97be99ecbfSAlex Deucher 	"PA",
98be99ecbfSAlex Deucher };
99be99ecbfSAlex Deucher 
10002f23f5fSAlex Deucher static const char *mmhub_client_ids_raven[][2] = {
10102f23f5fSAlex Deucher 	[0][0] = "MP1",
10202f23f5fSAlex Deucher 	[1][0] = "MP0",
10302f23f5fSAlex Deucher 	[2][0] = "VCN",
10402f23f5fSAlex Deucher 	[3][0] = "VCNU",
10502f23f5fSAlex Deucher 	[4][0] = "HDP",
10602f23f5fSAlex Deucher 	[5][0] = "DCE",
10702f23f5fSAlex Deucher 	[13][0] = "UTCL2",
10802f23f5fSAlex Deucher 	[19][0] = "TLS",
10902f23f5fSAlex Deucher 	[26][0] = "OSS",
11002f23f5fSAlex Deucher 	[27][0] = "SDMA0",
11102f23f5fSAlex Deucher 	[0][1] = "MP1",
11202f23f5fSAlex Deucher 	[1][1] = "MP0",
11302f23f5fSAlex Deucher 	[2][1] = "VCN",
11402f23f5fSAlex Deucher 	[3][1] = "VCNU",
11502f23f5fSAlex Deucher 	[4][1] = "HDP",
11602f23f5fSAlex Deucher 	[5][1] = "XDP",
11702f23f5fSAlex Deucher 	[6][1] = "DBGU0",
11802f23f5fSAlex Deucher 	[7][1] = "DCE",
11902f23f5fSAlex Deucher 	[8][1] = "DCEDWB0",
12002f23f5fSAlex Deucher 	[9][1] = "DCEDWB1",
12102f23f5fSAlex Deucher 	[26][1] = "OSS",
12202f23f5fSAlex Deucher 	[27][1] = "SDMA0",
12302f23f5fSAlex Deucher };
12402f23f5fSAlex Deucher 
12502f23f5fSAlex Deucher static const char *mmhub_client_ids_renoir[][2] = {
12602f23f5fSAlex Deucher 	[0][0] = "MP1",
12702f23f5fSAlex Deucher 	[1][0] = "MP0",
12802f23f5fSAlex Deucher 	[2][0] = "HDP",
12902f23f5fSAlex Deucher 	[4][0] = "DCEDMC",
13002f23f5fSAlex Deucher 	[5][0] = "DCEVGA",
13102f23f5fSAlex Deucher 	[13][0] = "UTCL2",
13202f23f5fSAlex Deucher 	[19][0] = "TLS",
13302f23f5fSAlex Deucher 	[26][0] = "OSS",
13402f23f5fSAlex Deucher 	[27][0] = "SDMA0",
13502f23f5fSAlex Deucher 	[28][0] = "VCN",
13602f23f5fSAlex Deucher 	[29][0] = "VCNU",
13702f23f5fSAlex Deucher 	[30][0] = "JPEG",
13802f23f5fSAlex Deucher 	[0][1] = "MP1",
13902f23f5fSAlex Deucher 	[1][1] = "MP0",
14002f23f5fSAlex Deucher 	[2][1] = "HDP",
14102f23f5fSAlex Deucher 	[3][1] = "XDP",
14202f23f5fSAlex Deucher 	[6][1] = "DBGU0",
14302f23f5fSAlex Deucher 	[7][1] = "DCEDMC",
14402f23f5fSAlex Deucher 	[8][1] = "DCEVGA",
14502f23f5fSAlex Deucher 	[9][1] = "DCEDWB",
14602f23f5fSAlex Deucher 	[26][1] = "OSS",
14702f23f5fSAlex Deucher 	[27][1] = "SDMA0",
14802f23f5fSAlex Deucher 	[28][1] = "VCN",
14902f23f5fSAlex Deucher 	[29][1] = "VCNU",
15002f23f5fSAlex Deucher 	[30][1] = "JPEG",
15102f23f5fSAlex Deucher };
15202f23f5fSAlex Deucher 
15302f23f5fSAlex Deucher static const char *mmhub_client_ids_vega10[][2] = {
15402f23f5fSAlex Deucher 	[0][0] = "MP0",
15502f23f5fSAlex Deucher 	[1][0] = "UVD",
15602f23f5fSAlex Deucher 	[2][0] = "UVDU",
15702f23f5fSAlex Deucher 	[3][0] = "HDP",
15802f23f5fSAlex Deucher 	[13][0] = "UTCL2",
15902f23f5fSAlex Deucher 	[14][0] = "OSS",
16002f23f5fSAlex Deucher 	[15][0] = "SDMA1",
16102f23f5fSAlex Deucher 	[32+0][0] = "VCE0",
16202f23f5fSAlex Deucher 	[32+1][0] = "VCE0U",
16302f23f5fSAlex Deucher 	[32+2][0] = "XDMA",
16402f23f5fSAlex Deucher 	[32+3][0] = "DCE",
16502f23f5fSAlex Deucher 	[32+4][0] = "MP1",
16602f23f5fSAlex Deucher 	[32+14][0] = "SDMA0",
16702f23f5fSAlex Deucher 	[0][1] = "MP0",
16802f23f5fSAlex Deucher 	[1][1] = "UVD",
16902f23f5fSAlex Deucher 	[2][1] = "UVDU",
17002f23f5fSAlex Deucher 	[3][1] = "DBGU0",
17102f23f5fSAlex Deucher 	[4][1] = "HDP",
17202f23f5fSAlex Deucher 	[5][1] = "XDP",
17302f23f5fSAlex Deucher 	[14][1] = "OSS",
17402f23f5fSAlex Deucher 	[15][1] = "SDMA0",
17502f23f5fSAlex Deucher 	[32+0][1] = "VCE0",
17602f23f5fSAlex Deucher 	[32+1][1] = "VCE0U",
17702f23f5fSAlex Deucher 	[32+2][1] = "XDMA",
17802f23f5fSAlex Deucher 	[32+3][1] = "DCE",
17902f23f5fSAlex Deucher 	[32+4][1] = "DCEDWB",
18002f23f5fSAlex Deucher 	[32+5][1] = "MP1",
18102f23f5fSAlex Deucher 	[32+6][1] = "DBGU1",
18202f23f5fSAlex Deucher 	[32+14][1] = "SDMA1",
18302f23f5fSAlex Deucher };
18402f23f5fSAlex Deucher 
18502f23f5fSAlex Deucher static const char *mmhub_client_ids_vega12[][2] = {
18602f23f5fSAlex Deucher 	[0][0] = "MP0",
18702f23f5fSAlex Deucher 	[1][0] = "VCE0",
18802f23f5fSAlex Deucher 	[2][0] = "VCE0U",
18902f23f5fSAlex Deucher 	[3][0] = "HDP",
19002f23f5fSAlex Deucher 	[13][0] = "UTCL2",
19102f23f5fSAlex Deucher 	[14][0] = "OSS",
19202f23f5fSAlex Deucher 	[15][0] = "SDMA1",
19302f23f5fSAlex Deucher 	[32+0][0] = "DCE",
19402f23f5fSAlex Deucher 	[32+1][0] = "XDMA",
19502f23f5fSAlex Deucher 	[32+2][0] = "UVD",
19602f23f5fSAlex Deucher 	[32+3][0] = "UVDU",
19702f23f5fSAlex Deucher 	[32+4][0] = "MP1",
19802f23f5fSAlex Deucher 	[32+15][0] = "SDMA0",
19902f23f5fSAlex Deucher 	[0][1] = "MP0",
20002f23f5fSAlex Deucher 	[1][1] = "VCE0",
20102f23f5fSAlex Deucher 	[2][1] = "VCE0U",
20202f23f5fSAlex Deucher 	[3][1] = "DBGU0",
20302f23f5fSAlex Deucher 	[4][1] = "HDP",
20402f23f5fSAlex Deucher 	[5][1] = "XDP",
20502f23f5fSAlex Deucher 	[14][1] = "OSS",
20602f23f5fSAlex Deucher 	[15][1] = "SDMA0",
20702f23f5fSAlex Deucher 	[32+0][1] = "DCE",
20802f23f5fSAlex Deucher 	[32+1][1] = "DCEDWB",
20902f23f5fSAlex Deucher 	[32+2][1] = "XDMA",
21002f23f5fSAlex Deucher 	[32+3][1] = "UVD",
21102f23f5fSAlex Deucher 	[32+4][1] = "UVDU",
21202f23f5fSAlex Deucher 	[32+5][1] = "MP1",
21302f23f5fSAlex Deucher 	[32+6][1] = "DBGU1",
21402f23f5fSAlex Deucher 	[32+15][1] = "SDMA1",
21502f23f5fSAlex Deucher };
21602f23f5fSAlex Deucher 
21702f23f5fSAlex Deucher static const char *mmhub_client_ids_vega20[][2] = {
21802f23f5fSAlex Deucher 	[0][0] = "XDMA",
21902f23f5fSAlex Deucher 	[1][0] = "DCE",
22002f23f5fSAlex Deucher 	[2][0] = "VCE0",
22102f23f5fSAlex Deucher 	[3][0] = "VCE0U",
22202f23f5fSAlex Deucher 	[4][0] = "UVD",
22302f23f5fSAlex Deucher 	[5][0] = "UVD1U",
22402f23f5fSAlex Deucher 	[13][0] = "OSS",
22502f23f5fSAlex Deucher 	[14][0] = "HDP",
22602f23f5fSAlex Deucher 	[15][0] = "SDMA0",
22702f23f5fSAlex Deucher 	[32+0][0] = "UVD",
22802f23f5fSAlex Deucher 	[32+1][0] = "UVDU",
22902f23f5fSAlex Deucher 	[32+2][0] = "MP1",
23002f23f5fSAlex Deucher 	[32+3][0] = "MP0",
23102f23f5fSAlex Deucher 	[32+12][0] = "UTCL2",
23202f23f5fSAlex Deucher 	[32+14][0] = "SDMA1",
23302f23f5fSAlex Deucher 	[0][1] = "XDMA",
23402f23f5fSAlex Deucher 	[1][1] = "DCE",
23502f23f5fSAlex Deucher 	[2][1] = "DCEDWB",
23602f23f5fSAlex Deucher 	[3][1] = "VCE0",
23702f23f5fSAlex Deucher 	[4][1] = "VCE0U",
23802f23f5fSAlex Deucher 	[5][1] = "UVD1",
23902f23f5fSAlex Deucher 	[6][1] = "UVD1U",
24002f23f5fSAlex Deucher 	[7][1] = "DBGU0",
24102f23f5fSAlex Deucher 	[8][1] = "XDP",
24202f23f5fSAlex Deucher 	[13][1] = "OSS",
24302f23f5fSAlex Deucher 	[14][1] = "HDP",
24402f23f5fSAlex Deucher 	[15][1] = "SDMA0",
24502f23f5fSAlex Deucher 	[32+0][1] = "UVD",
24602f23f5fSAlex Deucher 	[32+1][1] = "UVDU",
24702f23f5fSAlex Deucher 	[32+2][1] = "DBGU1",
24802f23f5fSAlex Deucher 	[32+3][1] = "MP1",
24902f23f5fSAlex Deucher 	[32+4][1] = "MP0",
25002f23f5fSAlex Deucher 	[32+14][1] = "SDMA1",
25102f23f5fSAlex Deucher };
25202f23f5fSAlex Deucher 
25302f23f5fSAlex Deucher static const char *mmhub_client_ids_arcturus[][2] = {
254e83db774SAlex Deucher 	[0][0] = "DBGU1",
255e83db774SAlex Deucher 	[1][0] = "XDP",
25602f23f5fSAlex Deucher 	[2][0] = "MP1",
25702f23f5fSAlex Deucher 	[14][0] = "HDP",
258e83db774SAlex Deucher 	[171][0] = "JPEG",
259e83db774SAlex Deucher 	[172][0] = "VCN",
260e83db774SAlex Deucher 	[173][0] = "VCNU",
261e83db774SAlex Deucher 	[203][0] = "JPEG1",
262e83db774SAlex Deucher 	[204][0] = "VCN1",
263e83db774SAlex Deucher 	[205][0] = "VCN1U",
264e83db774SAlex Deucher 	[256][0] = "SDMA0",
265e83db774SAlex Deucher 	[257][0] = "SDMA1",
266e83db774SAlex Deucher 	[258][0] = "SDMA2",
267e83db774SAlex Deucher 	[259][0] = "SDMA3",
268e83db774SAlex Deucher 	[260][0] = "SDMA4",
269e83db774SAlex Deucher 	[261][0] = "SDMA5",
270e83db774SAlex Deucher 	[262][0] = "SDMA6",
271e83db774SAlex Deucher 	[263][0] = "SDMA7",
272e83db774SAlex Deucher 	[384][0] = "OSS",
27302f23f5fSAlex Deucher 	[0][1] = "DBGU1",
27402f23f5fSAlex Deucher 	[1][1] = "XDP",
27502f23f5fSAlex Deucher 	[2][1] = "MP1",
27602f23f5fSAlex Deucher 	[14][1] = "HDP",
277e83db774SAlex Deucher 	[171][1] = "JPEG",
278e83db774SAlex Deucher 	[172][1] = "VCN",
279e83db774SAlex Deucher 	[173][1] = "VCNU",
280e83db774SAlex Deucher 	[203][1] = "JPEG1",
281e83db774SAlex Deucher 	[204][1] = "VCN1",
282e83db774SAlex Deucher 	[205][1] = "VCN1U",
283e83db774SAlex Deucher 	[256][1] = "SDMA0",
284e83db774SAlex Deucher 	[257][1] = "SDMA1",
285e83db774SAlex Deucher 	[258][1] = "SDMA2",
286e83db774SAlex Deucher 	[259][1] = "SDMA3",
287e83db774SAlex Deucher 	[260][1] = "SDMA4",
288e83db774SAlex Deucher 	[261][1] = "SDMA5",
289e83db774SAlex Deucher 	[262][1] = "SDMA6",
290e83db774SAlex Deucher 	[263][1] = "SDMA7",
291e83db774SAlex Deucher 	[384][1] = "OSS",
29202f23f5fSAlex Deucher };
293e60f8db5SAlex Xie 
294e844cd99SAlex Deucher static const char *mmhub_client_ids_aldebaran[][2] = {
295e844cd99SAlex Deucher 	[2][0] = "MP1",
296e844cd99SAlex Deucher 	[3][0] = "MP0",
297f4ec3e50SAlex Sierra 	[32+1][0] = "DBGU_IO0",
298f4ec3e50SAlex Sierra 	[32+2][0] = "DBGU_IO2",
299e844cd99SAlex Deucher 	[32+4][0] = "MPIO",
300e844cd99SAlex Deucher 	[96+11][0] = "JPEG0",
301e844cd99SAlex Deucher 	[96+12][0] = "VCN0",
302e844cd99SAlex Deucher 	[96+13][0] = "VCNU0",
303e844cd99SAlex Deucher 	[128+11][0] = "JPEG1",
304e844cd99SAlex Deucher 	[128+12][0] = "VCN1",
305e844cd99SAlex Deucher 	[128+13][0] = "VCNU1",
306f4ec3e50SAlex Sierra 	[160+1][0] = "XDP",
307e844cd99SAlex Deucher 	[160+14][0] = "HDP",
308f4ec3e50SAlex Sierra 	[256+0][0] = "SDMA0",
309f4ec3e50SAlex Sierra 	[256+1][0] = "SDMA1",
310f4ec3e50SAlex Sierra 	[256+2][0] = "SDMA2",
311f4ec3e50SAlex Sierra 	[256+3][0] = "SDMA3",
312f4ec3e50SAlex Sierra 	[256+4][0] = "SDMA4",
313f4ec3e50SAlex Sierra 	[384+0][0] = "OSS",
314e844cd99SAlex Deucher 	[2][1] = "MP1",
315e844cd99SAlex Deucher 	[3][1] = "MP0",
316e844cd99SAlex Deucher 	[32+1][1] = "DBGU_IO0",
317e844cd99SAlex Deucher 	[32+2][1] = "DBGU_IO2",
318e844cd99SAlex Deucher 	[32+4][1] = "MPIO",
319e844cd99SAlex Deucher 	[96+11][1] = "JPEG0",
320e844cd99SAlex Deucher 	[96+12][1] = "VCN0",
321e844cd99SAlex Deucher 	[96+13][1] = "VCNU0",
322e844cd99SAlex Deucher 	[128+11][1] = "JPEG1",
323e844cd99SAlex Deucher 	[128+12][1] = "VCN1",
324e844cd99SAlex Deucher 	[128+13][1] = "VCNU1",
325f4ec3e50SAlex Sierra 	[160+1][1] = "XDP",
326e844cd99SAlex Deucher 	[160+14][1] = "HDP",
327f4ec3e50SAlex Sierra 	[256+0][1] = "SDMA0",
328f4ec3e50SAlex Sierra 	[256+1][1] = "SDMA1",
329f4ec3e50SAlex Sierra 	[256+2][1] = "SDMA2",
330f4ec3e50SAlex Sierra 	[256+3][1] = "SDMA3",
331f4ec3e50SAlex Sierra 	[256+4][1] = "SDMA4",
332f4ec3e50SAlex Sierra 	[384+0][1] = "OSS",
333e844cd99SAlex Deucher };
334e844cd99SAlex Deucher 
335946a4d5bSShaoyun Liu static const struct soc15_reg_golden golden_settings_mmhub_1_0_0[] =
3365c583018SEvan Quan {
337946a4d5bSShaoyun Liu 	SOC15_REG_GOLDEN_VALUE(MMHUB, 0, mmDAGB1_WRCLI2, 0x00000007, 0xfe5fe0fa),
338946a4d5bSShaoyun Liu 	SOC15_REG_GOLDEN_VALUE(MMHUB, 0, mmMMEA1_DRAM_WR_CLI2GRP_MAP0, 0x00000030, 0x55555565)
3395c583018SEvan Quan };
3405c583018SEvan Quan 
341946a4d5bSShaoyun Liu static const struct soc15_reg_golden golden_settings_athub_1_0_0[] =
3425c583018SEvan Quan {
343946a4d5bSShaoyun Liu 	SOC15_REG_GOLDEN_VALUE(ATHUB, 0, mmRPB_ARB_CNTL, 0x0000ff00, 0x00000800),
344946a4d5bSShaoyun Liu 	SOC15_REG_GOLDEN_VALUE(ATHUB, 0, mmRPB_ARB_CNTL2, 0x00ff00ff, 0x00080008)
3455c583018SEvan Quan };
3465c583018SEvan Quan 
347791c4769Sxinhui pan static const uint32_t ecc_umc_mcumc_ctrl_addrs[] = {
348791c4769Sxinhui pan 	(0x000143c0 + 0x00000000),
349791c4769Sxinhui pan 	(0x000143c0 + 0x00000800),
350791c4769Sxinhui pan 	(0x000143c0 + 0x00001000),
351791c4769Sxinhui pan 	(0x000143c0 + 0x00001800),
352791c4769Sxinhui pan 	(0x000543c0 + 0x00000000),
353791c4769Sxinhui pan 	(0x000543c0 + 0x00000800),
354791c4769Sxinhui pan 	(0x000543c0 + 0x00001000),
355791c4769Sxinhui pan 	(0x000543c0 + 0x00001800),
356791c4769Sxinhui pan 	(0x000943c0 + 0x00000000),
357791c4769Sxinhui pan 	(0x000943c0 + 0x00000800),
358791c4769Sxinhui pan 	(0x000943c0 + 0x00001000),
359791c4769Sxinhui pan 	(0x000943c0 + 0x00001800),
360791c4769Sxinhui pan 	(0x000d43c0 + 0x00000000),
361791c4769Sxinhui pan 	(0x000d43c0 + 0x00000800),
362791c4769Sxinhui pan 	(0x000d43c0 + 0x00001000),
363791c4769Sxinhui pan 	(0x000d43c0 + 0x00001800),
364791c4769Sxinhui pan 	(0x001143c0 + 0x00000000),
365791c4769Sxinhui pan 	(0x001143c0 + 0x00000800),
366791c4769Sxinhui pan 	(0x001143c0 + 0x00001000),
367791c4769Sxinhui pan 	(0x001143c0 + 0x00001800),
368791c4769Sxinhui pan 	(0x001543c0 + 0x00000000),
369791c4769Sxinhui pan 	(0x001543c0 + 0x00000800),
370791c4769Sxinhui pan 	(0x001543c0 + 0x00001000),
371791c4769Sxinhui pan 	(0x001543c0 + 0x00001800),
372791c4769Sxinhui pan 	(0x001943c0 + 0x00000000),
373791c4769Sxinhui pan 	(0x001943c0 + 0x00000800),
374791c4769Sxinhui pan 	(0x001943c0 + 0x00001000),
375791c4769Sxinhui pan 	(0x001943c0 + 0x00001800),
376791c4769Sxinhui pan 	(0x001d43c0 + 0x00000000),
377791c4769Sxinhui pan 	(0x001d43c0 + 0x00000800),
378791c4769Sxinhui pan 	(0x001d43c0 + 0x00001000),
379791c4769Sxinhui pan 	(0x001d43c0 + 0x00001800),
38002bab923SDavid Panariti };
38102bab923SDavid Panariti 
382791c4769Sxinhui pan static const uint32_t ecc_umc_mcumc_ctrl_mask_addrs[] = {
383791c4769Sxinhui pan 	(0x000143e0 + 0x00000000),
384791c4769Sxinhui pan 	(0x000143e0 + 0x00000800),
385791c4769Sxinhui pan 	(0x000143e0 + 0x00001000),
386791c4769Sxinhui pan 	(0x000143e0 + 0x00001800),
387791c4769Sxinhui pan 	(0x000543e0 + 0x00000000),
388791c4769Sxinhui pan 	(0x000543e0 + 0x00000800),
389791c4769Sxinhui pan 	(0x000543e0 + 0x00001000),
390791c4769Sxinhui pan 	(0x000543e0 + 0x00001800),
391791c4769Sxinhui pan 	(0x000943e0 + 0x00000000),
392791c4769Sxinhui pan 	(0x000943e0 + 0x00000800),
393791c4769Sxinhui pan 	(0x000943e0 + 0x00001000),
394791c4769Sxinhui pan 	(0x000943e0 + 0x00001800),
395791c4769Sxinhui pan 	(0x000d43e0 + 0x00000000),
396791c4769Sxinhui pan 	(0x000d43e0 + 0x00000800),
397791c4769Sxinhui pan 	(0x000d43e0 + 0x00001000),
398791c4769Sxinhui pan 	(0x000d43e0 + 0x00001800),
399791c4769Sxinhui pan 	(0x001143e0 + 0x00000000),
400791c4769Sxinhui pan 	(0x001143e0 + 0x00000800),
401791c4769Sxinhui pan 	(0x001143e0 + 0x00001000),
402791c4769Sxinhui pan 	(0x001143e0 + 0x00001800),
403791c4769Sxinhui pan 	(0x001543e0 + 0x00000000),
404791c4769Sxinhui pan 	(0x001543e0 + 0x00000800),
405791c4769Sxinhui pan 	(0x001543e0 + 0x00001000),
406791c4769Sxinhui pan 	(0x001543e0 + 0x00001800),
407791c4769Sxinhui pan 	(0x001943e0 + 0x00000000),
408791c4769Sxinhui pan 	(0x001943e0 + 0x00000800),
409791c4769Sxinhui pan 	(0x001943e0 + 0x00001000),
410791c4769Sxinhui pan 	(0x001943e0 + 0x00001800),
411791c4769Sxinhui pan 	(0x001d43e0 + 0x00000000),
412791c4769Sxinhui pan 	(0x001d43e0 + 0x00000800),
413791c4769Sxinhui pan 	(0x001d43e0 + 0x00001000),
414791c4769Sxinhui pan 	(0x001d43e0 + 0x00001800),
41502bab923SDavid Panariti };
41602bab923SDavid Panariti 
417791c4769Sxinhui pan static int gmc_v9_0_ecc_interrupt_state(struct amdgpu_device *adev,
418791c4769Sxinhui pan 		struct amdgpu_irq_src *src,
419791c4769Sxinhui pan 		unsigned type,
420791c4769Sxinhui pan 		enum amdgpu_interrupt_state state)
421791c4769Sxinhui pan {
422791c4769Sxinhui pan 	u32 bits, i, tmp, reg;
423791c4769Sxinhui pan 
4241e2c6d55SJohn Clements 	/* Devices newer then VEGA10/12 shall have these programming
4251e2c6d55SJohn Clements 	     sequences performed by PSP BL */
4261e2c6d55SJohn Clements 	if (adev->asic_type >= CHIP_VEGA20)
4271e2c6d55SJohn Clements 		return 0;
4281e2c6d55SJohn Clements 
429791c4769Sxinhui pan 	bits = 0x7f;
430791c4769Sxinhui pan 
431791c4769Sxinhui pan 	switch (state) {
432791c4769Sxinhui pan 	case AMDGPU_IRQ_STATE_DISABLE:
433791c4769Sxinhui pan 		for (i = 0; i < ARRAY_SIZE(ecc_umc_mcumc_ctrl_addrs); i++) {
434791c4769Sxinhui pan 			reg = ecc_umc_mcumc_ctrl_addrs[i];
435791c4769Sxinhui pan 			tmp = RREG32(reg);
436791c4769Sxinhui pan 			tmp &= ~bits;
437791c4769Sxinhui pan 			WREG32(reg, tmp);
438791c4769Sxinhui pan 		}
439791c4769Sxinhui pan 		for (i = 0; i < ARRAY_SIZE(ecc_umc_mcumc_ctrl_mask_addrs); i++) {
440791c4769Sxinhui pan 			reg = ecc_umc_mcumc_ctrl_mask_addrs[i];
441791c4769Sxinhui pan 			tmp = RREG32(reg);
442791c4769Sxinhui pan 			tmp &= ~bits;
443791c4769Sxinhui pan 			WREG32(reg, tmp);
444791c4769Sxinhui pan 		}
445791c4769Sxinhui pan 		break;
446791c4769Sxinhui pan 	case AMDGPU_IRQ_STATE_ENABLE:
447791c4769Sxinhui pan 		for (i = 0; i < ARRAY_SIZE(ecc_umc_mcumc_ctrl_addrs); i++) {
448791c4769Sxinhui pan 			reg = ecc_umc_mcumc_ctrl_addrs[i];
449791c4769Sxinhui pan 			tmp = RREG32(reg);
450791c4769Sxinhui pan 			tmp |= bits;
451791c4769Sxinhui pan 			WREG32(reg, tmp);
452791c4769Sxinhui pan 		}
453791c4769Sxinhui pan 		for (i = 0; i < ARRAY_SIZE(ecc_umc_mcumc_ctrl_mask_addrs); i++) {
454791c4769Sxinhui pan 			reg = ecc_umc_mcumc_ctrl_mask_addrs[i];
455791c4769Sxinhui pan 			tmp = RREG32(reg);
456791c4769Sxinhui pan 			tmp |= bits;
457791c4769Sxinhui pan 			WREG32(reg, tmp);
458791c4769Sxinhui pan 		}
459791c4769Sxinhui pan 		break;
460791c4769Sxinhui pan 	default:
461791c4769Sxinhui pan 		break;
462791c4769Sxinhui pan 	}
463791c4769Sxinhui pan 
464791c4769Sxinhui pan 	return 0;
465791c4769Sxinhui pan }
466791c4769Sxinhui pan 
467e60f8db5SAlex Xie static int gmc_v9_0_vm_fault_interrupt_state(struct amdgpu_device *adev,
468e60f8db5SAlex Xie 					struct amdgpu_irq_src *src,
469e60f8db5SAlex Xie 					unsigned type,
470e60f8db5SAlex Xie 					enum amdgpu_interrupt_state state)
471e60f8db5SAlex Xie {
472e60f8db5SAlex Xie 	struct amdgpu_vmhub *hub;
473ae6d1416STom St Denis 	u32 tmp, reg, bits, i, j;
474e60f8db5SAlex Xie 
47511250164SChristian König 	bits = VM_CONTEXT1_CNTL__RANGE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK |
47611250164SChristian König 		VM_CONTEXT1_CNTL__DUMMY_PAGE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK |
47711250164SChristian König 		VM_CONTEXT1_CNTL__PDE0_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK |
47811250164SChristian König 		VM_CONTEXT1_CNTL__VALID_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK |
47911250164SChristian König 		VM_CONTEXT1_CNTL__READ_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK |
48011250164SChristian König 		VM_CONTEXT1_CNTL__WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK |
48111250164SChristian König 		VM_CONTEXT1_CNTL__EXECUTE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK;
48211250164SChristian König 
483e60f8db5SAlex Xie 	switch (state) {
484e60f8db5SAlex Xie 	case AMDGPU_IRQ_STATE_DISABLE:
485d9426c3dSLe Ma 		for_each_set_bit(j, adev->vmhubs_mask, AMDGPU_MAX_VMHUBS) {
486ae6d1416STom St Denis 			hub = &adev->vmhub[j];
487e60f8db5SAlex Xie 			for (i = 0; i < 16; i++) {
488e60f8db5SAlex Xie 				reg = hub->vm_context0_cntl + i;
48992f153bbSVictor Skvortsov 
490b93df61dSAlex Deucher 				/* This works because this interrupt is only
491b93df61dSAlex Deucher 				 * enabled at init/resume and disabled in
492b93df61dSAlex Deucher 				 * fini/suspend, so the overall state doesn't
493b93df61dSAlex Deucher 				 * change over the course of suspend/resume.
494b93df61dSAlex Deucher 				 */
495f4caf584SHawking Zhang 				if (adev->in_s0ix && (j == AMDGPU_GFXHUB(0)))
496b93df61dSAlex Deucher 					continue;
497b93df61dSAlex Deucher 
498f4caf584SHawking Zhang 				if (j >= AMDGPU_MMHUB0(0))
49992f153bbSVictor Skvortsov 					tmp = RREG32_SOC15_IP(MMHUB, reg);
500f4caf584SHawking Zhang 				else
501f4caf584SHawking Zhang 					tmp = RREG32_SOC15_IP(GC, reg);
50292f153bbSVictor Skvortsov 
503e60f8db5SAlex Xie 				tmp &= ~bits;
50492f153bbSVictor Skvortsov 
505f4caf584SHawking Zhang 				if (j >= AMDGPU_MMHUB0(0))
50692f153bbSVictor Skvortsov 					WREG32_SOC15_IP(MMHUB, reg, tmp);
507f4caf584SHawking Zhang 				else
508f4caf584SHawking Zhang 					WREG32_SOC15_IP(GC, reg, tmp);
509e60f8db5SAlex Xie 			}
510e60f8db5SAlex Xie 		}
511e60f8db5SAlex Xie 		break;
512e60f8db5SAlex Xie 	case AMDGPU_IRQ_STATE_ENABLE:
513d9426c3dSLe Ma 		for_each_set_bit(j, adev->vmhubs_mask, AMDGPU_MAX_VMHUBS) {
514ae6d1416STom St Denis 			hub = &adev->vmhub[j];
515e60f8db5SAlex Xie 			for (i = 0; i < 16; i++) {
516e60f8db5SAlex Xie 				reg = hub->vm_context0_cntl + i;
51792f153bbSVictor Skvortsov 
518b93df61dSAlex Deucher 				/* This works because this interrupt is only
519b93df61dSAlex Deucher 				 * enabled at init/resume and disabled in
520b93df61dSAlex Deucher 				 * fini/suspend, so the overall state doesn't
521b93df61dSAlex Deucher 				 * change over the course of suspend/resume.
522b93df61dSAlex Deucher 				 */
523f4caf584SHawking Zhang 				if (adev->in_s0ix && (j == AMDGPU_GFXHUB(0)))
524b93df61dSAlex Deucher 					continue;
525b93df61dSAlex Deucher 
526f4caf584SHawking Zhang 				if (j >= AMDGPU_MMHUB0(0))
52792f153bbSVictor Skvortsov 					tmp = RREG32_SOC15_IP(MMHUB, reg);
528f4caf584SHawking Zhang 				else
529f4caf584SHawking Zhang 					tmp = RREG32_SOC15_IP(GC, reg);
53092f153bbSVictor Skvortsov 
531e60f8db5SAlex Xie 				tmp |= bits;
53292f153bbSVictor Skvortsov 
533f4caf584SHawking Zhang 				if (j >= AMDGPU_MMHUB0(0))
53492f153bbSVictor Skvortsov 					WREG32_SOC15_IP(MMHUB, reg, tmp);
535f4caf584SHawking Zhang 				else
536f4caf584SHawking Zhang 					WREG32_SOC15_IP(GC, reg, tmp);
537e60f8db5SAlex Xie 			}
538e60f8db5SAlex Xie 		}
5399304ca4dSGustavo A. R. Silva 		break;
540e60f8db5SAlex Xie 	default:
541e60f8db5SAlex Xie 		break;
542e60f8db5SAlex Xie 	}
543e60f8db5SAlex Xie 
544e60f8db5SAlex Xie 	return 0;
545e60f8db5SAlex Xie }
546e60f8db5SAlex Xie 
547e60f8db5SAlex Xie static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev,
548e60f8db5SAlex Xie 				      struct amdgpu_irq_src *source,
549e60f8db5SAlex Xie 				      struct amdgpu_iv_entry *entry)
550e60f8db5SAlex Xie {
551c468f9e2SChristian König 	bool retry_fault = !!(entry->src_data[1] & 0x80);
552ff891a2eSPhilip Yang 	bool write_fault = !!(entry->src_data[1] & 0x20);
55302f23f5fSAlex Deucher 	uint32_t status = 0, cid = 0, rw = 0;
554e3898719SChristian König 	struct amdgpu_task_info task_info;
555e3898719SChristian König 	struct amdgpu_vmhub *hub;
55602f23f5fSAlex Deucher 	const char *mmhub_cid;
557e3898719SChristian König 	const char *hub_name;
558e3898719SChristian König 	u64 addr;
559318e431bSMukul Joshi 	uint32_t cam_index = 0;
560318e431bSMukul Joshi 	int ret;
56198b2e9caSLe Ma 	uint32_t node_id, xcc_id = 0;
562eaae4beeSPhilip Yang 
56398b2e9caSLe Ma 	node_id = entry->node_id;
564e60f8db5SAlex Xie 
565e60f8db5SAlex Xie 	addr = (u64)entry->src_data[0] << 12;
566e60f8db5SAlex Xie 	addr |= ((u64)entry->src_data[1] & 0xf) << 44;
567e60f8db5SAlex Xie 
5685fb34bd9SAlex Sierra 	if (entry->client_id == SOC15_IH_CLIENTID_VMC) {
5695fb34bd9SAlex Sierra 		hub_name = "mmhub0";
57098b2e9caSLe Ma 		hub = &adev->vmhub[AMDGPU_MMHUB0(node_id / 4)];
5715fb34bd9SAlex Sierra 	} else if (entry->client_id == SOC15_IH_CLIENTID_VMC1) {
5725fb34bd9SAlex Sierra 		hub_name = "mmhub1";
5735fb34bd9SAlex Sierra 		hub = &adev->vmhub[AMDGPU_MMHUB1(0)];
5745fb34bd9SAlex Sierra 	} else {
5755fb34bd9SAlex Sierra 		hub_name = "gfxhub0";
57698b2e9caSLe Ma 		if (adev->gfx.funcs->ih_node_to_logical_xcc) {
57798b2e9caSLe Ma 			xcc_id = adev->gfx.funcs->ih_node_to_logical_xcc(adev,
57898b2e9caSLe Ma 				node_id);
57998b2e9caSLe Ma 			if (xcc_id < 0)
58098b2e9caSLe Ma 				xcc_id = 0;
58198b2e9caSLe Ma 		}
58298b2e9caSLe Ma 		hub = &adev->vmhub[xcc_id];
5835fb34bd9SAlex Sierra 	}
5845fb34bd9SAlex Sierra 
5850291150dSChristian König 	if (retry_fault) {
586318e431bSMukul Joshi 		if (adev->irq.retry_cam_enabled) {
587318e431bSMukul Joshi 			/* Delegate it to a different ring if the hardware hasn't
588318e431bSMukul Joshi 			 * already done it.
589318e431bSMukul Joshi 			 */
590318e431bSMukul Joshi 			if (entry->ih == &adev->irq.ih) {
591318e431bSMukul Joshi 				amdgpu_irq_delegate(adev, entry, 8);
592318e431bSMukul Joshi 				return 1;
593318e431bSMukul Joshi 			}
59422666cc1SChristian König 
595318e431bSMukul Joshi 			cam_index = entry->src_data[2] & 0x3ff;
596318e431bSMukul Joshi 
597f5fe7edfSMukul Joshi 			ret = amdgpu_vm_handle_fault(adev, entry->pasid, entry->vmid, node_id,
5985fb34bd9SAlex Sierra 						     addr, write_fault);
599318e431bSMukul Joshi 			WDOORBELL32(adev->irq.retry_cam_doorbell_index, cam_index);
600318e431bSMukul Joshi 			if (ret)
601318e431bSMukul Joshi 				return 1;
602318e431bSMukul Joshi 		} else {
6030291150dSChristian König 			/* Process it onyl if it's the first fault for this address */
6040291150dSChristian König 			if (entry->ih != &adev->irq.ih_soft &&
6053c2d6ea2SPhilip Yang 			    amdgpu_gmc_filter_faults(adev, entry->ih, addr, entry->pasid,
6060291150dSChristian König 					     entry->timestamp))
6070291150dSChristian König 				return 1;
6080291150dSChristian König 
6090291150dSChristian König 			/* Delegate it to a different ring if the hardware hasn't
6100291150dSChristian König 			 * already done it.
6110291150dSChristian König 			 */
61258df0d71SSebastian Andrzej Siewior 			if (entry->ih == &adev->irq.ih) {
6130291150dSChristian König 				amdgpu_irq_delegate(adev, entry, 8);
6140291150dSChristian König 				return 1;
6150291150dSChristian König 			}
6160291150dSChristian König 
6170291150dSChristian König 			/* Try to handle the recoverable page faults by filling page
6180291150dSChristian König 			 * tables
6190291150dSChristian König 			 */
620f5fe7edfSMukul Joshi 			if (amdgpu_vm_handle_fault(adev, entry->pasid, entry->vmid, node_id,
6215fb34bd9SAlex Sierra 						   addr, write_fault))
6220291150dSChristian König 				return 1;
6230291150dSChristian König 		}
624318e431bSMukul Joshi 	}
625ec671737SChristian König 
626e3898719SChristian König 	if (!printk_ratelimit())
627e3898719SChristian König 		return 0;
62853499173SXiaojie Yuan 
629e60f8db5SAlex Xie 
63005794effSShirish S 	memset(&task_info, 0, sizeof(struct amdgpu_task_info));
631efaa9646SAndrey Grodzovsky 	amdgpu_vm_get_task_info(adev, entry->pasid, &task_info);
632efaa9646SAndrey Grodzovsky 
6334d6cbde3SFelix Kuehling 	dev_err(adev->dev,
634c468f9e2SChristian König 		"[%s] %s page fault (src_id:%u ring:%u vmid:%u "
635c468f9e2SChristian König 		"pasid:%u, for process %s pid %d thread %s pid %d)\n",
63651c60898SLe Ma 		hub_name, retry_fault ? "retry" : "no-retry",
637c4f46f22SChristian König 		entry->src_id, entry->ring_id, entry->vmid,
638efaa9646SAndrey Grodzovsky 		entry->pasid, task_info.process_name, task_info.tgid,
639efaa9646SAndrey Grodzovsky 		task_info.task_name, task_info.pid);
640be14729aSYong Zhao 	dev_err(adev->dev, "  in page starting at address 0x%016llx from IH client 0x%x (%s)\n",
641be14729aSYong Zhao 		addr, entry->client_id,
642be14729aSYong Zhao 		soc15_ih_clientid_name[entry->client_id]);
643e3898719SChristian König 
644eaae4beeSPhilip Yang 	if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 3))
645eaae4beeSPhilip Yang 		dev_err(adev->dev, "  cookie node_id %d fault from die %s%d%s\n",
646eaae4beeSPhilip Yang 			node_id, node_id % 4 == 3 ? "RSV" : "AID", node_id / 4,
647eaae4beeSPhilip Yang 			node_id % 4 == 1 ? ".XCD0" : node_id % 4 == 2 ? ".XCD1" : "");
648eaae4beeSPhilip Yang 
649e3898719SChristian König 	if (amdgpu_sriov_vf(adev))
650e3898719SChristian König 		return 0;
651e3898719SChristian König 
652e3898719SChristian König 	/*
653e3898719SChristian König 	 * Issue a dummy read to wait for the status register to
654e3898719SChristian König 	 * be updated to avoid reading an incorrect value due to
655e3898719SChristian König 	 * the new fast GRBM interface.
656e3898719SChristian König 	 */
657f4caf584SHawking Zhang 	if ((entry->vmid_src == AMDGPU_GFXHUB(0)) &&
658630e959fSAlex Deucher 	    (adev->ip_versions[GC_HWIP][0] < IP_VERSION(9, 4, 2)))
659e3898719SChristian König 		RREG32(hub->vm_l2_pro_fault_status);
660e3898719SChristian König 
661e3898719SChristian König 	status = RREG32(hub->vm_l2_pro_fault_status);
662e3898719SChristian König 	cid = REG_GET_FIELD(status, VM_L2_PROTECTION_FAULT_STATUS, CID);
663e3898719SChristian König 	rw = REG_GET_FIELD(status, VM_L2_PROTECTION_FAULT_STATUS, RW);
664e3898719SChristian König 	WREG32_P(hub->vm_l2_pro_fault_cntl, 1, ~1);
665e3898719SChristian König 
6664d6cbde3SFelix Kuehling 	dev_err(adev->dev,
6674d6cbde3SFelix Kuehling 		"VM_L2_PROTECTION_FAULT_STATUS:0x%08X\n",
6684d6cbde3SFelix Kuehling 		status);
66921e1217bSMukul Joshi 	if (entry->vmid_src == AMDGPU_GFXHUB(0)) {
670be99ecbfSAlex Deucher 		dev_err(adev->dev, "\t Faulty UTCL2 client ID: %s (0x%x)\n",
671e3898719SChristian König 			cid >= ARRAY_SIZE(gfxhub_client_ids) ? "unknown" :
672e3898719SChristian König 			gfxhub_client_ids[cid],
673be99ecbfSAlex Deucher 			cid);
67402f23f5fSAlex Deucher 	} else {
675630e959fSAlex Deucher 		switch (adev->ip_versions[MMHUB_HWIP][0]) {
676630e959fSAlex Deucher 		case IP_VERSION(9, 0, 0):
67702f23f5fSAlex Deucher 			mmhub_cid = mmhub_client_ids_vega10[cid][rw];
67802f23f5fSAlex Deucher 			break;
679630e959fSAlex Deucher 		case IP_VERSION(9, 3, 0):
68002f23f5fSAlex Deucher 			mmhub_cid = mmhub_client_ids_vega12[cid][rw];
68102f23f5fSAlex Deucher 			break;
682630e959fSAlex Deucher 		case IP_VERSION(9, 4, 0):
68302f23f5fSAlex Deucher 			mmhub_cid = mmhub_client_ids_vega20[cid][rw];
68402f23f5fSAlex Deucher 			break;
685630e959fSAlex Deucher 		case IP_VERSION(9, 4, 1):
68602f23f5fSAlex Deucher 			mmhub_cid = mmhub_client_ids_arcturus[cid][rw];
68702f23f5fSAlex Deucher 			break;
688630e959fSAlex Deucher 		case IP_VERSION(9, 1, 0):
689630e959fSAlex Deucher 		case IP_VERSION(9, 2, 0):
69002f23f5fSAlex Deucher 			mmhub_cid = mmhub_client_ids_raven[cid][rw];
69102f23f5fSAlex Deucher 			break;
692630e959fSAlex Deucher 		case IP_VERSION(1, 5, 0):
693630e959fSAlex Deucher 		case IP_VERSION(2, 4, 0):
69402f23f5fSAlex Deucher 			mmhub_cid = mmhub_client_ids_renoir[cid][rw];
69502f23f5fSAlex Deucher 			break;
696ab1a157eSHawking Zhang 		case IP_VERSION(1, 8, 0):
697630e959fSAlex Deucher 		case IP_VERSION(9, 4, 2):
698e844cd99SAlex Deucher 			mmhub_cid = mmhub_client_ids_aldebaran[cid][rw];
699e844cd99SAlex Deucher 			break;
70002f23f5fSAlex Deucher 		default:
70102f23f5fSAlex Deucher 			mmhub_cid = NULL;
70202f23f5fSAlex Deucher 			break;
70302f23f5fSAlex Deucher 		}
70402f23f5fSAlex Deucher 		dev_err(adev->dev, "\t Faulty UTCL2 client ID: %s (0x%x)\n",
70502f23f5fSAlex Deucher 			mmhub_cid ? mmhub_cid : "unknown", cid);
70602f23f5fSAlex Deucher 	}
7075ddd4a9aSYong Zhao 	dev_err(adev->dev, "\t MORE_FAULTS: 0x%lx\n",
7085ddd4a9aSYong Zhao 		REG_GET_FIELD(status,
7095ddd4a9aSYong Zhao 		VM_L2_PROTECTION_FAULT_STATUS, MORE_FAULTS));
7105ddd4a9aSYong Zhao 	dev_err(adev->dev, "\t WALKER_ERROR: 0x%lx\n",
7115ddd4a9aSYong Zhao 		REG_GET_FIELD(status,
7125ddd4a9aSYong Zhao 		VM_L2_PROTECTION_FAULT_STATUS, WALKER_ERROR));
7135ddd4a9aSYong Zhao 	dev_err(adev->dev, "\t PERMISSION_FAULTS: 0x%lx\n",
7145ddd4a9aSYong Zhao 		REG_GET_FIELD(status,
7155ddd4a9aSYong Zhao 		VM_L2_PROTECTION_FAULT_STATUS, PERMISSION_FAULTS));
7165ddd4a9aSYong Zhao 	dev_err(adev->dev, "\t MAPPING_ERROR: 0x%lx\n",
7175ddd4a9aSYong Zhao 		REG_GET_FIELD(status,
7185ddd4a9aSYong Zhao 		VM_L2_PROTECTION_FAULT_STATUS, MAPPING_ERROR));
71902f23f5fSAlex Deucher 	dev_err(adev->dev, "\t RW: 0x%x\n", rw);
720e60f8db5SAlex Xie 	return 0;
721e60f8db5SAlex Xie }
722e60f8db5SAlex Xie 
723e60f8db5SAlex Xie static const struct amdgpu_irq_src_funcs gmc_v9_0_irq_funcs = {
724e60f8db5SAlex Xie 	.set = gmc_v9_0_vm_fault_interrupt_state,
725e60f8db5SAlex Xie 	.process = gmc_v9_0_process_interrupt,
726e60f8db5SAlex Xie };
727e60f8db5SAlex Xie 
728791c4769Sxinhui pan 
729791c4769Sxinhui pan static const struct amdgpu_irq_src_funcs gmc_v9_0_ecc_funcs = {
730791c4769Sxinhui pan 	.set = gmc_v9_0_ecc_interrupt_state,
73134cc4fd9STao Zhou 	.process = amdgpu_umc_process_ecc_irq,
732791c4769Sxinhui pan };
733791c4769Sxinhui pan 
734e60f8db5SAlex Xie static void gmc_v9_0_set_irq_funcs(struct amdgpu_device *adev)
735e60f8db5SAlex Xie {
736770d13b1SChristian König 	adev->gmc.vm_fault.num_types = 1;
737770d13b1SChristian König 	adev->gmc.vm_fault.funcs = &gmc_v9_0_irq_funcs;
738791c4769Sxinhui pan 
73968d705ddSHawking Zhang 	if (!amdgpu_sriov_vf(adev) &&
74068d705ddSHawking Zhang 	    !adev->gmc.xgmi.connected_to_cpu) {
741791c4769Sxinhui pan 		adev->gmc.ecc_irq.num_types = 1;
742791c4769Sxinhui pan 		adev->gmc.ecc_irq.funcs = &gmc_v9_0_ecc_funcs;
743e60f8db5SAlex Xie 	}
7442ee9403eSZhigang Luo }
745e60f8db5SAlex Xie 
7462a79d868SYong Zhao static uint32_t gmc_v9_0_get_invalidate_req(unsigned int vmid,
7472a79d868SYong Zhao 					uint32_t flush_type)
74803f89febSChristian König {
74903f89febSChristian König 	u32 req = 0;
75003f89febSChristian König 
75103f89febSChristian König 	req = REG_SET_FIELD(req, VM_INVALIDATE_ENG0_REQ,
752c4f46f22SChristian König 			    PER_VMID_INVALIDATE_REQ, 1 << vmid);
7532a79d868SYong Zhao 	req = REG_SET_FIELD(req, VM_INVALIDATE_ENG0_REQ, FLUSH_TYPE, flush_type);
75403f89febSChristian König 	req = REG_SET_FIELD(req, VM_INVALIDATE_ENG0_REQ, INVALIDATE_L2_PTES, 1);
75503f89febSChristian König 	req = REG_SET_FIELD(req, VM_INVALIDATE_ENG0_REQ, INVALIDATE_L2_PDE0, 1);
75603f89febSChristian König 	req = REG_SET_FIELD(req, VM_INVALIDATE_ENG0_REQ, INVALIDATE_L2_PDE1, 1);
75703f89febSChristian König 	req = REG_SET_FIELD(req, VM_INVALIDATE_ENG0_REQ, INVALIDATE_L2_PDE2, 1);
75803f89febSChristian König 	req = REG_SET_FIELD(req, VM_INVALIDATE_ENG0_REQ, INVALIDATE_L1_PTES, 1);
75903f89febSChristian König 	req = REG_SET_FIELD(req, VM_INVALIDATE_ENG0_REQ,
76003f89febSChristian König 			    CLEAR_PROTECTION_FAULT_STATUS_ADDR,	0);
76103f89febSChristian König 
76203f89febSChristian König 	return req;
76303f89febSChristian König }
76403f89febSChristian König 
76590f6452cSchangzhu /**
76690f6452cSchangzhu  * gmc_v9_0_use_invalidate_semaphore - judge whether to use semaphore
76790f6452cSchangzhu  *
76890f6452cSchangzhu  * @adev: amdgpu_device pointer
76990f6452cSchangzhu  * @vmhub: vmhub type
77090f6452cSchangzhu  *
77190f6452cSchangzhu  */
77290f6452cSchangzhu static bool gmc_v9_0_use_invalidate_semaphore(struct amdgpu_device *adev,
77390f6452cSchangzhu 				       uint32_t vmhub)
77490f6452cSchangzhu {
775ab1a157eSHawking Zhang 	if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 2) ||
776ab1a157eSHawking Zhang 	    adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 3))
777d477c5aaSHawking Zhang 		return false;
778d477c5aaSHawking Zhang 
779f4caf584SHawking Zhang 	return ((vmhub == AMDGPU_MMHUB0(0) ||
780f4caf584SHawking Zhang 		 vmhub == AMDGPU_MMHUB1(0)) &&
78190f6452cSchangzhu 		(!amdgpu_sriov_vf(adev)) &&
78254f78a76SAlex Deucher 		(!(!(adev->apu_flags & AMD_APU_IS_RAVEN2) &&
78354f78a76SAlex Deucher 		   (adev->apu_flags & AMD_APU_IS_PICASSO))));
78490f6452cSchangzhu }
78590f6452cSchangzhu 
786ea930000SAlex Sierra static bool gmc_v9_0_get_atc_vmid_pasid_mapping_info(struct amdgpu_device *adev,
787ea930000SAlex Sierra 					uint8_t vmid, uint16_t *p_pasid)
788ea930000SAlex Sierra {
789ea930000SAlex Sierra 	uint32_t value;
790ea930000SAlex Sierra 
791ea930000SAlex Sierra 	value = RREG32(SOC15_REG_OFFSET(ATHUB, 0, mmATC_VMID0_PASID_MAPPING)
792ea930000SAlex Sierra 		     + vmid);
793ea930000SAlex Sierra 	*p_pasid = value & ATC_VMID0_PASID_MAPPING__PASID_MASK;
794ea930000SAlex Sierra 
795ea930000SAlex Sierra 	return !!(value & ATC_VMID0_PASID_MAPPING__VALID_MASK);
796ea930000SAlex Sierra }
797ea930000SAlex Sierra 
798e60f8db5SAlex Xie /*
799e60f8db5SAlex Xie  * GART
800e60f8db5SAlex Xie  * VMID 0 is the physical GPU addresses as used by the kernel.
801e60f8db5SAlex Xie  * VMIDs 1-15 are used for userspace clients and are handled
802e60f8db5SAlex Xie  * by the amdgpu vm/hsa code.
803e60f8db5SAlex Xie  */
804e60f8db5SAlex Xie 
805e60f8db5SAlex Xie /**
8062a79d868SYong Zhao  * gmc_v9_0_flush_gpu_tlb - tlb flush with certain type
807e60f8db5SAlex Xie  *
808e60f8db5SAlex Xie  * @adev: amdgpu_device pointer
809e60f8db5SAlex Xie  * @vmid: vm instance to flush
810bf0df09cSLee Jones  * @vmhub: which hub to flush
8112a79d868SYong Zhao  * @flush_type: the flush type
812e60f8db5SAlex Xie  *
8132a79d868SYong Zhao  * Flush the TLB for the requested page table using certain type.
814e60f8db5SAlex Xie  */
8153ff98548SOak Zeng static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
8163ff98548SOak Zeng 					uint32_t vmhub, uint32_t flush_type)
817e60f8db5SAlex Xie {
81890f6452cSchangzhu 	bool use_semaphore = gmc_v9_0_use_invalidate_semaphore(adev, vmhub);
819e60f8db5SAlex Xie 	const unsigned eng = 17;
820b80cd524SFelix Kuehling 	u32 j, inv_req, inv_req2, tmp;
8213ff98548SOak Zeng 	struct amdgpu_vmhub *hub;
822e60f8db5SAlex Xie 
823d9426c3dSLe Ma 	BUG_ON(vmhub >= AMDGPU_MAX_VMHUBS);
8243ff98548SOak Zeng 
8253ff98548SOak Zeng 	hub = &adev->vmhub[vmhub];
826b80cd524SFelix Kuehling 	if (adev->gmc.xgmi.num_physical_nodes &&
827630e959fSAlex Deucher 	    adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 0)) {
828b80cd524SFelix Kuehling 		/* Vega20+XGMI caches PTEs in TC and TLB. Add a
829b80cd524SFelix Kuehling 		 * heavy-weight TLB flush (type 2), which flushes
830b80cd524SFelix Kuehling 		 * both. Due to a race condition with concurrent
831b80cd524SFelix Kuehling 		 * memory accesses using the same TLB cache line, we
832b80cd524SFelix Kuehling 		 * still need a second TLB flush after this.
833b80cd524SFelix Kuehling 		 */
834b80cd524SFelix Kuehling 		inv_req = gmc_v9_0_get_invalidate_req(vmid, 2);
835b80cd524SFelix Kuehling 		inv_req2 = gmc_v9_0_get_invalidate_req(vmid, flush_type);
8362e8cc5d3SGraham Sider 	} else if (flush_type == 2 &&
8372e8cc5d3SGraham Sider 		   adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 3) &&
8382e8cc5d3SGraham Sider 		   adev->rev_id == 0) {
8392e8cc5d3SGraham Sider 		inv_req = gmc_v9_0_get_invalidate_req(vmid, 0);
8402e8cc5d3SGraham Sider 		inv_req2 = gmc_v9_0_get_invalidate_req(vmid, flush_type);
841b80cd524SFelix Kuehling 	} else {
84237c58ddfSFelix Kuehling 		inv_req = gmc_v9_0_get_invalidate_req(vmid, flush_type);
843b80cd524SFelix Kuehling 		inv_req2 = 0;
844b80cd524SFelix Kuehling 	}
845e60f8db5SAlex Xie 
84682d1a1b1SChengming Gui 	/* This is necessary for a HW workaround under SRIOV as well
84782d1a1b1SChengming Gui 	 * as GFXOFF under bare metal
84882d1a1b1SChengming Gui 	 */
849277bd337SLe Ma 	if (adev->gfx.kiq[0].ring.sched.ready &&
85082d1a1b1SChengming Gui 	    (amdgpu_sriov_runtime(adev) || !amdgpu_sriov_vf(adev)) &&
851d0fb18b5SAndrey Grodzovsky 	    down_read_trylock(&adev->reset_domain->sem)) {
852148f597dSHuang Rui 		uint32_t req = hub->vm_inv_eng0_req + hub->eng_distance * eng;
853148f597dSHuang Rui 		uint32_t ack = hub->vm_inv_eng0_ack + hub->eng_distance * eng;
854af5fe1e9SChristian König 
85537c58ddfSFelix Kuehling 		amdgpu_virt_kiq_reg_write_reg_wait(adev, req, ack, inv_req,
856af5fe1e9SChristian König 						   1 << vmid);
857d0fb18b5SAndrey Grodzovsky 		up_read(&adev->reset_domain->sem);
8583ff98548SOak Zeng 		return;
859fc0faf04SEmily Deng 	}
8603890d111SEmily Deng 
8613890d111SEmily Deng 	spin_lock(&adev->gmc.invalidate_lock);
862f920d1bbSchangzhu 
863f920d1bbSchangzhu 	/*
864f920d1bbSchangzhu 	 * It may lose gpuvm invalidate acknowldege state across power-gating
865f920d1bbSchangzhu 	 * off cycle, add semaphore acquire before invalidation and semaphore
866f920d1bbSchangzhu 	 * release after invalidation to avoid entering power gated state
867f920d1bbSchangzhu 	 * to WA the Issue
868f920d1bbSchangzhu 	 */
869f920d1bbSchangzhu 
870f920d1bbSchangzhu 	/* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
87190f6452cSchangzhu 	if (use_semaphore) {
872f920d1bbSchangzhu 		for (j = 0; j < adev->usec_timeout; j++) {
87392f153bbSVictor Skvortsov 			/* a read return value of 1 means semaphore acquire */
874f4caf584SHawking Zhang 			if (vmhub >= AMDGPU_MMHUB0(0))
87592f153bbSVictor Skvortsov 				tmp = RREG32_SOC15_IP_NO_KIQ(MMHUB, hub->vm_inv_eng0_sem + hub->eng_distance * eng);
876f4caf584SHawking Zhang 			else
877f4caf584SHawking Zhang 				tmp = RREG32_SOC15_IP_NO_KIQ(GC, hub->vm_inv_eng0_sem + hub->eng_distance * eng);
878f920d1bbSchangzhu 			if (tmp & 0x1)
879f920d1bbSchangzhu 				break;
880f920d1bbSchangzhu 			udelay(1);
881f920d1bbSchangzhu 		}
882f920d1bbSchangzhu 
883f920d1bbSchangzhu 		if (j >= adev->usec_timeout)
884f920d1bbSchangzhu 			DRM_ERROR("Timeout waiting for sem acquire in VM flush!\n");
885f920d1bbSchangzhu 	}
886f920d1bbSchangzhu 
887b80cd524SFelix Kuehling 	do {
888f4caf584SHawking Zhang 		if (vmhub >= AMDGPU_MMHUB0(0))
88992f153bbSVictor Skvortsov 			WREG32_SOC15_IP_NO_KIQ(MMHUB, hub->vm_inv_eng0_req + hub->eng_distance * eng, inv_req);
890f4caf584SHawking Zhang 		else
891f4caf584SHawking Zhang 			WREG32_SOC15_IP_NO_KIQ(GC, hub->vm_inv_eng0_req + hub->eng_distance * eng, inv_req);
89253499173SXiaojie Yuan 
89353499173SXiaojie Yuan 		/*
894b80cd524SFelix Kuehling 		 * Issue a dummy read to wait for the ACK register to
895b80cd524SFelix Kuehling 		 * be cleared to avoid a false ACK due to the new fast
896b80cd524SFelix Kuehling 		 * GRBM interface.
89753499173SXiaojie Yuan 		 */
898f4caf584SHawking Zhang 		if ((vmhub == AMDGPU_GFXHUB(0)) &&
899630e959fSAlex Deucher 		    (adev->ip_versions[GC_HWIP][0] < IP_VERSION(9, 4, 2)))
900148f597dSHuang Rui 			RREG32_NO_KIQ(hub->vm_inv_eng0_req +
901148f597dSHuang Rui 				      hub->eng_distance * eng);
90253499173SXiaojie Yuan 
903e60f8db5SAlex Xie 		for (j = 0; j < adev->usec_timeout; j++) {
904f4caf584SHawking Zhang 			if (vmhub >= AMDGPU_MMHUB0(0))
90592f153bbSVictor Skvortsov 				tmp = RREG32_SOC15_IP_NO_KIQ(MMHUB, hub->vm_inv_eng0_ack + hub->eng_distance * eng);
906f4caf584SHawking Zhang 			else
907f4caf584SHawking Zhang 				tmp = RREG32_SOC15_IP_NO_KIQ(GC, hub->vm_inv_eng0_ack + hub->eng_distance * eng);
908396557b0SChristian König 			if (tmp & (1 << vmid))
909e60f8db5SAlex Xie 				break;
910e60f8db5SAlex Xie 			udelay(1);
911e60f8db5SAlex Xie 		}
912f920d1bbSchangzhu 
913b80cd524SFelix Kuehling 		inv_req = inv_req2;
914b80cd524SFelix Kuehling 		inv_req2 = 0;
915b80cd524SFelix Kuehling 	} while (inv_req);
916b80cd524SFelix Kuehling 
917f920d1bbSchangzhu 	/* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
91892f153bbSVictor Skvortsov 	if (use_semaphore) {
919f920d1bbSchangzhu 		/*
920f920d1bbSchangzhu 		 * add semaphore release after invalidation,
921f920d1bbSchangzhu 		 * write with 0 means semaphore release
922f920d1bbSchangzhu 		 */
923f4caf584SHawking Zhang 		if (vmhub >= AMDGPU_MMHUB0(0))
924a0a0c69cSLijo Lazar 			WREG32_SOC15_IP_NO_KIQ(MMHUB, hub->vm_inv_eng0_sem + hub->eng_distance * eng, 0);
92592f153bbSVictor Skvortsov 		else
926a0a0c69cSLijo Lazar 			WREG32_SOC15_IP_NO_KIQ(GC, hub->vm_inv_eng0_sem + hub->eng_distance * eng, 0);
92792f153bbSVictor Skvortsov 	}
928f920d1bbSchangzhu 
9293890d111SEmily Deng 	spin_unlock(&adev->gmc.invalidate_lock);
930f920d1bbSchangzhu 
931396557b0SChristian König 	if (j < adev->usec_timeout)
9323ff98548SOak Zeng 		return;
933396557b0SChristian König 
934e60f8db5SAlex Xie 	DRM_ERROR("Timeout waiting for VM flush ACK!\n");
935e60f8db5SAlex Xie }
936e60f8db5SAlex Xie 
937ea930000SAlex Sierra /**
938ea930000SAlex Sierra  * gmc_v9_0_flush_gpu_tlb_pasid - tlb flush via pasid
939ea930000SAlex Sierra  *
940ea930000SAlex Sierra  * @adev: amdgpu_device pointer
941ea930000SAlex Sierra  * @pasid: pasid to be flush
942bf0df09cSLee Jones  * @flush_type: the flush type
943bf0df09cSLee Jones  * @all_hub: flush all hubs
944ea930000SAlex Sierra  *
945ea930000SAlex Sierra  * Flush the TLB for the requested pasid.
946ea930000SAlex Sierra  */
947ea930000SAlex Sierra static int gmc_v9_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev,
948ea930000SAlex Sierra 					uint16_t pasid, uint32_t flush_type,
949f87f6864SMukul Joshi 					bool all_hub, uint32_t inst)
950ea930000SAlex Sierra {
951ea930000SAlex Sierra 	int vmid, i;
952ea930000SAlex Sierra 	signed long r;
953ea930000SAlex Sierra 	uint32_t seq;
954ea930000SAlex Sierra 	uint16_t queried_pasid;
955ea930000SAlex Sierra 	bool ret;
956373008bfSDusica Milinkovic 	u32 usec_timeout = amdgpu_sriov_vf(adev) ? SRIOV_USEC_TIMEOUT : adev->usec_timeout;
957f87f6864SMukul Joshi 	struct amdgpu_ring *ring = &adev->gfx.kiq[inst].ring;
958f87f6864SMukul Joshi 	struct amdgpu_kiq *kiq = &adev->gfx.kiq[inst];
959ea930000SAlex Sierra 
96053b3f8f4SDennis Li 	if (amdgpu_in_reset(adev))
961ea930000SAlex Sierra 		return -EIO;
962ea930000SAlex Sierra 
963d0fb18b5SAndrey Grodzovsky 	if (ring->sched.ready && down_read_trylock(&adev->reset_domain->sem)) {
964b80cd524SFelix Kuehling 		/* Vega20+XGMI caches PTEs in TC and TLB. Add a
965b80cd524SFelix Kuehling 		 * heavy-weight TLB flush (type 2), which flushes
966b80cd524SFelix Kuehling 		 * both. Due to a race condition with concurrent
967b80cd524SFelix Kuehling 		 * memory accesses using the same TLB cache line, we
968b80cd524SFelix Kuehling 		 * still need a second TLB flush after this.
969b80cd524SFelix Kuehling 		 */
970b80cd524SFelix Kuehling 		bool vega20_xgmi_wa = (adev->gmc.xgmi.num_physical_nodes &&
971630e959fSAlex Deucher 				       adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 0));
972b80cd524SFelix Kuehling 		/* 2 dwords flush + 8 dwords fence */
973b80cd524SFelix Kuehling 		unsigned int ndw = kiq->pmf->invalidate_tlbs_size + 8;
974b80cd524SFelix Kuehling 
975b80cd524SFelix Kuehling 		if (vega20_xgmi_wa)
976b80cd524SFelix Kuehling 			ndw += kiq->pmf->invalidate_tlbs_size;
977b80cd524SFelix Kuehling 
978f87f6864SMukul Joshi 		spin_lock(&adev->gfx.kiq[inst].ring_lock);
97936a1707aSAlex Sierra 		/* 2 dwords flush + 8 dwords fence */
980b80cd524SFelix Kuehling 		amdgpu_ring_alloc(ring, ndw);
981b80cd524SFelix Kuehling 		if (vega20_xgmi_wa)
982b80cd524SFelix Kuehling 			kiq->pmf->kiq_invalidate_tlbs(ring,
983b80cd524SFelix Kuehling 						      pasid, 2, all_hub);
9842e8cc5d3SGraham Sider 
9852e8cc5d3SGraham Sider 		if (flush_type == 2 &&
9862e8cc5d3SGraham Sider 		    adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 3) &&
9872e8cc5d3SGraham Sider 		    adev->rev_id == 0)
9882e8cc5d3SGraham Sider 			kiq->pmf->kiq_invalidate_tlbs(ring,
9892e8cc5d3SGraham Sider 						pasid, 0, all_hub);
9902e8cc5d3SGraham Sider 
991ea930000SAlex Sierra 		kiq->pmf->kiq_invalidate_tlbs(ring,
992ea930000SAlex Sierra 					pasid, flush_type, all_hub);
99304e4e2e9SYintian Tao 		r = amdgpu_fence_emit_polling(ring, &seq, MAX_KIQ_REG_WAIT);
99404e4e2e9SYintian Tao 		if (r) {
99504e4e2e9SYintian Tao 			amdgpu_ring_undo(ring);
996f87f6864SMukul Joshi 			spin_unlock(&adev->gfx.kiq[inst].ring_lock);
997d0fb18b5SAndrey Grodzovsky 			up_read(&adev->reset_domain->sem);
99804e4e2e9SYintian Tao 			return -ETIME;
99904e4e2e9SYintian Tao 		}
100004e4e2e9SYintian Tao 
1001ea930000SAlex Sierra 		amdgpu_ring_commit(ring);
1002f87f6864SMukul Joshi 		spin_unlock(&adev->gfx.kiq[inst].ring_lock);
1003373008bfSDusica Milinkovic 		r = amdgpu_fence_wait_polling(ring, seq, usec_timeout);
1004ea930000SAlex Sierra 		if (r < 1) {
1005aac89168SDennis Li 			dev_err(adev->dev, "wait for kiq fence error: %ld.\n", r);
1006d0fb18b5SAndrey Grodzovsky 			up_read(&adev->reset_domain->sem);
1007ea930000SAlex Sierra 			return -ETIME;
1008ea930000SAlex Sierra 		}
1009d0fb18b5SAndrey Grodzovsky 		up_read(&adev->reset_domain->sem);
1010ea930000SAlex Sierra 		return 0;
1011ea930000SAlex Sierra 	}
1012ea930000SAlex Sierra 
1013ea930000SAlex Sierra 	for (vmid = 1; vmid < 16; vmid++) {
1014ea930000SAlex Sierra 
1015ea930000SAlex Sierra 		ret = gmc_v9_0_get_atc_vmid_pasid_mapping_info(adev, vmid,
1016ea930000SAlex Sierra 				&queried_pasid);
1017ea930000SAlex Sierra 		if (ret && queried_pasid == pasid) {
1018ea930000SAlex Sierra 			if (all_hub) {
1019d9426c3dSLe Ma 				for_each_set_bit(i, adev->vmhubs_mask, AMDGPU_MAX_VMHUBS)
1020ea930000SAlex Sierra 					gmc_v9_0_flush_gpu_tlb(adev, vmid,
1021fa34edbeSFelix Kuehling 							i, flush_type);
1022ea930000SAlex Sierra 			} else {
1023ea930000SAlex Sierra 				gmc_v9_0_flush_gpu_tlb(adev, vmid,
1024f4caf584SHawking Zhang 						AMDGPU_GFXHUB(0), flush_type);
1025ea930000SAlex Sierra 			}
1026ea930000SAlex Sierra 			break;
1027ea930000SAlex Sierra 		}
1028ea930000SAlex Sierra 	}
1029ea930000SAlex Sierra 
1030ea930000SAlex Sierra 	return 0;
1031ea930000SAlex Sierra 
1032ea930000SAlex Sierra }
1033ea930000SAlex Sierra 
10349096d6e5SChristian König static uint64_t gmc_v9_0_emit_flush_gpu_tlb(struct amdgpu_ring *ring,
1035c633c00bSChristian König 					    unsigned vmid, uint64_t pd_addr)
10369096d6e5SChristian König {
10370530553bSLe Ma 	bool use_semaphore = gmc_v9_0_use_invalidate_semaphore(ring->adev, ring->vm_hub);
1038250b4228SChristian König 	struct amdgpu_device *adev = ring->adev;
10390530553bSLe Ma 	struct amdgpu_vmhub *hub = &adev->vmhub[ring->vm_hub];
10402a79d868SYong Zhao 	uint32_t req = gmc_v9_0_get_invalidate_req(vmid, 0);
10419096d6e5SChristian König 	unsigned eng = ring->vm_inv_eng;
10429096d6e5SChristian König 
1043f920d1bbSchangzhu 	/*
1044f920d1bbSchangzhu 	 * It may lose gpuvm invalidate acknowldege state across power-gating
1045f920d1bbSchangzhu 	 * off cycle, add semaphore acquire before invalidation and semaphore
1046f920d1bbSchangzhu 	 * release after invalidation to avoid entering power gated state
1047f920d1bbSchangzhu 	 * to WA the Issue
1048f920d1bbSchangzhu 	 */
1049f920d1bbSchangzhu 
1050f920d1bbSchangzhu 	/* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
105190f6452cSchangzhu 	if (use_semaphore)
1052f920d1bbSchangzhu 		/* a read return value of 1 means semaphore acuqire */
1053f920d1bbSchangzhu 		amdgpu_ring_emit_reg_wait(ring,
1054148f597dSHuang Rui 					  hub->vm_inv_eng0_sem +
1055148f597dSHuang Rui 					  hub->eng_distance * eng, 0x1, 0x1);
1056f920d1bbSchangzhu 
1057148f597dSHuang Rui 	amdgpu_ring_emit_wreg(ring, hub->ctx0_ptb_addr_lo32 +
1058148f597dSHuang Rui 			      (hub->ctx_addr_distance * vmid),
10599096d6e5SChristian König 			      lower_32_bits(pd_addr));
10609096d6e5SChristian König 
1061148f597dSHuang Rui 	amdgpu_ring_emit_wreg(ring, hub->ctx0_ptb_addr_hi32 +
1062148f597dSHuang Rui 			      (hub->ctx_addr_distance * vmid),
10639096d6e5SChristian König 			      upper_32_bits(pd_addr));
10649096d6e5SChristian König 
1065148f597dSHuang Rui 	amdgpu_ring_emit_reg_write_reg_wait(ring, hub->vm_inv_eng0_req +
1066148f597dSHuang Rui 					    hub->eng_distance * eng,
1067148f597dSHuang Rui 					    hub->vm_inv_eng0_ack +
1068148f597dSHuang Rui 					    hub->eng_distance * eng,
1069f8bc9037SAlex Deucher 					    req, 1 << vmid);
1070f732b6b3SChristian König 
1071f920d1bbSchangzhu 	/* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
107290f6452cSchangzhu 	if (use_semaphore)
1073f920d1bbSchangzhu 		/*
1074f920d1bbSchangzhu 		 * add semaphore release after invalidation,
1075f920d1bbSchangzhu 		 * write with 0 means semaphore release
1076f920d1bbSchangzhu 		 */
1077148f597dSHuang Rui 		amdgpu_ring_emit_wreg(ring, hub->vm_inv_eng0_sem +
1078148f597dSHuang Rui 				      hub->eng_distance * eng, 0);
1079f920d1bbSchangzhu 
10809096d6e5SChristian König 	return pd_addr;
10819096d6e5SChristian König }
10829096d6e5SChristian König 
1083c633c00bSChristian König static void gmc_v9_0_emit_pasid_mapping(struct amdgpu_ring *ring, unsigned vmid,
1084c633c00bSChristian König 					unsigned pasid)
1085c633c00bSChristian König {
1086c633c00bSChristian König 	struct amdgpu_device *adev = ring->adev;
1087c633c00bSChristian König 	uint32_t reg;
1088c633c00bSChristian König 
1089f2d66571SLe Ma 	/* Do nothing because there's no lut register for mmhub1. */
1090f4caf584SHawking Zhang 	if (ring->vm_hub == AMDGPU_MMHUB1(0))
1091f2d66571SLe Ma 		return;
1092f2d66571SLe Ma 
1093f4caf584SHawking Zhang 	if (ring->vm_hub == AMDGPU_GFXHUB(0))
1094c633c00bSChristian König 		reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_VMID_0_LUT) + vmid;
1095c633c00bSChristian König 	else
1096c633c00bSChristian König 		reg = SOC15_REG_OFFSET(OSSSYS, 0, mmIH_VMID_0_LUT_MM) + vmid;
1097c633c00bSChristian König 
1098c633c00bSChristian König 	amdgpu_ring_emit_wreg(ring, reg, pasid);
1099c633c00bSChristian König }
1100c633c00bSChristian König 
1101e60f8db5SAlex Xie /*
1102e60f8db5SAlex Xie  * PTE format on VEGA 10:
1103e60f8db5SAlex Xie  * 63:59 reserved
1104e60f8db5SAlex Xie  * 58:57 mtype
1105e60f8db5SAlex Xie  * 56 F
1106e60f8db5SAlex Xie  * 55 L
1107e60f8db5SAlex Xie  * 54 P
1108e60f8db5SAlex Xie  * 53 SW
1109e60f8db5SAlex Xie  * 52 T
1110e60f8db5SAlex Xie  * 50:48 reserved
1111e60f8db5SAlex Xie  * 47:12 4k physical page base address
1112e60f8db5SAlex Xie  * 11:7 fragment
1113e60f8db5SAlex Xie  * 6 write
1114e60f8db5SAlex Xie  * 5 read
1115e60f8db5SAlex Xie  * 4 exe
1116e60f8db5SAlex Xie  * 3 Z
1117e60f8db5SAlex Xie  * 2 snooped
1118e60f8db5SAlex Xie  * 1 system
1119e60f8db5SAlex Xie  * 0 valid
1120e60f8db5SAlex Xie  *
1121e60f8db5SAlex Xie  * PDE format on VEGA 10:
1122e60f8db5SAlex Xie  * 63:59 block fragment size
1123e60f8db5SAlex Xie  * 58:55 reserved
1124e60f8db5SAlex Xie  * 54 P
1125e60f8db5SAlex Xie  * 53:48 reserved
1126e60f8db5SAlex Xie  * 47:6 physical base address of PD or PTE
1127e60f8db5SAlex Xie  * 5:3 reserved
1128e60f8db5SAlex Xie  * 2 C
1129e60f8db5SAlex Xie  * 1 system
1130e60f8db5SAlex Xie  * 0 valid
1131e60f8db5SAlex Xie  */
1132e60f8db5SAlex Xie 
113371776b6dSChristian König static uint64_t gmc_v9_0_map_mtype(struct amdgpu_device *adev, uint32_t flags)
1134e60f8db5SAlex Xie 
1135e60f8db5SAlex Xie {
113671776b6dSChristian König 	switch (flags) {
1137e60f8db5SAlex Xie 	case AMDGPU_VM_MTYPE_DEFAULT:
113871776b6dSChristian König 		return AMDGPU_PTE_MTYPE_VG10(MTYPE_NC);
1139e60f8db5SAlex Xie 	case AMDGPU_VM_MTYPE_NC:
114071776b6dSChristian König 		return AMDGPU_PTE_MTYPE_VG10(MTYPE_NC);
1141e60f8db5SAlex Xie 	case AMDGPU_VM_MTYPE_WC:
114271776b6dSChristian König 		return AMDGPU_PTE_MTYPE_VG10(MTYPE_WC);
1143093e48c0SOak Zeng 	case AMDGPU_VM_MTYPE_RW:
114471776b6dSChristian König 		return AMDGPU_PTE_MTYPE_VG10(MTYPE_RW);
1145e60f8db5SAlex Xie 	case AMDGPU_VM_MTYPE_CC:
114671776b6dSChristian König 		return AMDGPU_PTE_MTYPE_VG10(MTYPE_CC);
1147e60f8db5SAlex Xie 	case AMDGPU_VM_MTYPE_UC:
114871776b6dSChristian König 		return AMDGPU_PTE_MTYPE_VG10(MTYPE_UC);
1149e60f8db5SAlex Xie 	default:
115071776b6dSChristian König 		return AMDGPU_PTE_MTYPE_VG10(MTYPE_NC);
1151e60f8db5SAlex Xie 	}
1152e60f8db5SAlex Xie }
1153e60f8db5SAlex Xie 
11543de676d8SChristian König static void gmc_v9_0_get_vm_pde(struct amdgpu_device *adev, int level,
11553de676d8SChristian König 				uint64_t *addr, uint64_t *flags)
1156f75e237cSChristian König {
1157bbc9fb10SChristian König 	if (!(*flags & AMDGPU_PDE_PTE) && !(*flags & AMDGPU_PTE_SYSTEM))
11580ca565abSOak Zeng 		*addr = amdgpu_gmc_vram_mc2pa(adev, *addr);
11593de676d8SChristian König 	BUG_ON(*addr & 0xFFFF00000000003FULL);
11606a42fd6fSChristian König 
1161770d13b1SChristian König 	if (!adev->gmc.translate_further)
11626a42fd6fSChristian König 		return;
11636a42fd6fSChristian König 
11646a42fd6fSChristian König 	if (level == AMDGPU_VM_PDB1) {
11656a42fd6fSChristian König 		/* Set the block fragment size */
11666a42fd6fSChristian König 		if (!(*flags & AMDGPU_PDE_PTE))
11676a42fd6fSChristian König 			*flags |= AMDGPU_PDE_BFS(0x9);
11686a42fd6fSChristian König 
11696a42fd6fSChristian König 	} else if (level == AMDGPU_VM_PDB0) {
117037a0bad6SMukul Joshi 		if (*flags & AMDGPU_PDE_PTE) {
11716a42fd6fSChristian König 			*flags &= ~AMDGPU_PDE_PTE;
117237a0bad6SMukul Joshi 			if (!(*flags & AMDGPU_PTE_VALID))
117337a0bad6SMukul Joshi 				*addr |= 1 << PAGE_SHIFT;
117437a0bad6SMukul Joshi 		} else {
11756a42fd6fSChristian König 			*flags |= AMDGPU_PTE_TF;
11766a42fd6fSChristian König 		}
1177f75e237cSChristian König 	}
117837a0bad6SMukul Joshi }
1179f75e237cSChristian König 
1180d1a372afSFelix Kuehling static void gmc_v9_0_get_coherence_flags(struct amdgpu_device *adev,
1181d1a372afSFelix Kuehling 					 struct amdgpu_bo *bo,
1182d1a372afSFelix Kuehling 					 struct amdgpu_bo_va_mapping *mapping,
1183d1a372afSFelix Kuehling 					 uint64_t *flags)
1184d1a372afSFelix Kuehling {
1185d1a372afSFelix Kuehling 	struct amdgpu_device *bo_adev = amdgpu_ttm_adev(bo->tbo.bdev);
1186d1a372afSFelix Kuehling 	bool is_vram = bo->tbo.resource->mem_type == TTM_PL_VRAM;
1187d1a372afSFelix Kuehling 	bool coherent = bo->flags & AMDGPU_GEM_CREATE_COHERENT;
1188d1a372afSFelix Kuehling 	bool uncached = bo->flags & AMDGPU_GEM_CREATE_UNCACHED;
11891e4a0033SFelix Kuehling 	/* TODO: memory partitions struct amdgpu_vm *vm = mapping->bo_va->base.vm;*/
11901e4a0033SFelix Kuehling 	unsigned int mtype_local, mtype;
1191d1a372afSFelix Kuehling 	bool snoop = false;
11921e4a0033SFelix Kuehling 	bool is_local;
1193d1a372afSFelix Kuehling 
1194d1a372afSFelix Kuehling 	switch (adev->ip_versions[GC_HWIP][0]) {
1195d1a372afSFelix Kuehling 	case IP_VERSION(9, 4, 1):
1196d1a372afSFelix Kuehling 	case IP_VERSION(9, 4, 2):
1197d1a372afSFelix Kuehling 		if (is_vram) {
1198d1a372afSFelix Kuehling 			if (bo_adev == adev) {
1199d1a372afSFelix Kuehling 				if (uncached)
1200d1a372afSFelix Kuehling 					mtype = MTYPE_UC;
1201d1a372afSFelix Kuehling 				else if (coherent)
1202d1a372afSFelix Kuehling 					mtype = MTYPE_CC;
1203d1a372afSFelix Kuehling 				else
1204d1a372afSFelix Kuehling 					mtype = MTYPE_RW;
1205d1a372afSFelix Kuehling 				/* FIXME: is this still needed? Or does
1206d1a372afSFelix Kuehling 				 * amdgpu_ttm_tt_pde_flags already handle this?
1207d1a372afSFelix Kuehling 				 */
1208ab1a157eSHawking Zhang 				if ((adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 2) ||
1209ab1a157eSHawking Zhang 				     adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 3)) &&
1210d1a372afSFelix Kuehling 				    adev->gmc.xgmi.connected_to_cpu)
1211d1a372afSFelix Kuehling 					snoop = true;
1212d1a372afSFelix Kuehling 			} else {
1213d1a372afSFelix Kuehling 				if (uncached || coherent)
1214d1a372afSFelix Kuehling 					mtype = MTYPE_UC;
1215d1a372afSFelix Kuehling 				else
1216d1a372afSFelix Kuehling 					mtype = MTYPE_NC;
1217d1a372afSFelix Kuehling 				if (mapping->bo_va->is_xgmi)
1218d1a372afSFelix Kuehling 					snoop = true;
1219d1a372afSFelix Kuehling 			}
1220d1a372afSFelix Kuehling 		} else {
1221d1a372afSFelix Kuehling 			if (uncached || coherent)
1222d1a372afSFelix Kuehling 				mtype = MTYPE_UC;
1223d1a372afSFelix Kuehling 			else
1224d1a372afSFelix Kuehling 				mtype = MTYPE_NC;
1225d1a372afSFelix Kuehling 			/* FIXME: is this still needed? Or does
1226d1a372afSFelix Kuehling 			 * amdgpu_ttm_tt_pde_flags already handle this?
1227d1a372afSFelix Kuehling 			 */
1228d1a372afSFelix Kuehling 			snoop = true;
1229d1a372afSFelix Kuehling 		}
1230d1a372afSFelix Kuehling 		break;
1231753b999aSRajneesh Bhardwaj 	case IP_VERSION(9, 4, 3):
12321e4a0033SFelix Kuehling 		/* Only local VRAM BOs or system memory on non-NUMA APUs
12331e4a0033SFelix Kuehling 		 * can be assumed to be local in their entirety. Choose
12341e4a0033SFelix Kuehling 		 * MTYPE_NC as safe fallback for all system memory BOs on
12351e4a0033SFelix Kuehling 		 * NUMA systems. Their MTYPE can be overridden per-page in
12361e4a0033SFelix Kuehling 		 * gmc_v9_0_override_vm_pte_flags.
1237753b999aSRajneesh Bhardwaj 		 */
12381e4a0033SFelix Kuehling 		mtype_local = amdgpu_use_mtype_cc_wa ? MTYPE_CC : MTYPE_RW;
12391e4a0033SFelix Kuehling 		is_local = (!is_vram && (adev->flags & AMD_IS_APU) &&
12401e4a0033SFelix Kuehling 			    num_possible_nodes() <= 1) ||
12411e4a0033SFelix Kuehling 			   (is_vram && adev == bo_adev /* TODO: memory partitions &&
12421e4a0033SFelix Kuehling 			    bo->mem_id == vm->mem_id*/);
1243753b999aSRajneesh Bhardwaj 		snoop = true;
1244753b999aSRajneesh Bhardwaj 		if (uncached) {
1245753b999aSRajneesh Bhardwaj 			mtype = MTYPE_UC;
1246753b999aSRajneesh Bhardwaj 		} else if (adev->flags & AMD_IS_APU) {
12471e4a0033SFelix Kuehling 			mtype = is_local ? mtype_local : MTYPE_NC;
1248753b999aSRajneesh Bhardwaj 		} else {
1249753b999aSRajneesh Bhardwaj 			/* dGPU */
12501e4a0033SFelix Kuehling 			if (is_local)
12511e4a0033SFelix Kuehling 				mtype = mtype_local;
1252d839a158SGraham Sider 			else if (is_vram)
1253753b999aSRajneesh Bhardwaj 				mtype = MTYPE_NC;
1254d839a158SGraham Sider 			else
1255d839a158SGraham Sider 				mtype = MTYPE_UC;
1256753b999aSRajneesh Bhardwaj 		}
1257753b999aSRajneesh Bhardwaj 
1258753b999aSRajneesh Bhardwaj 		break;
1259d1a372afSFelix Kuehling 	default:
1260d1a372afSFelix Kuehling 		if (uncached || coherent)
1261d1a372afSFelix Kuehling 			mtype = MTYPE_UC;
1262d1a372afSFelix Kuehling 		else
1263d1a372afSFelix Kuehling 			mtype = MTYPE_NC;
1264d1a372afSFelix Kuehling 
1265d1a372afSFelix Kuehling 		/* FIXME: is this still needed? Or does
1266d1a372afSFelix Kuehling 		 * amdgpu_ttm_tt_pde_flags already handle this?
1267d1a372afSFelix Kuehling 		 */
1268d1a372afSFelix Kuehling 		if (!is_vram)
1269d1a372afSFelix Kuehling 			snoop = true;
1270d1a372afSFelix Kuehling 	}
1271d1a372afSFelix Kuehling 
1272d1a372afSFelix Kuehling 	if (mtype != MTYPE_NC)
1273d1a372afSFelix Kuehling 		*flags = (*flags & ~AMDGPU_PTE_MTYPE_VG10_MASK) |
1274d1a372afSFelix Kuehling 			 AMDGPU_PTE_MTYPE_VG10(mtype);
1275d1a372afSFelix Kuehling 	*flags |= snoop ? AMDGPU_PTE_SNOOPED : 0;
1276d1a372afSFelix Kuehling }
1277d1a372afSFelix Kuehling 
1278cbfae36cSChristian König static void gmc_v9_0_get_vm_pte(struct amdgpu_device *adev,
1279cbfae36cSChristian König 				struct amdgpu_bo_va_mapping *mapping,
1280cbfae36cSChristian König 				uint64_t *flags)
1281cbfae36cSChristian König {
12829c3db58bSChristian König 	struct amdgpu_bo *bo = mapping->bo_va->base.bo;
12839c3db58bSChristian König 
1284cbfae36cSChristian König 	*flags &= ~AMDGPU_PTE_EXECUTABLE;
1285cbfae36cSChristian König 	*flags |= mapping->flags & AMDGPU_PTE_EXECUTABLE;
1286cbfae36cSChristian König 
1287cbfae36cSChristian König 	*flags &= ~AMDGPU_PTE_MTYPE_VG10_MASK;
1288cbfae36cSChristian König 	*flags |= mapping->flags & AMDGPU_PTE_MTYPE_VG10_MASK;
1289cbfae36cSChristian König 
1290cbfae36cSChristian König 	if (mapping->flags & AMDGPU_PTE_PRT) {
1291cbfae36cSChristian König 		*flags |= AMDGPU_PTE_PRT;
1292cbfae36cSChristian König 		*flags &= ~AMDGPU_PTE_VALID;
1293cbfae36cSChristian König 	}
1294cbfae36cSChristian König 
12959c3db58bSChristian König 	if (bo && bo->tbo.resource)
1296d1a372afSFelix Kuehling 		gmc_v9_0_get_coherence_flags(adev, mapping->bo_va->base.bo,
1297d1a372afSFelix Kuehling 					     mapping, flags);
1298cbfae36cSChristian König }
1299cbfae36cSChristian König 
1300*352b919cSFelix Kuehling static void gmc_v9_0_override_vm_pte_flags(struct amdgpu_device *adev,
1301*352b919cSFelix Kuehling 					   struct amdgpu_vm *vm,
1302*352b919cSFelix Kuehling 					   uint64_t addr, uint64_t *flags)
1303*352b919cSFelix Kuehling {
1304*352b919cSFelix Kuehling 	int local_node, nid;
1305*352b919cSFelix Kuehling 
1306*352b919cSFelix Kuehling 	/* Only GFX 9.4.3 APUs associate GPUs with NUMA nodes. Local system
1307*352b919cSFelix Kuehling 	 * memory can use more efficient MTYPEs.
1308*352b919cSFelix Kuehling 	 */
1309*352b919cSFelix Kuehling 	if (adev->ip_versions[GC_HWIP][0] != IP_VERSION(9, 4, 3))
1310*352b919cSFelix Kuehling 		return;
1311*352b919cSFelix Kuehling 
1312*352b919cSFelix Kuehling 	/* Only direct-mapped memory allows us to determine the NUMA node from
1313*352b919cSFelix Kuehling 	 * the DMA address.
1314*352b919cSFelix Kuehling 	 */
1315*352b919cSFelix Kuehling 	if (!adev->ram_is_direct_mapped) {
1316*352b919cSFelix Kuehling 		dev_dbg(adev->dev, "RAM is not direct mapped\n");
1317*352b919cSFelix Kuehling 		return;
1318*352b919cSFelix Kuehling 	}
1319*352b919cSFelix Kuehling 
1320*352b919cSFelix Kuehling 	/* Only override mappings with MTYPE_NC, which is the safe default for
1321*352b919cSFelix Kuehling 	 * cacheable memory.
1322*352b919cSFelix Kuehling 	 */
1323*352b919cSFelix Kuehling 	if ((*flags & AMDGPU_PTE_MTYPE_VG10_MASK) !=
1324*352b919cSFelix Kuehling 	    AMDGPU_PTE_MTYPE_VG10(MTYPE_NC)) {
1325*352b919cSFelix Kuehling 		dev_dbg(adev->dev, "MTYPE is not NC\n");
1326*352b919cSFelix Kuehling 		return;
1327*352b919cSFelix Kuehling 	}
1328*352b919cSFelix Kuehling 
1329*352b919cSFelix Kuehling 	/* TODO: memory partitions. mem_id is hard-coded to 0 for now.
1330*352b919cSFelix Kuehling 	 * FIXME: Only supported on native mode for now. For carve-out, the
1331*352b919cSFelix Kuehling 	 * NUMA affinity of the GPU/VM needs to come from the PCI info because
1332*352b919cSFelix Kuehling 	 * memory partitions are not associated with different NUMA nodes.
1333*352b919cSFelix Kuehling 	 */
1334*352b919cSFelix Kuehling 	if (adev->gmc.is_app_apu) {
1335*352b919cSFelix Kuehling 		local_node = adev->gmc.mem_partitions[/*vm->mem_id*/0].numa.node;
1336*352b919cSFelix Kuehling 	} else {
1337*352b919cSFelix Kuehling 		dev_dbg(adev->dev, "Only native mode APU is supported.\n");
1338*352b919cSFelix Kuehling 		return;
1339*352b919cSFelix Kuehling 	}
1340*352b919cSFelix Kuehling 
1341*352b919cSFelix Kuehling 	/* Only handle real RAM. Mappings of PCIe resources don't have struct
1342*352b919cSFelix Kuehling 	 * page or NUMA nodes.
1343*352b919cSFelix Kuehling 	 */
1344*352b919cSFelix Kuehling 	if (!page_is_ram(addr >> PAGE_SHIFT)) {
1345*352b919cSFelix Kuehling 		dev_dbg(adev->dev, "Page is not RAM.\n");
1346*352b919cSFelix Kuehling 		return;
1347*352b919cSFelix Kuehling 	}
1348*352b919cSFelix Kuehling 	nid = pfn_to_nid(addr >> PAGE_SHIFT);
1349*352b919cSFelix Kuehling 	dev_dbg(adev->dev, "vm->mem_id=%d, local_node=%d, nid=%d\n",
1350*352b919cSFelix Kuehling 		/*vm->mem_id*/0, local_node, nid);
1351*352b919cSFelix Kuehling 	if (nid == local_node) {
1352*352b919cSFelix Kuehling 		unsigned int mtype_local =
1353*352b919cSFelix Kuehling 			amdgpu_use_mtype_cc_wa ? MTYPE_CC : MTYPE_RW;
1354*352b919cSFelix Kuehling 		uint64_t old_flags = *flags;
1355*352b919cSFelix Kuehling 
1356*352b919cSFelix Kuehling 		*flags = (*flags & ~AMDGPU_PTE_MTYPE_VG10_MASK) |
1357*352b919cSFelix Kuehling 			 AMDGPU_PTE_MTYPE_VG10(mtype_local);
1358*352b919cSFelix Kuehling 		dev_dbg(adev->dev, "flags updated from %llx to %llx\n",
1359*352b919cSFelix Kuehling 			old_flags, *flags);
1360*352b919cSFelix Kuehling 	}
1361*352b919cSFelix Kuehling }
1362*352b919cSFelix Kuehling 
13637b885f0eSAlex Deucher static unsigned gmc_v9_0_get_vbios_fb_size(struct amdgpu_device *adev)
13647b885f0eSAlex Deucher {
13657b885f0eSAlex Deucher 	u32 d1vga_control = RREG32_SOC15(DCE, 0, mmD1VGA_CONTROL);
13667b885f0eSAlex Deucher 	unsigned size;
13677b885f0eSAlex Deucher 
1368dc5d4affSHarry Wentland 	/* TODO move to DC so GMC doesn't need to hard-code DCN registers */
1369dc5d4affSHarry Wentland 
13707b885f0eSAlex Deucher 	if (REG_GET_FIELD(d1vga_control, D1VGA_CONTROL, D1VGA_MODE_ENABLE)) {
13717b885f0eSAlex Deucher 		size = AMDGPU_VBIOS_VGA_ALLOCATION;
13727b885f0eSAlex Deucher 	} else {
13737b885f0eSAlex Deucher 		u32 viewport;
13747b885f0eSAlex Deucher 
1375630e959fSAlex Deucher 		switch (adev->ip_versions[DCE_HWIP][0]) {
1376630e959fSAlex Deucher 		case IP_VERSION(1, 0, 0):
1377630e959fSAlex Deucher 		case IP_VERSION(1, 0, 1):
13787b885f0eSAlex Deucher 			viewport = RREG32_SOC15(DCE, 0, mmHUBP0_DCSURF_PRI_VIEWPORT_DIMENSION);
13797b885f0eSAlex Deucher 			size = (REG_GET_FIELD(viewport,
13807b885f0eSAlex Deucher 					      HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION, PRI_VIEWPORT_HEIGHT) *
13817b885f0eSAlex Deucher 				REG_GET_FIELD(viewport,
13827b885f0eSAlex Deucher 					      HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION, PRI_VIEWPORT_WIDTH) *
13837b885f0eSAlex Deucher 				4);
13847b885f0eSAlex Deucher 			break;
1385dc5d4affSHarry Wentland 		case IP_VERSION(2, 1, 0):
1386dc5d4affSHarry Wentland 			viewport = RREG32_SOC15(DCE, 0, mmHUBP0_DCSURF_PRI_VIEWPORT_DIMENSION_DCN2);
1387dc5d4affSHarry Wentland 			size = (REG_GET_FIELD(viewport,
1388dc5d4affSHarry Wentland 					      HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION, PRI_VIEWPORT_HEIGHT) *
1389dc5d4affSHarry Wentland 				REG_GET_FIELD(viewport,
1390dc5d4affSHarry Wentland 					      HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION, PRI_VIEWPORT_WIDTH) *
1391dc5d4affSHarry Wentland 				4);
1392dc5d4affSHarry Wentland 			break;
13937b885f0eSAlex Deucher 		default:
13947b885f0eSAlex Deucher 			viewport = RREG32_SOC15(DCE, 0, mmSCL0_VIEWPORT_SIZE);
13957b885f0eSAlex Deucher 			size = (REG_GET_FIELD(viewport, SCL0_VIEWPORT_SIZE, VIEWPORT_HEIGHT) *
13967b885f0eSAlex Deucher 				REG_GET_FIELD(viewport, SCL0_VIEWPORT_SIZE, VIEWPORT_WIDTH) *
13977b885f0eSAlex Deucher 				4);
13987b885f0eSAlex Deucher 			break;
13997b885f0eSAlex Deucher 		}
14007b885f0eSAlex Deucher 	}
14017b885f0eSAlex Deucher 
14027b885f0eSAlex Deucher 	return size;
14037b885f0eSAlex Deucher }
14047b885f0eSAlex Deucher 
1405b6f90baaSLijo Lazar static enum amdgpu_memory_partition
14060f2e1d62SLijo Lazar gmc_v9_0_get_memory_partition(struct amdgpu_device *adev, u32 *supp_modes)
1407b6f90baaSLijo Lazar {
1408b6f90baaSLijo Lazar 	enum amdgpu_memory_partition mode = UNKNOWN_MEMORY_PARTITION_MODE;
1409b6f90baaSLijo Lazar 
1410b6f90baaSLijo Lazar 	if (adev->nbio.funcs->get_memory_partition_mode)
14110f2e1d62SLijo Lazar 		mode = adev->nbio.funcs->get_memory_partition_mode(adev,
14120f2e1d62SLijo Lazar 								   supp_modes);
1413b6f90baaSLijo Lazar 
1414b6f90baaSLijo Lazar 	return mode;
1415b6f90baaSLijo Lazar }
1416b6f90baaSLijo Lazar 
14170f2e1d62SLijo Lazar static enum amdgpu_memory_partition
14180f2e1d62SLijo Lazar gmc_v9_0_query_memory_partition(struct amdgpu_device *adev)
14190f2e1d62SLijo Lazar {
142046f7b4deSGavin Wan 	if (amdgpu_sriov_vf(adev))
142146f7b4deSGavin Wan 		return AMDGPU_NPS1_PARTITION_MODE;
142246f7b4deSGavin Wan 
14230f2e1d62SLijo Lazar 	return gmc_v9_0_get_memory_partition(adev, NULL);
14240f2e1d62SLijo Lazar }
14250f2e1d62SLijo Lazar 
1426132f34e4SChristian König static const struct amdgpu_gmc_funcs gmc_v9_0_gmc_funcs = {
1427132f34e4SChristian König 	.flush_gpu_tlb = gmc_v9_0_flush_gpu_tlb,
1428ea930000SAlex Sierra 	.flush_gpu_tlb_pasid = gmc_v9_0_flush_gpu_tlb_pasid,
14299096d6e5SChristian König 	.emit_flush_gpu_tlb = gmc_v9_0_emit_flush_gpu_tlb,
1430c633c00bSChristian König 	.emit_pasid_mapping = gmc_v9_0_emit_pasid_mapping,
143171776b6dSChristian König 	.map_mtype = gmc_v9_0_map_mtype,
1432cbfae36cSChristian König 	.get_vm_pde = gmc_v9_0_get_vm_pde,
14337b885f0eSAlex Deucher 	.get_vm_pte = gmc_v9_0_get_vm_pte,
1434*352b919cSFelix Kuehling 	.override_vm_pte_flags = gmc_v9_0_override_vm_pte_flags,
14357b885f0eSAlex Deucher 	.get_vbios_fb_size = gmc_v9_0_get_vbios_fb_size,
1436b6f90baaSLijo Lazar 	.query_mem_partition_mode = &gmc_v9_0_query_memory_partition,
1437e60f8db5SAlex Xie };
1438e60f8db5SAlex Xie 
1439132f34e4SChristian König static void gmc_v9_0_set_gmc_funcs(struct amdgpu_device *adev)
1440e60f8db5SAlex Xie {
1441132f34e4SChristian König 	adev->gmc.gmc_funcs = &gmc_v9_0_gmc_funcs;
1442e60f8db5SAlex Xie }
1443e60f8db5SAlex Xie 
14445b6b35aaSHawking Zhang static void gmc_v9_0_set_umc_funcs(struct amdgpu_device *adev)
14455b6b35aaSHawking Zhang {
1446630e959fSAlex Deucher 	switch (adev->ip_versions[UMC_HWIP][0]) {
1447630e959fSAlex Deucher 	case IP_VERSION(6, 0, 0):
1448e7da754bSMonk Liu 		adev->umc.funcs = &umc_v6_0_funcs;
1449e7da754bSMonk Liu 		break;
1450630e959fSAlex Deucher 	case IP_VERSION(6, 1, 1):
14513aacf4eaSTao Zhou 		adev->umc.max_ras_err_cnt_per_query = UMC_V6_1_TOTAL_CHANNEL_NUM;
14523aacf4eaSTao Zhou 		adev->umc.channel_inst_num = UMC_V6_1_CHANNEL_INSTANCE_NUM;
14533aacf4eaSTao Zhou 		adev->umc.umc_inst_num = UMC_V6_1_UMC_INSTANCE_NUM;
14544cf781c2SJohn Clements 		adev->umc.channel_offs = UMC_V6_1_PER_CHANNEL_OFFSET_VG20;
1455e69c7857STao Zhou 		adev->umc.retire_unit = 1;
14564cf781c2SJohn Clements 		adev->umc.channel_idx_tbl = &umc_v6_1_channel_idx_tbl[0][0];
1457efe17d5aSyipechai 		adev->umc.ras = &umc_v6_1_ras;
14584cf781c2SJohn Clements 		break;
1459630e959fSAlex Deucher 	case IP_VERSION(6, 1, 2):
14603aacf4eaSTao Zhou 		adev->umc.max_ras_err_cnt_per_query = UMC_V6_1_TOTAL_CHANNEL_NUM;
14613aacf4eaSTao Zhou 		adev->umc.channel_inst_num = UMC_V6_1_CHANNEL_INSTANCE_NUM;
14623aacf4eaSTao Zhou 		adev->umc.umc_inst_num = UMC_V6_1_UMC_INSTANCE_NUM;
14634cf781c2SJohn Clements 		adev->umc.channel_offs = UMC_V6_1_PER_CHANNEL_OFFSET_ARCT;
1464e69c7857STao Zhou 		adev->umc.retire_unit = 1;
14653aacf4eaSTao Zhou 		adev->umc.channel_idx_tbl = &umc_v6_1_channel_idx_tbl[0][0];
1466efe17d5aSyipechai 		adev->umc.ras = &umc_v6_1_ras;
14675b6b35aaSHawking Zhang 		break;
1468630e959fSAlex Deucher 	case IP_VERSION(6, 7, 0):
1469498d46feSTao Zhou 		adev->umc.max_ras_err_cnt_per_query =
1470498d46feSTao Zhou 			UMC_V6_7_TOTAL_CHANNEL_NUM * UMC_V6_7_BAD_PAGE_NUM_PER_CHANNEL;
1471719e433eSMukul Joshi 		adev->umc.channel_inst_num = UMC_V6_7_CHANNEL_INSTANCE_NUM;
1472719e433eSMukul Joshi 		adev->umc.umc_inst_num = UMC_V6_7_UMC_INSTANCE_NUM;
1473186c8a85SJohn Clements 		adev->umc.channel_offs = UMC_V6_7_PER_CHANNEL_OFFSET;
1474e69c7857STao Zhou 		adev->umc.retire_unit = (UMC_V6_7_NA_MAP_PA_NUM * 2);
1475186c8a85SJohn Clements 		if (!adev->gmc.xgmi.connected_to_cpu)
1476efe17d5aSyipechai 			adev->umc.ras = &umc_v6_7_ras;
1477186c8a85SJohn Clements 		if (1 & adev->smuio.funcs->get_die_id(adev))
1478186c8a85SJohn Clements 			adev->umc.channel_idx_tbl = &umc_v6_7_channel_idx_tbl_first[0][0];
1479186c8a85SJohn Clements 		else
1480186c8a85SJohn Clements 			adev->umc.channel_idx_tbl = &umc_v6_7_channel_idx_tbl_second[0][0];
1481186c8a85SJohn Clements 		break;
14825b6b35aaSHawking Zhang 	default:
14835b6b35aaSHawking Zhang 		break;
14845b6b35aaSHawking Zhang 	}
14855b6b35aaSHawking Zhang }
14865b6b35aaSHawking Zhang 
14873d093da0STao Zhou static void gmc_v9_0_set_mmhub_funcs(struct amdgpu_device *adev)
14883d093da0STao Zhou {
1489630e959fSAlex Deucher 	switch (adev->ip_versions[MMHUB_HWIP][0]) {
1490630e959fSAlex Deucher 	case IP_VERSION(9, 4, 1):
1491f6c3623bSDennis Li 		adev->mmhub.funcs = &mmhub_v9_4_funcs;
1492f6c3623bSDennis Li 		break;
1493630e959fSAlex Deucher 	case IP_VERSION(9, 4, 2):
14944da999cdSOak Zeng 		adev->mmhub.funcs = &mmhub_v1_7_funcs;
14954da999cdSOak Zeng 		break;
1496018f7300SLe Ma 	case IP_VERSION(1, 8, 0):
1497018f7300SLe Ma 		adev->mmhub.funcs = &mmhub_v1_8_funcs;
1498018f7300SLe Ma 		break;
14993d093da0STao Zhou 	default:
15009fb1506eSOak Zeng 		adev->mmhub.funcs = &mmhub_v1_0_funcs;
15013d093da0STao Zhou 		break;
15023d093da0STao Zhou 	}
15033d093da0STao Zhou }
15043d093da0STao Zhou 
1505d844c6d7SHawking Zhang static void gmc_v9_0_set_mmhub_ras_funcs(struct amdgpu_device *adev)
1506d844c6d7SHawking Zhang {
1507630e959fSAlex Deucher 	switch (adev->ip_versions[MMHUB_HWIP][0]) {
1508630e959fSAlex Deucher 	case IP_VERSION(9, 4, 0):
15095e67bba3Syipechai 		adev->mmhub.ras = &mmhub_v1_0_ras;
1510d844c6d7SHawking Zhang 		break;
1511630e959fSAlex Deucher 	case IP_VERSION(9, 4, 1):
15125e67bba3Syipechai 		adev->mmhub.ras = &mmhub_v9_4_ras;
1513d844c6d7SHawking Zhang 		break;
1514630e959fSAlex Deucher 	case IP_VERSION(9, 4, 2):
15155e67bba3Syipechai 		adev->mmhub.ras = &mmhub_v1_7_ras;
1516d844c6d7SHawking Zhang 		break;
151773c2b3fdSHawking Zhang 	case IP_VERSION(1, 8, 0):
151873c2b3fdSHawking Zhang 		adev->mmhub.ras = &mmhub_v1_8_ras;
151973c2b3fdSHawking Zhang 		break;
1520d844c6d7SHawking Zhang 	default:
1521d844c6d7SHawking Zhang 		/* mmhub ras is not available */
1522d844c6d7SHawking Zhang 		break;
1523d844c6d7SHawking Zhang 	}
1524d844c6d7SHawking Zhang }
1525d844c6d7SHawking Zhang 
15268ffff9b4SOak Zeng static void gmc_v9_0_set_gfxhub_funcs(struct amdgpu_device *adev)
15278ffff9b4SOak Zeng {
1528018f7300SLe Ma 	if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 3))
1529018f7300SLe Ma 		adev->gfxhub.funcs = &gfxhub_v1_2_funcs;
1530018f7300SLe Ma 	else
15318ffff9b4SOak Zeng 		adev->gfxhub.funcs = &gfxhub_v1_0_funcs;
15328ffff9b4SOak Zeng }
15338ffff9b4SOak Zeng 
15346f12507fSHawking Zhang static void gmc_v9_0_set_hdp_ras_funcs(struct amdgpu_device *adev)
15356f12507fSHawking Zhang {
15366d76e904Syipechai 	adev->hdp.ras = &hdp_v4_0_ras;
15376f12507fSHawking Zhang }
15386f12507fSHawking Zhang 
15397f544c54SHawking Zhang static void gmc_v9_0_set_mca_ras_funcs(struct amdgpu_device *adev)
15403907c492SJohn Clements {
15417f544c54SHawking Zhang 	struct amdgpu_mca *mca = &adev->mca;
15427f544c54SHawking Zhang 
1543630e959fSAlex Deucher 	/* is UMC the right IP to check for MCA?  Maybe DF? */
1544630e959fSAlex Deucher 	switch (adev->ip_versions[UMC_HWIP][0]) {
1545630e959fSAlex Deucher 	case IP_VERSION(6, 7, 0):
15467f544c54SHawking Zhang 		if (!adev->gmc.xgmi.connected_to_cpu) {
15477f544c54SHawking Zhang 			mca->mp0.ras = &mca_v3_0_mp0_ras;
15487f544c54SHawking Zhang 			mca->mp1.ras = &mca_v3_0_mp1_ras;
15497f544c54SHawking Zhang 			mca->mpio.ras = &mca_v3_0_mpio_ras;
15507f544c54SHawking Zhang 		}
15513907c492SJohn Clements 		break;
15523907c492SJohn Clements 	default:
15533907c492SJohn Clements 		break;
15543907c492SJohn Clements 	}
15553907c492SJohn Clements }
15563907c492SJohn Clements 
1557da9d669eSHawking Zhang static void gmc_v9_0_set_xgmi_ras_funcs(struct amdgpu_device *adev)
1558da9d669eSHawking Zhang {
1559da9d669eSHawking Zhang 	if (!adev->gmc.xgmi.connected_to_cpu)
1560da9d669eSHawking Zhang 		adev->gmc.xgmi.ras = &xgmi_ras;
1561da9d669eSHawking Zhang }
1562da9d669eSHawking Zhang 
1563e60f8db5SAlex Xie static int gmc_v9_0_early_init(void *handle)
1564e60f8db5SAlex Xie {
1565e60f8db5SAlex Xie 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
1566e60f8db5SAlex Xie 
15679eb7681fSShiwu Zhang 	/*
15689eb7681fSShiwu Zhang 	 * 9.4.0, 9.4.1 and 9.4.3 don't have XGMI defined
15699eb7681fSShiwu Zhang 	 * in their IP discovery tables
15709eb7681fSShiwu Zhang 	 */
15719eb7681fSShiwu Zhang 	if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 0) ||
15729eb7681fSShiwu Zhang 	    adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 1) ||
15739eb7681fSShiwu Zhang 	    adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 3))
157431691b8dSRajneesh Bhardwaj 		adev->gmc.xgmi.supported = true;
157531691b8dSRajneesh Bhardwaj 
1576630e959fSAlex Deucher 	if (adev->ip_versions[XGMI_HWIP][0] == IP_VERSION(6, 1, 0)) {
157731691b8dSRajneesh Bhardwaj 		adev->gmc.xgmi.supported = true;
157831691b8dSRajneesh Bhardwaj 		adev->gmc.xgmi.connected_to_cpu =
157931691b8dSRajneesh Bhardwaj 			adev->smuio.funcs->is_host_gpu_xgmi_supported(adev);
158031691b8dSRajneesh Bhardwaj 	}
158131691b8dSRajneesh Bhardwaj 
1582497db7eaSRajneesh Bhardwaj 	if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 3)) {
1583497db7eaSRajneesh Bhardwaj 		enum amdgpu_pkg_type pkg_type =
1584497db7eaSRajneesh Bhardwaj 			adev->smuio.funcs->get_pkg_type(adev);
1585497db7eaSRajneesh Bhardwaj 		/* On GFXIP 9.4.3. APU, there is no physical VRAM domain present
1586497db7eaSRajneesh Bhardwaj 		 * and the APU, can be in used two possible modes:
1587497db7eaSRajneesh Bhardwaj 		 *  - carveout mode
1588497db7eaSRajneesh Bhardwaj 		 *  - native APU mode
1589497db7eaSRajneesh Bhardwaj 		 * "is_app_apu" can be used to identify the APU in the native
1590497db7eaSRajneesh Bhardwaj 		 * mode.
1591497db7eaSRajneesh Bhardwaj 		 */
1592497db7eaSRajneesh Bhardwaj 		adev->gmc.is_app_apu = (pkg_type == AMDGPU_PKG_TYPE_APU &&
1593497db7eaSRajneesh Bhardwaj 					!pci_resource_len(adev->pdev, 0));
1594497db7eaSRajneesh Bhardwaj 	}
1595497db7eaSRajneesh Bhardwaj 
159649070c4eSHawking Zhang 	gmc_v9_0_set_gmc_funcs(adev);
159749070c4eSHawking Zhang 	gmc_v9_0_set_irq_funcs(adev);
159849070c4eSHawking Zhang 	gmc_v9_0_set_umc_funcs(adev);
159949070c4eSHawking Zhang 	gmc_v9_0_set_mmhub_funcs(adev);
1600d844c6d7SHawking Zhang 	gmc_v9_0_set_mmhub_ras_funcs(adev);
160149070c4eSHawking Zhang 	gmc_v9_0_set_gfxhub_funcs(adev);
16026f12507fSHawking Zhang 	gmc_v9_0_set_hdp_ras_funcs(adev);
16037f544c54SHawking Zhang 	gmc_v9_0_set_mca_ras_funcs(adev);
1604da9d669eSHawking Zhang 	gmc_v9_0_set_xgmi_ras_funcs(adev);
160549070c4eSHawking Zhang 
1606770d13b1SChristian König 	adev->gmc.shared_aperture_start = 0x2000000000000000ULL;
1607770d13b1SChristian König 	adev->gmc.shared_aperture_end =
1608770d13b1SChristian König 		adev->gmc.shared_aperture_start + (4ULL << 30) - 1;
1609bfa8eea2SFlora Cui 	adev->gmc.private_aperture_start = 0x1000000000000000ULL;
1610770d13b1SChristian König 	adev->gmc.private_aperture_end =
1611770d13b1SChristian König 		adev->gmc.private_aperture_start + (4ULL << 30) - 1;
1612a7ea6548SAlex Deucher 
1613e60f8db5SAlex Xie 	return 0;
1614e60f8db5SAlex Xie }
1615e60f8db5SAlex Xie 
1616e60f8db5SAlex Xie static int gmc_v9_0_late_init(void *handle)
1617e60f8db5SAlex Xie {
1618e60f8db5SAlex Xie 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
1619c5b6e585STao Zhou 	int r;
16204789c463SChristian König 
1621bdbe90f0SAlex Deucher 	r = amdgpu_gmc_allocate_vm_inv_eng(adev);
1622c713a461SEvan Quan 	if (r)
1623c713a461SEvan Quan 		return r;
16244a20300bSGuchun Chen 
16254a20300bSGuchun Chen 	/*
16264a20300bSGuchun Chen 	 * Workaround performance drop issue with VBIOS enables partial
16274a20300bSGuchun Chen 	 * writes, while disables HBM ECC for vega10.
16284a20300bSGuchun Chen 	 */
1629630e959fSAlex Deucher 	if (!amdgpu_sriov_vf(adev) &&
1630630e959fSAlex Deucher 	    (adev->ip_versions[UMC_HWIP][0] == IP_VERSION(6, 0, 0))) {
16318ab0d6f0SLuben Tuikov 		if (!(adev->ras_enabled & (1 << AMDGPU_RAS_BLOCK__UMC))) {
1632cace4bffSHawking Zhang 			if (adev->df.funcs &&
1633cace4bffSHawking Zhang 			    adev->df.funcs->enable_ecc_force_par_wr_rmw)
1634bdf84a80SJoseph Greathouse 				adev->df.funcs->enable_ecc_force_par_wr_rmw(adev, false);
16354a20300bSGuchun Chen 		}
1636f49ea9f8SHawking Zhang 	}
163702bab923SDavid Panariti 
16388f6368a9SJohn Clements 	if (!amdgpu_persistent_edc_harvesting_supported(adev)) {
16395e67bba3Syipechai 		if (adev->mmhub.ras && adev->mmhub.ras->ras_block.hw_ops &&
16405e67bba3Syipechai 		    adev->mmhub.ras->ras_block.hw_ops->reset_ras_error_count)
16415e67bba3Syipechai 			adev->mmhub.ras->ras_block.hw_ops->reset_ras_error_count(adev);
1642fe5211f1SHawking Zhang 
16436d76e904Syipechai 		if (adev->hdp.ras && adev->hdp.ras->ras_block.hw_ops &&
16446d76e904Syipechai 		    adev->hdp.ras->ras_block.hw_ops->reset_ras_error_count)
16456d76e904Syipechai 			adev->hdp.ras->ras_block.hw_ops->reset_ras_error_count(adev);
16468f6368a9SJohn Clements 	}
164778871b6cSHawking Zhang 
1648ba083492STao Zhou 	r = amdgpu_gmc_ras_late_init(adev);
1649791c4769Sxinhui pan 	if (r)
1650e60f8db5SAlex Xie 		return r;
1651e60f8db5SAlex Xie 
1652770d13b1SChristian König 	return amdgpu_irq_get(adev, &adev->gmc.vm_fault, 0);
1653e60f8db5SAlex Xie }
1654e60f8db5SAlex Xie 
1655e60f8db5SAlex Xie static void gmc_v9_0_vram_gtt_location(struct amdgpu_device *adev,
1656770d13b1SChristian König 					struct amdgpu_gmc *mc)
1657e60f8db5SAlex Xie {
1658adbe2e3dSZhigang Luo 	u64 base = adev->mmhub.funcs->get_fb_location(adev);
16599d4f837aSFrank.Min 
16606fdd68b1SAlex Deucher 	/* add the xgmi offset of the physical node */
16616fdd68b1SAlex Deucher 	base += adev->gmc.xgmi.physical_node_id * adev->gmc.xgmi.node_segment_size;
1662f527f310SOak Zeng 	if (adev->gmc.xgmi.connected_to_cpu) {
1663f527f310SOak Zeng 		amdgpu_gmc_sysvm_location(adev, mc);
1664f527f310SOak Zeng 	} else {
166583afe835SOak Zeng 		amdgpu_gmc_vram_location(adev, mc, base);
1666961c75cfSChristian König 		amdgpu_gmc_gart_location(adev, mc);
1667c3e1b43cSChristian König 		amdgpu_gmc_agp_location(adev, mc);
1668f527f310SOak Zeng 	}
1669e60f8db5SAlex Xie 	/* base offset of vram pages */
16708ffff9b4SOak Zeng 	adev->vm_manager.vram_base_offset = adev->gfxhub.funcs->get_mc_fb_offset(adev);
16716fdd68b1SAlex Deucher 
16726fdd68b1SAlex Deucher 	/* XXX: add the xgmi offset of the physical node? */
16736fdd68b1SAlex Deucher 	adev->vm_manager.vram_base_offset +=
16746fdd68b1SAlex Deucher 		adev->gmc.xgmi.physical_node_id * adev->gmc.xgmi.node_segment_size;
1675e60f8db5SAlex Xie }
1676e60f8db5SAlex Xie 
1677e60f8db5SAlex Xie /**
1678e60f8db5SAlex Xie  * gmc_v9_0_mc_init - initialize the memory controller driver params
1679e60f8db5SAlex Xie  *
1680e60f8db5SAlex Xie  * @adev: amdgpu_device pointer
1681e60f8db5SAlex Xie  *
1682e60f8db5SAlex Xie  * Look up the amount of vram, vram width, and decide how to place
1683e60f8db5SAlex Xie  * vram and gart within the GPU's physical address space.
1684e60f8db5SAlex Xie  * Returns 0 for success.
1685e60f8db5SAlex Xie  */
1686e60f8db5SAlex Xie static int gmc_v9_0_mc_init(struct amdgpu_device *adev)
1687e60f8db5SAlex Xie {
1688e60f8db5SAlex Xie 	int r;
1689e60f8db5SAlex Xie 
1690e60f8db5SAlex Xie 	/* size in MB on si */
1691228ce176SRajneesh Bhardwaj 	if (!adev->gmc.is_app_apu) {
1692770d13b1SChristian König 		adev->gmc.mc_vram_size =
1693bebc0762SHawking Zhang 			adev->nbio.funcs->get_memsize(adev) * 1024ULL * 1024ULL;
1694228ce176SRajneesh Bhardwaj 	} else {
1695228ce176SRajneesh Bhardwaj 		DRM_DEBUG("Set mc_vram_size = 0 for APP APU\n");
1696228ce176SRajneesh Bhardwaj 		adev->gmc.mc_vram_size = 0;
1697228ce176SRajneesh Bhardwaj 	}
1698770d13b1SChristian König 	adev->gmc.real_vram_size = adev->gmc.mc_vram_size;
1699e60f8db5SAlex Xie 
1700be566196SOak Zeng 	if (!(adev->flags & AMD_IS_APU) &&
1701be566196SOak Zeng 	    !adev->gmc.xgmi.connected_to_cpu) {
1702e60f8db5SAlex Xie 		r = amdgpu_device_resize_fb_bar(adev);
1703e60f8db5SAlex Xie 		if (r)
1704e60f8db5SAlex Xie 			return r;
1705e60f8db5SAlex Xie 	}
1706770d13b1SChristian König 	adev->gmc.aper_base = pci_resource_start(adev->pdev, 0);
1707770d13b1SChristian König 	adev->gmc.aper_size = pci_resource_len(adev->pdev, 0);
1708e60f8db5SAlex Xie 
1709156a81beSChunming Zhou #ifdef CONFIG_X86_64
171031691b8dSRajneesh Bhardwaj 	/*
171131691b8dSRajneesh Bhardwaj 	 * AMD Accelerated Processing Platform (APP) supporting GPU-HOST xgmi
171231691b8dSRajneesh Bhardwaj 	 * interface can use VRAM through here as it appears system reserved
171331691b8dSRajneesh Bhardwaj 	 * memory in host address space.
171431691b8dSRajneesh Bhardwaj 	 *
171531691b8dSRajneesh Bhardwaj 	 * For APUs, VRAM is just the stolen system memory and can be accessed
171631691b8dSRajneesh Bhardwaj 	 * directly.
171731691b8dSRajneesh Bhardwaj 	 *
171831691b8dSRajneesh Bhardwaj 	 * Otherwise, use the legacy Host Data Path (HDP) through PCIe BAR.
171931691b8dSRajneesh Bhardwaj 	 */
172031691b8dSRajneesh Bhardwaj 
172131691b8dSRajneesh Bhardwaj 	/* check whether both host-gpu and gpu-gpu xgmi links exist */
1722b0a3bbf9SGavin Wan 	if ((!amdgpu_sriov_vf(adev) &&
1723b0a3bbf9SGavin Wan 		(adev->flags & AMD_IS_APU) && !amdgpu_passthrough(adev)) ||
17243de60d96SHawking Zhang 	    (adev->gmc.xgmi.supported &&
17253de60d96SHawking Zhang 	     adev->gmc.xgmi.connected_to_cpu)) {
17263de60d96SHawking Zhang 		adev->gmc.aper_base =
17273de60d96SHawking Zhang 			adev->gfxhub.funcs->get_mc_fb_offset(adev) +
17283de60d96SHawking Zhang 			adev->gmc.xgmi.physical_node_id *
172931691b8dSRajneesh Bhardwaj 			adev->gmc.xgmi.node_segment_size;
1730156a81beSChunming Zhou 		adev->gmc.aper_size = adev->gmc.real_vram_size;
1731156a81beSChunming Zhou 	}
173231691b8dSRajneesh Bhardwaj 
1733156a81beSChunming Zhou #endif
1734770d13b1SChristian König 	adev->gmc.visible_vram_size = adev->gmc.aper_size;
1735e60f8db5SAlex Xie 
1736e60f8db5SAlex Xie 	/* set the gart size */
1737e60f8db5SAlex Xie 	if (amdgpu_gart_size == -1) {
1738630e959fSAlex Deucher 		switch (adev->ip_versions[GC_HWIP][0]) {
1739630e959fSAlex Deucher 		case IP_VERSION(9, 0, 1):  /* all engines support GPUVM */
1740630e959fSAlex Deucher 		case IP_VERSION(9, 2, 1):  /* all engines support GPUVM */
1741630e959fSAlex Deucher 		case IP_VERSION(9, 4, 0):
1742630e959fSAlex Deucher 		case IP_VERSION(9, 4, 1):
1743630e959fSAlex Deucher 		case IP_VERSION(9, 4, 2):
1744ab1a157eSHawking Zhang 		case IP_VERSION(9, 4, 3):
1745e60f8db5SAlex Xie 		default:
1746fe19b862SMonk Liu 			adev->gmc.gart_size = 512ULL << 20;
1747e60f8db5SAlex Xie 			break;
1748630e959fSAlex Deucher 		case IP_VERSION(9, 1, 0):   /* DCE SG support */
1749630e959fSAlex Deucher 		case IP_VERSION(9, 2, 2):   /* DCE SG support */
1750630e959fSAlex Deucher 		case IP_VERSION(9, 3, 0):
1751770d13b1SChristian König 			adev->gmc.gart_size = 1024ULL << 20;
1752e60f8db5SAlex Xie 			break;
1753e60f8db5SAlex Xie 		}
1754e60f8db5SAlex Xie 	} else {
1755770d13b1SChristian König 		adev->gmc.gart_size = (u64)amdgpu_gart_size << 20;
1756e60f8db5SAlex Xie 	}
1757e60f8db5SAlex Xie 
1758f1dc12caSOak Zeng 	adev->gmc.gart_size += adev->pm.smu_prv_buffer_size;
1759f1dc12caSOak Zeng 
1760770d13b1SChristian König 	gmc_v9_0_vram_gtt_location(adev, &adev->gmc);
1761e60f8db5SAlex Xie 
1762e60f8db5SAlex Xie 	return 0;
1763e60f8db5SAlex Xie }
1764e60f8db5SAlex Xie 
1765e60f8db5SAlex Xie static int gmc_v9_0_gart_init(struct amdgpu_device *adev)
1766e60f8db5SAlex Xie {
1767e60f8db5SAlex Xie 	int r;
1768e60f8db5SAlex Xie 
17691123b989SChristian König 	if (adev->gart.bo) {
1770e60f8db5SAlex Xie 		WARN(1, "VEGA10 PCIE GART already initialized\n");
1771e60f8db5SAlex Xie 		return 0;
1772e60f8db5SAlex Xie 	}
17737b454b3aSOak Zeng 
17747b454b3aSOak Zeng 	if (adev->gmc.xgmi.connected_to_cpu) {
17757b454b3aSOak Zeng 		adev->gmc.vmid0_page_table_depth = 1;
17767b454b3aSOak Zeng 		adev->gmc.vmid0_page_table_block_size = 12;
17777b454b3aSOak Zeng 	} else {
17787b454b3aSOak Zeng 		adev->gmc.vmid0_page_table_depth = 0;
17797b454b3aSOak Zeng 		adev->gmc.vmid0_page_table_block_size = 0;
17807b454b3aSOak Zeng 	}
17817b454b3aSOak Zeng 
1782e60f8db5SAlex Xie 	/* Initialize common gart structure */
1783e60f8db5SAlex Xie 	r = amdgpu_gart_init(adev);
1784e60f8db5SAlex Xie 	if (r)
1785e60f8db5SAlex Xie 		return r;
1786e60f8db5SAlex Xie 	adev->gart.table_size = adev->gart.num_gpu_pages * 8;
17877596ab68SHawking Zhang 	adev->gart.gart_pte_flags = AMDGPU_PTE_MTYPE_VG10(MTYPE_UC) |
1788e60f8db5SAlex Xie 				 AMDGPU_PTE_EXECUTABLE;
1789522510a6SOak Zeng 
1790c9a502e9SFelix Kuehling 	if (!adev->gmc.real_vram_size) {
1791c9a502e9SFelix Kuehling 		dev_info(adev->dev, "Put GART in system memory for APU\n");
1792c9a502e9SFelix Kuehling 		r = amdgpu_gart_table_ram_alloc(adev);
1793c9a502e9SFelix Kuehling 		if (r)
1794c9a502e9SFelix Kuehling 			dev_err(adev->dev, "Failed to allocate GART in system memory\n");
1795c9a502e9SFelix Kuehling 	} else {
1796522510a6SOak Zeng 		r = amdgpu_gart_table_vram_alloc(adev);
1797522510a6SOak Zeng 		if (r)
1798522510a6SOak Zeng 			return r;
1799522510a6SOak Zeng 
1800c9a502e9SFelix Kuehling 		if (adev->gmc.xgmi.connected_to_cpu)
1801522510a6SOak Zeng 			r = amdgpu_gmc_pdb0_alloc(adev);
1802522510a6SOak Zeng 	}
1803522510a6SOak Zeng 
1804522510a6SOak Zeng 	return r;
1805e60f8db5SAlex Xie }
1806e60f8db5SAlex Xie 
1807b0a2db9bSAlex Deucher /**
1808b0a2db9bSAlex Deucher  * gmc_v9_0_save_registers - saves regs
1809b0a2db9bSAlex Deucher  *
1810b0a2db9bSAlex Deucher  * @adev: amdgpu_device pointer
1811b0a2db9bSAlex Deucher  *
1812b0a2db9bSAlex Deucher  * This saves potential register values that should be
1813b0a2db9bSAlex Deucher  * restored upon resume
1814b0a2db9bSAlex Deucher  */
1815b0a2db9bSAlex Deucher static void gmc_v9_0_save_registers(struct amdgpu_device *adev)
1816ebdef28eSAlex Deucher {
1817630e959fSAlex Deucher 	if ((adev->ip_versions[DCE_HWIP][0] == IP_VERSION(1, 0, 0)) ||
1818630e959fSAlex Deucher 	    (adev->ip_versions[DCE_HWIP][0] == IP_VERSION(1, 0, 1)))
1819b0a2db9bSAlex Deucher 		adev->gmc.sdpif_register = RREG32_SOC15(DCE, 0, mmDCHUBBUB_SDPIF_MMIO_CNTRL_0);
1820ebdef28eSAlex Deucher }
1821ebdef28eSAlex Deucher 
1822a433f1f5SLijo Lazar static bool gmc_v9_0_validate_partition_info(struct amdgpu_device *adev)
1823a433f1f5SLijo Lazar {
1824a433f1f5SLijo Lazar 	enum amdgpu_memory_partition mode;
1825a433f1f5SLijo Lazar 	u32 supp_modes;
1826a433f1f5SLijo Lazar 	bool valid;
1827a433f1f5SLijo Lazar 
1828a433f1f5SLijo Lazar 	mode = gmc_v9_0_get_memory_partition(adev, &supp_modes);
1829a433f1f5SLijo Lazar 
1830a433f1f5SLijo Lazar 	/* Mode detected by hardware not present in supported modes */
1831a433f1f5SLijo Lazar 	if ((mode != UNKNOWN_MEMORY_PARTITION_MODE) &&
1832a433f1f5SLijo Lazar 	    !(BIT(mode - 1) & supp_modes))
1833a433f1f5SLijo Lazar 		return false;
1834a433f1f5SLijo Lazar 
1835a433f1f5SLijo Lazar 	switch (mode) {
1836a433f1f5SLijo Lazar 	case UNKNOWN_MEMORY_PARTITION_MODE:
1837a433f1f5SLijo Lazar 	case AMDGPU_NPS1_PARTITION_MODE:
1838a433f1f5SLijo Lazar 		valid = (adev->gmc.num_mem_partitions == 1);
1839a433f1f5SLijo Lazar 		break;
1840a433f1f5SLijo Lazar 	case AMDGPU_NPS2_PARTITION_MODE:
1841a433f1f5SLijo Lazar 		valid = (adev->gmc.num_mem_partitions == 2);
1842a433f1f5SLijo Lazar 		break;
1843a433f1f5SLijo Lazar 	case AMDGPU_NPS4_PARTITION_MODE:
1844a433f1f5SLijo Lazar 		valid = (adev->gmc.num_mem_partitions == 3 ||
1845a433f1f5SLijo Lazar 			 adev->gmc.num_mem_partitions == 4);
1846a433f1f5SLijo Lazar 		break;
1847a433f1f5SLijo Lazar 	default:
1848a433f1f5SLijo Lazar 		valid = false;
1849a433f1f5SLijo Lazar 	}
1850a433f1f5SLijo Lazar 
1851a433f1f5SLijo Lazar 	return valid;
1852a433f1f5SLijo Lazar }
1853a433f1f5SLijo Lazar 
1854a433f1f5SLijo Lazar static bool gmc_v9_0_is_node_present(int *node_ids, int num_ids, int nid)
1855a433f1f5SLijo Lazar {
1856a433f1f5SLijo Lazar 	int i;
1857a433f1f5SLijo Lazar 
1858a433f1f5SLijo Lazar 	/* Check if node with id 'nid' is present in 'node_ids' array */
1859a433f1f5SLijo Lazar 	for (i = 0; i < num_ids; ++i)
1860a433f1f5SLijo Lazar 		if (node_ids[i] == nid)
1861a433f1f5SLijo Lazar 			return true;
1862a433f1f5SLijo Lazar 
1863a433f1f5SLijo Lazar 	return false;
1864a433f1f5SLijo Lazar }
1865a433f1f5SLijo Lazar 
1866a433f1f5SLijo Lazar static void
1867a433f1f5SLijo Lazar gmc_v9_0_init_acpi_mem_ranges(struct amdgpu_device *adev,
1868a433f1f5SLijo Lazar 			      struct amdgpu_mem_partition_info *mem_ranges)
1869a433f1f5SLijo Lazar {
1870a433f1f5SLijo Lazar 	int num_ranges = 0, ret, mem_groups;
1871a433f1f5SLijo Lazar 	struct amdgpu_numa_info numa_info;
1872a433f1f5SLijo Lazar 	int node_ids[MAX_MEM_RANGES];
1873a433f1f5SLijo Lazar 	int num_xcc, xcc_id;
1874a433f1f5SLijo Lazar 	uint32_t xcc_mask;
1875a433f1f5SLijo Lazar 
1876a433f1f5SLijo Lazar 	num_xcc = NUM_XCC(adev->gfx.xcc_mask);
1877a433f1f5SLijo Lazar 	xcc_mask = (1U << num_xcc) - 1;
1878a433f1f5SLijo Lazar 	mem_groups = hweight32(adev->aid_mask);
1879a433f1f5SLijo Lazar 
1880a433f1f5SLijo Lazar 	for_each_inst(xcc_id, xcc_mask)	{
1881a433f1f5SLijo Lazar 		ret = amdgpu_acpi_get_mem_info(adev, xcc_id, &numa_info);
1882a433f1f5SLijo Lazar 		if (ret)
1883a433f1f5SLijo Lazar 			continue;
1884a433f1f5SLijo Lazar 
1885a433f1f5SLijo Lazar 		if (numa_info.nid == NUMA_NO_NODE) {
1886a433f1f5SLijo Lazar 			mem_ranges[0].size = numa_info.size;
1887a433f1f5SLijo Lazar 			mem_ranges[0].numa.node = numa_info.nid;
1888a433f1f5SLijo Lazar 			num_ranges = 1;
1889a433f1f5SLijo Lazar 			break;
1890a433f1f5SLijo Lazar 		}
1891a433f1f5SLijo Lazar 
1892a433f1f5SLijo Lazar 		if (gmc_v9_0_is_node_present(node_ids, num_ranges,
1893a433f1f5SLijo Lazar 					     numa_info.nid))
1894a433f1f5SLijo Lazar 			continue;
1895a433f1f5SLijo Lazar 
1896a433f1f5SLijo Lazar 		node_ids[num_ranges] = numa_info.nid;
1897a433f1f5SLijo Lazar 		mem_ranges[num_ranges].numa.node = numa_info.nid;
1898a433f1f5SLijo Lazar 		mem_ranges[num_ranges].size = numa_info.size;
1899a433f1f5SLijo Lazar 		++num_ranges;
1900a433f1f5SLijo Lazar 	}
1901a433f1f5SLijo Lazar 
1902a433f1f5SLijo Lazar 	adev->gmc.num_mem_partitions = num_ranges;
1903a433f1f5SLijo Lazar 
1904a433f1f5SLijo Lazar 	/* If there is only partition, don't use entire size */
1905a433f1f5SLijo Lazar 	if (adev->gmc.num_mem_partitions == 1)
1906a433f1f5SLijo Lazar 		mem_ranges[0].size =
1907a433f1f5SLijo Lazar 			(mem_ranges[0].size * (mem_groups - 1) / mem_groups);
1908a433f1f5SLijo Lazar }
1909a433f1f5SLijo Lazar 
1910a433f1f5SLijo Lazar static void
1911a433f1f5SLijo Lazar gmc_v9_0_init_sw_mem_ranges(struct amdgpu_device *adev,
1912a433f1f5SLijo Lazar 			    struct amdgpu_mem_partition_info *mem_ranges)
1913a433f1f5SLijo Lazar {
1914a433f1f5SLijo Lazar 	enum amdgpu_memory_partition mode;
1915a433f1f5SLijo Lazar 	u32 start_addr = 0, size;
1916a433f1f5SLijo Lazar 	int i;
1917a433f1f5SLijo Lazar 
1918a433f1f5SLijo Lazar 	mode = gmc_v9_0_query_memory_partition(adev);
1919a433f1f5SLijo Lazar 
1920a433f1f5SLijo Lazar 	switch (mode) {
1921a433f1f5SLijo Lazar 	case UNKNOWN_MEMORY_PARTITION_MODE:
1922a433f1f5SLijo Lazar 	case AMDGPU_NPS1_PARTITION_MODE:
1923a433f1f5SLijo Lazar 		adev->gmc.num_mem_partitions = 1;
1924a433f1f5SLijo Lazar 		break;
1925a433f1f5SLijo Lazar 	case AMDGPU_NPS2_PARTITION_MODE:
1926a433f1f5SLijo Lazar 		adev->gmc.num_mem_partitions = 2;
1927a433f1f5SLijo Lazar 		break;
1928a433f1f5SLijo Lazar 	case AMDGPU_NPS4_PARTITION_MODE:
1929a433f1f5SLijo Lazar 		if (adev->flags & AMD_IS_APU)
1930a433f1f5SLijo Lazar 			adev->gmc.num_mem_partitions = 3;
1931a433f1f5SLijo Lazar 		else
1932a433f1f5SLijo Lazar 			adev->gmc.num_mem_partitions = 4;
1933a433f1f5SLijo Lazar 		break;
1934a433f1f5SLijo Lazar 	default:
1935a433f1f5SLijo Lazar 		adev->gmc.num_mem_partitions = 1;
1936a433f1f5SLijo Lazar 		break;
1937a433f1f5SLijo Lazar 	}
1938a433f1f5SLijo Lazar 
1939a433f1f5SLijo Lazar 	size = (adev->gmc.real_vram_size >> AMDGPU_GPU_PAGE_SHIFT) /
1940a433f1f5SLijo Lazar 	       adev->gmc.num_mem_partitions;
1941a433f1f5SLijo Lazar 
1942a433f1f5SLijo Lazar 	for (i = 0; i < adev->gmc.num_mem_partitions; ++i) {
1943a433f1f5SLijo Lazar 		mem_ranges[i].range.fpfn = start_addr;
1944a433f1f5SLijo Lazar 		mem_ranges[i].size = ((u64)size << AMDGPU_GPU_PAGE_SHIFT);
1945a433f1f5SLijo Lazar 		mem_ranges[i].range.lpfn = start_addr + size - 1;
1946a433f1f5SLijo Lazar 		start_addr += size;
1947a433f1f5SLijo Lazar 	}
1948a433f1f5SLijo Lazar 
1949a433f1f5SLijo Lazar 	/* Adjust the last one */
1950a433f1f5SLijo Lazar 	mem_ranges[adev->gmc.num_mem_partitions - 1].range.lpfn =
1951a433f1f5SLijo Lazar 		(adev->gmc.real_vram_size >> AMDGPU_GPU_PAGE_SHIFT) - 1;
1952a433f1f5SLijo Lazar 	mem_ranges[adev->gmc.num_mem_partitions - 1].size =
1953a433f1f5SLijo Lazar 		adev->gmc.real_vram_size -
1954a433f1f5SLijo Lazar 		((u64)mem_ranges[adev->gmc.num_mem_partitions - 1].range.fpfn
1955a433f1f5SLijo Lazar 		 << AMDGPU_GPU_PAGE_SHIFT);
1956a433f1f5SLijo Lazar }
1957a433f1f5SLijo Lazar 
1958a433f1f5SLijo Lazar static int gmc_v9_0_init_mem_ranges(struct amdgpu_device *adev)
1959a433f1f5SLijo Lazar {
1960a433f1f5SLijo Lazar 	bool valid;
1961a433f1f5SLijo Lazar 
1962a433f1f5SLijo Lazar 	adev->gmc.mem_partitions = kzalloc(
1963a433f1f5SLijo Lazar 		MAX_MEM_RANGES * sizeof(struct amdgpu_mem_partition_info),
1964a433f1f5SLijo Lazar 		GFP_KERNEL);
1965a433f1f5SLijo Lazar 
1966a433f1f5SLijo Lazar 	if (!adev->gmc.mem_partitions)
1967a433f1f5SLijo Lazar 		return -ENOMEM;
1968a433f1f5SLijo Lazar 
1969a433f1f5SLijo Lazar 	/* TODO : Get the range from PSP/Discovery for dGPU */
1970a433f1f5SLijo Lazar 	if (adev->gmc.is_app_apu)
1971a433f1f5SLijo Lazar 		gmc_v9_0_init_acpi_mem_ranges(adev, adev->gmc.mem_partitions);
1972a433f1f5SLijo Lazar 	else
1973a433f1f5SLijo Lazar 		gmc_v9_0_init_sw_mem_ranges(adev, adev->gmc.mem_partitions);
1974a433f1f5SLijo Lazar 
197546f7b4deSGavin Wan 	if (amdgpu_sriov_vf(adev))
197646f7b4deSGavin Wan 		valid = true;
197746f7b4deSGavin Wan 	else
1978a433f1f5SLijo Lazar 		valid = gmc_v9_0_validate_partition_info(adev);
1979a433f1f5SLijo Lazar 	if (!valid) {
1980a433f1f5SLijo Lazar 		/* TODO: handle invalid case */
1981a433f1f5SLijo Lazar 		dev_WARN(adev->dev,
1982a433f1f5SLijo Lazar 			 "Mem ranges not matching with hardware config");
1983a433f1f5SLijo Lazar 	}
1984a433f1f5SLijo Lazar 
1985a433f1f5SLijo Lazar 	return 0;
1986a433f1f5SLijo Lazar }
1987a433f1f5SLijo Lazar 
1988e60f8db5SAlex Xie static int gmc_v9_0_sw_init(void *handle)
1989e60f8db5SAlex Xie {
199024bf9fd1SHarish Kasiviswanathan 	int r, vram_width = 0, vram_type = 0, vram_vendor = 0, dma_addr_bits;
1991e60f8db5SAlex Xie 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
19927a1efad0SLijo Lazar 	unsigned long inst_mask = adev->aid_mask;
1993e60f8db5SAlex Xie 
19948ffff9b4SOak Zeng 	adev->gfxhub.funcs->init(adev);
19959fb1506eSOak Zeng 
19969fb1506eSOak Zeng 	adev->mmhub.funcs->init(adev);
1997e60f8db5SAlex Xie 
1998770d13b1SChristian König 	spin_lock_init(&adev->gmc.invalidate_lock);
1999e60f8db5SAlex Xie 
2000ad02e08eSOri Messinger 	r = amdgpu_atomfirmware_get_vram_info(adev,
2001ad02e08eSOri Messinger 		&vram_width, &vram_type, &vram_vendor);
2002631cdbd2SAlex Deucher 	if (amdgpu_sriov_vf(adev))
2003631cdbd2SAlex Deucher 		/* For Vega10 SR-IOV, vram_width can't be read from ATOM as RAVEN,
2004631cdbd2SAlex Deucher 		 * and DF related registers is not readable, seems hardcord is the
2005631cdbd2SAlex Deucher 		 * only way to set the correct vram_width
2006631cdbd2SAlex Deucher 		 */
2007631cdbd2SAlex Deucher 		adev->gmc.vram_width = 2048;
2008631cdbd2SAlex Deucher 	else if (amdgpu_emu_mode != 1)
2009631cdbd2SAlex Deucher 		adev->gmc.vram_width = vram_width;
2010631cdbd2SAlex Deucher 
2011631cdbd2SAlex Deucher 	if (!adev->gmc.vram_width) {
2012631cdbd2SAlex Deucher 		int chansize, numchan;
2013631cdbd2SAlex Deucher 
2014631cdbd2SAlex Deucher 		/* hbm memory channel size */
2015631cdbd2SAlex Deucher 		if (adev->flags & AMD_IS_APU)
2016631cdbd2SAlex Deucher 			chansize = 64;
2017631cdbd2SAlex Deucher 		else
2018631cdbd2SAlex Deucher 			chansize = 128;
2019cace4bffSHawking Zhang 		if (adev->df.funcs &&
2020cace4bffSHawking Zhang 		    adev->df.funcs->get_hbm_channel_number) {
2021bdf84a80SJoseph Greathouse 			numchan = adev->df.funcs->get_hbm_channel_number(adev);
2022631cdbd2SAlex Deucher 			adev->gmc.vram_width = numchan * chansize;
2023631cdbd2SAlex Deucher 		}
2024cace4bffSHawking Zhang 	}
2025631cdbd2SAlex Deucher 
2026631cdbd2SAlex Deucher 	adev->gmc.vram_type = vram_type;
2027ad02e08eSOri Messinger 	adev->gmc.vram_vendor = vram_vendor;
2028630e959fSAlex Deucher 	switch (adev->ip_versions[GC_HWIP][0]) {
2029630e959fSAlex Deucher 	case IP_VERSION(9, 1, 0):
2030630e959fSAlex Deucher 	case IP_VERSION(9, 2, 2):
2031d9426c3dSLe Ma 		set_bit(AMDGPU_GFXHUB(0), adev->vmhubs_mask);
2032d9426c3dSLe Ma 		set_bit(AMDGPU_MMHUB0(0), adev->vmhubs_mask);
20331daa2bfaSLe Ma 
20346a42fd6fSChristian König 		if (adev->rev_id == 0x0 || adev->rev_id == 0x1) {
2035f3368128SChristian König 			amdgpu_vm_adjust_size(adev, 256 * 1024, 9, 3, 48);
20366a42fd6fSChristian König 		} else {
20376a42fd6fSChristian König 			/* vm_size is 128TB + 512GB for legacy 3-level page support */
20386a42fd6fSChristian König 			amdgpu_vm_adjust_size(adev, 128 * 1024 + 512, 9, 2, 48);
2039770d13b1SChristian König 			adev->gmc.translate_further =
20406a42fd6fSChristian König 				adev->vm_manager.num_level > 1;
20416a42fd6fSChristian König 		}
2042e60f8db5SAlex Xie 		break;
2043630e959fSAlex Deucher 	case IP_VERSION(9, 0, 1):
2044630e959fSAlex Deucher 	case IP_VERSION(9, 2, 1):
2045630e959fSAlex Deucher 	case IP_VERSION(9, 4, 0):
2046630e959fSAlex Deucher 	case IP_VERSION(9, 3, 0):
2047630e959fSAlex Deucher 	case IP_VERSION(9, 4, 2):
2048d9426c3dSLe Ma 		set_bit(AMDGPU_GFXHUB(0), adev->vmhubs_mask);
2049d9426c3dSLe Ma 		set_bit(AMDGPU_MMHUB0(0), adev->vmhubs_mask);
20508787ee01SHuang Rui 
2051e60f8db5SAlex Xie 		/*
2052e60f8db5SAlex Xie 		 * To fulfill 4-level page support,
2053e60f8db5SAlex Xie 		 * vm size is 256TB (48bit), maximum size of Vega10,
2054e60f8db5SAlex Xie 		 * block size 512 (9bit)
2055e60f8db5SAlex Xie 		 */
2056cdba61daSwentalou 		/* sriov restrict max_pfn below AMDGPU_GMC_HOLE */
2057cdba61daSwentalou 		if (amdgpu_sriov_vf(adev))
2058cdba61daSwentalou 			amdgpu_vm_adjust_size(adev, 256 * 1024, 9, 3, 47);
2059cdba61daSwentalou 		else
2060f3368128SChristian König 			amdgpu_vm_adjust_size(adev, 256 * 1024, 9, 3, 48);
2061352e683bSJoseph Greathouse 		if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 2))
2062352e683bSJoseph Greathouse 			adev->gmc.translate_further = adev->vm_manager.num_level > 1;
2063e60f8db5SAlex Xie 		break;
2064630e959fSAlex Deucher 	case IP_VERSION(9, 4, 1):
2065d9426c3dSLe Ma 		set_bit(AMDGPU_GFXHUB(0), adev->vmhubs_mask);
2066d9426c3dSLe Ma 		set_bit(AMDGPU_MMHUB0(0), adev->vmhubs_mask);
2067d9426c3dSLe Ma 		set_bit(AMDGPU_MMHUB1(0), adev->vmhubs_mask);
2068c8a6e2a3SLe Ma 
20693de2ff5dSLe Ma 		/* Keep the vm size same with Vega20 */
20703de2ff5dSLe Ma 		amdgpu_vm_adjust_size(adev, 256 * 1024, 9, 3, 48);
2071352e683bSJoseph Greathouse 		adev->gmc.translate_further = adev->vm_manager.num_level > 1;
20723de2ff5dSLe Ma 		break;
2073ce8a12a5SLe Ma 	case IP_VERSION(9, 4, 3):
20748078f1c6SLijo Lazar 		bitmap_set(adev->vmhubs_mask, AMDGPU_GFXHUB(0),
20758078f1c6SLijo Lazar 				  NUM_XCC(adev->gfx.xcc_mask));
20767a1efad0SLijo Lazar 
20777a1efad0SLijo Lazar 		inst_mask <<= AMDGPU_MMHUB0(0);
20787a1efad0SLijo Lazar 		bitmap_or(adev->vmhubs_mask, adev->vmhubs_mask, &inst_mask, 32);
2079ce8a12a5SLe Ma 
2080ce8a12a5SLe Ma 		amdgpu_vm_adjust_size(adev, 256 * 1024, 9, 3, 48);
2081ce8a12a5SLe Ma 		break;
2082e60f8db5SAlex Xie 	default:
2083e60f8db5SAlex Xie 		break;
2084e60f8db5SAlex Xie 	}
2085e60f8db5SAlex Xie 
2086e60f8db5SAlex Xie 	/* This interrupt is VMC page fault.*/
208744a99b65SAndrey Grodzovsky 	r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_VMC, VMC_1_0__SRCID__VM_FAULT,
2088770d13b1SChristian König 				&adev->gmc.vm_fault);
208930da7bb1SChristian König 	if (r)
209030da7bb1SChristian König 		return r;
209130da7bb1SChristian König 
2092630e959fSAlex Deucher 	if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 1)) {
20937d19b15fSLe Ma 		r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_VMC1, VMC_1_0__SRCID__VM_FAULT,
20947d19b15fSLe Ma 					&adev->gmc.vm_fault);
20957d19b15fSLe Ma 		if (r)
20967d19b15fSLe Ma 			return r;
20977d19b15fSLe Ma 	}
20987d19b15fSLe Ma 
209944a99b65SAndrey Grodzovsky 	r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_UTCL2, UTCL2_1_0__SRCID__FAULT,
2100770d13b1SChristian König 				&adev->gmc.vm_fault);
2101e60f8db5SAlex Xie 
2102e60f8db5SAlex Xie 	if (r)
2103e60f8db5SAlex Xie 		return r;
2104e60f8db5SAlex Xie 
210568d705ddSHawking Zhang 	if (!amdgpu_sriov_vf(adev) &&
210668d705ddSHawking Zhang 	    !adev->gmc.xgmi.connected_to_cpu) {
2107791c4769Sxinhui pan 		/* interrupt sent to DF. */
2108791c4769Sxinhui pan 		r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_DF, 0,
2109791c4769Sxinhui pan 				      &adev->gmc.ecc_irq);
2110791c4769Sxinhui pan 		if (r)
2111791c4769Sxinhui pan 			return r;
21122ee9403eSZhigang Luo 	}
2113791c4769Sxinhui pan 
2114e60f8db5SAlex Xie 	/* Set the internal MC address mask
2115e60f8db5SAlex Xie 	 * This is the max address of the GPU's
2116e60f8db5SAlex Xie 	 * internal address space.
2117e60f8db5SAlex Xie 	 */
2118770d13b1SChristian König 	adev->gmc.mc_mask = 0xffffffffffffULL; /* 48 bit MC */
2119e60f8db5SAlex Xie 
212012c4d7edSLijo Lazar 	dma_addr_bits = adev->ip_versions[GC_HWIP][0] >= IP_VERSION(9, 4, 2) ? 48:44;
212124bf9fd1SHarish Kasiviswanathan 	r = dma_set_mask_and_coherent(adev->dev, DMA_BIT_MASK(dma_addr_bits));
2122e60f8db5SAlex Xie 	if (r) {
2123e60f8db5SAlex Xie 		printk(KERN_WARNING "amdgpu: No suitable DMA available.\n");
2124244511f3SChristoph Hellwig 		return r;
2125e60f8db5SAlex Xie 	}
212624bf9fd1SHarish Kasiviswanathan 	adev->need_swiotlb = drm_need_swiotlb(dma_addr_bits);
2127e60f8db5SAlex Xie 
2128e60f8db5SAlex Xie 	r = gmc_v9_0_mc_init(adev);
2129e60f8db5SAlex Xie 	if (r)
2130e60f8db5SAlex Xie 		return r;
2131e60f8db5SAlex Xie 
21327b885f0eSAlex Deucher 	amdgpu_gmc_get_vbios_allocations(adev);
2133ebdef28eSAlex Deucher 
2134a433f1f5SLijo Lazar 	if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 3)) {
2135a433f1f5SLijo Lazar 		r = gmc_v9_0_init_mem_ranges(adev);
2136a433f1f5SLijo Lazar 		if (r)
2137a433f1f5SLijo Lazar 			return r;
2138a433f1f5SLijo Lazar 	}
2139a433f1f5SLijo Lazar 
2140e60f8db5SAlex Xie 	/* Memory manager */
2141e60f8db5SAlex Xie 	r = amdgpu_bo_init(adev);
2142e60f8db5SAlex Xie 	if (r)
2143e60f8db5SAlex Xie 		return r;
2144e60f8db5SAlex Xie 
2145e60f8db5SAlex Xie 	r = gmc_v9_0_gart_init(adev);
2146e60f8db5SAlex Xie 	if (r)
2147e60f8db5SAlex Xie 		return r;
2148e60f8db5SAlex Xie 
214905ec3edaSChristian König 	/*
215005ec3edaSChristian König 	 * number of VMs
215105ec3edaSChristian König 	 * VMID 0 is reserved for System
215281659b20SFelix Kuehling 	 * amdgpu graphics/compute will use VMIDs 1..n-1
215381659b20SFelix Kuehling 	 * amdkfd will use VMIDs n..15
215481659b20SFelix Kuehling 	 *
215581659b20SFelix Kuehling 	 * The first KFD VMID is 8 for GPUs with graphics, 3 for
215681659b20SFelix Kuehling 	 * compute-only GPUs. On compute-only GPUs that leaves 2 VMIDs
215781659b20SFelix Kuehling 	 * for video processing.
215805ec3edaSChristian König 	 */
215981659b20SFelix Kuehling 	adev->vm_manager.first_kfd_vmid =
2160630e959fSAlex Deucher 		(adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 1) ||
2161ab1a157eSHawking Zhang 		 adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 2) ||
2162ab1a157eSHawking Zhang 		 adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 3)) ? 3 : 8;
216305ec3edaSChristian König 
216405ec3edaSChristian König 	amdgpu_vm_manager_init(adev);
216505ec3edaSChristian König 
2166b0a2db9bSAlex Deucher 	gmc_v9_0_save_registers(adev);
2167b0a2db9bSAlex Deucher 
2168a6dcf9a7SHawking Zhang 	r = amdgpu_gmc_ras_sw_init(adev);
2169a6dcf9a7SHawking Zhang 	if (r)
2170a6dcf9a7SHawking Zhang 		return r;
2171a6dcf9a7SHawking Zhang 
2172b6f90baaSLijo Lazar 	if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 3))
2173b6f90baaSLijo Lazar 		amdgpu_gmc_sysfs_init(adev);
2174b6f90baaSLijo Lazar 
217505ec3edaSChristian König 	return 0;
2176e60f8db5SAlex Xie }
2177e60f8db5SAlex Xie 
2178e60f8db5SAlex Xie static int gmc_v9_0_sw_fini(void *handle)
2179e60f8db5SAlex Xie {
2180e60f8db5SAlex Xie 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
2181e60f8db5SAlex Xie 
2182b6f90baaSLijo Lazar 	if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 3))
2183b6f90baaSLijo Lazar 		amdgpu_gmc_sysfs_fini(adev);
2184a433f1f5SLijo Lazar 	adev->gmc.num_mem_partitions = 0;
2185a433f1f5SLijo Lazar 	kfree(adev->gmc.mem_partitions);
2186b6f90baaSLijo Lazar 
21872adf1344STao Zhou 	amdgpu_gmc_ras_fini(adev);
2188f59548c8SMonk Liu 	amdgpu_gem_force_release(adev);
2189e60f8db5SAlex Xie 	amdgpu_vm_manager_fini(adev);
2190c9a502e9SFelix Kuehling 	if (!adev->gmc.real_vram_size) {
2191c9a502e9SFelix Kuehling 		dev_info(adev->dev, "Put GART in system memory for APU free\n");
2192c9a502e9SFelix Kuehling 		amdgpu_gart_table_ram_free(adev);
2193c9a502e9SFelix Kuehling 	} else {
2194a3d9103eSAndrey Grodzovsky 		amdgpu_gart_table_vram_free(adev);
2195c9a502e9SFelix Kuehling 	}
21962d505453SGuchun Chen 	amdgpu_bo_free_kernel(&adev->gmc.pdb0_bo, NULL, &adev->gmc.ptr_pdb0);
2197e60f8db5SAlex Xie 	amdgpu_bo_fini(adev);
2198e60f8db5SAlex Xie 
2199e60f8db5SAlex Xie 	return 0;
2200e60f8db5SAlex Xie }
2201e60f8db5SAlex Xie 
2202e60f8db5SAlex Xie static void gmc_v9_0_init_golden_registers(struct amdgpu_device *adev)
2203e60f8db5SAlex Xie {
2204946a4d5bSShaoyun Liu 
2205630e959fSAlex Deucher 	switch (adev->ip_versions[MMHUB_HWIP][0]) {
2206630e959fSAlex Deucher 	case IP_VERSION(9, 0, 0):
22074cd4c5c0SMonk Liu 		if (amdgpu_sriov_vf(adev))
220898cad2deSTrigger Huang 			break;
2209df561f66SGustavo A. R. Silva 		fallthrough;
2210630e959fSAlex Deucher 	case IP_VERSION(9, 4, 0):
2211946a4d5bSShaoyun Liu 		soc15_program_register_sequence(adev,
22125c583018SEvan Quan 						golden_settings_mmhub_1_0_0,
2213c47b41a7SChristian König 						ARRAY_SIZE(golden_settings_mmhub_1_0_0));
2214946a4d5bSShaoyun Liu 		soc15_program_register_sequence(adev,
22155c583018SEvan Quan 						golden_settings_athub_1_0_0,
2216c47b41a7SChristian König 						ARRAY_SIZE(golden_settings_athub_1_0_0));
2217e60f8db5SAlex Xie 		break;
2218630e959fSAlex Deucher 	case IP_VERSION(9, 1, 0):
2219630e959fSAlex Deucher 	case IP_VERSION(9, 2, 0):
22208787ee01SHuang Rui 		/* TODO for renoir */
2221946a4d5bSShaoyun Liu 		soc15_program_register_sequence(adev,
22225c583018SEvan Quan 						golden_settings_athub_1_0_0,
2223c47b41a7SChristian König 						ARRAY_SIZE(golden_settings_athub_1_0_0));
2224e4f3abaaSChunming Zhou 		break;
2225e60f8db5SAlex Xie 	default:
2226e60f8db5SAlex Xie 		break;
2227e60f8db5SAlex Xie 	}
2228e60f8db5SAlex Xie }
2229e60f8db5SAlex Xie 
2230e60f8db5SAlex Xie /**
2231c2ecd79bSShirish S  * gmc_v9_0_restore_registers - restores regs
2232c2ecd79bSShirish S  *
2233c2ecd79bSShirish S  * @adev: amdgpu_device pointer
2234c2ecd79bSShirish S  *
2235c2ecd79bSShirish S  * This restores register values, saved at suspend.
2236c2ecd79bSShirish S  */
2237b0a2db9bSAlex Deucher void gmc_v9_0_restore_registers(struct amdgpu_device *adev)
2238c2ecd79bSShirish S {
2239630e959fSAlex Deucher 	if ((adev->ip_versions[DCE_HWIP][0] == IP_VERSION(1, 0, 0)) ||
2240630e959fSAlex Deucher 	    (adev->ip_versions[DCE_HWIP][0] == IP_VERSION(1, 0, 1))) {
2241f8646661SAlex Deucher 		WREG32_SOC15(DCE, 0, mmDCHUBBUB_SDPIF_MMIO_CNTRL_0, adev->gmc.sdpif_register);
22420eaa8012SShirish S 		WARN_ON(adev->gmc.sdpif_register !=
22430eaa8012SShirish S 			RREG32_SOC15(DCE, 0, mmDCHUBBUB_SDPIF_MMIO_CNTRL_0));
22440eaa8012SShirish S 	}
2245c2ecd79bSShirish S }
2246c2ecd79bSShirish S 
2247c2ecd79bSShirish S /**
2248e60f8db5SAlex Xie  * gmc_v9_0_gart_enable - gart enable
2249e60f8db5SAlex Xie  *
2250e60f8db5SAlex Xie  * @adev: amdgpu_device pointer
2251e60f8db5SAlex Xie  */
2252e60f8db5SAlex Xie static int gmc_v9_0_gart_enable(struct amdgpu_device *adev)
2253e60f8db5SAlex Xie {
2254cb1545f7SOak Zeng 	int r;
2255e60f8db5SAlex Xie 
2256522510a6SOak Zeng 	if (adev->gmc.xgmi.connected_to_cpu)
2257522510a6SOak Zeng 		amdgpu_gmc_init_pdb0(adev);
2258522510a6SOak Zeng 
22591123b989SChristian König 	if (adev->gart.bo == NULL) {
2260e60f8db5SAlex Xie 		dev_err(adev->dev, "No VRAM object for PCIE GART.\n");
2261e60f8db5SAlex Xie 		return -EINVAL;
2262e60f8db5SAlex Xie 	}
2263522510a6SOak Zeng 
22641b08dfb8SChristian König 	amdgpu_gtt_mgr_recover(&adev->mman.gtt_mgr);
2265b93df61dSAlex Deucher 
2266b93df61dSAlex Deucher 	if (!adev->in_s0ix) {
22678ffff9b4SOak Zeng 		r = adev->gfxhub.funcs->gart_enable(adev);
2268e60f8db5SAlex Xie 		if (r)
2269e60f8db5SAlex Xie 			return r;
2270b93df61dSAlex Deucher 	}
2271e60f8db5SAlex Xie 
22729fb1506eSOak Zeng 	r = adev->mmhub.funcs->gart_enable(adev);
2273e60f8db5SAlex Xie 	if (r)
2274e60f8db5SAlex Xie 		return r;
2275e60f8db5SAlex Xie 
2276522510a6SOak Zeng 	DRM_INFO("PCIE GART of %uM enabled.\n",
2277522510a6SOak Zeng 		 (unsigned)(adev->gmc.gart_size >> 20));
2278522510a6SOak Zeng 	if (adev->gmc.pdb0_bo)
2279522510a6SOak Zeng 		DRM_INFO("PDB0 located at 0x%016llX\n",
2280522510a6SOak Zeng 				(unsigned long long)amdgpu_bo_gpu_offset(adev->gmc.pdb0_bo));
2281522510a6SOak Zeng 	DRM_INFO("PTB located at 0x%016llX\n",
2282cb1545f7SOak Zeng 			(unsigned long long)amdgpu_bo_gpu_offset(adev->gart.bo));
2283522510a6SOak Zeng 
2284cb1545f7SOak Zeng 	return 0;
2285cb1545f7SOak Zeng }
2286cb1545f7SOak Zeng 
2287cb1545f7SOak Zeng static int gmc_v9_0_hw_init(void *handle)
2288cb1545f7SOak Zeng {
2289cb1545f7SOak Zeng 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
2290cb1545f7SOak Zeng 	bool value;
2291479e3b02SXiaojian Du 	int i, r;
2292cb1545f7SOak Zeng 
2293cb1545f7SOak Zeng 	/* The sequence of these two function calls matters.*/
2294cb1545f7SOak Zeng 	gmc_v9_0_init_golden_registers(adev);
2295cb1545f7SOak Zeng 
2296cb1545f7SOak Zeng 	if (adev->mode_info.num_crtc) {
2297cb1545f7SOak Zeng 		/* Lockout access through VGA aperture*/
2298cb1545f7SOak Zeng 		WREG32_FIELD15(DCE, 0, VGA_HDP_CONTROL, VGA_MEMORY_DISABLE, 1);
2299cb1545f7SOak Zeng 		/* disable VGA render */
2300cb1545f7SOak Zeng 		WREG32_FIELD15(DCE, 0, VGA_RENDER_CONTROL, VGA_VSTATUS_CNTL, 0);
2301cb1545f7SOak Zeng 	}
2302cb1545f7SOak Zeng 
23039fb1506eSOak Zeng 	if (adev->mmhub.funcs->update_power_gating)
23049fb1506eSOak Zeng 		adev->mmhub.funcs->update_power_gating(adev, true);
23059fb1506eSOak Zeng 
2306455d40c9SLikun Gao 	adev->hdp.funcs->init_registers(adev);
2307fe2b5323STiecheng Zhou 
23081d4e0a8cSMonk Liu 	/* After HDP is initialized, flush HDP.*/
2309455d40c9SLikun Gao 	adev->hdp.funcs->flush_hdp(adev, NULL);
23101d4e0a8cSMonk Liu 
2311e60f8db5SAlex Xie 	if (amdgpu_vm_fault_stop == AMDGPU_VM_FAULT_STOP_ALWAYS)
2312e60f8db5SAlex Xie 		value = false;
2313e60f8db5SAlex Xie 	else
2314e60f8db5SAlex Xie 		value = true;
2315e60f8db5SAlex Xie 
231620bf2f6fSZhigang Luo 	if (!amdgpu_sriov_vf(adev)) {
2317b93df61dSAlex Deucher 		if (!adev->in_s0ix)
23188ffff9b4SOak Zeng 			adev->gfxhub.funcs->set_fault_enable_default(adev, value);
23199fb1506eSOak Zeng 		adev->mmhub.funcs->set_fault_enable_default(adev, value);
232020bf2f6fSZhigang Luo 	}
2321d9426c3dSLe Ma 	for_each_set_bit(i, adev->vmhubs_mask, AMDGPU_MAX_VMHUBS) {
2322f4caf584SHawking Zhang 		if (adev->in_s0ix && (i == AMDGPU_GFXHUB(0)))
2323b93df61dSAlex Deucher 			continue;
23243ff98548SOak Zeng 		gmc_v9_0_flush_gpu_tlb(adev, 0, i, 0);
2325b93df61dSAlex Deucher 	}
2326e60f8db5SAlex Xie 
2327e7da754bSMonk Liu 	if (adev->umc.funcs && adev->umc.funcs->init_registers)
2328e7da754bSMonk Liu 		adev->umc.funcs->init_registers(adev);
2329e7da754bSMonk Liu 
2330479e3b02SXiaojian Du 	r = gmc_v9_0_gart_enable(adev);
2331479e3b02SXiaojian Du 	if (r)
2332479e3b02SXiaojian Du 		return r;
2333479e3b02SXiaojian Du 
2334479e3b02SXiaojian Du 	if (amdgpu_emu_mode == 1)
2335479e3b02SXiaojian Du 		return amdgpu_gmc_vram_checking(adev);
2336479e3b02SXiaojian Du 	else
2337479e3b02SXiaojian Du 		return r;
2338e60f8db5SAlex Xie }
2339e60f8db5SAlex Xie 
2340e60f8db5SAlex Xie /**
2341e60f8db5SAlex Xie  * gmc_v9_0_gart_disable - gart disable
2342e60f8db5SAlex Xie  *
2343e60f8db5SAlex Xie  * @adev: amdgpu_device pointer
2344e60f8db5SAlex Xie  *
2345e60f8db5SAlex Xie  * This disables all VM page table.
2346e60f8db5SAlex Xie  */
2347e60f8db5SAlex Xie static void gmc_v9_0_gart_disable(struct amdgpu_device *adev)
2348e60f8db5SAlex Xie {
2349b93df61dSAlex Deucher 	if (!adev->in_s0ix)
23508ffff9b4SOak Zeng 		adev->gfxhub.funcs->gart_disable(adev);
23519fb1506eSOak Zeng 	adev->mmhub.funcs->gart_disable(adev);
2352e60f8db5SAlex Xie }
2353e60f8db5SAlex Xie 
2354e60f8db5SAlex Xie static int gmc_v9_0_hw_fini(void *handle)
2355e60f8db5SAlex Xie {
2356e60f8db5SAlex Xie 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
2357e60f8db5SAlex Xie 
235871cf9e72SLeslie Shi 	gmc_v9_0_gart_disable(adev);
235971cf9e72SLeslie Shi 
23605dd696aeSTrigger Huang 	if (amdgpu_sriov_vf(adev)) {
23615dd696aeSTrigger Huang 		/* full access mode, so don't touch any GMC register */
23625dd696aeSTrigger Huang 		DRM_DEBUG("For SRIOV client, shouldn't do anything.\n");
23635dd696aeSTrigger Huang 		return 0;
23645dd696aeSTrigger Huang 	}
23655dd696aeSTrigger Huang 
236617252701SEvan Quan 	/*
236717252701SEvan Quan 	 * Pair the operations did in gmc_v9_0_hw_init and thus maintain
236817252701SEvan Quan 	 * a correct cached state for GMC. Otherwise, the "gate" again
236917252701SEvan Quan 	 * operation on S3 resuming will fail due to wrong cached state.
237017252701SEvan Quan 	 */
237117252701SEvan Quan 	if (adev->mmhub.funcs->update_power_gating)
237217252701SEvan Quan 		adev->mmhub.funcs->update_power_gating(adev, false);
237317252701SEvan Quan 
2374770d13b1SChristian König 	amdgpu_irq_put(adev, &adev->gmc.vm_fault, 0);
2375e60f8db5SAlex Xie 
2376e60f8db5SAlex Xie 	return 0;
2377e60f8db5SAlex Xie }
2378e60f8db5SAlex Xie 
2379e60f8db5SAlex Xie static int gmc_v9_0_suspend(void *handle)
2380e60f8db5SAlex Xie {
2381e60f8db5SAlex Xie 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
2382e60f8db5SAlex Xie 
2383c24a3c05SLiu Shixin 	return gmc_v9_0_hw_fini(adev);
2384e60f8db5SAlex Xie }
2385e60f8db5SAlex Xie 
2386e60f8db5SAlex Xie static int gmc_v9_0_resume(void *handle)
2387e60f8db5SAlex Xie {
2388e60f8db5SAlex Xie 	int r;
2389e60f8db5SAlex Xie 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
2390e60f8db5SAlex Xie 
2391e60f8db5SAlex Xie 	r = gmc_v9_0_hw_init(adev);
2392e60f8db5SAlex Xie 	if (r)
2393e60f8db5SAlex Xie 		return r;
2394e60f8db5SAlex Xie 
2395620f774fSChristian König 	amdgpu_vmid_reset_all(adev);
2396e60f8db5SAlex Xie 
239732601d48SChristian König 	return 0;
2398e60f8db5SAlex Xie }
2399e60f8db5SAlex Xie 
2400e60f8db5SAlex Xie static bool gmc_v9_0_is_idle(void *handle)
2401e60f8db5SAlex Xie {
2402e60f8db5SAlex Xie 	/* MC is always ready in GMC v9.*/
2403e60f8db5SAlex Xie 	return true;
2404e60f8db5SAlex Xie }
2405e60f8db5SAlex Xie 
2406e60f8db5SAlex Xie static int gmc_v9_0_wait_for_idle(void *handle)
2407e60f8db5SAlex Xie {
2408e60f8db5SAlex Xie 	/* There is no need to wait for MC idle in GMC v9.*/
2409e60f8db5SAlex Xie 	return 0;
2410e60f8db5SAlex Xie }
2411e60f8db5SAlex Xie 
2412e60f8db5SAlex Xie static int gmc_v9_0_soft_reset(void *handle)
2413e60f8db5SAlex Xie {
2414e60f8db5SAlex Xie 	/* XXX for emulation.*/
2415e60f8db5SAlex Xie 	return 0;
2416e60f8db5SAlex Xie }
2417e60f8db5SAlex Xie 
2418e60f8db5SAlex Xie static int gmc_v9_0_set_clockgating_state(void *handle,
2419e60f8db5SAlex Xie 					enum amd_clockgating_state state)
2420e60f8db5SAlex Xie {
2421d5583d4fSHuang Rui 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
2422d5583d4fSHuang Rui 
24239fb1506eSOak Zeng 	adev->mmhub.funcs->set_clockgating(adev, state);
2424bee7b51aSLe Ma 
2425bee7b51aSLe Ma 	athub_v1_0_set_clockgating(adev, state);
2426bee7b51aSLe Ma 
2427bee7b51aSLe Ma 	return 0;
2428e60f8db5SAlex Xie }
2429e60f8db5SAlex Xie 
243025faeddcSEvan Quan static void gmc_v9_0_get_clockgating_state(void *handle, u64 *flags)
243113052be5SHuang Rui {
243213052be5SHuang Rui 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
243313052be5SHuang Rui 
24349fb1506eSOak Zeng 	adev->mmhub.funcs->get_clockgating(adev, flags);
2435bee7b51aSLe Ma 
2436bee7b51aSLe Ma 	athub_v1_0_get_clockgating(adev, flags);
243713052be5SHuang Rui }
243813052be5SHuang Rui 
2439e60f8db5SAlex Xie static int gmc_v9_0_set_powergating_state(void *handle,
2440e60f8db5SAlex Xie 					enum amd_powergating_state state)
2441e60f8db5SAlex Xie {
2442e60f8db5SAlex Xie 	return 0;
2443e60f8db5SAlex Xie }
2444e60f8db5SAlex Xie 
2445e60f8db5SAlex Xie const struct amd_ip_funcs gmc_v9_0_ip_funcs = {
2446e60f8db5SAlex Xie 	.name = "gmc_v9_0",
2447e60f8db5SAlex Xie 	.early_init = gmc_v9_0_early_init,
2448e60f8db5SAlex Xie 	.late_init = gmc_v9_0_late_init,
2449e60f8db5SAlex Xie 	.sw_init = gmc_v9_0_sw_init,
2450e60f8db5SAlex Xie 	.sw_fini = gmc_v9_0_sw_fini,
2451e60f8db5SAlex Xie 	.hw_init = gmc_v9_0_hw_init,
2452e60f8db5SAlex Xie 	.hw_fini = gmc_v9_0_hw_fini,
2453e60f8db5SAlex Xie 	.suspend = gmc_v9_0_suspend,
2454e60f8db5SAlex Xie 	.resume = gmc_v9_0_resume,
2455e60f8db5SAlex Xie 	.is_idle = gmc_v9_0_is_idle,
2456e60f8db5SAlex Xie 	.wait_for_idle = gmc_v9_0_wait_for_idle,
2457e60f8db5SAlex Xie 	.soft_reset = gmc_v9_0_soft_reset,
2458e60f8db5SAlex Xie 	.set_clockgating_state = gmc_v9_0_set_clockgating_state,
2459e60f8db5SAlex Xie 	.set_powergating_state = gmc_v9_0_set_powergating_state,
246013052be5SHuang Rui 	.get_clockgating_state = gmc_v9_0_get_clockgating_state,
2461e60f8db5SAlex Xie };
2462e60f8db5SAlex Xie 
2463e60f8db5SAlex Xie const struct amdgpu_ip_block_version gmc_v9_0_ip_block =
2464e60f8db5SAlex Xie {
2465e60f8db5SAlex Xie 	.type = AMD_IP_BLOCK_TYPE_GMC,
2466e60f8db5SAlex Xie 	.major = 9,
2467e60f8db5SAlex Xie 	.minor = 0,
2468e60f8db5SAlex Xie 	.rev = 0,
2469e60f8db5SAlex Xie 	.funcs = &gmc_v9_0_ip_funcs,
2470e60f8db5SAlex Xie };
2471