162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci * Copyright 2011 Advanced Micro Devices, Inc.
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
562306a36Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
662306a36Sopenharmony_ci * to deal in the Software without restriction, including without limitation
762306a36Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
862306a36Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
962306a36Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
1062306a36Sopenharmony_ci *
1162306a36Sopenharmony_ci * The above copyright notice and this permission notice shall be included in
1262306a36Sopenharmony_ci * all copies or substantial portions of the Software.
1362306a36Sopenharmony_ci *
1462306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1562306a36Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1662306a36Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1762306a36Sopenharmony_ci * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
1862306a36Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
1962306a36Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
2062306a36Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE.
2162306a36Sopenharmony_ci *
2262306a36Sopenharmony_ci * Authors: Alex Deucher
2362306a36Sopenharmony_ci */
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci#include <linux/firmware.h>
2662306a36Sopenharmony_ci#include <linux/module.h>
2762306a36Sopenharmony_ci#include <linux/pci.h>
2862306a36Sopenharmony_ci#include <linux/slab.h>
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci#include <drm/drm_vblank.h>
3162306a36Sopenharmony_ci#include <drm/radeon_drm.h>
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci#include "atom.h"
3462306a36Sopenharmony_ci#include "clearstate_si.h"
3562306a36Sopenharmony_ci#include "evergreen.h"
3662306a36Sopenharmony_ci#include "r600.h"
3762306a36Sopenharmony_ci#include "radeon.h"
3862306a36Sopenharmony_ci#include "radeon_asic.h"
3962306a36Sopenharmony_ci#include "radeon_audio.h"
4062306a36Sopenharmony_ci#include "radeon_ucode.h"
4162306a36Sopenharmony_ci#include "si_blit_shaders.h"
4262306a36Sopenharmony_ci#include "si.h"
4362306a36Sopenharmony_ci#include "sid.h"
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/TAHITI_pfp.bin");
4762306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/TAHITI_me.bin");
4862306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/TAHITI_ce.bin");
4962306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/TAHITI_mc.bin");
5062306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/TAHITI_mc2.bin");
5162306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/TAHITI_rlc.bin");
5262306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/TAHITI_smc.bin");
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/tahiti_pfp.bin");
5562306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/tahiti_me.bin");
5662306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/tahiti_ce.bin");
5762306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/tahiti_mc.bin");
5862306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/tahiti_rlc.bin");
5962306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/tahiti_smc.bin");
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/PITCAIRN_pfp.bin");
6262306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/PITCAIRN_me.bin");
6362306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/PITCAIRN_ce.bin");
6462306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/PITCAIRN_mc.bin");
6562306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/PITCAIRN_mc2.bin");
6662306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/PITCAIRN_rlc.bin");
6762306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/PITCAIRN_smc.bin");
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/pitcairn_pfp.bin");
7062306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/pitcairn_me.bin");
7162306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/pitcairn_ce.bin");
7262306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/pitcairn_mc.bin");
7362306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/pitcairn_rlc.bin");
7462306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/pitcairn_smc.bin");
7562306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/pitcairn_k_smc.bin");
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/VERDE_pfp.bin");
7862306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/VERDE_me.bin");
7962306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/VERDE_ce.bin");
8062306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/VERDE_mc.bin");
8162306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/VERDE_mc2.bin");
8262306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/VERDE_rlc.bin");
8362306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/VERDE_smc.bin");
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/verde_pfp.bin");
8662306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/verde_me.bin");
8762306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/verde_ce.bin");
8862306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/verde_mc.bin");
8962306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/verde_rlc.bin");
9062306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/verde_smc.bin");
9162306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/verde_k_smc.bin");
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/OLAND_pfp.bin");
9462306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/OLAND_me.bin");
9562306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/OLAND_ce.bin");
9662306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/OLAND_mc.bin");
9762306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/OLAND_mc2.bin");
9862306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/OLAND_rlc.bin");
9962306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/OLAND_smc.bin");
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/oland_pfp.bin");
10262306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/oland_me.bin");
10362306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/oland_ce.bin");
10462306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/oland_mc.bin");
10562306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/oland_rlc.bin");
10662306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/oland_smc.bin");
10762306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/oland_k_smc.bin");
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/HAINAN_pfp.bin");
11062306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/HAINAN_me.bin");
11162306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/HAINAN_ce.bin");
11262306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/HAINAN_mc.bin");
11362306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/HAINAN_mc2.bin");
11462306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/HAINAN_rlc.bin");
11562306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/HAINAN_smc.bin");
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/hainan_pfp.bin");
11862306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/hainan_me.bin");
11962306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/hainan_ce.bin");
12062306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/hainan_mc.bin");
12162306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/hainan_rlc.bin");
12262306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/hainan_smc.bin");
12362306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/hainan_k_smc.bin");
12462306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/banks_k_2_smc.bin");
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/si58_mc.bin");
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_cistatic u32 si_get_cu_active_bitmap(struct radeon_device *rdev, u32 se, u32 sh);
12962306a36Sopenharmony_cistatic void si_pcie_gen3_enable(struct radeon_device *rdev);
13062306a36Sopenharmony_cistatic void si_program_aspm(struct radeon_device *rdev);
13162306a36Sopenharmony_ciextern void sumo_rlc_fini(struct radeon_device *rdev);
13262306a36Sopenharmony_ciextern int sumo_rlc_init(struct radeon_device *rdev);
13362306a36Sopenharmony_cistatic void si_enable_gui_idle_interrupt(struct radeon_device *rdev,
13462306a36Sopenharmony_ci					 bool enable);
13562306a36Sopenharmony_cistatic void si_init_pg(struct radeon_device *rdev);
13662306a36Sopenharmony_cistatic void si_init_cg(struct radeon_device *rdev);
13762306a36Sopenharmony_cistatic void si_fini_pg(struct radeon_device *rdev);
13862306a36Sopenharmony_cistatic void si_fini_cg(struct radeon_device *rdev);
13962306a36Sopenharmony_cistatic void si_rlc_stop(struct radeon_device *rdev);
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_cistatic const u32 crtc_offsets[] =
14262306a36Sopenharmony_ci{
14362306a36Sopenharmony_ci	EVERGREEN_CRTC0_REGISTER_OFFSET,
14462306a36Sopenharmony_ci	EVERGREEN_CRTC1_REGISTER_OFFSET,
14562306a36Sopenharmony_ci	EVERGREEN_CRTC2_REGISTER_OFFSET,
14662306a36Sopenharmony_ci	EVERGREEN_CRTC3_REGISTER_OFFSET,
14762306a36Sopenharmony_ci	EVERGREEN_CRTC4_REGISTER_OFFSET,
14862306a36Sopenharmony_ci	EVERGREEN_CRTC5_REGISTER_OFFSET
14962306a36Sopenharmony_ci};
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_cistatic const u32 si_disp_int_status[] =
15262306a36Sopenharmony_ci{
15362306a36Sopenharmony_ci	DISP_INTERRUPT_STATUS,
15462306a36Sopenharmony_ci	DISP_INTERRUPT_STATUS_CONTINUE,
15562306a36Sopenharmony_ci	DISP_INTERRUPT_STATUS_CONTINUE2,
15662306a36Sopenharmony_ci	DISP_INTERRUPT_STATUS_CONTINUE3,
15762306a36Sopenharmony_ci	DISP_INTERRUPT_STATUS_CONTINUE4,
15862306a36Sopenharmony_ci	DISP_INTERRUPT_STATUS_CONTINUE5
15962306a36Sopenharmony_ci};
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ci#define DC_HPDx_CONTROL(x)        (DC_HPD1_CONTROL     + (x * 0xc))
16262306a36Sopenharmony_ci#define DC_HPDx_INT_CONTROL(x)    (DC_HPD1_INT_CONTROL + (x * 0xc))
16362306a36Sopenharmony_ci#define DC_HPDx_INT_STATUS_REG(x) (DC_HPD1_INT_STATUS  + (x * 0xc))
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_cistatic const u32 verde_rlc_save_restore_register_list[] =
16662306a36Sopenharmony_ci{
16762306a36Sopenharmony_ci	(0x8000 << 16) | (0x98f4 >> 2),
16862306a36Sopenharmony_ci	0x00000000,
16962306a36Sopenharmony_ci	(0x8040 << 16) | (0x98f4 >> 2),
17062306a36Sopenharmony_ci	0x00000000,
17162306a36Sopenharmony_ci	(0x8000 << 16) | (0xe80 >> 2),
17262306a36Sopenharmony_ci	0x00000000,
17362306a36Sopenharmony_ci	(0x8040 << 16) | (0xe80 >> 2),
17462306a36Sopenharmony_ci	0x00000000,
17562306a36Sopenharmony_ci	(0x8000 << 16) | (0x89bc >> 2),
17662306a36Sopenharmony_ci	0x00000000,
17762306a36Sopenharmony_ci	(0x8040 << 16) | (0x89bc >> 2),
17862306a36Sopenharmony_ci	0x00000000,
17962306a36Sopenharmony_ci	(0x8000 << 16) | (0x8c1c >> 2),
18062306a36Sopenharmony_ci	0x00000000,
18162306a36Sopenharmony_ci	(0x8040 << 16) | (0x8c1c >> 2),
18262306a36Sopenharmony_ci	0x00000000,
18362306a36Sopenharmony_ci	(0x9c00 << 16) | (0x98f0 >> 2),
18462306a36Sopenharmony_ci	0x00000000,
18562306a36Sopenharmony_ci	(0x9c00 << 16) | (0xe7c >> 2),
18662306a36Sopenharmony_ci	0x00000000,
18762306a36Sopenharmony_ci	(0x8000 << 16) | (0x9148 >> 2),
18862306a36Sopenharmony_ci	0x00000000,
18962306a36Sopenharmony_ci	(0x8040 << 16) | (0x9148 >> 2),
19062306a36Sopenharmony_ci	0x00000000,
19162306a36Sopenharmony_ci	(0x9c00 << 16) | (0x9150 >> 2),
19262306a36Sopenharmony_ci	0x00000000,
19362306a36Sopenharmony_ci	(0x9c00 << 16) | (0x897c >> 2),
19462306a36Sopenharmony_ci	0x00000000,
19562306a36Sopenharmony_ci	(0x9c00 << 16) | (0x8d8c >> 2),
19662306a36Sopenharmony_ci	0x00000000,
19762306a36Sopenharmony_ci	(0x9c00 << 16) | (0xac54 >> 2),
19862306a36Sopenharmony_ci	0X00000000,
19962306a36Sopenharmony_ci	0x3,
20062306a36Sopenharmony_ci	(0x9c00 << 16) | (0x98f8 >> 2),
20162306a36Sopenharmony_ci	0x00000000,
20262306a36Sopenharmony_ci	(0x9c00 << 16) | (0x9910 >> 2),
20362306a36Sopenharmony_ci	0x00000000,
20462306a36Sopenharmony_ci	(0x9c00 << 16) | (0x9914 >> 2),
20562306a36Sopenharmony_ci	0x00000000,
20662306a36Sopenharmony_ci	(0x9c00 << 16) | (0x9918 >> 2),
20762306a36Sopenharmony_ci	0x00000000,
20862306a36Sopenharmony_ci	(0x9c00 << 16) | (0x991c >> 2),
20962306a36Sopenharmony_ci	0x00000000,
21062306a36Sopenharmony_ci	(0x9c00 << 16) | (0x9920 >> 2),
21162306a36Sopenharmony_ci	0x00000000,
21262306a36Sopenharmony_ci	(0x9c00 << 16) | (0x9924 >> 2),
21362306a36Sopenharmony_ci	0x00000000,
21462306a36Sopenharmony_ci	(0x9c00 << 16) | (0x9928 >> 2),
21562306a36Sopenharmony_ci	0x00000000,
21662306a36Sopenharmony_ci	(0x9c00 << 16) | (0x992c >> 2),
21762306a36Sopenharmony_ci	0x00000000,
21862306a36Sopenharmony_ci	(0x9c00 << 16) | (0x9930 >> 2),
21962306a36Sopenharmony_ci	0x00000000,
22062306a36Sopenharmony_ci	(0x9c00 << 16) | (0x9934 >> 2),
22162306a36Sopenharmony_ci	0x00000000,
22262306a36Sopenharmony_ci	(0x9c00 << 16) | (0x9938 >> 2),
22362306a36Sopenharmony_ci	0x00000000,
22462306a36Sopenharmony_ci	(0x9c00 << 16) | (0x993c >> 2),
22562306a36Sopenharmony_ci	0x00000000,
22662306a36Sopenharmony_ci	(0x9c00 << 16) | (0x9940 >> 2),
22762306a36Sopenharmony_ci	0x00000000,
22862306a36Sopenharmony_ci	(0x9c00 << 16) | (0x9944 >> 2),
22962306a36Sopenharmony_ci	0x00000000,
23062306a36Sopenharmony_ci	(0x9c00 << 16) | (0x9948 >> 2),
23162306a36Sopenharmony_ci	0x00000000,
23262306a36Sopenharmony_ci	(0x9c00 << 16) | (0x994c >> 2),
23362306a36Sopenharmony_ci	0x00000000,
23462306a36Sopenharmony_ci	(0x9c00 << 16) | (0x9950 >> 2),
23562306a36Sopenharmony_ci	0x00000000,
23662306a36Sopenharmony_ci	(0x9c00 << 16) | (0x9954 >> 2),
23762306a36Sopenharmony_ci	0x00000000,
23862306a36Sopenharmony_ci	(0x9c00 << 16) | (0x9958 >> 2),
23962306a36Sopenharmony_ci	0x00000000,
24062306a36Sopenharmony_ci	(0x9c00 << 16) | (0x995c >> 2),
24162306a36Sopenharmony_ci	0x00000000,
24262306a36Sopenharmony_ci	(0x9c00 << 16) | (0x9960 >> 2),
24362306a36Sopenharmony_ci	0x00000000,
24462306a36Sopenharmony_ci	(0x9c00 << 16) | (0x9964 >> 2),
24562306a36Sopenharmony_ci	0x00000000,
24662306a36Sopenharmony_ci	(0x9c00 << 16) | (0x9968 >> 2),
24762306a36Sopenharmony_ci	0x00000000,
24862306a36Sopenharmony_ci	(0x9c00 << 16) | (0x996c >> 2),
24962306a36Sopenharmony_ci	0x00000000,
25062306a36Sopenharmony_ci	(0x9c00 << 16) | (0x9970 >> 2),
25162306a36Sopenharmony_ci	0x00000000,
25262306a36Sopenharmony_ci	(0x9c00 << 16) | (0x9974 >> 2),
25362306a36Sopenharmony_ci	0x00000000,
25462306a36Sopenharmony_ci	(0x9c00 << 16) | (0x9978 >> 2),
25562306a36Sopenharmony_ci	0x00000000,
25662306a36Sopenharmony_ci	(0x9c00 << 16) | (0x997c >> 2),
25762306a36Sopenharmony_ci	0x00000000,
25862306a36Sopenharmony_ci	(0x9c00 << 16) | (0x9980 >> 2),
25962306a36Sopenharmony_ci	0x00000000,
26062306a36Sopenharmony_ci	(0x9c00 << 16) | (0x9984 >> 2),
26162306a36Sopenharmony_ci	0x00000000,
26262306a36Sopenharmony_ci	(0x9c00 << 16) | (0x9988 >> 2),
26362306a36Sopenharmony_ci	0x00000000,
26462306a36Sopenharmony_ci	(0x9c00 << 16) | (0x998c >> 2),
26562306a36Sopenharmony_ci	0x00000000,
26662306a36Sopenharmony_ci	(0x9c00 << 16) | (0x8c00 >> 2),
26762306a36Sopenharmony_ci	0x00000000,
26862306a36Sopenharmony_ci	(0x9c00 << 16) | (0x8c14 >> 2),
26962306a36Sopenharmony_ci	0x00000000,
27062306a36Sopenharmony_ci	(0x9c00 << 16) | (0x8c04 >> 2),
27162306a36Sopenharmony_ci	0x00000000,
27262306a36Sopenharmony_ci	(0x9c00 << 16) | (0x8c08 >> 2),
27362306a36Sopenharmony_ci	0x00000000,
27462306a36Sopenharmony_ci	(0x8000 << 16) | (0x9b7c >> 2),
27562306a36Sopenharmony_ci	0x00000000,
27662306a36Sopenharmony_ci	(0x8040 << 16) | (0x9b7c >> 2),
27762306a36Sopenharmony_ci	0x00000000,
27862306a36Sopenharmony_ci	(0x8000 << 16) | (0xe84 >> 2),
27962306a36Sopenharmony_ci	0x00000000,
28062306a36Sopenharmony_ci	(0x8040 << 16) | (0xe84 >> 2),
28162306a36Sopenharmony_ci	0x00000000,
28262306a36Sopenharmony_ci	(0x8000 << 16) | (0x89c0 >> 2),
28362306a36Sopenharmony_ci	0x00000000,
28462306a36Sopenharmony_ci	(0x8040 << 16) | (0x89c0 >> 2),
28562306a36Sopenharmony_ci	0x00000000,
28662306a36Sopenharmony_ci	(0x8000 << 16) | (0x914c >> 2),
28762306a36Sopenharmony_ci	0x00000000,
28862306a36Sopenharmony_ci	(0x8040 << 16) | (0x914c >> 2),
28962306a36Sopenharmony_ci	0x00000000,
29062306a36Sopenharmony_ci	(0x8000 << 16) | (0x8c20 >> 2),
29162306a36Sopenharmony_ci	0x00000000,
29262306a36Sopenharmony_ci	(0x8040 << 16) | (0x8c20 >> 2),
29362306a36Sopenharmony_ci	0x00000000,
29462306a36Sopenharmony_ci	(0x8000 << 16) | (0x9354 >> 2),
29562306a36Sopenharmony_ci	0x00000000,
29662306a36Sopenharmony_ci	(0x8040 << 16) | (0x9354 >> 2),
29762306a36Sopenharmony_ci	0x00000000,
29862306a36Sopenharmony_ci	(0x9c00 << 16) | (0x9060 >> 2),
29962306a36Sopenharmony_ci	0x00000000,
30062306a36Sopenharmony_ci	(0x9c00 << 16) | (0x9364 >> 2),
30162306a36Sopenharmony_ci	0x00000000,
30262306a36Sopenharmony_ci	(0x9c00 << 16) | (0x9100 >> 2),
30362306a36Sopenharmony_ci	0x00000000,
30462306a36Sopenharmony_ci	(0x9c00 << 16) | (0x913c >> 2),
30562306a36Sopenharmony_ci	0x00000000,
30662306a36Sopenharmony_ci	(0x8000 << 16) | (0x90e0 >> 2),
30762306a36Sopenharmony_ci	0x00000000,
30862306a36Sopenharmony_ci	(0x8000 << 16) | (0x90e4 >> 2),
30962306a36Sopenharmony_ci	0x00000000,
31062306a36Sopenharmony_ci	(0x8000 << 16) | (0x90e8 >> 2),
31162306a36Sopenharmony_ci	0x00000000,
31262306a36Sopenharmony_ci	(0x8040 << 16) | (0x90e0 >> 2),
31362306a36Sopenharmony_ci	0x00000000,
31462306a36Sopenharmony_ci	(0x8040 << 16) | (0x90e4 >> 2),
31562306a36Sopenharmony_ci	0x00000000,
31662306a36Sopenharmony_ci	(0x8040 << 16) | (0x90e8 >> 2),
31762306a36Sopenharmony_ci	0x00000000,
31862306a36Sopenharmony_ci	(0x9c00 << 16) | (0x8bcc >> 2),
31962306a36Sopenharmony_ci	0x00000000,
32062306a36Sopenharmony_ci	(0x9c00 << 16) | (0x8b24 >> 2),
32162306a36Sopenharmony_ci	0x00000000,
32262306a36Sopenharmony_ci	(0x9c00 << 16) | (0x88c4 >> 2),
32362306a36Sopenharmony_ci	0x00000000,
32462306a36Sopenharmony_ci	(0x9c00 << 16) | (0x8e50 >> 2),
32562306a36Sopenharmony_ci	0x00000000,
32662306a36Sopenharmony_ci	(0x9c00 << 16) | (0x8c0c >> 2),
32762306a36Sopenharmony_ci	0x00000000,
32862306a36Sopenharmony_ci	(0x9c00 << 16) | (0x8e58 >> 2),
32962306a36Sopenharmony_ci	0x00000000,
33062306a36Sopenharmony_ci	(0x9c00 << 16) | (0x8e5c >> 2),
33162306a36Sopenharmony_ci	0x00000000,
33262306a36Sopenharmony_ci	(0x9c00 << 16) | (0x9508 >> 2),
33362306a36Sopenharmony_ci	0x00000000,
33462306a36Sopenharmony_ci	(0x9c00 << 16) | (0x950c >> 2),
33562306a36Sopenharmony_ci	0x00000000,
33662306a36Sopenharmony_ci	(0x9c00 << 16) | (0x9494 >> 2),
33762306a36Sopenharmony_ci	0x00000000,
33862306a36Sopenharmony_ci	(0x9c00 << 16) | (0xac0c >> 2),
33962306a36Sopenharmony_ci	0x00000000,
34062306a36Sopenharmony_ci	(0x9c00 << 16) | (0xac10 >> 2),
34162306a36Sopenharmony_ci	0x00000000,
34262306a36Sopenharmony_ci	(0x9c00 << 16) | (0xac14 >> 2),
34362306a36Sopenharmony_ci	0x00000000,
34462306a36Sopenharmony_ci	(0x9c00 << 16) | (0xae00 >> 2),
34562306a36Sopenharmony_ci	0x00000000,
34662306a36Sopenharmony_ci	(0x9c00 << 16) | (0xac08 >> 2),
34762306a36Sopenharmony_ci	0x00000000,
34862306a36Sopenharmony_ci	(0x9c00 << 16) | (0x88d4 >> 2),
34962306a36Sopenharmony_ci	0x00000000,
35062306a36Sopenharmony_ci	(0x9c00 << 16) | (0x88c8 >> 2),
35162306a36Sopenharmony_ci	0x00000000,
35262306a36Sopenharmony_ci	(0x9c00 << 16) | (0x88cc >> 2),
35362306a36Sopenharmony_ci	0x00000000,
35462306a36Sopenharmony_ci	(0x9c00 << 16) | (0x89b0 >> 2),
35562306a36Sopenharmony_ci	0x00000000,
35662306a36Sopenharmony_ci	(0x9c00 << 16) | (0x8b10 >> 2),
35762306a36Sopenharmony_ci	0x00000000,
35862306a36Sopenharmony_ci	(0x9c00 << 16) | (0x8a14 >> 2),
35962306a36Sopenharmony_ci	0x00000000,
36062306a36Sopenharmony_ci	(0x9c00 << 16) | (0x9830 >> 2),
36162306a36Sopenharmony_ci	0x00000000,
36262306a36Sopenharmony_ci	(0x9c00 << 16) | (0x9834 >> 2),
36362306a36Sopenharmony_ci	0x00000000,
36462306a36Sopenharmony_ci	(0x9c00 << 16) | (0x9838 >> 2),
36562306a36Sopenharmony_ci	0x00000000,
36662306a36Sopenharmony_ci	(0x9c00 << 16) | (0x9a10 >> 2),
36762306a36Sopenharmony_ci	0x00000000,
36862306a36Sopenharmony_ci	(0x8000 << 16) | (0x9870 >> 2),
36962306a36Sopenharmony_ci	0x00000000,
37062306a36Sopenharmony_ci	(0x8000 << 16) | (0x9874 >> 2),
37162306a36Sopenharmony_ci	0x00000000,
37262306a36Sopenharmony_ci	(0x8001 << 16) | (0x9870 >> 2),
37362306a36Sopenharmony_ci	0x00000000,
37462306a36Sopenharmony_ci	(0x8001 << 16) | (0x9874 >> 2),
37562306a36Sopenharmony_ci	0x00000000,
37662306a36Sopenharmony_ci	(0x8040 << 16) | (0x9870 >> 2),
37762306a36Sopenharmony_ci	0x00000000,
37862306a36Sopenharmony_ci	(0x8040 << 16) | (0x9874 >> 2),
37962306a36Sopenharmony_ci	0x00000000,
38062306a36Sopenharmony_ci	(0x8041 << 16) | (0x9870 >> 2),
38162306a36Sopenharmony_ci	0x00000000,
38262306a36Sopenharmony_ci	(0x8041 << 16) | (0x9874 >> 2),
38362306a36Sopenharmony_ci	0x00000000,
38462306a36Sopenharmony_ci	0x00000000
38562306a36Sopenharmony_ci};
38662306a36Sopenharmony_ci
38762306a36Sopenharmony_cistatic const u32 tahiti_golden_rlc_registers[] =
38862306a36Sopenharmony_ci{
38962306a36Sopenharmony_ci	0xc424, 0xffffffff, 0x00601005,
39062306a36Sopenharmony_ci	0xc47c, 0xffffffff, 0x10104040,
39162306a36Sopenharmony_ci	0xc488, 0xffffffff, 0x0100000a,
39262306a36Sopenharmony_ci	0xc314, 0xffffffff, 0x00000800,
39362306a36Sopenharmony_ci	0xc30c, 0xffffffff, 0x800000f4,
39462306a36Sopenharmony_ci	0xf4a8, 0xffffffff, 0x00000000
39562306a36Sopenharmony_ci};
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_cistatic const u32 tahiti_golden_registers[] =
39862306a36Sopenharmony_ci{
39962306a36Sopenharmony_ci	0x9a10, 0x00010000, 0x00018208,
40062306a36Sopenharmony_ci	0x9830, 0xffffffff, 0x00000000,
40162306a36Sopenharmony_ci	0x9834, 0xf00fffff, 0x00000400,
40262306a36Sopenharmony_ci	0x9838, 0x0002021c, 0x00020200,
40362306a36Sopenharmony_ci	0xc78, 0x00000080, 0x00000000,
40462306a36Sopenharmony_ci	0xd030, 0x000300c0, 0x00800040,
40562306a36Sopenharmony_ci	0xd830, 0x000300c0, 0x00800040,
40662306a36Sopenharmony_ci	0x5bb0, 0x000000f0, 0x00000070,
40762306a36Sopenharmony_ci	0x5bc0, 0x00200000, 0x50100000,
40862306a36Sopenharmony_ci	0x7030, 0x31000311, 0x00000011,
40962306a36Sopenharmony_ci	0x277c, 0x00000003, 0x000007ff,
41062306a36Sopenharmony_ci	0x240c, 0x000007ff, 0x00000000,
41162306a36Sopenharmony_ci	0x8a14, 0xf000001f, 0x00000007,
41262306a36Sopenharmony_ci	0x8b24, 0xffffffff, 0x00ffffff,
41362306a36Sopenharmony_ci	0x8b10, 0x0000ff0f, 0x00000000,
41462306a36Sopenharmony_ci	0x28a4c, 0x07ffffff, 0x4e000000,
41562306a36Sopenharmony_ci	0x28350, 0x3f3f3fff, 0x2a00126a,
41662306a36Sopenharmony_ci	0x30, 0x000000ff, 0x0040,
41762306a36Sopenharmony_ci	0x34, 0x00000040, 0x00004040,
41862306a36Sopenharmony_ci	0x9100, 0x07ffffff, 0x03000000,
41962306a36Sopenharmony_ci	0x8e88, 0x01ff1f3f, 0x00000000,
42062306a36Sopenharmony_ci	0x8e84, 0x01ff1f3f, 0x00000000,
42162306a36Sopenharmony_ci	0x9060, 0x0000007f, 0x00000020,
42262306a36Sopenharmony_ci	0x9508, 0x00010000, 0x00010000,
42362306a36Sopenharmony_ci	0xac14, 0x00000200, 0x000002fb,
42462306a36Sopenharmony_ci	0xac10, 0xffffffff, 0x0000543b,
42562306a36Sopenharmony_ci	0xac0c, 0xffffffff, 0xa9210876,
42662306a36Sopenharmony_ci	0x88d0, 0xffffffff, 0x000fff40,
42762306a36Sopenharmony_ci	0x88d4, 0x0000001f, 0x00000010,
42862306a36Sopenharmony_ci	0x1410, 0x20000000, 0x20fffed8,
42962306a36Sopenharmony_ci	0x15c0, 0x000c0fc0, 0x000c0400
43062306a36Sopenharmony_ci};
43162306a36Sopenharmony_ci
43262306a36Sopenharmony_cistatic const u32 tahiti_golden_registers2[] =
43362306a36Sopenharmony_ci{
43462306a36Sopenharmony_ci	0xc64, 0x00000001, 0x00000001
43562306a36Sopenharmony_ci};
43662306a36Sopenharmony_ci
43762306a36Sopenharmony_cistatic const u32 pitcairn_golden_rlc_registers[] =
43862306a36Sopenharmony_ci{
43962306a36Sopenharmony_ci	0xc424, 0xffffffff, 0x00601004,
44062306a36Sopenharmony_ci	0xc47c, 0xffffffff, 0x10102020,
44162306a36Sopenharmony_ci	0xc488, 0xffffffff, 0x01000020,
44262306a36Sopenharmony_ci	0xc314, 0xffffffff, 0x00000800,
44362306a36Sopenharmony_ci	0xc30c, 0xffffffff, 0x800000a4
44462306a36Sopenharmony_ci};
44562306a36Sopenharmony_ci
44662306a36Sopenharmony_cistatic const u32 pitcairn_golden_registers[] =
44762306a36Sopenharmony_ci{
44862306a36Sopenharmony_ci	0x9a10, 0x00010000, 0x00018208,
44962306a36Sopenharmony_ci	0x9830, 0xffffffff, 0x00000000,
45062306a36Sopenharmony_ci	0x9834, 0xf00fffff, 0x00000400,
45162306a36Sopenharmony_ci	0x9838, 0x0002021c, 0x00020200,
45262306a36Sopenharmony_ci	0xc78, 0x00000080, 0x00000000,
45362306a36Sopenharmony_ci	0xd030, 0x000300c0, 0x00800040,
45462306a36Sopenharmony_ci	0xd830, 0x000300c0, 0x00800040,
45562306a36Sopenharmony_ci	0x5bb0, 0x000000f0, 0x00000070,
45662306a36Sopenharmony_ci	0x5bc0, 0x00200000, 0x50100000,
45762306a36Sopenharmony_ci	0x7030, 0x31000311, 0x00000011,
45862306a36Sopenharmony_ci	0x2ae4, 0x00073ffe, 0x000022a2,
45962306a36Sopenharmony_ci	0x240c, 0x000007ff, 0x00000000,
46062306a36Sopenharmony_ci	0x8a14, 0xf000001f, 0x00000007,
46162306a36Sopenharmony_ci	0x8b24, 0xffffffff, 0x00ffffff,
46262306a36Sopenharmony_ci	0x8b10, 0x0000ff0f, 0x00000000,
46362306a36Sopenharmony_ci	0x28a4c, 0x07ffffff, 0x4e000000,
46462306a36Sopenharmony_ci	0x28350, 0x3f3f3fff, 0x2a00126a,
46562306a36Sopenharmony_ci	0x30, 0x000000ff, 0x0040,
46662306a36Sopenharmony_ci	0x34, 0x00000040, 0x00004040,
46762306a36Sopenharmony_ci	0x9100, 0x07ffffff, 0x03000000,
46862306a36Sopenharmony_ci	0x9060, 0x0000007f, 0x00000020,
46962306a36Sopenharmony_ci	0x9508, 0x00010000, 0x00010000,
47062306a36Sopenharmony_ci	0xac14, 0x000003ff, 0x000000f7,
47162306a36Sopenharmony_ci	0xac10, 0xffffffff, 0x00000000,
47262306a36Sopenharmony_ci	0xac0c, 0xffffffff, 0x32761054,
47362306a36Sopenharmony_ci	0x88d4, 0x0000001f, 0x00000010,
47462306a36Sopenharmony_ci	0x15c0, 0x000c0fc0, 0x000c0400
47562306a36Sopenharmony_ci};
47662306a36Sopenharmony_ci
47762306a36Sopenharmony_cistatic const u32 verde_golden_rlc_registers[] =
47862306a36Sopenharmony_ci{
47962306a36Sopenharmony_ci	0xc424, 0xffffffff, 0x033f1005,
48062306a36Sopenharmony_ci	0xc47c, 0xffffffff, 0x10808020,
48162306a36Sopenharmony_ci	0xc488, 0xffffffff, 0x00800008,
48262306a36Sopenharmony_ci	0xc314, 0xffffffff, 0x00001000,
48362306a36Sopenharmony_ci	0xc30c, 0xffffffff, 0x80010014
48462306a36Sopenharmony_ci};
48562306a36Sopenharmony_ci
48662306a36Sopenharmony_cistatic const u32 verde_golden_registers[] =
48762306a36Sopenharmony_ci{
48862306a36Sopenharmony_ci	0x9a10, 0x00010000, 0x00018208,
48962306a36Sopenharmony_ci	0x9830, 0xffffffff, 0x00000000,
49062306a36Sopenharmony_ci	0x9834, 0xf00fffff, 0x00000400,
49162306a36Sopenharmony_ci	0x9838, 0x0002021c, 0x00020200,
49262306a36Sopenharmony_ci	0xc78, 0x00000080, 0x00000000,
49362306a36Sopenharmony_ci	0xd030, 0x000300c0, 0x00800040,
49462306a36Sopenharmony_ci	0xd030, 0x000300c0, 0x00800040,
49562306a36Sopenharmony_ci	0xd830, 0x000300c0, 0x00800040,
49662306a36Sopenharmony_ci	0xd830, 0x000300c0, 0x00800040,
49762306a36Sopenharmony_ci	0x5bb0, 0x000000f0, 0x00000070,
49862306a36Sopenharmony_ci	0x5bc0, 0x00200000, 0x50100000,
49962306a36Sopenharmony_ci	0x7030, 0x31000311, 0x00000011,
50062306a36Sopenharmony_ci	0x2ae4, 0x00073ffe, 0x000022a2,
50162306a36Sopenharmony_ci	0x2ae4, 0x00073ffe, 0x000022a2,
50262306a36Sopenharmony_ci	0x2ae4, 0x00073ffe, 0x000022a2,
50362306a36Sopenharmony_ci	0x240c, 0x000007ff, 0x00000000,
50462306a36Sopenharmony_ci	0x240c, 0x000007ff, 0x00000000,
50562306a36Sopenharmony_ci	0x240c, 0x000007ff, 0x00000000,
50662306a36Sopenharmony_ci	0x8a14, 0xf000001f, 0x00000007,
50762306a36Sopenharmony_ci	0x8a14, 0xf000001f, 0x00000007,
50862306a36Sopenharmony_ci	0x8a14, 0xf000001f, 0x00000007,
50962306a36Sopenharmony_ci	0x8b24, 0xffffffff, 0x00ffffff,
51062306a36Sopenharmony_ci	0x8b10, 0x0000ff0f, 0x00000000,
51162306a36Sopenharmony_ci	0x28a4c, 0x07ffffff, 0x4e000000,
51262306a36Sopenharmony_ci	0x28350, 0x3f3f3fff, 0x0000124a,
51362306a36Sopenharmony_ci	0x28350, 0x3f3f3fff, 0x0000124a,
51462306a36Sopenharmony_ci	0x28350, 0x3f3f3fff, 0x0000124a,
51562306a36Sopenharmony_ci	0x30, 0x000000ff, 0x0040,
51662306a36Sopenharmony_ci	0x34, 0x00000040, 0x00004040,
51762306a36Sopenharmony_ci	0x9100, 0x07ffffff, 0x03000000,
51862306a36Sopenharmony_ci	0x9100, 0x07ffffff, 0x03000000,
51962306a36Sopenharmony_ci	0x8e88, 0x01ff1f3f, 0x00000000,
52062306a36Sopenharmony_ci	0x8e88, 0x01ff1f3f, 0x00000000,
52162306a36Sopenharmony_ci	0x8e88, 0x01ff1f3f, 0x00000000,
52262306a36Sopenharmony_ci	0x8e84, 0x01ff1f3f, 0x00000000,
52362306a36Sopenharmony_ci	0x8e84, 0x01ff1f3f, 0x00000000,
52462306a36Sopenharmony_ci	0x8e84, 0x01ff1f3f, 0x00000000,
52562306a36Sopenharmony_ci	0x9060, 0x0000007f, 0x00000020,
52662306a36Sopenharmony_ci	0x9508, 0x00010000, 0x00010000,
52762306a36Sopenharmony_ci	0xac14, 0x000003ff, 0x00000003,
52862306a36Sopenharmony_ci	0xac14, 0x000003ff, 0x00000003,
52962306a36Sopenharmony_ci	0xac14, 0x000003ff, 0x00000003,
53062306a36Sopenharmony_ci	0xac10, 0xffffffff, 0x00000000,
53162306a36Sopenharmony_ci	0xac10, 0xffffffff, 0x00000000,
53262306a36Sopenharmony_ci	0xac10, 0xffffffff, 0x00000000,
53362306a36Sopenharmony_ci	0xac0c, 0xffffffff, 0x00001032,
53462306a36Sopenharmony_ci	0xac0c, 0xffffffff, 0x00001032,
53562306a36Sopenharmony_ci	0xac0c, 0xffffffff, 0x00001032,
53662306a36Sopenharmony_ci	0x88d4, 0x0000001f, 0x00000010,
53762306a36Sopenharmony_ci	0x88d4, 0x0000001f, 0x00000010,
53862306a36Sopenharmony_ci	0x88d4, 0x0000001f, 0x00000010,
53962306a36Sopenharmony_ci	0x15c0, 0x000c0fc0, 0x000c0400
54062306a36Sopenharmony_ci};
54162306a36Sopenharmony_ci
54262306a36Sopenharmony_cistatic const u32 oland_golden_rlc_registers[] =
54362306a36Sopenharmony_ci{
54462306a36Sopenharmony_ci	0xc424, 0xffffffff, 0x00601005,
54562306a36Sopenharmony_ci	0xc47c, 0xffffffff, 0x10104040,
54662306a36Sopenharmony_ci	0xc488, 0xffffffff, 0x0100000a,
54762306a36Sopenharmony_ci	0xc314, 0xffffffff, 0x00000800,
54862306a36Sopenharmony_ci	0xc30c, 0xffffffff, 0x800000f4
54962306a36Sopenharmony_ci};
55062306a36Sopenharmony_ci
55162306a36Sopenharmony_cistatic const u32 oland_golden_registers[] =
55262306a36Sopenharmony_ci{
55362306a36Sopenharmony_ci	0x9a10, 0x00010000, 0x00018208,
55462306a36Sopenharmony_ci	0x9830, 0xffffffff, 0x00000000,
55562306a36Sopenharmony_ci	0x9834, 0xf00fffff, 0x00000400,
55662306a36Sopenharmony_ci	0x9838, 0x0002021c, 0x00020200,
55762306a36Sopenharmony_ci	0xc78, 0x00000080, 0x00000000,
55862306a36Sopenharmony_ci	0xd030, 0x000300c0, 0x00800040,
55962306a36Sopenharmony_ci	0xd830, 0x000300c0, 0x00800040,
56062306a36Sopenharmony_ci	0x5bb0, 0x000000f0, 0x00000070,
56162306a36Sopenharmony_ci	0x5bc0, 0x00200000, 0x50100000,
56262306a36Sopenharmony_ci	0x7030, 0x31000311, 0x00000011,
56362306a36Sopenharmony_ci	0x2ae4, 0x00073ffe, 0x000022a2,
56462306a36Sopenharmony_ci	0x240c, 0x000007ff, 0x00000000,
56562306a36Sopenharmony_ci	0x8a14, 0xf000001f, 0x00000007,
56662306a36Sopenharmony_ci	0x8b24, 0xffffffff, 0x00ffffff,
56762306a36Sopenharmony_ci	0x8b10, 0x0000ff0f, 0x00000000,
56862306a36Sopenharmony_ci	0x28a4c, 0x07ffffff, 0x4e000000,
56962306a36Sopenharmony_ci	0x28350, 0x3f3f3fff, 0x00000082,
57062306a36Sopenharmony_ci	0x30, 0x000000ff, 0x0040,
57162306a36Sopenharmony_ci	0x34, 0x00000040, 0x00004040,
57262306a36Sopenharmony_ci	0x9100, 0x07ffffff, 0x03000000,
57362306a36Sopenharmony_ci	0x9060, 0x0000007f, 0x00000020,
57462306a36Sopenharmony_ci	0x9508, 0x00010000, 0x00010000,
57562306a36Sopenharmony_ci	0xac14, 0x000003ff, 0x000000f3,
57662306a36Sopenharmony_ci	0xac10, 0xffffffff, 0x00000000,
57762306a36Sopenharmony_ci	0xac0c, 0xffffffff, 0x00003210,
57862306a36Sopenharmony_ci	0x88d4, 0x0000001f, 0x00000010,
57962306a36Sopenharmony_ci	0x15c0, 0x000c0fc0, 0x000c0400
58062306a36Sopenharmony_ci};
58162306a36Sopenharmony_ci
58262306a36Sopenharmony_cistatic const u32 hainan_golden_registers[] =
58362306a36Sopenharmony_ci{
58462306a36Sopenharmony_ci	0x9a10, 0x00010000, 0x00018208,
58562306a36Sopenharmony_ci	0x9830, 0xffffffff, 0x00000000,
58662306a36Sopenharmony_ci	0x9834, 0xf00fffff, 0x00000400,
58762306a36Sopenharmony_ci	0x9838, 0x0002021c, 0x00020200,
58862306a36Sopenharmony_ci	0xd0c0, 0xff000fff, 0x00000100,
58962306a36Sopenharmony_ci	0xd030, 0x000300c0, 0x00800040,
59062306a36Sopenharmony_ci	0xd8c0, 0xff000fff, 0x00000100,
59162306a36Sopenharmony_ci	0xd830, 0x000300c0, 0x00800040,
59262306a36Sopenharmony_ci	0x2ae4, 0x00073ffe, 0x000022a2,
59362306a36Sopenharmony_ci	0x240c, 0x000007ff, 0x00000000,
59462306a36Sopenharmony_ci	0x8a14, 0xf000001f, 0x00000007,
59562306a36Sopenharmony_ci	0x8b24, 0xffffffff, 0x00ffffff,
59662306a36Sopenharmony_ci	0x8b10, 0x0000ff0f, 0x00000000,
59762306a36Sopenharmony_ci	0x28a4c, 0x07ffffff, 0x4e000000,
59862306a36Sopenharmony_ci	0x28350, 0x3f3f3fff, 0x00000000,
59962306a36Sopenharmony_ci	0x30, 0x000000ff, 0x0040,
60062306a36Sopenharmony_ci	0x34, 0x00000040, 0x00004040,
60162306a36Sopenharmony_ci	0x9100, 0x03e00000, 0x03600000,
60262306a36Sopenharmony_ci	0x9060, 0x0000007f, 0x00000020,
60362306a36Sopenharmony_ci	0x9508, 0x00010000, 0x00010000,
60462306a36Sopenharmony_ci	0xac14, 0x000003ff, 0x000000f1,
60562306a36Sopenharmony_ci	0xac10, 0xffffffff, 0x00000000,
60662306a36Sopenharmony_ci	0xac0c, 0xffffffff, 0x00003210,
60762306a36Sopenharmony_ci	0x88d4, 0x0000001f, 0x00000010,
60862306a36Sopenharmony_ci	0x15c0, 0x000c0fc0, 0x000c0400
60962306a36Sopenharmony_ci};
61062306a36Sopenharmony_ci
61162306a36Sopenharmony_cistatic const u32 hainan_golden_registers2[] =
61262306a36Sopenharmony_ci{
61362306a36Sopenharmony_ci	0x98f8, 0xffffffff, 0x02010001
61462306a36Sopenharmony_ci};
61562306a36Sopenharmony_ci
61662306a36Sopenharmony_cistatic const u32 tahiti_mgcg_cgcg_init[] =
61762306a36Sopenharmony_ci{
61862306a36Sopenharmony_ci	0xc400, 0xffffffff, 0xfffffffc,
61962306a36Sopenharmony_ci	0x802c, 0xffffffff, 0xe0000000,
62062306a36Sopenharmony_ci	0x9a60, 0xffffffff, 0x00000100,
62162306a36Sopenharmony_ci	0x92a4, 0xffffffff, 0x00000100,
62262306a36Sopenharmony_ci	0xc164, 0xffffffff, 0x00000100,
62362306a36Sopenharmony_ci	0x9774, 0xffffffff, 0x00000100,
62462306a36Sopenharmony_ci	0x8984, 0xffffffff, 0x06000100,
62562306a36Sopenharmony_ci	0x8a18, 0xffffffff, 0x00000100,
62662306a36Sopenharmony_ci	0x92a0, 0xffffffff, 0x00000100,
62762306a36Sopenharmony_ci	0xc380, 0xffffffff, 0x00000100,
62862306a36Sopenharmony_ci	0x8b28, 0xffffffff, 0x00000100,
62962306a36Sopenharmony_ci	0x9144, 0xffffffff, 0x00000100,
63062306a36Sopenharmony_ci	0x8d88, 0xffffffff, 0x00000100,
63162306a36Sopenharmony_ci	0x8d8c, 0xffffffff, 0x00000100,
63262306a36Sopenharmony_ci	0x9030, 0xffffffff, 0x00000100,
63362306a36Sopenharmony_ci	0x9034, 0xffffffff, 0x00000100,
63462306a36Sopenharmony_ci	0x9038, 0xffffffff, 0x00000100,
63562306a36Sopenharmony_ci	0x903c, 0xffffffff, 0x00000100,
63662306a36Sopenharmony_ci	0xad80, 0xffffffff, 0x00000100,
63762306a36Sopenharmony_ci	0xac54, 0xffffffff, 0x00000100,
63862306a36Sopenharmony_ci	0x897c, 0xffffffff, 0x06000100,
63962306a36Sopenharmony_ci	0x9868, 0xffffffff, 0x00000100,
64062306a36Sopenharmony_ci	0x9510, 0xffffffff, 0x00000100,
64162306a36Sopenharmony_ci	0xaf04, 0xffffffff, 0x00000100,
64262306a36Sopenharmony_ci	0xae04, 0xffffffff, 0x00000100,
64362306a36Sopenharmony_ci	0x949c, 0xffffffff, 0x00000100,
64462306a36Sopenharmony_ci	0x802c, 0xffffffff, 0xe0000000,
64562306a36Sopenharmony_ci	0x9160, 0xffffffff, 0x00010000,
64662306a36Sopenharmony_ci	0x9164, 0xffffffff, 0x00030002,
64762306a36Sopenharmony_ci	0x9168, 0xffffffff, 0x00040007,
64862306a36Sopenharmony_ci	0x916c, 0xffffffff, 0x00060005,
64962306a36Sopenharmony_ci	0x9170, 0xffffffff, 0x00090008,
65062306a36Sopenharmony_ci	0x9174, 0xffffffff, 0x00020001,
65162306a36Sopenharmony_ci	0x9178, 0xffffffff, 0x00040003,
65262306a36Sopenharmony_ci	0x917c, 0xffffffff, 0x00000007,
65362306a36Sopenharmony_ci	0x9180, 0xffffffff, 0x00060005,
65462306a36Sopenharmony_ci	0x9184, 0xffffffff, 0x00090008,
65562306a36Sopenharmony_ci	0x9188, 0xffffffff, 0x00030002,
65662306a36Sopenharmony_ci	0x918c, 0xffffffff, 0x00050004,
65762306a36Sopenharmony_ci	0x9190, 0xffffffff, 0x00000008,
65862306a36Sopenharmony_ci	0x9194, 0xffffffff, 0x00070006,
65962306a36Sopenharmony_ci	0x9198, 0xffffffff, 0x000a0009,
66062306a36Sopenharmony_ci	0x919c, 0xffffffff, 0x00040003,
66162306a36Sopenharmony_ci	0x91a0, 0xffffffff, 0x00060005,
66262306a36Sopenharmony_ci	0x91a4, 0xffffffff, 0x00000009,
66362306a36Sopenharmony_ci	0x91a8, 0xffffffff, 0x00080007,
66462306a36Sopenharmony_ci	0x91ac, 0xffffffff, 0x000b000a,
66562306a36Sopenharmony_ci	0x91b0, 0xffffffff, 0x00050004,
66662306a36Sopenharmony_ci	0x91b4, 0xffffffff, 0x00070006,
66762306a36Sopenharmony_ci	0x91b8, 0xffffffff, 0x0008000b,
66862306a36Sopenharmony_ci	0x91bc, 0xffffffff, 0x000a0009,
66962306a36Sopenharmony_ci	0x91c0, 0xffffffff, 0x000d000c,
67062306a36Sopenharmony_ci	0x91c4, 0xffffffff, 0x00060005,
67162306a36Sopenharmony_ci	0x91c8, 0xffffffff, 0x00080007,
67262306a36Sopenharmony_ci	0x91cc, 0xffffffff, 0x0000000b,
67362306a36Sopenharmony_ci	0x91d0, 0xffffffff, 0x000a0009,
67462306a36Sopenharmony_ci	0x91d4, 0xffffffff, 0x000d000c,
67562306a36Sopenharmony_ci	0x91d8, 0xffffffff, 0x00070006,
67662306a36Sopenharmony_ci	0x91dc, 0xffffffff, 0x00090008,
67762306a36Sopenharmony_ci	0x91e0, 0xffffffff, 0x0000000c,
67862306a36Sopenharmony_ci	0x91e4, 0xffffffff, 0x000b000a,
67962306a36Sopenharmony_ci	0x91e8, 0xffffffff, 0x000e000d,
68062306a36Sopenharmony_ci	0x91ec, 0xffffffff, 0x00080007,
68162306a36Sopenharmony_ci	0x91f0, 0xffffffff, 0x000a0009,
68262306a36Sopenharmony_ci	0x91f4, 0xffffffff, 0x0000000d,
68362306a36Sopenharmony_ci	0x91f8, 0xffffffff, 0x000c000b,
68462306a36Sopenharmony_ci	0x91fc, 0xffffffff, 0x000f000e,
68562306a36Sopenharmony_ci	0x9200, 0xffffffff, 0x00090008,
68662306a36Sopenharmony_ci	0x9204, 0xffffffff, 0x000b000a,
68762306a36Sopenharmony_ci	0x9208, 0xffffffff, 0x000c000f,
68862306a36Sopenharmony_ci	0x920c, 0xffffffff, 0x000e000d,
68962306a36Sopenharmony_ci	0x9210, 0xffffffff, 0x00110010,
69062306a36Sopenharmony_ci	0x9214, 0xffffffff, 0x000a0009,
69162306a36Sopenharmony_ci	0x9218, 0xffffffff, 0x000c000b,
69262306a36Sopenharmony_ci	0x921c, 0xffffffff, 0x0000000f,
69362306a36Sopenharmony_ci	0x9220, 0xffffffff, 0x000e000d,
69462306a36Sopenharmony_ci	0x9224, 0xffffffff, 0x00110010,
69562306a36Sopenharmony_ci	0x9228, 0xffffffff, 0x000b000a,
69662306a36Sopenharmony_ci	0x922c, 0xffffffff, 0x000d000c,
69762306a36Sopenharmony_ci	0x9230, 0xffffffff, 0x00000010,
69862306a36Sopenharmony_ci	0x9234, 0xffffffff, 0x000f000e,
69962306a36Sopenharmony_ci	0x9238, 0xffffffff, 0x00120011,
70062306a36Sopenharmony_ci	0x923c, 0xffffffff, 0x000c000b,
70162306a36Sopenharmony_ci	0x9240, 0xffffffff, 0x000e000d,
70262306a36Sopenharmony_ci	0x9244, 0xffffffff, 0x00000011,
70362306a36Sopenharmony_ci	0x9248, 0xffffffff, 0x0010000f,
70462306a36Sopenharmony_ci	0x924c, 0xffffffff, 0x00130012,
70562306a36Sopenharmony_ci	0x9250, 0xffffffff, 0x000d000c,
70662306a36Sopenharmony_ci	0x9254, 0xffffffff, 0x000f000e,
70762306a36Sopenharmony_ci	0x9258, 0xffffffff, 0x00100013,
70862306a36Sopenharmony_ci	0x925c, 0xffffffff, 0x00120011,
70962306a36Sopenharmony_ci	0x9260, 0xffffffff, 0x00150014,
71062306a36Sopenharmony_ci	0x9264, 0xffffffff, 0x000e000d,
71162306a36Sopenharmony_ci	0x9268, 0xffffffff, 0x0010000f,
71262306a36Sopenharmony_ci	0x926c, 0xffffffff, 0x00000013,
71362306a36Sopenharmony_ci	0x9270, 0xffffffff, 0x00120011,
71462306a36Sopenharmony_ci	0x9274, 0xffffffff, 0x00150014,
71562306a36Sopenharmony_ci	0x9278, 0xffffffff, 0x000f000e,
71662306a36Sopenharmony_ci	0x927c, 0xffffffff, 0x00110010,
71762306a36Sopenharmony_ci	0x9280, 0xffffffff, 0x00000014,
71862306a36Sopenharmony_ci	0x9284, 0xffffffff, 0x00130012,
71962306a36Sopenharmony_ci	0x9288, 0xffffffff, 0x00160015,
72062306a36Sopenharmony_ci	0x928c, 0xffffffff, 0x0010000f,
72162306a36Sopenharmony_ci	0x9290, 0xffffffff, 0x00120011,
72262306a36Sopenharmony_ci	0x9294, 0xffffffff, 0x00000015,
72362306a36Sopenharmony_ci	0x9298, 0xffffffff, 0x00140013,
72462306a36Sopenharmony_ci	0x929c, 0xffffffff, 0x00170016,
72562306a36Sopenharmony_ci	0x9150, 0xffffffff, 0x96940200,
72662306a36Sopenharmony_ci	0x8708, 0xffffffff, 0x00900100,
72762306a36Sopenharmony_ci	0xc478, 0xffffffff, 0x00000080,
72862306a36Sopenharmony_ci	0xc404, 0xffffffff, 0x0020003f,
72962306a36Sopenharmony_ci	0x30, 0xffffffff, 0x0000001c,
73062306a36Sopenharmony_ci	0x34, 0x000f0000, 0x000f0000,
73162306a36Sopenharmony_ci	0x160c, 0xffffffff, 0x00000100,
73262306a36Sopenharmony_ci	0x1024, 0xffffffff, 0x00000100,
73362306a36Sopenharmony_ci	0x102c, 0x00000101, 0x00000000,
73462306a36Sopenharmony_ci	0x20a8, 0xffffffff, 0x00000104,
73562306a36Sopenharmony_ci	0x264c, 0x000c0000, 0x000c0000,
73662306a36Sopenharmony_ci	0x2648, 0x000c0000, 0x000c0000,
73762306a36Sopenharmony_ci	0x55e4, 0xff000fff, 0x00000100,
73862306a36Sopenharmony_ci	0x55e8, 0x00000001, 0x00000001,
73962306a36Sopenharmony_ci	0x2f50, 0x00000001, 0x00000001,
74062306a36Sopenharmony_ci	0x30cc, 0xc0000fff, 0x00000104,
74162306a36Sopenharmony_ci	0xc1e4, 0x00000001, 0x00000001,
74262306a36Sopenharmony_ci	0xd0c0, 0xfffffff0, 0x00000100,
74362306a36Sopenharmony_ci	0xd8c0, 0xfffffff0, 0x00000100
74462306a36Sopenharmony_ci};
74562306a36Sopenharmony_ci
74662306a36Sopenharmony_cistatic const u32 pitcairn_mgcg_cgcg_init[] =
74762306a36Sopenharmony_ci{
74862306a36Sopenharmony_ci	0xc400, 0xffffffff, 0xfffffffc,
74962306a36Sopenharmony_ci	0x802c, 0xffffffff, 0xe0000000,
75062306a36Sopenharmony_ci	0x9a60, 0xffffffff, 0x00000100,
75162306a36Sopenharmony_ci	0x92a4, 0xffffffff, 0x00000100,
75262306a36Sopenharmony_ci	0xc164, 0xffffffff, 0x00000100,
75362306a36Sopenharmony_ci	0x9774, 0xffffffff, 0x00000100,
75462306a36Sopenharmony_ci	0x8984, 0xffffffff, 0x06000100,
75562306a36Sopenharmony_ci	0x8a18, 0xffffffff, 0x00000100,
75662306a36Sopenharmony_ci	0x92a0, 0xffffffff, 0x00000100,
75762306a36Sopenharmony_ci	0xc380, 0xffffffff, 0x00000100,
75862306a36Sopenharmony_ci	0x8b28, 0xffffffff, 0x00000100,
75962306a36Sopenharmony_ci	0x9144, 0xffffffff, 0x00000100,
76062306a36Sopenharmony_ci	0x8d88, 0xffffffff, 0x00000100,
76162306a36Sopenharmony_ci	0x8d8c, 0xffffffff, 0x00000100,
76262306a36Sopenharmony_ci	0x9030, 0xffffffff, 0x00000100,
76362306a36Sopenharmony_ci	0x9034, 0xffffffff, 0x00000100,
76462306a36Sopenharmony_ci	0x9038, 0xffffffff, 0x00000100,
76562306a36Sopenharmony_ci	0x903c, 0xffffffff, 0x00000100,
76662306a36Sopenharmony_ci	0xad80, 0xffffffff, 0x00000100,
76762306a36Sopenharmony_ci	0xac54, 0xffffffff, 0x00000100,
76862306a36Sopenharmony_ci	0x897c, 0xffffffff, 0x06000100,
76962306a36Sopenharmony_ci	0x9868, 0xffffffff, 0x00000100,
77062306a36Sopenharmony_ci	0x9510, 0xffffffff, 0x00000100,
77162306a36Sopenharmony_ci	0xaf04, 0xffffffff, 0x00000100,
77262306a36Sopenharmony_ci	0xae04, 0xffffffff, 0x00000100,
77362306a36Sopenharmony_ci	0x949c, 0xffffffff, 0x00000100,
77462306a36Sopenharmony_ci	0x802c, 0xffffffff, 0xe0000000,
77562306a36Sopenharmony_ci	0x9160, 0xffffffff, 0x00010000,
77662306a36Sopenharmony_ci	0x9164, 0xffffffff, 0x00030002,
77762306a36Sopenharmony_ci	0x9168, 0xffffffff, 0x00040007,
77862306a36Sopenharmony_ci	0x916c, 0xffffffff, 0x00060005,
77962306a36Sopenharmony_ci	0x9170, 0xffffffff, 0x00090008,
78062306a36Sopenharmony_ci	0x9174, 0xffffffff, 0x00020001,
78162306a36Sopenharmony_ci	0x9178, 0xffffffff, 0x00040003,
78262306a36Sopenharmony_ci	0x917c, 0xffffffff, 0x00000007,
78362306a36Sopenharmony_ci	0x9180, 0xffffffff, 0x00060005,
78462306a36Sopenharmony_ci	0x9184, 0xffffffff, 0x00090008,
78562306a36Sopenharmony_ci	0x9188, 0xffffffff, 0x00030002,
78662306a36Sopenharmony_ci	0x918c, 0xffffffff, 0x00050004,
78762306a36Sopenharmony_ci	0x9190, 0xffffffff, 0x00000008,
78862306a36Sopenharmony_ci	0x9194, 0xffffffff, 0x00070006,
78962306a36Sopenharmony_ci	0x9198, 0xffffffff, 0x000a0009,
79062306a36Sopenharmony_ci	0x919c, 0xffffffff, 0x00040003,
79162306a36Sopenharmony_ci	0x91a0, 0xffffffff, 0x00060005,
79262306a36Sopenharmony_ci	0x91a4, 0xffffffff, 0x00000009,
79362306a36Sopenharmony_ci	0x91a8, 0xffffffff, 0x00080007,
79462306a36Sopenharmony_ci	0x91ac, 0xffffffff, 0x000b000a,
79562306a36Sopenharmony_ci	0x91b0, 0xffffffff, 0x00050004,
79662306a36Sopenharmony_ci	0x91b4, 0xffffffff, 0x00070006,
79762306a36Sopenharmony_ci	0x91b8, 0xffffffff, 0x0008000b,
79862306a36Sopenharmony_ci	0x91bc, 0xffffffff, 0x000a0009,
79962306a36Sopenharmony_ci	0x91c0, 0xffffffff, 0x000d000c,
80062306a36Sopenharmony_ci	0x9200, 0xffffffff, 0x00090008,
80162306a36Sopenharmony_ci	0x9204, 0xffffffff, 0x000b000a,
80262306a36Sopenharmony_ci	0x9208, 0xffffffff, 0x000c000f,
80362306a36Sopenharmony_ci	0x920c, 0xffffffff, 0x000e000d,
80462306a36Sopenharmony_ci	0x9210, 0xffffffff, 0x00110010,
80562306a36Sopenharmony_ci	0x9214, 0xffffffff, 0x000a0009,
80662306a36Sopenharmony_ci	0x9218, 0xffffffff, 0x000c000b,
80762306a36Sopenharmony_ci	0x921c, 0xffffffff, 0x0000000f,
80862306a36Sopenharmony_ci	0x9220, 0xffffffff, 0x000e000d,
80962306a36Sopenharmony_ci	0x9224, 0xffffffff, 0x00110010,
81062306a36Sopenharmony_ci	0x9228, 0xffffffff, 0x000b000a,
81162306a36Sopenharmony_ci	0x922c, 0xffffffff, 0x000d000c,
81262306a36Sopenharmony_ci	0x9230, 0xffffffff, 0x00000010,
81362306a36Sopenharmony_ci	0x9234, 0xffffffff, 0x000f000e,
81462306a36Sopenharmony_ci	0x9238, 0xffffffff, 0x00120011,
81562306a36Sopenharmony_ci	0x923c, 0xffffffff, 0x000c000b,
81662306a36Sopenharmony_ci	0x9240, 0xffffffff, 0x000e000d,
81762306a36Sopenharmony_ci	0x9244, 0xffffffff, 0x00000011,
81862306a36Sopenharmony_ci	0x9248, 0xffffffff, 0x0010000f,
81962306a36Sopenharmony_ci	0x924c, 0xffffffff, 0x00130012,
82062306a36Sopenharmony_ci	0x9250, 0xffffffff, 0x000d000c,
82162306a36Sopenharmony_ci	0x9254, 0xffffffff, 0x000f000e,
82262306a36Sopenharmony_ci	0x9258, 0xffffffff, 0x00100013,
82362306a36Sopenharmony_ci	0x925c, 0xffffffff, 0x00120011,
82462306a36Sopenharmony_ci	0x9260, 0xffffffff, 0x00150014,
82562306a36Sopenharmony_ci	0x9150, 0xffffffff, 0x96940200,
82662306a36Sopenharmony_ci	0x8708, 0xffffffff, 0x00900100,
82762306a36Sopenharmony_ci	0xc478, 0xffffffff, 0x00000080,
82862306a36Sopenharmony_ci	0xc404, 0xffffffff, 0x0020003f,
82962306a36Sopenharmony_ci	0x30, 0xffffffff, 0x0000001c,
83062306a36Sopenharmony_ci	0x34, 0x000f0000, 0x000f0000,
83162306a36Sopenharmony_ci	0x160c, 0xffffffff, 0x00000100,
83262306a36Sopenharmony_ci	0x1024, 0xffffffff, 0x00000100,
83362306a36Sopenharmony_ci	0x102c, 0x00000101, 0x00000000,
83462306a36Sopenharmony_ci	0x20a8, 0xffffffff, 0x00000104,
83562306a36Sopenharmony_ci	0x55e4, 0xff000fff, 0x00000100,
83662306a36Sopenharmony_ci	0x55e8, 0x00000001, 0x00000001,
83762306a36Sopenharmony_ci	0x2f50, 0x00000001, 0x00000001,
83862306a36Sopenharmony_ci	0x30cc, 0xc0000fff, 0x00000104,
83962306a36Sopenharmony_ci	0xc1e4, 0x00000001, 0x00000001,
84062306a36Sopenharmony_ci	0xd0c0, 0xfffffff0, 0x00000100,
84162306a36Sopenharmony_ci	0xd8c0, 0xfffffff0, 0x00000100
84262306a36Sopenharmony_ci};
84362306a36Sopenharmony_ci
84462306a36Sopenharmony_cistatic const u32 verde_mgcg_cgcg_init[] =
84562306a36Sopenharmony_ci{
84662306a36Sopenharmony_ci	0xc400, 0xffffffff, 0xfffffffc,
84762306a36Sopenharmony_ci	0x802c, 0xffffffff, 0xe0000000,
84862306a36Sopenharmony_ci	0x9a60, 0xffffffff, 0x00000100,
84962306a36Sopenharmony_ci	0x92a4, 0xffffffff, 0x00000100,
85062306a36Sopenharmony_ci	0xc164, 0xffffffff, 0x00000100,
85162306a36Sopenharmony_ci	0x9774, 0xffffffff, 0x00000100,
85262306a36Sopenharmony_ci	0x8984, 0xffffffff, 0x06000100,
85362306a36Sopenharmony_ci	0x8a18, 0xffffffff, 0x00000100,
85462306a36Sopenharmony_ci	0x92a0, 0xffffffff, 0x00000100,
85562306a36Sopenharmony_ci	0xc380, 0xffffffff, 0x00000100,
85662306a36Sopenharmony_ci	0x8b28, 0xffffffff, 0x00000100,
85762306a36Sopenharmony_ci	0x9144, 0xffffffff, 0x00000100,
85862306a36Sopenharmony_ci	0x8d88, 0xffffffff, 0x00000100,
85962306a36Sopenharmony_ci	0x8d8c, 0xffffffff, 0x00000100,
86062306a36Sopenharmony_ci	0x9030, 0xffffffff, 0x00000100,
86162306a36Sopenharmony_ci	0x9034, 0xffffffff, 0x00000100,
86262306a36Sopenharmony_ci	0x9038, 0xffffffff, 0x00000100,
86362306a36Sopenharmony_ci	0x903c, 0xffffffff, 0x00000100,
86462306a36Sopenharmony_ci	0xad80, 0xffffffff, 0x00000100,
86562306a36Sopenharmony_ci	0xac54, 0xffffffff, 0x00000100,
86662306a36Sopenharmony_ci	0x897c, 0xffffffff, 0x06000100,
86762306a36Sopenharmony_ci	0x9868, 0xffffffff, 0x00000100,
86862306a36Sopenharmony_ci	0x9510, 0xffffffff, 0x00000100,
86962306a36Sopenharmony_ci	0xaf04, 0xffffffff, 0x00000100,
87062306a36Sopenharmony_ci	0xae04, 0xffffffff, 0x00000100,
87162306a36Sopenharmony_ci	0x949c, 0xffffffff, 0x00000100,
87262306a36Sopenharmony_ci	0x802c, 0xffffffff, 0xe0000000,
87362306a36Sopenharmony_ci	0x9160, 0xffffffff, 0x00010000,
87462306a36Sopenharmony_ci	0x9164, 0xffffffff, 0x00030002,
87562306a36Sopenharmony_ci	0x9168, 0xffffffff, 0x00040007,
87662306a36Sopenharmony_ci	0x916c, 0xffffffff, 0x00060005,
87762306a36Sopenharmony_ci	0x9170, 0xffffffff, 0x00090008,
87862306a36Sopenharmony_ci	0x9174, 0xffffffff, 0x00020001,
87962306a36Sopenharmony_ci	0x9178, 0xffffffff, 0x00040003,
88062306a36Sopenharmony_ci	0x917c, 0xffffffff, 0x00000007,
88162306a36Sopenharmony_ci	0x9180, 0xffffffff, 0x00060005,
88262306a36Sopenharmony_ci	0x9184, 0xffffffff, 0x00090008,
88362306a36Sopenharmony_ci	0x9188, 0xffffffff, 0x00030002,
88462306a36Sopenharmony_ci	0x918c, 0xffffffff, 0x00050004,
88562306a36Sopenharmony_ci	0x9190, 0xffffffff, 0x00000008,
88662306a36Sopenharmony_ci	0x9194, 0xffffffff, 0x00070006,
88762306a36Sopenharmony_ci	0x9198, 0xffffffff, 0x000a0009,
88862306a36Sopenharmony_ci	0x919c, 0xffffffff, 0x00040003,
88962306a36Sopenharmony_ci	0x91a0, 0xffffffff, 0x00060005,
89062306a36Sopenharmony_ci	0x91a4, 0xffffffff, 0x00000009,
89162306a36Sopenharmony_ci	0x91a8, 0xffffffff, 0x00080007,
89262306a36Sopenharmony_ci	0x91ac, 0xffffffff, 0x000b000a,
89362306a36Sopenharmony_ci	0x91b0, 0xffffffff, 0x00050004,
89462306a36Sopenharmony_ci	0x91b4, 0xffffffff, 0x00070006,
89562306a36Sopenharmony_ci	0x91b8, 0xffffffff, 0x0008000b,
89662306a36Sopenharmony_ci	0x91bc, 0xffffffff, 0x000a0009,
89762306a36Sopenharmony_ci	0x91c0, 0xffffffff, 0x000d000c,
89862306a36Sopenharmony_ci	0x9200, 0xffffffff, 0x00090008,
89962306a36Sopenharmony_ci	0x9204, 0xffffffff, 0x000b000a,
90062306a36Sopenharmony_ci	0x9208, 0xffffffff, 0x000c000f,
90162306a36Sopenharmony_ci	0x920c, 0xffffffff, 0x000e000d,
90262306a36Sopenharmony_ci	0x9210, 0xffffffff, 0x00110010,
90362306a36Sopenharmony_ci	0x9214, 0xffffffff, 0x000a0009,
90462306a36Sopenharmony_ci	0x9218, 0xffffffff, 0x000c000b,
90562306a36Sopenharmony_ci	0x921c, 0xffffffff, 0x0000000f,
90662306a36Sopenharmony_ci	0x9220, 0xffffffff, 0x000e000d,
90762306a36Sopenharmony_ci	0x9224, 0xffffffff, 0x00110010,
90862306a36Sopenharmony_ci	0x9228, 0xffffffff, 0x000b000a,
90962306a36Sopenharmony_ci	0x922c, 0xffffffff, 0x000d000c,
91062306a36Sopenharmony_ci	0x9230, 0xffffffff, 0x00000010,
91162306a36Sopenharmony_ci	0x9234, 0xffffffff, 0x000f000e,
91262306a36Sopenharmony_ci	0x9238, 0xffffffff, 0x00120011,
91362306a36Sopenharmony_ci	0x923c, 0xffffffff, 0x000c000b,
91462306a36Sopenharmony_ci	0x9240, 0xffffffff, 0x000e000d,
91562306a36Sopenharmony_ci	0x9244, 0xffffffff, 0x00000011,
91662306a36Sopenharmony_ci	0x9248, 0xffffffff, 0x0010000f,
91762306a36Sopenharmony_ci	0x924c, 0xffffffff, 0x00130012,
91862306a36Sopenharmony_ci	0x9250, 0xffffffff, 0x000d000c,
91962306a36Sopenharmony_ci	0x9254, 0xffffffff, 0x000f000e,
92062306a36Sopenharmony_ci	0x9258, 0xffffffff, 0x00100013,
92162306a36Sopenharmony_ci	0x925c, 0xffffffff, 0x00120011,
92262306a36Sopenharmony_ci	0x9260, 0xffffffff, 0x00150014,
92362306a36Sopenharmony_ci	0x9150, 0xffffffff, 0x96940200,
92462306a36Sopenharmony_ci	0x8708, 0xffffffff, 0x00900100,
92562306a36Sopenharmony_ci	0xc478, 0xffffffff, 0x00000080,
92662306a36Sopenharmony_ci	0xc404, 0xffffffff, 0x0020003f,
92762306a36Sopenharmony_ci	0x30, 0xffffffff, 0x0000001c,
92862306a36Sopenharmony_ci	0x34, 0x000f0000, 0x000f0000,
92962306a36Sopenharmony_ci	0x160c, 0xffffffff, 0x00000100,
93062306a36Sopenharmony_ci	0x1024, 0xffffffff, 0x00000100,
93162306a36Sopenharmony_ci	0x102c, 0x00000101, 0x00000000,
93262306a36Sopenharmony_ci	0x20a8, 0xffffffff, 0x00000104,
93362306a36Sopenharmony_ci	0x264c, 0x000c0000, 0x000c0000,
93462306a36Sopenharmony_ci	0x2648, 0x000c0000, 0x000c0000,
93562306a36Sopenharmony_ci	0x55e4, 0xff000fff, 0x00000100,
93662306a36Sopenharmony_ci	0x55e8, 0x00000001, 0x00000001,
93762306a36Sopenharmony_ci	0x2f50, 0x00000001, 0x00000001,
93862306a36Sopenharmony_ci	0x30cc, 0xc0000fff, 0x00000104,
93962306a36Sopenharmony_ci	0xc1e4, 0x00000001, 0x00000001,
94062306a36Sopenharmony_ci	0xd0c0, 0xfffffff0, 0x00000100,
94162306a36Sopenharmony_ci	0xd8c0, 0xfffffff0, 0x00000100
94262306a36Sopenharmony_ci};
94362306a36Sopenharmony_ci
94462306a36Sopenharmony_cistatic const u32 oland_mgcg_cgcg_init[] =
94562306a36Sopenharmony_ci{
94662306a36Sopenharmony_ci	0xc400, 0xffffffff, 0xfffffffc,
94762306a36Sopenharmony_ci	0x802c, 0xffffffff, 0xe0000000,
94862306a36Sopenharmony_ci	0x9a60, 0xffffffff, 0x00000100,
94962306a36Sopenharmony_ci	0x92a4, 0xffffffff, 0x00000100,
95062306a36Sopenharmony_ci	0xc164, 0xffffffff, 0x00000100,
95162306a36Sopenharmony_ci	0x9774, 0xffffffff, 0x00000100,
95262306a36Sopenharmony_ci	0x8984, 0xffffffff, 0x06000100,
95362306a36Sopenharmony_ci	0x8a18, 0xffffffff, 0x00000100,
95462306a36Sopenharmony_ci	0x92a0, 0xffffffff, 0x00000100,
95562306a36Sopenharmony_ci	0xc380, 0xffffffff, 0x00000100,
95662306a36Sopenharmony_ci	0x8b28, 0xffffffff, 0x00000100,
95762306a36Sopenharmony_ci	0x9144, 0xffffffff, 0x00000100,
95862306a36Sopenharmony_ci	0x8d88, 0xffffffff, 0x00000100,
95962306a36Sopenharmony_ci	0x8d8c, 0xffffffff, 0x00000100,
96062306a36Sopenharmony_ci	0x9030, 0xffffffff, 0x00000100,
96162306a36Sopenharmony_ci	0x9034, 0xffffffff, 0x00000100,
96262306a36Sopenharmony_ci	0x9038, 0xffffffff, 0x00000100,
96362306a36Sopenharmony_ci	0x903c, 0xffffffff, 0x00000100,
96462306a36Sopenharmony_ci	0xad80, 0xffffffff, 0x00000100,
96562306a36Sopenharmony_ci	0xac54, 0xffffffff, 0x00000100,
96662306a36Sopenharmony_ci	0x897c, 0xffffffff, 0x06000100,
96762306a36Sopenharmony_ci	0x9868, 0xffffffff, 0x00000100,
96862306a36Sopenharmony_ci	0x9510, 0xffffffff, 0x00000100,
96962306a36Sopenharmony_ci	0xaf04, 0xffffffff, 0x00000100,
97062306a36Sopenharmony_ci	0xae04, 0xffffffff, 0x00000100,
97162306a36Sopenharmony_ci	0x949c, 0xffffffff, 0x00000100,
97262306a36Sopenharmony_ci	0x802c, 0xffffffff, 0xe0000000,
97362306a36Sopenharmony_ci	0x9160, 0xffffffff, 0x00010000,
97462306a36Sopenharmony_ci	0x9164, 0xffffffff, 0x00030002,
97562306a36Sopenharmony_ci	0x9168, 0xffffffff, 0x00040007,
97662306a36Sopenharmony_ci	0x916c, 0xffffffff, 0x00060005,
97762306a36Sopenharmony_ci	0x9170, 0xffffffff, 0x00090008,
97862306a36Sopenharmony_ci	0x9174, 0xffffffff, 0x00020001,
97962306a36Sopenharmony_ci	0x9178, 0xffffffff, 0x00040003,
98062306a36Sopenharmony_ci	0x917c, 0xffffffff, 0x00000007,
98162306a36Sopenharmony_ci	0x9180, 0xffffffff, 0x00060005,
98262306a36Sopenharmony_ci	0x9184, 0xffffffff, 0x00090008,
98362306a36Sopenharmony_ci	0x9188, 0xffffffff, 0x00030002,
98462306a36Sopenharmony_ci	0x918c, 0xffffffff, 0x00050004,
98562306a36Sopenharmony_ci	0x9190, 0xffffffff, 0x00000008,
98662306a36Sopenharmony_ci	0x9194, 0xffffffff, 0x00070006,
98762306a36Sopenharmony_ci	0x9198, 0xffffffff, 0x000a0009,
98862306a36Sopenharmony_ci	0x919c, 0xffffffff, 0x00040003,
98962306a36Sopenharmony_ci	0x91a0, 0xffffffff, 0x00060005,
99062306a36Sopenharmony_ci	0x91a4, 0xffffffff, 0x00000009,
99162306a36Sopenharmony_ci	0x91a8, 0xffffffff, 0x00080007,
99262306a36Sopenharmony_ci	0x91ac, 0xffffffff, 0x000b000a,
99362306a36Sopenharmony_ci	0x91b0, 0xffffffff, 0x00050004,
99462306a36Sopenharmony_ci	0x91b4, 0xffffffff, 0x00070006,
99562306a36Sopenharmony_ci	0x91b8, 0xffffffff, 0x0008000b,
99662306a36Sopenharmony_ci	0x91bc, 0xffffffff, 0x000a0009,
99762306a36Sopenharmony_ci	0x91c0, 0xffffffff, 0x000d000c,
99862306a36Sopenharmony_ci	0x91c4, 0xffffffff, 0x00060005,
99962306a36Sopenharmony_ci	0x91c8, 0xffffffff, 0x00080007,
100062306a36Sopenharmony_ci	0x91cc, 0xffffffff, 0x0000000b,
100162306a36Sopenharmony_ci	0x91d0, 0xffffffff, 0x000a0009,
100262306a36Sopenharmony_ci	0x91d4, 0xffffffff, 0x000d000c,
100362306a36Sopenharmony_ci	0x9150, 0xffffffff, 0x96940200,
100462306a36Sopenharmony_ci	0x8708, 0xffffffff, 0x00900100,
100562306a36Sopenharmony_ci	0xc478, 0xffffffff, 0x00000080,
100662306a36Sopenharmony_ci	0xc404, 0xffffffff, 0x0020003f,
100762306a36Sopenharmony_ci	0x30, 0xffffffff, 0x0000001c,
100862306a36Sopenharmony_ci	0x34, 0x000f0000, 0x000f0000,
100962306a36Sopenharmony_ci	0x160c, 0xffffffff, 0x00000100,
101062306a36Sopenharmony_ci	0x1024, 0xffffffff, 0x00000100,
101162306a36Sopenharmony_ci	0x102c, 0x00000101, 0x00000000,
101262306a36Sopenharmony_ci	0x20a8, 0xffffffff, 0x00000104,
101362306a36Sopenharmony_ci	0x264c, 0x000c0000, 0x000c0000,
101462306a36Sopenharmony_ci	0x2648, 0x000c0000, 0x000c0000,
101562306a36Sopenharmony_ci	0x55e4, 0xff000fff, 0x00000100,
101662306a36Sopenharmony_ci	0x55e8, 0x00000001, 0x00000001,
101762306a36Sopenharmony_ci	0x2f50, 0x00000001, 0x00000001,
101862306a36Sopenharmony_ci	0x30cc, 0xc0000fff, 0x00000104,
101962306a36Sopenharmony_ci	0xc1e4, 0x00000001, 0x00000001,
102062306a36Sopenharmony_ci	0xd0c0, 0xfffffff0, 0x00000100,
102162306a36Sopenharmony_ci	0xd8c0, 0xfffffff0, 0x00000100
102262306a36Sopenharmony_ci};
102362306a36Sopenharmony_ci
102462306a36Sopenharmony_cistatic const u32 hainan_mgcg_cgcg_init[] =
102562306a36Sopenharmony_ci{
102662306a36Sopenharmony_ci	0xc400, 0xffffffff, 0xfffffffc,
102762306a36Sopenharmony_ci	0x802c, 0xffffffff, 0xe0000000,
102862306a36Sopenharmony_ci	0x9a60, 0xffffffff, 0x00000100,
102962306a36Sopenharmony_ci	0x92a4, 0xffffffff, 0x00000100,
103062306a36Sopenharmony_ci	0xc164, 0xffffffff, 0x00000100,
103162306a36Sopenharmony_ci	0x9774, 0xffffffff, 0x00000100,
103262306a36Sopenharmony_ci	0x8984, 0xffffffff, 0x06000100,
103362306a36Sopenharmony_ci	0x8a18, 0xffffffff, 0x00000100,
103462306a36Sopenharmony_ci	0x92a0, 0xffffffff, 0x00000100,
103562306a36Sopenharmony_ci	0xc380, 0xffffffff, 0x00000100,
103662306a36Sopenharmony_ci	0x8b28, 0xffffffff, 0x00000100,
103762306a36Sopenharmony_ci	0x9144, 0xffffffff, 0x00000100,
103862306a36Sopenharmony_ci	0x8d88, 0xffffffff, 0x00000100,
103962306a36Sopenharmony_ci	0x8d8c, 0xffffffff, 0x00000100,
104062306a36Sopenharmony_ci	0x9030, 0xffffffff, 0x00000100,
104162306a36Sopenharmony_ci	0x9034, 0xffffffff, 0x00000100,
104262306a36Sopenharmony_ci	0x9038, 0xffffffff, 0x00000100,
104362306a36Sopenharmony_ci	0x903c, 0xffffffff, 0x00000100,
104462306a36Sopenharmony_ci	0xad80, 0xffffffff, 0x00000100,
104562306a36Sopenharmony_ci	0xac54, 0xffffffff, 0x00000100,
104662306a36Sopenharmony_ci	0x897c, 0xffffffff, 0x06000100,
104762306a36Sopenharmony_ci	0x9868, 0xffffffff, 0x00000100,
104862306a36Sopenharmony_ci	0x9510, 0xffffffff, 0x00000100,
104962306a36Sopenharmony_ci	0xaf04, 0xffffffff, 0x00000100,
105062306a36Sopenharmony_ci	0xae04, 0xffffffff, 0x00000100,
105162306a36Sopenharmony_ci	0x949c, 0xffffffff, 0x00000100,
105262306a36Sopenharmony_ci	0x802c, 0xffffffff, 0xe0000000,
105362306a36Sopenharmony_ci	0x9160, 0xffffffff, 0x00010000,
105462306a36Sopenharmony_ci	0x9164, 0xffffffff, 0x00030002,
105562306a36Sopenharmony_ci	0x9168, 0xffffffff, 0x00040007,
105662306a36Sopenharmony_ci	0x916c, 0xffffffff, 0x00060005,
105762306a36Sopenharmony_ci	0x9170, 0xffffffff, 0x00090008,
105862306a36Sopenharmony_ci	0x9174, 0xffffffff, 0x00020001,
105962306a36Sopenharmony_ci	0x9178, 0xffffffff, 0x00040003,
106062306a36Sopenharmony_ci	0x917c, 0xffffffff, 0x00000007,
106162306a36Sopenharmony_ci	0x9180, 0xffffffff, 0x00060005,
106262306a36Sopenharmony_ci	0x9184, 0xffffffff, 0x00090008,
106362306a36Sopenharmony_ci	0x9188, 0xffffffff, 0x00030002,
106462306a36Sopenharmony_ci	0x918c, 0xffffffff, 0x00050004,
106562306a36Sopenharmony_ci	0x9190, 0xffffffff, 0x00000008,
106662306a36Sopenharmony_ci	0x9194, 0xffffffff, 0x00070006,
106762306a36Sopenharmony_ci	0x9198, 0xffffffff, 0x000a0009,
106862306a36Sopenharmony_ci	0x919c, 0xffffffff, 0x00040003,
106962306a36Sopenharmony_ci	0x91a0, 0xffffffff, 0x00060005,
107062306a36Sopenharmony_ci	0x91a4, 0xffffffff, 0x00000009,
107162306a36Sopenharmony_ci	0x91a8, 0xffffffff, 0x00080007,
107262306a36Sopenharmony_ci	0x91ac, 0xffffffff, 0x000b000a,
107362306a36Sopenharmony_ci	0x91b0, 0xffffffff, 0x00050004,
107462306a36Sopenharmony_ci	0x91b4, 0xffffffff, 0x00070006,
107562306a36Sopenharmony_ci	0x91b8, 0xffffffff, 0x0008000b,
107662306a36Sopenharmony_ci	0x91bc, 0xffffffff, 0x000a0009,
107762306a36Sopenharmony_ci	0x91c0, 0xffffffff, 0x000d000c,
107862306a36Sopenharmony_ci	0x91c4, 0xffffffff, 0x00060005,
107962306a36Sopenharmony_ci	0x91c8, 0xffffffff, 0x00080007,
108062306a36Sopenharmony_ci	0x91cc, 0xffffffff, 0x0000000b,
108162306a36Sopenharmony_ci	0x91d0, 0xffffffff, 0x000a0009,
108262306a36Sopenharmony_ci	0x91d4, 0xffffffff, 0x000d000c,
108362306a36Sopenharmony_ci	0x9150, 0xffffffff, 0x96940200,
108462306a36Sopenharmony_ci	0x8708, 0xffffffff, 0x00900100,
108562306a36Sopenharmony_ci	0xc478, 0xffffffff, 0x00000080,
108662306a36Sopenharmony_ci	0xc404, 0xffffffff, 0x0020003f,
108762306a36Sopenharmony_ci	0x30, 0xffffffff, 0x0000001c,
108862306a36Sopenharmony_ci	0x34, 0x000f0000, 0x000f0000,
108962306a36Sopenharmony_ci	0x160c, 0xffffffff, 0x00000100,
109062306a36Sopenharmony_ci	0x1024, 0xffffffff, 0x00000100,
109162306a36Sopenharmony_ci	0x20a8, 0xffffffff, 0x00000104,
109262306a36Sopenharmony_ci	0x264c, 0x000c0000, 0x000c0000,
109362306a36Sopenharmony_ci	0x2648, 0x000c0000, 0x000c0000,
109462306a36Sopenharmony_ci	0x2f50, 0x00000001, 0x00000001,
109562306a36Sopenharmony_ci	0x30cc, 0xc0000fff, 0x00000104,
109662306a36Sopenharmony_ci	0xc1e4, 0x00000001, 0x00000001,
109762306a36Sopenharmony_ci	0xd0c0, 0xfffffff0, 0x00000100,
109862306a36Sopenharmony_ci	0xd8c0, 0xfffffff0, 0x00000100
109962306a36Sopenharmony_ci};
110062306a36Sopenharmony_ci
110162306a36Sopenharmony_cistatic u32 verde_pg_init[] =
110262306a36Sopenharmony_ci{
110362306a36Sopenharmony_ci	0x353c, 0xffffffff, 0x40000,
110462306a36Sopenharmony_ci	0x3538, 0xffffffff, 0x200010ff,
110562306a36Sopenharmony_ci	0x353c, 0xffffffff, 0x0,
110662306a36Sopenharmony_ci	0x353c, 0xffffffff, 0x0,
110762306a36Sopenharmony_ci	0x353c, 0xffffffff, 0x0,
110862306a36Sopenharmony_ci	0x353c, 0xffffffff, 0x0,
110962306a36Sopenharmony_ci	0x353c, 0xffffffff, 0x0,
111062306a36Sopenharmony_ci	0x353c, 0xffffffff, 0x7007,
111162306a36Sopenharmony_ci	0x3538, 0xffffffff, 0x300010ff,
111262306a36Sopenharmony_ci	0x353c, 0xffffffff, 0x0,
111362306a36Sopenharmony_ci	0x353c, 0xffffffff, 0x0,
111462306a36Sopenharmony_ci	0x353c, 0xffffffff, 0x0,
111562306a36Sopenharmony_ci	0x353c, 0xffffffff, 0x0,
111662306a36Sopenharmony_ci	0x353c, 0xffffffff, 0x0,
111762306a36Sopenharmony_ci	0x353c, 0xffffffff, 0x400000,
111862306a36Sopenharmony_ci	0x3538, 0xffffffff, 0x100010ff,
111962306a36Sopenharmony_ci	0x353c, 0xffffffff, 0x0,
112062306a36Sopenharmony_ci	0x353c, 0xffffffff, 0x0,
112162306a36Sopenharmony_ci	0x353c, 0xffffffff, 0x0,
112262306a36Sopenharmony_ci	0x353c, 0xffffffff, 0x0,
112362306a36Sopenharmony_ci	0x353c, 0xffffffff, 0x0,
112462306a36Sopenharmony_ci	0x353c, 0xffffffff, 0x120200,
112562306a36Sopenharmony_ci	0x3538, 0xffffffff, 0x500010ff,
112662306a36Sopenharmony_ci	0x353c, 0xffffffff, 0x0,
112762306a36Sopenharmony_ci	0x353c, 0xffffffff, 0x0,
112862306a36Sopenharmony_ci	0x353c, 0xffffffff, 0x0,
112962306a36Sopenharmony_ci	0x353c, 0xffffffff, 0x0,
113062306a36Sopenharmony_ci	0x353c, 0xffffffff, 0x0,
113162306a36Sopenharmony_ci	0x353c, 0xffffffff, 0x1e1e16,
113262306a36Sopenharmony_ci	0x3538, 0xffffffff, 0x600010ff,
113362306a36Sopenharmony_ci	0x353c, 0xffffffff, 0x0,
113462306a36Sopenharmony_ci	0x353c, 0xffffffff, 0x0,
113562306a36Sopenharmony_ci	0x353c, 0xffffffff, 0x0,
113662306a36Sopenharmony_ci	0x353c, 0xffffffff, 0x0,
113762306a36Sopenharmony_ci	0x353c, 0xffffffff, 0x0,
113862306a36Sopenharmony_ci	0x353c, 0xffffffff, 0x171f1e,
113962306a36Sopenharmony_ci	0x3538, 0xffffffff, 0x700010ff,
114062306a36Sopenharmony_ci	0x353c, 0xffffffff, 0x0,
114162306a36Sopenharmony_ci	0x353c, 0xffffffff, 0x0,
114262306a36Sopenharmony_ci	0x353c, 0xffffffff, 0x0,
114362306a36Sopenharmony_ci	0x353c, 0xffffffff, 0x0,
114462306a36Sopenharmony_ci	0x353c, 0xffffffff, 0x0,
114562306a36Sopenharmony_ci	0x353c, 0xffffffff, 0x0,
114662306a36Sopenharmony_ci	0x3538, 0xffffffff, 0x9ff,
114762306a36Sopenharmony_ci	0x3500, 0xffffffff, 0x0,
114862306a36Sopenharmony_ci	0x3504, 0xffffffff, 0x10000800,
114962306a36Sopenharmony_ci	0x3504, 0xffffffff, 0xf,
115062306a36Sopenharmony_ci	0x3504, 0xffffffff, 0xf,
115162306a36Sopenharmony_ci	0x3500, 0xffffffff, 0x4,
115262306a36Sopenharmony_ci	0x3504, 0xffffffff, 0x1000051e,
115362306a36Sopenharmony_ci	0x3504, 0xffffffff, 0xffff,
115462306a36Sopenharmony_ci	0x3504, 0xffffffff, 0xffff,
115562306a36Sopenharmony_ci	0x3500, 0xffffffff, 0x8,
115662306a36Sopenharmony_ci	0x3504, 0xffffffff, 0x80500,
115762306a36Sopenharmony_ci	0x3500, 0xffffffff, 0x12,
115862306a36Sopenharmony_ci	0x3504, 0xffffffff, 0x9050c,
115962306a36Sopenharmony_ci	0x3500, 0xffffffff, 0x1d,
116062306a36Sopenharmony_ci	0x3504, 0xffffffff, 0xb052c,
116162306a36Sopenharmony_ci	0x3500, 0xffffffff, 0x2a,
116262306a36Sopenharmony_ci	0x3504, 0xffffffff, 0x1053e,
116362306a36Sopenharmony_ci	0x3500, 0xffffffff, 0x2d,
116462306a36Sopenharmony_ci	0x3504, 0xffffffff, 0x10546,
116562306a36Sopenharmony_ci	0x3500, 0xffffffff, 0x30,
116662306a36Sopenharmony_ci	0x3504, 0xffffffff, 0xa054e,
116762306a36Sopenharmony_ci	0x3500, 0xffffffff, 0x3c,
116862306a36Sopenharmony_ci	0x3504, 0xffffffff, 0x1055f,
116962306a36Sopenharmony_ci	0x3500, 0xffffffff, 0x3f,
117062306a36Sopenharmony_ci	0x3504, 0xffffffff, 0x10567,
117162306a36Sopenharmony_ci	0x3500, 0xffffffff, 0x42,
117262306a36Sopenharmony_ci	0x3504, 0xffffffff, 0x1056f,
117362306a36Sopenharmony_ci	0x3500, 0xffffffff, 0x45,
117462306a36Sopenharmony_ci	0x3504, 0xffffffff, 0x10572,
117562306a36Sopenharmony_ci	0x3500, 0xffffffff, 0x48,
117662306a36Sopenharmony_ci	0x3504, 0xffffffff, 0x20575,
117762306a36Sopenharmony_ci	0x3500, 0xffffffff, 0x4c,
117862306a36Sopenharmony_ci	0x3504, 0xffffffff, 0x190801,
117962306a36Sopenharmony_ci	0x3500, 0xffffffff, 0x67,
118062306a36Sopenharmony_ci	0x3504, 0xffffffff, 0x1082a,
118162306a36Sopenharmony_ci	0x3500, 0xffffffff, 0x6a,
118262306a36Sopenharmony_ci	0x3504, 0xffffffff, 0x1b082d,
118362306a36Sopenharmony_ci	0x3500, 0xffffffff, 0x87,
118462306a36Sopenharmony_ci	0x3504, 0xffffffff, 0x310851,
118562306a36Sopenharmony_ci	0x3500, 0xffffffff, 0xba,
118662306a36Sopenharmony_ci	0x3504, 0xffffffff, 0x891,
118762306a36Sopenharmony_ci	0x3500, 0xffffffff, 0xbc,
118862306a36Sopenharmony_ci	0x3504, 0xffffffff, 0x893,
118962306a36Sopenharmony_ci	0x3500, 0xffffffff, 0xbe,
119062306a36Sopenharmony_ci	0x3504, 0xffffffff, 0x20895,
119162306a36Sopenharmony_ci	0x3500, 0xffffffff, 0xc2,
119262306a36Sopenharmony_ci	0x3504, 0xffffffff, 0x20899,
119362306a36Sopenharmony_ci	0x3500, 0xffffffff, 0xc6,
119462306a36Sopenharmony_ci	0x3504, 0xffffffff, 0x2089d,
119562306a36Sopenharmony_ci	0x3500, 0xffffffff, 0xca,
119662306a36Sopenharmony_ci	0x3504, 0xffffffff, 0x8a1,
119762306a36Sopenharmony_ci	0x3500, 0xffffffff, 0xcc,
119862306a36Sopenharmony_ci	0x3504, 0xffffffff, 0x8a3,
119962306a36Sopenharmony_ci	0x3500, 0xffffffff, 0xce,
120062306a36Sopenharmony_ci	0x3504, 0xffffffff, 0x308a5,
120162306a36Sopenharmony_ci	0x3500, 0xffffffff, 0xd3,
120262306a36Sopenharmony_ci	0x3504, 0xffffffff, 0x6d08cd,
120362306a36Sopenharmony_ci	0x3500, 0xffffffff, 0x142,
120462306a36Sopenharmony_ci	0x3504, 0xffffffff, 0x2000095a,
120562306a36Sopenharmony_ci	0x3504, 0xffffffff, 0x1,
120662306a36Sopenharmony_ci	0x3500, 0xffffffff, 0x144,
120762306a36Sopenharmony_ci	0x3504, 0xffffffff, 0x301f095b,
120862306a36Sopenharmony_ci	0x3500, 0xffffffff, 0x165,
120962306a36Sopenharmony_ci	0x3504, 0xffffffff, 0xc094d,
121062306a36Sopenharmony_ci	0x3500, 0xffffffff, 0x173,
121162306a36Sopenharmony_ci	0x3504, 0xffffffff, 0xf096d,
121262306a36Sopenharmony_ci	0x3500, 0xffffffff, 0x184,
121362306a36Sopenharmony_ci	0x3504, 0xffffffff, 0x15097f,
121462306a36Sopenharmony_ci	0x3500, 0xffffffff, 0x19b,
121562306a36Sopenharmony_ci	0x3504, 0xffffffff, 0xc0998,
121662306a36Sopenharmony_ci	0x3500, 0xffffffff, 0x1a9,
121762306a36Sopenharmony_ci	0x3504, 0xffffffff, 0x409a7,
121862306a36Sopenharmony_ci	0x3500, 0xffffffff, 0x1af,
121962306a36Sopenharmony_ci	0x3504, 0xffffffff, 0xcdc,
122062306a36Sopenharmony_ci	0x3500, 0xffffffff, 0x1b1,
122162306a36Sopenharmony_ci	0x3504, 0xffffffff, 0x800,
122262306a36Sopenharmony_ci	0x3508, 0xffffffff, 0x6c9b2000,
122362306a36Sopenharmony_ci	0x3510, 0xfc00, 0x2000,
122462306a36Sopenharmony_ci	0x3544, 0xffffffff, 0xfc0,
122562306a36Sopenharmony_ci	0x28d4, 0x00000100, 0x100
122662306a36Sopenharmony_ci};
122762306a36Sopenharmony_ci
122862306a36Sopenharmony_cistatic void si_init_golden_registers(struct radeon_device *rdev)
122962306a36Sopenharmony_ci{
123062306a36Sopenharmony_ci	switch (rdev->family) {
123162306a36Sopenharmony_ci	case CHIP_TAHITI:
123262306a36Sopenharmony_ci		radeon_program_register_sequence(rdev,
123362306a36Sopenharmony_ci						 tahiti_golden_registers,
123462306a36Sopenharmony_ci						 (const u32)ARRAY_SIZE(tahiti_golden_registers));
123562306a36Sopenharmony_ci		radeon_program_register_sequence(rdev,
123662306a36Sopenharmony_ci						 tahiti_golden_rlc_registers,
123762306a36Sopenharmony_ci						 (const u32)ARRAY_SIZE(tahiti_golden_rlc_registers));
123862306a36Sopenharmony_ci		radeon_program_register_sequence(rdev,
123962306a36Sopenharmony_ci						 tahiti_mgcg_cgcg_init,
124062306a36Sopenharmony_ci						 (const u32)ARRAY_SIZE(tahiti_mgcg_cgcg_init));
124162306a36Sopenharmony_ci		radeon_program_register_sequence(rdev,
124262306a36Sopenharmony_ci						 tahiti_golden_registers2,
124362306a36Sopenharmony_ci						 (const u32)ARRAY_SIZE(tahiti_golden_registers2));
124462306a36Sopenharmony_ci		break;
124562306a36Sopenharmony_ci	case CHIP_PITCAIRN:
124662306a36Sopenharmony_ci		radeon_program_register_sequence(rdev,
124762306a36Sopenharmony_ci						 pitcairn_golden_registers,
124862306a36Sopenharmony_ci						 (const u32)ARRAY_SIZE(pitcairn_golden_registers));
124962306a36Sopenharmony_ci		radeon_program_register_sequence(rdev,
125062306a36Sopenharmony_ci						 pitcairn_golden_rlc_registers,
125162306a36Sopenharmony_ci						 (const u32)ARRAY_SIZE(pitcairn_golden_rlc_registers));
125262306a36Sopenharmony_ci		radeon_program_register_sequence(rdev,
125362306a36Sopenharmony_ci						 pitcairn_mgcg_cgcg_init,
125462306a36Sopenharmony_ci						 (const u32)ARRAY_SIZE(pitcairn_mgcg_cgcg_init));
125562306a36Sopenharmony_ci		break;
125662306a36Sopenharmony_ci	case CHIP_VERDE:
125762306a36Sopenharmony_ci		radeon_program_register_sequence(rdev,
125862306a36Sopenharmony_ci						 verde_golden_registers,
125962306a36Sopenharmony_ci						 (const u32)ARRAY_SIZE(verde_golden_registers));
126062306a36Sopenharmony_ci		radeon_program_register_sequence(rdev,
126162306a36Sopenharmony_ci						 verde_golden_rlc_registers,
126262306a36Sopenharmony_ci						 (const u32)ARRAY_SIZE(verde_golden_rlc_registers));
126362306a36Sopenharmony_ci		radeon_program_register_sequence(rdev,
126462306a36Sopenharmony_ci						 verde_mgcg_cgcg_init,
126562306a36Sopenharmony_ci						 (const u32)ARRAY_SIZE(verde_mgcg_cgcg_init));
126662306a36Sopenharmony_ci		radeon_program_register_sequence(rdev,
126762306a36Sopenharmony_ci						 verde_pg_init,
126862306a36Sopenharmony_ci						 (const u32)ARRAY_SIZE(verde_pg_init));
126962306a36Sopenharmony_ci		break;
127062306a36Sopenharmony_ci	case CHIP_OLAND:
127162306a36Sopenharmony_ci		radeon_program_register_sequence(rdev,
127262306a36Sopenharmony_ci						 oland_golden_registers,
127362306a36Sopenharmony_ci						 (const u32)ARRAY_SIZE(oland_golden_registers));
127462306a36Sopenharmony_ci		radeon_program_register_sequence(rdev,
127562306a36Sopenharmony_ci						 oland_golden_rlc_registers,
127662306a36Sopenharmony_ci						 (const u32)ARRAY_SIZE(oland_golden_rlc_registers));
127762306a36Sopenharmony_ci		radeon_program_register_sequence(rdev,
127862306a36Sopenharmony_ci						 oland_mgcg_cgcg_init,
127962306a36Sopenharmony_ci						 (const u32)ARRAY_SIZE(oland_mgcg_cgcg_init));
128062306a36Sopenharmony_ci		break;
128162306a36Sopenharmony_ci	case CHIP_HAINAN:
128262306a36Sopenharmony_ci		radeon_program_register_sequence(rdev,
128362306a36Sopenharmony_ci						 hainan_golden_registers,
128462306a36Sopenharmony_ci						 (const u32)ARRAY_SIZE(hainan_golden_registers));
128562306a36Sopenharmony_ci		radeon_program_register_sequence(rdev,
128662306a36Sopenharmony_ci						 hainan_golden_registers2,
128762306a36Sopenharmony_ci						 (const u32)ARRAY_SIZE(hainan_golden_registers2));
128862306a36Sopenharmony_ci		radeon_program_register_sequence(rdev,
128962306a36Sopenharmony_ci						 hainan_mgcg_cgcg_init,
129062306a36Sopenharmony_ci						 (const u32)ARRAY_SIZE(hainan_mgcg_cgcg_init));
129162306a36Sopenharmony_ci		break;
129262306a36Sopenharmony_ci	default:
129362306a36Sopenharmony_ci		break;
129462306a36Sopenharmony_ci	}
129562306a36Sopenharmony_ci}
129662306a36Sopenharmony_ci
129762306a36Sopenharmony_ci/**
129862306a36Sopenharmony_ci * si_get_allowed_info_register - fetch the register for the info ioctl
129962306a36Sopenharmony_ci *
130062306a36Sopenharmony_ci * @rdev: radeon_device pointer
130162306a36Sopenharmony_ci * @reg: register offset in bytes
130262306a36Sopenharmony_ci * @val: register value
130362306a36Sopenharmony_ci *
130462306a36Sopenharmony_ci * Returns 0 for success or -EINVAL for an invalid register
130562306a36Sopenharmony_ci *
130662306a36Sopenharmony_ci */
130762306a36Sopenharmony_ciint si_get_allowed_info_register(struct radeon_device *rdev,
130862306a36Sopenharmony_ci				 u32 reg, u32 *val)
130962306a36Sopenharmony_ci{
131062306a36Sopenharmony_ci	switch (reg) {
131162306a36Sopenharmony_ci	case GRBM_STATUS:
131262306a36Sopenharmony_ci	case GRBM_STATUS2:
131362306a36Sopenharmony_ci	case GRBM_STATUS_SE0:
131462306a36Sopenharmony_ci	case GRBM_STATUS_SE1:
131562306a36Sopenharmony_ci	case SRBM_STATUS:
131662306a36Sopenharmony_ci	case SRBM_STATUS2:
131762306a36Sopenharmony_ci	case (DMA_STATUS_REG + DMA0_REGISTER_OFFSET):
131862306a36Sopenharmony_ci	case (DMA_STATUS_REG + DMA1_REGISTER_OFFSET):
131962306a36Sopenharmony_ci	case UVD_STATUS:
132062306a36Sopenharmony_ci		*val = RREG32(reg);
132162306a36Sopenharmony_ci		return 0;
132262306a36Sopenharmony_ci	default:
132362306a36Sopenharmony_ci		return -EINVAL;
132462306a36Sopenharmony_ci	}
132562306a36Sopenharmony_ci}
132662306a36Sopenharmony_ci
132762306a36Sopenharmony_ci#define PCIE_BUS_CLK                10000
132862306a36Sopenharmony_ci#define TCLK                        (PCIE_BUS_CLK / 10)
132962306a36Sopenharmony_ci
133062306a36Sopenharmony_ci/**
133162306a36Sopenharmony_ci * si_get_xclk - get the xclk
133262306a36Sopenharmony_ci *
133362306a36Sopenharmony_ci * @rdev: radeon_device pointer
133462306a36Sopenharmony_ci *
133562306a36Sopenharmony_ci * Returns the reference clock used by the gfx engine
133662306a36Sopenharmony_ci * (SI).
133762306a36Sopenharmony_ci */
133862306a36Sopenharmony_ciu32 si_get_xclk(struct radeon_device *rdev)
133962306a36Sopenharmony_ci{
134062306a36Sopenharmony_ci	u32 reference_clock = rdev->clock.spll.reference_freq;
134162306a36Sopenharmony_ci	u32 tmp;
134262306a36Sopenharmony_ci
134362306a36Sopenharmony_ci	tmp = RREG32(CG_CLKPIN_CNTL_2);
134462306a36Sopenharmony_ci	if (tmp & MUX_TCLK_TO_XCLK)
134562306a36Sopenharmony_ci		return TCLK;
134662306a36Sopenharmony_ci
134762306a36Sopenharmony_ci	tmp = RREG32(CG_CLKPIN_CNTL);
134862306a36Sopenharmony_ci	if (tmp & XTALIN_DIVIDE)
134962306a36Sopenharmony_ci		return reference_clock / 4;
135062306a36Sopenharmony_ci
135162306a36Sopenharmony_ci	return reference_clock;
135262306a36Sopenharmony_ci}
135362306a36Sopenharmony_ci
135462306a36Sopenharmony_ci/* get temperature in millidegrees */
135562306a36Sopenharmony_ciint si_get_temp(struct radeon_device *rdev)
135662306a36Sopenharmony_ci{
135762306a36Sopenharmony_ci	u32 temp;
135862306a36Sopenharmony_ci	int actual_temp = 0;
135962306a36Sopenharmony_ci
136062306a36Sopenharmony_ci	temp = (RREG32(CG_MULT_THERMAL_STATUS) & CTF_TEMP_MASK) >>
136162306a36Sopenharmony_ci		CTF_TEMP_SHIFT;
136262306a36Sopenharmony_ci
136362306a36Sopenharmony_ci	if (temp & 0x200)
136462306a36Sopenharmony_ci		actual_temp = 255;
136562306a36Sopenharmony_ci	else
136662306a36Sopenharmony_ci		actual_temp = temp & 0x1ff;
136762306a36Sopenharmony_ci
136862306a36Sopenharmony_ci	actual_temp = (actual_temp * 1000);
136962306a36Sopenharmony_ci
137062306a36Sopenharmony_ci	return actual_temp;
137162306a36Sopenharmony_ci}
137262306a36Sopenharmony_ci
137362306a36Sopenharmony_ci#define TAHITI_IO_MC_REGS_SIZE 36
137462306a36Sopenharmony_ci
137562306a36Sopenharmony_cistatic const u32 tahiti_io_mc_regs[TAHITI_IO_MC_REGS_SIZE][2] = {
137662306a36Sopenharmony_ci	{0x0000006f, 0x03044000},
137762306a36Sopenharmony_ci	{0x00000070, 0x0480c018},
137862306a36Sopenharmony_ci	{0x00000071, 0x00000040},
137962306a36Sopenharmony_ci	{0x00000072, 0x01000000},
138062306a36Sopenharmony_ci	{0x00000074, 0x000000ff},
138162306a36Sopenharmony_ci	{0x00000075, 0x00143400},
138262306a36Sopenharmony_ci	{0x00000076, 0x08ec0800},
138362306a36Sopenharmony_ci	{0x00000077, 0x040000cc},
138462306a36Sopenharmony_ci	{0x00000079, 0x00000000},
138562306a36Sopenharmony_ci	{0x0000007a, 0x21000409},
138662306a36Sopenharmony_ci	{0x0000007c, 0x00000000},
138762306a36Sopenharmony_ci	{0x0000007d, 0xe8000000},
138862306a36Sopenharmony_ci	{0x0000007e, 0x044408a8},
138962306a36Sopenharmony_ci	{0x0000007f, 0x00000003},
139062306a36Sopenharmony_ci	{0x00000080, 0x00000000},
139162306a36Sopenharmony_ci	{0x00000081, 0x01000000},
139262306a36Sopenharmony_ci	{0x00000082, 0x02000000},
139362306a36Sopenharmony_ci	{0x00000083, 0x00000000},
139462306a36Sopenharmony_ci	{0x00000084, 0xe3f3e4f4},
139562306a36Sopenharmony_ci	{0x00000085, 0x00052024},
139662306a36Sopenharmony_ci	{0x00000087, 0x00000000},
139762306a36Sopenharmony_ci	{0x00000088, 0x66036603},
139862306a36Sopenharmony_ci	{0x00000089, 0x01000000},
139962306a36Sopenharmony_ci	{0x0000008b, 0x1c0a0000},
140062306a36Sopenharmony_ci	{0x0000008c, 0xff010000},
140162306a36Sopenharmony_ci	{0x0000008e, 0xffffefff},
140262306a36Sopenharmony_ci	{0x0000008f, 0xfff3efff},
140362306a36Sopenharmony_ci	{0x00000090, 0xfff3efbf},
140462306a36Sopenharmony_ci	{0x00000094, 0x00101101},
140562306a36Sopenharmony_ci	{0x00000095, 0x00000fff},
140662306a36Sopenharmony_ci	{0x00000096, 0x00116fff},
140762306a36Sopenharmony_ci	{0x00000097, 0x60010000},
140862306a36Sopenharmony_ci	{0x00000098, 0x10010000},
140962306a36Sopenharmony_ci	{0x00000099, 0x00006000},
141062306a36Sopenharmony_ci	{0x0000009a, 0x00001000},
141162306a36Sopenharmony_ci	{0x0000009f, 0x00a77400}
141262306a36Sopenharmony_ci};
141362306a36Sopenharmony_ci
141462306a36Sopenharmony_cistatic const u32 pitcairn_io_mc_regs[TAHITI_IO_MC_REGS_SIZE][2] = {
141562306a36Sopenharmony_ci	{0x0000006f, 0x03044000},
141662306a36Sopenharmony_ci	{0x00000070, 0x0480c018},
141762306a36Sopenharmony_ci	{0x00000071, 0x00000040},
141862306a36Sopenharmony_ci	{0x00000072, 0x01000000},
141962306a36Sopenharmony_ci	{0x00000074, 0x000000ff},
142062306a36Sopenharmony_ci	{0x00000075, 0x00143400},
142162306a36Sopenharmony_ci	{0x00000076, 0x08ec0800},
142262306a36Sopenharmony_ci	{0x00000077, 0x040000cc},
142362306a36Sopenharmony_ci	{0x00000079, 0x00000000},
142462306a36Sopenharmony_ci	{0x0000007a, 0x21000409},
142562306a36Sopenharmony_ci	{0x0000007c, 0x00000000},
142662306a36Sopenharmony_ci	{0x0000007d, 0xe8000000},
142762306a36Sopenharmony_ci	{0x0000007e, 0x044408a8},
142862306a36Sopenharmony_ci	{0x0000007f, 0x00000003},
142962306a36Sopenharmony_ci	{0x00000080, 0x00000000},
143062306a36Sopenharmony_ci	{0x00000081, 0x01000000},
143162306a36Sopenharmony_ci	{0x00000082, 0x02000000},
143262306a36Sopenharmony_ci	{0x00000083, 0x00000000},
143362306a36Sopenharmony_ci	{0x00000084, 0xe3f3e4f4},
143462306a36Sopenharmony_ci	{0x00000085, 0x00052024},
143562306a36Sopenharmony_ci	{0x00000087, 0x00000000},
143662306a36Sopenharmony_ci	{0x00000088, 0x66036603},
143762306a36Sopenharmony_ci	{0x00000089, 0x01000000},
143862306a36Sopenharmony_ci	{0x0000008b, 0x1c0a0000},
143962306a36Sopenharmony_ci	{0x0000008c, 0xff010000},
144062306a36Sopenharmony_ci	{0x0000008e, 0xffffefff},
144162306a36Sopenharmony_ci	{0x0000008f, 0xfff3efff},
144262306a36Sopenharmony_ci	{0x00000090, 0xfff3efbf},
144362306a36Sopenharmony_ci	{0x00000094, 0x00101101},
144462306a36Sopenharmony_ci	{0x00000095, 0x00000fff},
144562306a36Sopenharmony_ci	{0x00000096, 0x00116fff},
144662306a36Sopenharmony_ci	{0x00000097, 0x60010000},
144762306a36Sopenharmony_ci	{0x00000098, 0x10010000},
144862306a36Sopenharmony_ci	{0x00000099, 0x00006000},
144962306a36Sopenharmony_ci	{0x0000009a, 0x00001000},
145062306a36Sopenharmony_ci	{0x0000009f, 0x00a47400}
145162306a36Sopenharmony_ci};
145262306a36Sopenharmony_ci
145362306a36Sopenharmony_cistatic const u32 verde_io_mc_regs[TAHITI_IO_MC_REGS_SIZE][2] = {
145462306a36Sopenharmony_ci	{0x0000006f, 0x03044000},
145562306a36Sopenharmony_ci	{0x00000070, 0x0480c018},
145662306a36Sopenharmony_ci	{0x00000071, 0x00000040},
145762306a36Sopenharmony_ci	{0x00000072, 0x01000000},
145862306a36Sopenharmony_ci	{0x00000074, 0x000000ff},
145962306a36Sopenharmony_ci	{0x00000075, 0x00143400},
146062306a36Sopenharmony_ci	{0x00000076, 0x08ec0800},
146162306a36Sopenharmony_ci	{0x00000077, 0x040000cc},
146262306a36Sopenharmony_ci	{0x00000079, 0x00000000},
146362306a36Sopenharmony_ci	{0x0000007a, 0x21000409},
146462306a36Sopenharmony_ci	{0x0000007c, 0x00000000},
146562306a36Sopenharmony_ci	{0x0000007d, 0xe8000000},
146662306a36Sopenharmony_ci	{0x0000007e, 0x044408a8},
146762306a36Sopenharmony_ci	{0x0000007f, 0x00000003},
146862306a36Sopenharmony_ci	{0x00000080, 0x00000000},
146962306a36Sopenharmony_ci	{0x00000081, 0x01000000},
147062306a36Sopenharmony_ci	{0x00000082, 0x02000000},
147162306a36Sopenharmony_ci	{0x00000083, 0x00000000},
147262306a36Sopenharmony_ci	{0x00000084, 0xe3f3e4f4},
147362306a36Sopenharmony_ci	{0x00000085, 0x00052024},
147462306a36Sopenharmony_ci	{0x00000087, 0x00000000},
147562306a36Sopenharmony_ci	{0x00000088, 0x66036603},
147662306a36Sopenharmony_ci	{0x00000089, 0x01000000},
147762306a36Sopenharmony_ci	{0x0000008b, 0x1c0a0000},
147862306a36Sopenharmony_ci	{0x0000008c, 0xff010000},
147962306a36Sopenharmony_ci	{0x0000008e, 0xffffefff},
148062306a36Sopenharmony_ci	{0x0000008f, 0xfff3efff},
148162306a36Sopenharmony_ci	{0x00000090, 0xfff3efbf},
148262306a36Sopenharmony_ci	{0x00000094, 0x00101101},
148362306a36Sopenharmony_ci	{0x00000095, 0x00000fff},
148462306a36Sopenharmony_ci	{0x00000096, 0x00116fff},
148562306a36Sopenharmony_ci	{0x00000097, 0x60010000},
148662306a36Sopenharmony_ci	{0x00000098, 0x10010000},
148762306a36Sopenharmony_ci	{0x00000099, 0x00006000},
148862306a36Sopenharmony_ci	{0x0000009a, 0x00001000},
148962306a36Sopenharmony_ci	{0x0000009f, 0x00a37400}
149062306a36Sopenharmony_ci};
149162306a36Sopenharmony_ci
149262306a36Sopenharmony_cistatic const u32 oland_io_mc_regs[TAHITI_IO_MC_REGS_SIZE][2] = {
149362306a36Sopenharmony_ci	{0x0000006f, 0x03044000},
149462306a36Sopenharmony_ci	{0x00000070, 0x0480c018},
149562306a36Sopenharmony_ci	{0x00000071, 0x00000040},
149662306a36Sopenharmony_ci	{0x00000072, 0x01000000},
149762306a36Sopenharmony_ci	{0x00000074, 0x000000ff},
149862306a36Sopenharmony_ci	{0x00000075, 0x00143400},
149962306a36Sopenharmony_ci	{0x00000076, 0x08ec0800},
150062306a36Sopenharmony_ci	{0x00000077, 0x040000cc},
150162306a36Sopenharmony_ci	{0x00000079, 0x00000000},
150262306a36Sopenharmony_ci	{0x0000007a, 0x21000409},
150362306a36Sopenharmony_ci	{0x0000007c, 0x00000000},
150462306a36Sopenharmony_ci	{0x0000007d, 0xe8000000},
150562306a36Sopenharmony_ci	{0x0000007e, 0x044408a8},
150662306a36Sopenharmony_ci	{0x0000007f, 0x00000003},
150762306a36Sopenharmony_ci	{0x00000080, 0x00000000},
150862306a36Sopenharmony_ci	{0x00000081, 0x01000000},
150962306a36Sopenharmony_ci	{0x00000082, 0x02000000},
151062306a36Sopenharmony_ci	{0x00000083, 0x00000000},
151162306a36Sopenharmony_ci	{0x00000084, 0xe3f3e4f4},
151262306a36Sopenharmony_ci	{0x00000085, 0x00052024},
151362306a36Sopenharmony_ci	{0x00000087, 0x00000000},
151462306a36Sopenharmony_ci	{0x00000088, 0x66036603},
151562306a36Sopenharmony_ci	{0x00000089, 0x01000000},
151662306a36Sopenharmony_ci	{0x0000008b, 0x1c0a0000},
151762306a36Sopenharmony_ci	{0x0000008c, 0xff010000},
151862306a36Sopenharmony_ci	{0x0000008e, 0xffffefff},
151962306a36Sopenharmony_ci	{0x0000008f, 0xfff3efff},
152062306a36Sopenharmony_ci	{0x00000090, 0xfff3efbf},
152162306a36Sopenharmony_ci	{0x00000094, 0x00101101},
152262306a36Sopenharmony_ci	{0x00000095, 0x00000fff},
152362306a36Sopenharmony_ci	{0x00000096, 0x00116fff},
152462306a36Sopenharmony_ci	{0x00000097, 0x60010000},
152562306a36Sopenharmony_ci	{0x00000098, 0x10010000},
152662306a36Sopenharmony_ci	{0x00000099, 0x00006000},
152762306a36Sopenharmony_ci	{0x0000009a, 0x00001000},
152862306a36Sopenharmony_ci	{0x0000009f, 0x00a17730}
152962306a36Sopenharmony_ci};
153062306a36Sopenharmony_ci
153162306a36Sopenharmony_cistatic const u32 hainan_io_mc_regs[TAHITI_IO_MC_REGS_SIZE][2] = {
153262306a36Sopenharmony_ci	{0x0000006f, 0x03044000},
153362306a36Sopenharmony_ci	{0x00000070, 0x0480c018},
153462306a36Sopenharmony_ci	{0x00000071, 0x00000040},
153562306a36Sopenharmony_ci	{0x00000072, 0x01000000},
153662306a36Sopenharmony_ci	{0x00000074, 0x000000ff},
153762306a36Sopenharmony_ci	{0x00000075, 0x00143400},
153862306a36Sopenharmony_ci	{0x00000076, 0x08ec0800},
153962306a36Sopenharmony_ci	{0x00000077, 0x040000cc},
154062306a36Sopenharmony_ci	{0x00000079, 0x00000000},
154162306a36Sopenharmony_ci	{0x0000007a, 0x21000409},
154262306a36Sopenharmony_ci	{0x0000007c, 0x00000000},
154362306a36Sopenharmony_ci	{0x0000007d, 0xe8000000},
154462306a36Sopenharmony_ci	{0x0000007e, 0x044408a8},
154562306a36Sopenharmony_ci	{0x0000007f, 0x00000003},
154662306a36Sopenharmony_ci	{0x00000080, 0x00000000},
154762306a36Sopenharmony_ci	{0x00000081, 0x01000000},
154862306a36Sopenharmony_ci	{0x00000082, 0x02000000},
154962306a36Sopenharmony_ci	{0x00000083, 0x00000000},
155062306a36Sopenharmony_ci	{0x00000084, 0xe3f3e4f4},
155162306a36Sopenharmony_ci	{0x00000085, 0x00052024},
155262306a36Sopenharmony_ci	{0x00000087, 0x00000000},
155362306a36Sopenharmony_ci	{0x00000088, 0x66036603},
155462306a36Sopenharmony_ci	{0x00000089, 0x01000000},
155562306a36Sopenharmony_ci	{0x0000008b, 0x1c0a0000},
155662306a36Sopenharmony_ci	{0x0000008c, 0xff010000},
155762306a36Sopenharmony_ci	{0x0000008e, 0xffffefff},
155862306a36Sopenharmony_ci	{0x0000008f, 0xfff3efff},
155962306a36Sopenharmony_ci	{0x00000090, 0xfff3efbf},
156062306a36Sopenharmony_ci	{0x00000094, 0x00101101},
156162306a36Sopenharmony_ci	{0x00000095, 0x00000fff},
156262306a36Sopenharmony_ci	{0x00000096, 0x00116fff},
156362306a36Sopenharmony_ci	{0x00000097, 0x60010000},
156462306a36Sopenharmony_ci	{0x00000098, 0x10010000},
156562306a36Sopenharmony_ci	{0x00000099, 0x00006000},
156662306a36Sopenharmony_ci	{0x0000009a, 0x00001000},
156762306a36Sopenharmony_ci	{0x0000009f, 0x00a07730}
156862306a36Sopenharmony_ci};
156962306a36Sopenharmony_ci
157062306a36Sopenharmony_ci/* ucode loading */
157162306a36Sopenharmony_ciint si_mc_load_microcode(struct radeon_device *rdev)
157262306a36Sopenharmony_ci{
157362306a36Sopenharmony_ci	const __be32 *fw_data = NULL;
157462306a36Sopenharmony_ci	const __le32 *new_fw_data = NULL;
157562306a36Sopenharmony_ci	u32 running;
157662306a36Sopenharmony_ci	u32 *io_mc_regs = NULL;
157762306a36Sopenharmony_ci	const __le32 *new_io_mc_regs = NULL;
157862306a36Sopenharmony_ci	int i, regs_size, ucode_size;
157962306a36Sopenharmony_ci
158062306a36Sopenharmony_ci	if (!rdev->mc_fw)
158162306a36Sopenharmony_ci		return -EINVAL;
158262306a36Sopenharmony_ci
158362306a36Sopenharmony_ci	if (rdev->new_fw) {
158462306a36Sopenharmony_ci		const struct mc_firmware_header_v1_0 *hdr =
158562306a36Sopenharmony_ci			(const struct mc_firmware_header_v1_0 *)rdev->mc_fw->data;
158662306a36Sopenharmony_ci
158762306a36Sopenharmony_ci		radeon_ucode_print_mc_hdr(&hdr->header);
158862306a36Sopenharmony_ci		regs_size = le32_to_cpu(hdr->io_debug_size_bytes) / (4 * 2);
158962306a36Sopenharmony_ci		new_io_mc_regs = (const __le32 *)
159062306a36Sopenharmony_ci			(rdev->mc_fw->data + le32_to_cpu(hdr->io_debug_array_offset_bytes));
159162306a36Sopenharmony_ci		ucode_size = le32_to_cpu(hdr->header.ucode_size_bytes) / 4;
159262306a36Sopenharmony_ci		new_fw_data = (const __le32 *)
159362306a36Sopenharmony_ci			(rdev->mc_fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes));
159462306a36Sopenharmony_ci	} else {
159562306a36Sopenharmony_ci		ucode_size = rdev->mc_fw->size / 4;
159662306a36Sopenharmony_ci
159762306a36Sopenharmony_ci		switch (rdev->family) {
159862306a36Sopenharmony_ci		case CHIP_TAHITI:
159962306a36Sopenharmony_ci			io_mc_regs = (u32 *)&tahiti_io_mc_regs;
160062306a36Sopenharmony_ci			regs_size = TAHITI_IO_MC_REGS_SIZE;
160162306a36Sopenharmony_ci			break;
160262306a36Sopenharmony_ci		case CHIP_PITCAIRN:
160362306a36Sopenharmony_ci			io_mc_regs = (u32 *)&pitcairn_io_mc_regs;
160462306a36Sopenharmony_ci			regs_size = TAHITI_IO_MC_REGS_SIZE;
160562306a36Sopenharmony_ci			break;
160662306a36Sopenharmony_ci		case CHIP_VERDE:
160762306a36Sopenharmony_ci		default:
160862306a36Sopenharmony_ci			io_mc_regs = (u32 *)&verde_io_mc_regs;
160962306a36Sopenharmony_ci			regs_size = TAHITI_IO_MC_REGS_SIZE;
161062306a36Sopenharmony_ci			break;
161162306a36Sopenharmony_ci		case CHIP_OLAND:
161262306a36Sopenharmony_ci			io_mc_regs = (u32 *)&oland_io_mc_regs;
161362306a36Sopenharmony_ci			regs_size = TAHITI_IO_MC_REGS_SIZE;
161462306a36Sopenharmony_ci			break;
161562306a36Sopenharmony_ci		case CHIP_HAINAN:
161662306a36Sopenharmony_ci			io_mc_regs = (u32 *)&hainan_io_mc_regs;
161762306a36Sopenharmony_ci			regs_size = TAHITI_IO_MC_REGS_SIZE;
161862306a36Sopenharmony_ci			break;
161962306a36Sopenharmony_ci		}
162062306a36Sopenharmony_ci		fw_data = (const __be32 *)rdev->mc_fw->data;
162162306a36Sopenharmony_ci	}
162262306a36Sopenharmony_ci
162362306a36Sopenharmony_ci	running = RREG32(MC_SEQ_SUP_CNTL) & RUN_MASK;
162462306a36Sopenharmony_ci
162562306a36Sopenharmony_ci	if (running == 0) {
162662306a36Sopenharmony_ci		/* reset the engine and set to writable */
162762306a36Sopenharmony_ci		WREG32(MC_SEQ_SUP_CNTL, 0x00000008);
162862306a36Sopenharmony_ci		WREG32(MC_SEQ_SUP_CNTL, 0x00000010);
162962306a36Sopenharmony_ci
163062306a36Sopenharmony_ci		/* load mc io regs */
163162306a36Sopenharmony_ci		for (i = 0; i < regs_size; i++) {
163262306a36Sopenharmony_ci			if (rdev->new_fw) {
163362306a36Sopenharmony_ci				WREG32(MC_SEQ_IO_DEBUG_INDEX, le32_to_cpup(new_io_mc_regs++));
163462306a36Sopenharmony_ci				WREG32(MC_SEQ_IO_DEBUG_DATA, le32_to_cpup(new_io_mc_regs++));
163562306a36Sopenharmony_ci			} else {
163662306a36Sopenharmony_ci				WREG32(MC_SEQ_IO_DEBUG_INDEX, io_mc_regs[(i << 1)]);
163762306a36Sopenharmony_ci				WREG32(MC_SEQ_IO_DEBUG_DATA, io_mc_regs[(i << 1) + 1]);
163862306a36Sopenharmony_ci			}
163962306a36Sopenharmony_ci		}
164062306a36Sopenharmony_ci		/* load the MC ucode */
164162306a36Sopenharmony_ci		for (i = 0; i < ucode_size; i++) {
164262306a36Sopenharmony_ci			if (rdev->new_fw)
164362306a36Sopenharmony_ci				WREG32(MC_SEQ_SUP_PGM, le32_to_cpup(new_fw_data++));
164462306a36Sopenharmony_ci			else
164562306a36Sopenharmony_ci				WREG32(MC_SEQ_SUP_PGM, be32_to_cpup(fw_data++));
164662306a36Sopenharmony_ci		}
164762306a36Sopenharmony_ci
164862306a36Sopenharmony_ci		/* put the engine back into the active state */
164962306a36Sopenharmony_ci		WREG32(MC_SEQ_SUP_CNTL, 0x00000008);
165062306a36Sopenharmony_ci		WREG32(MC_SEQ_SUP_CNTL, 0x00000004);
165162306a36Sopenharmony_ci		WREG32(MC_SEQ_SUP_CNTL, 0x00000001);
165262306a36Sopenharmony_ci
165362306a36Sopenharmony_ci		/* wait for training to complete */
165462306a36Sopenharmony_ci		for (i = 0; i < rdev->usec_timeout; i++) {
165562306a36Sopenharmony_ci			if (RREG32(MC_SEQ_TRAIN_WAKEUP_CNTL) & TRAIN_DONE_D0)
165662306a36Sopenharmony_ci				break;
165762306a36Sopenharmony_ci			udelay(1);
165862306a36Sopenharmony_ci		}
165962306a36Sopenharmony_ci		for (i = 0; i < rdev->usec_timeout; i++) {
166062306a36Sopenharmony_ci			if (RREG32(MC_SEQ_TRAIN_WAKEUP_CNTL) & TRAIN_DONE_D1)
166162306a36Sopenharmony_ci				break;
166262306a36Sopenharmony_ci			udelay(1);
166362306a36Sopenharmony_ci		}
166462306a36Sopenharmony_ci	}
166562306a36Sopenharmony_ci
166662306a36Sopenharmony_ci	return 0;
166762306a36Sopenharmony_ci}
166862306a36Sopenharmony_ci
166962306a36Sopenharmony_cistatic int si_init_microcode(struct radeon_device *rdev)
167062306a36Sopenharmony_ci{
167162306a36Sopenharmony_ci	const char *chip_name;
167262306a36Sopenharmony_ci	const char *new_chip_name;
167362306a36Sopenharmony_ci	size_t pfp_req_size, me_req_size, ce_req_size, rlc_req_size, mc_req_size;
167462306a36Sopenharmony_ci	size_t smc_req_size, mc2_req_size;
167562306a36Sopenharmony_ci	char fw_name[30];
167662306a36Sopenharmony_ci	int err;
167762306a36Sopenharmony_ci	int new_fw = 0;
167862306a36Sopenharmony_ci	bool new_smc = false;
167962306a36Sopenharmony_ci	bool si58_fw = false;
168062306a36Sopenharmony_ci	bool banks2_fw = false;
168162306a36Sopenharmony_ci
168262306a36Sopenharmony_ci	DRM_DEBUG("\n");
168362306a36Sopenharmony_ci
168462306a36Sopenharmony_ci	switch (rdev->family) {
168562306a36Sopenharmony_ci	case CHIP_TAHITI:
168662306a36Sopenharmony_ci		chip_name = "TAHITI";
168762306a36Sopenharmony_ci		new_chip_name = "tahiti";
168862306a36Sopenharmony_ci		pfp_req_size = SI_PFP_UCODE_SIZE * 4;
168962306a36Sopenharmony_ci		me_req_size = SI_PM4_UCODE_SIZE * 4;
169062306a36Sopenharmony_ci		ce_req_size = SI_CE_UCODE_SIZE * 4;
169162306a36Sopenharmony_ci		rlc_req_size = SI_RLC_UCODE_SIZE * 4;
169262306a36Sopenharmony_ci		mc_req_size = SI_MC_UCODE_SIZE * 4;
169362306a36Sopenharmony_ci		mc2_req_size = TAHITI_MC_UCODE_SIZE * 4;
169462306a36Sopenharmony_ci		smc_req_size = ALIGN(TAHITI_SMC_UCODE_SIZE, 4);
169562306a36Sopenharmony_ci		break;
169662306a36Sopenharmony_ci	case CHIP_PITCAIRN:
169762306a36Sopenharmony_ci		chip_name = "PITCAIRN";
169862306a36Sopenharmony_ci		if ((rdev->pdev->revision == 0x81) &&
169962306a36Sopenharmony_ci		    ((rdev->pdev->device == 0x6810) ||
170062306a36Sopenharmony_ci		     (rdev->pdev->device == 0x6811)))
170162306a36Sopenharmony_ci			new_smc = true;
170262306a36Sopenharmony_ci		new_chip_name = "pitcairn";
170362306a36Sopenharmony_ci		pfp_req_size = SI_PFP_UCODE_SIZE * 4;
170462306a36Sopenharmony_ci		me_req_size = SI_PM4_UCODE_SIZE * 4;
170562306a36Sopenharmony_ci		ce_req_size = SI_CE_UCODE_SIZE * 4;
170662306a36Sopenharmony_ci		rlc_req_size = SI_RLC_UCODE_SIZE * 4;
170762306a36Sopenharmony_ci		mc_req_size = SI_MC_UCODE_SIZE * 4;
170862306a36Sopenharmony_ci		mc2_req_size = PITCAIRN_MC_UCODE_SIZE * 4;
170962306a36Sopenharmony_ci		smc_req_size = ALIGN(PITCAIRN_SMC_UCODE_SIZE, 4);
171062306a36Sopenharmony_ci		break;
171162306a36Sopenharmony_ci	case CHIP_VERDE:
171262306a36Sopenharmony_ci		chip_name = "VERDE";
171362306a36Sopenharmony_ci		if (((rdev->pdev->device == 0x6820) &&
171462306a36Sopenharmony_ci		     ((rdev->pdev->revision == 0x81) ||
171562306a36Sopenharmony_ci		      (rdev->pdev->revision == 0x83))) ||
171662306a36Sopenharmony_ci		    ((rdev->pdev->device == 0x6821) &&
171762306a36Sopenharmony_ci		     ((rdev->pdev->revision == 0x83) ||
171862306a36Sopenharmony_ci		      (rdev->pdev->revision == 0x87))) ||
171962306a36Sopenharmony_ci		    ((rdev->pdev->revision == 0x87) &&
172062306a36Sopenharmony_ci		     ((rdev->pdev->device == 0x6823) ||
172162306a36Sopenharmony_ci		      (rdev->pdev->device == 0x682b))))
172262306a36Sopenharmony_ci			new_smc = true;
172362306a36Sopenharmony_ci		new_chip_name = "verde";
172462306a36Sopenharmony_ci		pfp_req_size = SI_PFP_UCODE_SIZE * 4;
172562306a36Sopenharmony_ci		me_req_size = SI_PM4_UCODE_SIZE * 4;
172662306a36Sopenharmony_ci		ce_req_size = SI_CE_UCODE_SIZE * 4;
172762306a36Sopenharmony_ci		rlc_req_size = SI_RLC_UCODE_SIZE * 4;
172862306a36Sopenharmony_ci		mc_req_size = SI_MC_UCODE_SIZE * 4;
172962306a36Sopenharmony_ci		mc2_req_size = VERDE_MC_UCODE_SIZE * 4;
173062306a36Sopenharmony_ci		smc_req_size = ALIGN(VERDE_SMC_UCODE_SIZE, 4);
173162306a36Sopenharmony_ci		break;
173262306a36Sopenharmony_ci	case CHIP_OLAND:
173362306a36Sopenharmony_ci		chip_name = "OLAND";
173462306a36Sopenharmony_ci		if (((rdev->pdev->revision == 0x81) &&
173562306a36Sopenharmony_ci		     ((rdev->pdev->device == 0x6600) ||
173662306a36Sopenharmony_ci		      (rdev->pdev->device == 0x6604) ||
173762306a36Sopenharmony_ci		      (rdev->pdev->device == 0x6605) ||
173862306a36Sopenharmony_ci		      (rdev->pdev->device == 0x6610))) ||
173962306a36Sopenharmony_ci		    ((rdev->pdev->revision == 0x83) &&
174062306a36Sopenharmony_ci		     (rdev->pdev->device == 0x6610)))
174162306a36Sopenharmony_ci			new_smc = true;
174262306a36Sopenharmony_ci		new_chip_name = "oland";
174362306a36Sopenharmony_ci		pfp_req_size = SI_PFP_UCODE_SIZE * 4;
174462306a36Sopenharmony_ci		me_req_size = SI_PM4_UCODE_SIZE * 4;
174562306a36Sopenharmony_ci		ce_req_size = SI_CE_UCODE_SIZE * 4;
174662306a36Sopenharmony_ci		rlc_req_size = SI_RLC_UCODE_SIZE * 4;
174762306a36Sopenharmony_ci		mc_req_size = mc2_req_size = OLAND_MC_UCODE_SIZE * 4;
174862306a36Sopenharmony_ci		smc_req_size = ALIGN(OLAND_SMC_UCODE_SIZE, 4);
174962306a36Sopenharmony_ci		break;
175062306a36Sopenharmony_ci	case CHIP_HAINAN:
175162306a36Sopenharmony_ci		chip_name = "HAINAN";
175262306a36Sopenharmony_ci		if (((rdev->pdev->revision == 0x81) &&
175362306a36Sopenharmony_ci		     (rdev->pdev->device == 0x6660)) ||
175462306a36Sopenharmony_ci		    ((rdev->pdev->revision == 0x83) &&
175562306a36Sopenharmony_ci		     ((rdev->pdev->device == 0x6660) ||
175662306a36Sopenharmony_ci		      (rdev->pdev->device == 0x6663) ||
175762306a36Sopenharmony_ci		      (rdev->pdev->device == 0x6665) ||
175862306a36Sopenharmony_ci		      (rdev->pdev->device == 0x6667))))
175962306a36Sopenharmony_ci			new_smc = true;
176062306a36Sopenharmony_ci		else if ((rdev->pdev->revision == 0xc3) &&
176162306a36Sopenharmony_ci			 (rdev->pdev->device == 0x6665))
176262306a36Sopenharmony_ci			banks2_fw = true;
176362306a36Sopenharmony_ci		new_chip_name = "hainan";
176462306a36Sopenharmony_ci		pfp_req_size = SI_PFP_UCODE_SIZE * 4;
176562306a36Sopenharmony_ci		me_req_size = SI_PM4_UCODE_SIZE * 4;
176662306a36Sopenharmony_ci		ce_req_size = SI_CE_UCODE_SIZE * 4;
176762306a36Sopenharmony_ci		rlc_req_size = SI_RLC_UCODE_SIZE * 4;
176862306a36Sopenharmony_ci		mc_req_size = mc2_req_size = OLAND_MC_UCODE_SIZE * 4;
176962306a36Sopenharmony_ci		smc_req_size = ALIGN(HAINAN_SMC_UCODE_SIZE, 4);
177062306a36Sopenharmony_ci		break;
177162306a36Sopenharmony_ci	default: BUG();
177262306a36Sopenharmony_ci	}
177362306a36Sopenharmony_ci
177462306a36Sopenharmony_ci	/* this memory configuration requires special firmware */
177562306a36Sopenharmony_ci	if (((RREG32(MC_SEQ_MISC0) & 0xff000000) >> 24) == 0x58)
177662306a36Sopenharmony_ci		si58_fw = true;
177762306a36Sopenharmony_ci
177862306a36Sopenharmony_ci	DRM_INFO("Loading %s Microcode\n", new_chip_name);
177962306a36Sopenharmony_ci
178062306a36Sopenharmony_ci	snprintf(fw_name, sizeof(fw_name), "radeon/%s_pfp.bin", new_chip_name);
178162306a36Sopenharmony_ci	err = request_firmware(&rdev->pfp_fw, fw_name, rdev->dev);
178262306a36Sopenharmony_ci	if (err) {
178362306a36Sopenharmony_ci		snprintf(fw_name, sizeof(fw_name), "radeon/%s_pfp.bin", chip_name);
178462306a36Sopenharmony_ci		err = request_firmware(&rdev->pfp_fw, fw_name, rdev->dev);
178562306a36Sopenharmony_ci		if (err)
178662306a36Sopenharmony_ci			goto out;
178762306a36Sopenharmony_ci		if (rdev->pfp_fw->size != pfp_req_size) {
178862306a36Sopenharmony_ci			pr_err("si_cp: Bogus length %zu in firmware \"%s\"\n",
178962306a36Sopenharmony_ci			       rdev->pfp_fw->size, fw_name);
179062306a36Sopenharmony_ci			err = -EINVAL;
179162306a36Sopenharmony_ci			goto out;
179262306a36Sopenharmony_ci		}
179362306a36Sopenharmony_ci	} else {
179462306a36Sopenharmony_ci		err = radeon_ucode_validate(rdev->pfp_fw);
179562306a36Sopenharmony_ci		if (err) {
179662306a36Sopenharmony_ci			pr_err("si_cp: validation failed for firmware \"%s\"\n",
179762306a36Sopenharmony_ci			       fw_name);
179862306a36Sopenharmony_ci			goto out;
179962306a36Sopenharmony_ci		} else {
180062306a36Sopenharmony_ci			new_fw++;
180162306a36Sopenharmony_ci		}
180262306a36Sopenharmony_ci	}
180362306a36Sopenharmony_ci
180462306a36Sopenharmony_ci	snprintf(fw_name, sizeof(fw_name), "radeon/%s_me.bin", new_chip_name);
180562306a36Sopenharmony_ci	err = request_firmware(&rdev->me_fw, fw_name, rdev->dev);
180662306a36Sopenharmony_ci	if (err) {
180762306a36Sopenharmony_ci		snprintf(fw_name, sizeof(fw_name), "radeon/%s_me.bin", chip_name);
180862306a36Sopenharmony_ci		err = request_firmware(&rdev->me_fw, fw_name, rdev->dev);
180962306a36Sopenharmony_ci		if (err)
181062306a36Sopenharmony_ci			goto out;
181162306a36Sopenharmony_ci		if (rdev->me_fw->size != me_req_size) {
181262306a36Sopenharmony_ci			pr_err("si_cp: Bogus length %zu in firmware \"%s\"\n",
181362306a36Sopenharmony_ci			       rdev->me_fw->size, fw_name);
181462306a36Sopenharmony_ci			err = -EINVAL;
181562306a36Sopenharmony_ci		}
181662306a36Sopenharmony_ci	} else {
181762306a36Sopenharmony_ci		err = radeon_ucode_validate(rdev->me_fw);
181862306a36Sopenharmony_ci		if (err) {
181962306a36Sopenharmony_ci			pr_err("si_cp: validation failed for firmware \"%s\"\n",
182062306a36Sopenharmony_ci			       fw_name);
182162306a36Sopenharmony_ci			goto out;
182262306a36Sopenharmony_ci		} else {
182362306a36Sopenharmony_ci			new_fw++;
182462306a36Sopenharmony_ci		}
182562306a36Sopenharmony_ci	}
182662306a36Sopenharmony_ci
182762306a36Sopenharmony_ci	snprintf(fw_name, sizeof(fw_name), "radeon/%s_ce.bin", new_chip_name);
182862306a36Sopenharmony_ci	err = request_firmware(&rdev->ce_fw, fw_name, rdev->dev);
182962306a36Sopenharmony_ci	if (err) {
183062306a36Sopenharmony_ci		snprintf(fw_name, sizeof(fw_name), "radeon/%s_ce.bin", chip_name);
183162306a36Sopenharmony_ci		err = request_firmware(&rdev->ce_fw, fw_name, rdev->dev);
183262306a36Sopenharmony_ci		if (err)
183362306a36Sopenharmony_ci			goto out;
183462306a36Sopenharmony_ci		if (rdev->ce_fw->size != ce_req_size) {
183562306a36Sopenharmony_ci			pr_err("si_cp: Bogus length %zu in firmware \"%s\"\n",
183662306a36Sopenharmony_ci			       rdev->ce_fw->size, fw_name);
183762306a36Sopenharmony_ci			err = -EINVAL;
183862306a36Sopenharmony_ci		}
183962306a36Sopenharmony_ci	} else {
184062306a36Sopenharmony_ci		err = radeon_ucode_validate(rdev->ce_fw);
184162306a36Sopenharmony_ci		if (err) {
184262306a36Sopenharmony_ci			pr_err("si_cp: validation failed for firmware \"%s\"\n",
184362306a36Sopenharmony_ci			       fw_name);
184462306a36Sopenharmony_ci			goto out;
184562306a36Sopenharmony_ci		} else {
184662306a36Sopenharmony_ci			new_fw++;
184762306a36Sopenharmony_ci		}
184862306a36Sopenharmony_ci	}
184962306a36Sopenharmony_ci
185062306a36Sopenharmony_ci	snprintf(fw_name, sizeof(fw_name), "radeon/%s_rlc.bin", new_chip_name);
185162306a36Sopenharmony_ci	err = request_firmware(&rdev->rlc_fw, fw_name, rdev->dev);
185262306a36Sopenharmony_ci	if (err) {
185362306a36Sopenharmony_ci		snprintf(fw_name, sizeof(fw_name), "radeon/%s_rlc.bin", chip_name);
185462306a36Sopenharmony_ci		err = request_firmware(&rdev->rlc_fw, fw_name, rdev->dev);
185562306a36Sopenharmony_ci		if (err)
185662306a36Sopenharmony_ci			goto out;
185762306a36Sopenharmony_ci		if (rdev->rlc_fw->size != rlc_req_size) {
185862306a36Sopenharmony_ci			pr_err("si_rlc: Bogus length %zu in firmware \"%s\"\n",
185962306a36Sopenharmony_ci			       rdev->rlc_fw->size, fw_name);
186062306a36Sopenharmony_ci			err = -EINVAL;
186162306a36Sopenharmony_ci		}
186262306a36Sopenharmony_ci	} else {
186362306a36Sopenharmony_ci		err = radeon_ucode_validate(rdev->rlc_fw);
186462306a36Sopenharmony_ci		if (err) {
186562306a36Sopenharmony_ci			pr_err("si_cp: validation failed for firmware \"%s\"\n",
186662306a36Sopenharmony_ci			       fw_name);
186762306a36Sopenharmony_ci			goto out;
186862306a36Sopenharmony_ci		} else {
186962306a36Sopenharmony_ci			new_fw++;
187062306a36Sopenharmony_ci		}
187162306a36Sopenharmony_ci	}
187262306a36Sopenharmony_ci
187362306a36Sopenharmony_ci	if (si58_fw)
187462306a36Sopenharmony_ci		snprintf(fw_name, sizeof(fw_name), "radeon/si58_mc.bin");
187562306a36Sopenharmony_ci	else
187662306a36Sopenharmony_ci		snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin", new_chip_name);
187762306a36Sopenharmony_ci	err = request_firmware(&rdev->mc_fw, fw_name, rdev->dev);
187862306a36Sopenharmony_ci	if (err) {
187962306a36Sopenharmony_ci		snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc2.bin", chip_name);
188062306a36Sopenharmony_ci		err = request_firmware(&rdev->mc_fw, fw_name, rdev->dev);
188162306a36Sopenharmony_ci		if (err) {
188262306a36Sopenharmony_ci			snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin", chip_name);
188362306a36Sopenharmony_ci			err = request_firmware(&rdev->mc_fw, fw_name, rdev->dev);
188462306a36Sopenharmony_ci			if (err)
188562306a36Sopenharmony_ci				goto out;
188662306a36Sopenharmony_ci		}
188762306a36Sopenharmony_ci		if ((rdev->mc_fw->size != mc_req_size) &&
188862306a36Sopenharmony_ci		    (rdev->mc_fw->size != mc2_req_size)) {
188962306a36Sopenharmony_ci			pr_err("si_mc: Bogus length %zu in firmware \"%s\"\n",
189062306a36Sopenharmony_ci			       rdev->mc_fw->size, fw_name);
189162306a36Sopenharmony_ci			err = -EINVAL;
189262306a36Sopenharmony_ci		}
189362306a36Sopenharmony_ci		DRM_INFO("%s: %zu bytes\n", fw_name, rdev->mc_fw->size);
189462306a36Sopenharmony_ci	} else {
189562306a36Sopenharmony_ci		err = radeon_ucode_validate(rdev->mc_fw);
189662306a36Sopenharmony_ci		if (err) {
189762306a36Sopenharmony_ci			pr_err("si_cp: validation failed for firmware \"%s\"\n",
189862306a36Sopenharmony_ci			       fw_name);
189962306a36Sopenharmony_ci			goto out;
190062306a36Sopenharmony_ci		} else {
190162306a36Sopenharmony_ci			new_fw++;
190262306a36Sopenharmony_ci		}
190362306a36Sopenharmony_ci	}
190462306a36Sopenharmony_ci
190562306a36Sopenharmony_ci	if (banks2_fw)
190662306a36Sopenharmony_ci		snprintf(fw_name, sizeof(fw_name), "radeon/banks_k_2_smc.bin");
190762306a36Sopenharmony_ci	else if (new_smc)
190862306a36Sopenharmony_ci		snprintf(fw_name, sizeof(fw_name), "radeon/%s_k_smc.bin", new_chip_name);
190962306a36Sopenharmony_ci	else
191062306a36Sopenharmony_ci		snprintf(fw_name, sizeof(fw_name), "radeon/%s_smc.bin", new_chip_name);
191162306a36Sopenharmony_ci	err = request_firmware(&rdev->smc_fw, fw_name, rdev->dev);
191262306a36Sopenharmony_ci	if (err) {
191362306a36Sopenharmony_ci		snprintf(fw_name, sizeof(fw_name), "radeon/%s_smc.bin", chip_name);
191462306a36Sopenharmony_ci		err = request_firmware(&rdev->smc_fw, fw_name, rdev->dev);
191562306a36Sopenharmony_ci		if (err) {
191662306a36Sopenharmony_ci			pr_err("smc: error loading firmware \"%s\"\n", fw_name);
191762306a36Sopenharmony_ci			release_firmware(rdev->smc_fw);
191862306a36Sopenharmony_ci			rdev->smc_fw = NULL;
191962306a36Sopenharmony_ci			err = 0;
192062306a36Sopenharmony_ci		} else if (rdev->smc_fw->size != smc_req_size) {
192162306a36Sopenharmony_ci			pr_err("si_smc: Bogus length %zu in firmware \"%s\"\n",
192262306a36Sopenharmony_ci			       rdev->smc_fw->size, fw_name);
192362306a36Sopenharmony_ci			err = -EINVAL;
192462306a36Sopenharmony_ci		}
192562306a36Sopenharmony_ci	} else {
192662306a36Sopenharmony_ci		err = radeon_ucode_validate(rdev->smc_fw);
192762306a36Sopenharmony_ci		if (err) {
192862306a36Sopenharmony_ci			pr_err("si_cp: validation failed for firmware \"%s\"\n",
192962306a36Sopenharmony_ci			       fw_name);
193062306a36Sopenharmony_ci			goto out;
193162306a36Sopenharmony_ci		} else {
193262306a36Sopenharmony_ci			new_fw++;
193362306a36Sopenharmony_ci		}
193462306a36Sopenharmony_ci	}
193562306a36Sopenharmony_ci
193662306a36Sopenharmony_ci	if (new_fw == 0) {
193762306a36Sopenharmony_ci		rdev->new_fw = false;
193862306a36Sopenharmony_ci	} else if (new_fw < 6) {
193962306a36Sopenharmony_ci		pr_err("si_fw: mixing new and old firmware!\n");
194062306a36Sopenharmony_ci		err = -EINVAL;
194162306a36Sopenharmony_ci	} else {
194262306a36Sopenharmony_ci		rdev->new_fw = true;
194362306a36Sopenharmony_ci	}
194462306a36Sopenharmony_ciout:
194562306a36Sopenharmony_ci	if (err) {
194662306a36Sopenharmony_ci		if (err != -EINVAL)
194762306a36Sopenharmony_ci			pr_err("si_cp: Failed to load firmware \"%s\"\n",
194862306a36Sopenharmony_ci			       fw_name);
194962306a36Sopenharmony_ci		release_firmware(rdev->pfp_fw);
195062306a36Sopenharmony_ci		rdev->pfp_fw = NULL;
195162306a36Sopenharmony_ci		release_firmware(rdev->me_fw);
195262306a36Sopenharmony_ci		rdev->me_fw = NULL;
195362306a36Sopenharmony_ci		release_firmware(rdev->ce_fw);
195462306a36Sopenharmony_ci		rdev->ce_fw = NULL;
195562306a36Sopenharmony_ci		release_firmware(rdev->rlc_fw);
195662306a36Sopenharmony_ci		rdev->rlc_fw = NULL;
195762306a36Sopenharmony_ci		release_firmware(rdev->mc_fw);
195862306a36Sopenharmony_ci		rdev->mc_fw = NULL;
195962306a36Sopenharmony_ci		release_firmware(rdev->smc_fw);
196062306a36Sopenharmony_ci		rdev->smc_fw = NULL;
196162306a36Sopenharmony_ci	}
196262306a36Sopenharmony_ci	return err;
196362306a36Sopenharmony_ci}
196462306a36Sopenharmony_ci
196562306a36Sopenharmony_ci/* watermark setup */
196662306a36Sopenharmony_cistatic u32 dce6_line_buffer_adjust(struct radeon_device *rdev,
196762306a36Sopenharmony_ci				   struct radeon_crtc *radeon_crtc,
196862306a36Sopenharmony_ci				   struct drm_display_mode *mode,
196962306a36Sopenharmony_ci				   struct drm_display_mode *other_mode)
197062306a36Sopenharmony_ci{
197162306a36Sopenharmony_ci	u32 tmp, buffer_alloc, i;
197262306a36Sopenharmony_ci	u32 pipe_offset = radeon_crtc->crtc_id * 0x20;
197362306a36Sopenharmony_ci	/*
197462306a36Sopenharmony_ci	 * Line Buffer Setup
197562306a36Sopenharmony_ci	 * There are 3 line buffers, each one shared by 2 display controllers.
197662306a36Sopenharmony_ci	 * DC_LB_MEMORY_SPLIT controls how that line buffer is shared between
197762306a36Sopenharmony_ci	 * the display controllers.  The paritioning is done via one of four
197862306a36Sopenharmony_ci	 * preset allocations specified in bits 21:20:
197962306a36Sopenharmony_ci	 *  0 - half lb
198062306a36Sopenharmony_ci	 *  2 - whole lb, other crtc must be disabled
198162306a36Sopenharmony_ci	 */
198262306a36Sopenharmony_ci	/* this can get tricky if we have two large displays on a paired group
198362306a36Sopenharmony_ci	 * of crtcs.  Ideally for multiple large displays we'd assign them to
198462306a36Sopenharmony_ci	 * non-linked crtcs for maximum line buffer allocation.
198562306a36Sopenharmony_ci	 */
198662306a36Sopenharmony_ci	if (radeon_crtc->base.enabled && mode) {
198762306a36Sopenharmony_ci		if (other_mode) {
198862306a36Sopenharmony_ci			tmp = 0; /* 1/2 */
198962306a36Sopenharmony_ci			buffer_alloc = 1;
199062306a36Sopenharmony_ci		} else {
199162306a36Sopenharmony_ci			tmp = 2; /* whole */
199262306a36Sopenharmony_ci			buffer_alloc = 2;
199362306a36Sopenharmony_ci		}
199462306a36Sopenharmony_ci	} else {
199562306a36Sopenharmony_ci		tmp = 0;
199662306a36Sopenharmony_ci		buffer_alloc = 0;
199762306a36Sopenharmony_ci	}
199862306a36Sopenharmony_ci
199962306a36Sopenharmony_ci	WREG32(DC_LB_MEMORY_SPLIT + radeon_crtc->crtc_offset,
200062306a36Sopenharmony_ci	       DC_LB_MEMORY_CONFIG(tmp));
200162306a36Sopenharmony_ci
200262306a36Sopenharmony_ci	WREG32(PIPE0_DMIF_BUFFER_CONTROL + pipe_offset,
200362306a36Sopenharmony_ci	       DMIF_BUFFERS_ALLOCATED(buffer_alloc));
200462306a36Sopenharmony_ci	for (i = 0; i < rdev->usec_timeout; i++) {
200562306a36Sopenharmony_ci		if (RREG32(PIPE0_DMIF_BUFFER_CONTROL + pipe_offset) &
200662306a36Sopenharmony_ci		    DMIF_BUFFERS_ALLOCATED_COMPLETED)
200762306a36Sopenharmony_ci			break;
200862306a36Sopenharmony_ci		udelay(1);
200962306a36Sopenharmony_ci	}
201062306a36Sopenharmony_ci
201162306a36Sopenharmony_ci	if (radeon_crtc->base.enabled && mode) {
201262306a36Sopenharmony_ci		switch (tmp) {
201362306a36Sopenharmony_ci		case 0:
201462306a36Sopenharmony_ci		default:
201562306a36Sopenharmony_ci			return 4096 * 2;
201662306a36Sopenharmony_ci		case 2:
201762306a36Sopenharmony_ci			return 8192 * 2;
201862306a36Sopenharmony_ci		}
201962306a36Sopenharmony_ci	}
202062306a36Sopenharmony_ci
202162306a36Sopenharmony_ci	/* controller not enabled, so no lb used */
202262306a36Sopenharmony_ci	return 0;
202362306a36Sopenharmony_ci}
202462306a36Sopenharmony_ci
202562306a36Sopenharmony_cistatic u32 si_get_number_of_dram_channels(struct radeon_device *rdev)
202662306a36Sopenharmony_ci{
202762306a36Sopenharmony_ci	u32 tmp = RREG32(MC_SHARED_CHMAP);
202862306a36Sopenharmony_ci
202962306a36Sopenharmony_ci	switch ((tmp & NOOFCHAN_MASK) >> NOOFCHAN_SHIFT) {
203062306a36Sopenharmony_ci	case 0:
203162306a36Sopenharmony_ci	default:
203262306a36Sopenharmony_ci		return 1;
203362306a36Sopenharmony_ci	case 1:
203462306a36Sopenharmony_ci		return 2;
203562306a36Sopenharmony_ci	case 2:
203662306a36Sopenharmony_ci		return 4;
203762306a36Sopenharmony_ci	case 3:
203862306a36Sopenharmony_ci		return 8;
203962306a36Sopenharmony_ci	case 4:
204062306a36Sopenharmony_ci		return 3;
204162306a36Sopenharmony_ci	case 5:
204262306a36Sopenharmony_ci		return 6;
204362306a36Sopenharmony_ci	case 6:
204462306a36Sopenharmony_ci		return 10;
204562306a36Sopenharmony_ci	case 7:
204662306a36Sopenharmony_ci		return 12;
204762306a36Sopenharmony_ci	case 8:
204862306a36Sopenharmony_ci		return 16;
204962306a36Sopenharmony_ci	}
205062306a36Sopenharmony_ci}
205162306a36Sopenharmony_ci
205262306a36Sopenharmony_cistruct dce6_wm_params {
205362306a36Sopenharmony_ci	u32 dram_channels; /* number of dram channels */
205462306a36Sopenharmony_ci	u32 yclk;          /* bandwidth per dram data pin in kHz */
205562306a36Sopenharmony_ci	u32 sclk;          /* engine clock in kHz */
205662306a36Sopenharmony_ci	u32 disp_clk;      /* display clock in kHz */
205762306a36Sopenharmony_ci	u32 src_width;     /* viewport width */
205862306a36Sopenharmony_ci	u32 active_time;   /* active display time in ns */
205962306a36Sopenharmony_ci	u32 blank_time;    /* blank time in ns */
206062306a36Sopenharmony_ci	bool interlaced;    /* mode is interlaced */
206162306a36Sopenharmony_ci	fixed20_12 vsc;    /* vertical scale ratio */
206262306a36Sopenharmony_ci	u32 num_heads;     /* number of active crtcs */
206362306a36Sopenharmony_ci	u32 bytes_per_pixel; /* bytes per pixel display + overlay */
206462306a36Sopenharmony_ci	u32 lb_size;       /* line buffer allocated to pipe */
206562306a36Sopenharmony_ci	u32 vtaps;         /* vertical scaler taps */
206662306a36Sopenharmony_ci};
206762306a36Sopenharmony_ci
206862306a36Sopenharmony_cistatic u32 dce6_dram_bandwidth(struct dce6_wm_params *wm)
206962306a36Sopenharmony_ci{
207062306a36Sopenharmony_ci	/* Calculate raw DRAM Bandwidth */
207162306a36Sopenharmony_ci	fixed20_12 dram_efficiency; /* 0.7 */
207262306a36Sopenharmony_ci	fixed20_12 yclk, dram_channels, bandwidth;
207362306a36Sopenharmony_ci	fixed20_12 a;
207462306a36Sopenharmony_ci
207562306a36Sopenharmony_ci	a.full = dfixed_const(1000);
207662306a36Sopenharmony_ci	yclk.full = dfixed_const(wm->yclk);
207762306a36Sopenharmony_ci	yclk.full = dfixed_div(yclk, a);
207862306a36Sopenharmony_ci	dram_channels.full = dfixed_const(wm->dram_channels * 4);
207962306a36Sopenharmony_ci	a.full = dfixed_const(10);
208062306a36Sopenharmony_ci	dram_efficiency.full = dfixed_const(7);
208162306a36Sopenharmony_ci	dram_efficiency.full = dfixed_div(dram_efficiency, a);
208262306a36Sopenharmony_ci	bandwidth.full = dfixed_mul(dram_channels, yclk);
208362306a36Sopenharmony_ci	bandwidth.full = dfixed_mul(bandwidth, dram_efficiency);
208462306a36Sopenharmony_ci
208562306a36Sopenharmony_ci	return dfixed_trunc(bandwidth);
208662306a36Sopenharmony_ci}
208762306a36Sopenharmony_ci
208862306a36Sopenharmony_cistatic u32 dce6_dram_bandwidth_for_display(struct dce6_wm_params *wm)
208962306a36Sopenharmony_ci{
209062306a36Sopenharmony_ci	/* Calculate DRAM Bandwidth and the part allocated to display. */
209162306a36Sopenharmony_ci	fixed20_12 disp_dram_allocation; /* 0.3 to 0.7 */
209262306a36Sopenharmony_ci	fixed20_12 yclk, dram_channels, bandwidth;
209362306a36Sopenharmony_ci	fixed20_12 a;
209462306a36Sopenharmony_ci
209562306a36Sopenharmony_ci	a.full = dfixed_const(1000);
209662306a36Sopenharmony_ci	yclk.full = dfixed_const(wm->yclk);
209762306a36Sopenharmony_ci	yclk.full = dfixed_div(yclk, a);
209862306a36Sopenharmony_ci	dram_channels.full = dfixed_const(wm->dram_channels * 4);
209962306a36Sopenharmony_ci	a.full = dfixed_const(10);
210062306a36Sopenharmony_ci	disp_dram_allocation.full = dfixed_const(3); /* XXX worse case value 0.3 */
210162306a36Sopenharmony_ci	disp_dram_allocation.full = dfixed_div(disp_dram_allocation, a);
210262306a36Sopenharmony_ci	bandwidth.full = dfixed_mul(dram_channels, yclk);
210362306a36Sopenharmony_ci	bandwidth.full = dfixed_mul(bandwidth, disp_dram_allocation);
210462306a36Sopenharmony_ci
210562306a36Sopenharmony_ci	return dfixed_trunc(bandwidth);
210662306a36Sopenharmony_ci}
210762306a36Sopenharmony_ci
210862306a36Sopenharmony_cistatic u32 dce6_data_return_bandwidth(struct dce6_wm_params *wm)
210962306a36Sopenharmony_ci{
211062306a36Sopenharmony_ci	/* Calculate the display Data return Bandwidth */
211162306a36Sopenharmony_ci	fixed20_12 return_efficiency; /* 0.8 */
211262306a36Sopenharmony_ci	fixed20_12 sclk, bandwidth;
211362306a36Sopenharmony_ci	fixed20_12 a;
211462306a36Sopenharmony_ci
211562306a36Sopenharmony_ci	a.full = dfixed_const(1000);
211662306a36Sopenharmony_ci	sclk.full = dfixed_const(wm->sclk);
211762306a36Sopenharmony_ci	sclk.full = dfixed_div(sclk, a);
211862306a36Sopenharmony_ci	a.full = dfixed_const(10);
211962306a36Sopenharmony_ci	return_efficiency.full = dfixed_const(8);
212062306a36Sopenharmony_ci	return_efficiency.full = dfixed_div(return_efficiency, a);
212162306a36Sopenharmony_ci	a.full = dfixed_const(32);
212262306a36Sopenharmony_ci	bandwidth.full = dfixed_mul(a, sclk);
212362306a36Sopenharmony_ci	bandwidth.full = dfixed_mul(bandwidth, return_efficiency);
212462306a36Sopenharmony_ci
212562306a36Sopenharmony_ci	return dfixed_trunc(bandwidth);
212662306a36Sopenharmony_ci}
212762306a36Sopenharmony_ci
212862306a36Sopenharmony_cistatic u32 dce6_get_dmif_bytes_per_request(struct dce6_wm_params *wm)
212962306a36Sopenharmony_ci{
213062306a36Sopenharmony_ci	return 32;
213162306a36Sopenharmony_ci}
213262306a36Sopenharmony_ci
213362306a36Sopenharmony_cistatic u32 dce6_dmif_request_bandwidth(struct dce6_wm_params *wm)
213462306a36Sopenharmony_ci{
213562306a36Sopenharmony_ci	/* Calculate the DMIF Request Bandwidth */
213662306a36Sopenharmony_ci	fixed20_12 disp_clk_request_efficiency; /* 0.8 */
213762306a36Sopenharmony_ci	fixed20_12 disp_clk, sclk, bandwidth;
213862306a36Sopenharmony_ci	fixed20_12 a, b1, b2;
213962306a36Sopenharmony_ci	u32 min_bandwidth;
214062306a36Sopenharmony_ci
214162306a36Sopenharmony_ci	a.full = dfixed_const(1000);
214262306a36Sopenharmony_ci	disp_clk.full = dfixed_const(wm->disp_clk);
214362306a36Sopenharmony_ci	disp_clk.full = dfixed_div(disp_clk, a);
214462306a36Sopenharmony_ci	a.full = dfixed_const(dce6_get_dmif_bytes_per_request(wm) / 2);
214562306a36Sopenharmony_ci	b1.full = dfixed_mul(a, disp_clk);
214662306a36Sopenharmony_ci
214762306a36Sopenharmony_ci	a.full = dfixed_const(1000);
214862306a36Sopenharmony_ci	sclk.full = dfixed_const(wm->sclk);
214962306a36Sopenharmony_ci	sclk.full = dfixed_div(sclk, a);
215062306a36Sopenharmony_ci	a.full = dfixed_const(dce6_get_dmif_bytes_per_request(wm));
215162306a36Sopenharmony_ci	b2.full = dfixed_mul(a, sclk);
215262306a36Sopenharmony_ci
215362306a36Sopenharmony_ci	a.full = dfixed_const(10);
215462306a36Sopenharmony_ci	disp_clk_request_efficiency.full = dfixed_const(8);
215562306a36Sopenharmony_ci	disp_clk_request_efficiency.full = dfixed_div(disp_clk_request_efficiency, a);
215662306a36Sopenharmony_ci
215762306a36Sopenharmony_ci	min_bandwidth = min(dfixed_trunc(b1), dfixed_trunc(b2));
215862306a36Sopenharmony_ci
215962306a36Sopenharmony_ci	a.full = dfixed_const(min_bandwidth);
216062306a36Sopenharmony_ci	bandwidth.full = dfixed_mul(a, disp_clk_request_efficiency);
216162306a36Sopenharmony_ci
216262306a36Sopenharmony_ci	return dfixed_trunc(bandwidth);
216362306a36Sopenharmony_ci}
216462306a36Sopenharmony_ci
216562306a36Sopenharmony_cistatic u32 dce6_available_bandwidth(struct dce6_wm_params *wm)
216662306a36Sopenharmony_ci{
216762306a36Sopenharmony_ci	/* Calculate the Available bandwidth. Display can use this temporarily but not in average. */
216862306a36Sopenharmony_ci	u32 dram_bandwidth = dce6_dram_bandwidth(wm);
216962306a36Sopenharmony_ci	u32 data_return_bandwidth = dce6_data_return_bandwidth(wm);
217062306a36Sopenharmony_ci	u32 dmif_req_bandwidth = dce6_dmif_request_bandwidth(wm);
217162306a36Sopenharmony_ci
217262306a36Sopenharmony_ci	return min(dram_bandwidth, min(data_return_bandwidth, dmif_req_bandwidth));
217362306a36Sopenharmony_ci}
217462306a36Sopenharmony_ci
217562306a36Sopenharmony_cistatic u32 dce6_average_bandwidth(struct dce6_wm_params *wm)
217662306a36Sopenharmony_ci{
217762306a36Sopenharmony_ci	/* Calculate the display mode Average Bandwidth
217862306a36Sopenharmony_ci	 * DisplayMode should contain the source and destination dimensions,
217962306a36Sopenharmony_ci	 * timing, etc.
218062306a36Sopenharmony_ci	 */
218162306a36Sopenharmony_ci	fixed20_12 bpp;
218262306a36Sopenharmony_ci	fixed20_12 line_time;
218362306a36Sopenharmony_ci	fixed20_12 src_width;
218462306a36Sopenharmony_ci	fixed20_12 bandwidth;
218562306a36Sopenharmony_ci	fixed20_12 a;
218662306a36Sopenharmony_ci
218762306a36Sopenharmony_ci	a.full = dfixed_const(1000);
218862306a36Sopenharmony_ci	line_time.full = dfixed_const(wm->active_time + wm->blank_time);
218962306a36Sopenharmony_ci	line_time.full = dfixed_div(line_time, a);
219062306a36Sopenharmony_ci	bpp.full = dfixed_const(wm->bytes_per_pixel);
219162306a36Sopenharmony_ci	src_width.full = dfixed_const(wm->src_width);
219262306a36Sopenharmony_ci	bandwidth.full = dfixed_mul(src_width, bpp);
219362306a36Sopenharmony_ci	bandwidth.full = dfixed_mul(bandwidth, wm->vsc);
219462306a36Sopenharmony_ci	bandwidth.full = dfixed_div(bandwidth, line_time);
219562306a36Sopenharmony_ci
219662306a36Sopenharmony_ci	return dfixed_trunc(bandwidth);
219762306a36Sopenharmony_ci}
219862306a36Sopenharmony_ci
219962306a36Sopenharmony_cistatic u32 dce6_latency_watermark(struct dce6_wm_params *wm)
220062306a36Sopenharmony_ci{
220162306a36Sopenharmony_ci	/* First calcualte the latency in ns */
220262306a36Sopenharmony_ci	u32 mc_latency = 2000; /* 2000 ns. */
220362306a36Sopenharmony_ci	u32 available_bandwidth = dce6_available_bandwidth(wm);
220462306a36Sopenharmony_ci	u32 worst_chunk_return_time = (512 * 8 * 1000) / available_bandwidth;
220562306a36Sopenharmony_ci	u32 cursor_line_pair_return_time = (128 * 4 * 1000) / available_bandwidth;
220662306a36Sopenharmony_ci	u32 dc_latency = 40000000 / wm->disp_clk; /* dc pipe latency */
220762306a36Sopenharmony_ci	u32 other_heads_data_return_time = ((wm->num_heads + 1) * worst_chunk_return_time) +
220862306a36Sopenharmony_ci		(wm->num_heads * cursor_line_pair_return_time);
220962306a36Sopenharmony_ci	u32 latency = mc_latency + other_heads_data_return_time + dc_latency;
221062306a36Sopenharmony_ci	u32 max_src_lines_per_dst_line, lb_fill_bw, line_fill_time;
221162306a36Sopenharmony_ci	u32 tmp, dmif_size = 12288;
221262306a36Sopenharmony_ci	fixed20_12 a, b, c;
221362306a36Sopenharmony_ci
221462306a36Sopenharmony_ci	if (wm->num_heads == 0)
221562306a36Sopenharmony_ci		return 0;
221662306a36Sopenharmony_ci
221762306a36Sopenharmony_ci	a.full = dfixed_const(2);
221862306a36Sopenharmony_ci	b.full = dfixed_const(1);
221962306a36Sopenharmony_ci	if ((wm->vsc.full > a.full) ||
222062306a36Sopenharmony_ci	    ((wm->vsc.full > b.full) && (wm->vtaps >= 3)) ||
222162306a36Sopenharmony_ci	    (wm->vtaps >= 5) ||
222262306a36Sopenharmony_ci	    ((wm->vsc.full >= a.full) && wm->interlaced))
222362306a36Sopenharmony_ci		max_src_lines_per_dst_line = 4;
222462306a36Sopenharmony_ci	else
222562306a36Sopenharmony_ci		max_src_lines_per_dst_line = 2;
222662306a36Sopenharmony_ci
222762306a36Sopenharmony_ci	a.full = dfixed_const(available_bandwidth);
222862306a36Sopenharmony_ci	b.full = dfixed_const(wm->num_heads);
222962306a36Sopenharmony_ci	a.full = dfixed_div(a, b);
223062306a36Sopenharmony_ci	tmp = div_u64((u64) dmif_size * (u64) wm->disp_clk, mc_latency + 512);
223162306a36Sopenharmony_ci	tmp = min(dfixed_trunc(a), tmp);
223262306a36Sopenharmony_ci
223362306a36Sopenharmony_ci	lb_fill_bw = min(tmp, wm->disp_clk * wm->bytes_per_pixel / 1000);
223462306a36Sopenharmony_ci
223562306a36Sopenharmony_ci	a.full = dfixed_const(max_src_lines_per_dst_line * wm->src_width * wm->bytes_per_pixel);
223662306a36Sopenharmony_ci	b.full = dfixed_const(1000);
223762306a36Sopenharmony_ci	c.full = dfixed_const(lb_fill_bw);
223862306a36Sopenharmony_ci	b.full = dfixed_div(c, b);
223962306a36Sopenharmony_ci	a.full = dfixed_div(a, b);
224062306a36Sopenharmony_ci	line_fill_time = dfixed_trunc(a);
224162306a36Sopenharmony_ci
224262306a36Sopenharmony_ci	if (line_fill_time < wm->active_time)
224362306a36Sopenharmony_ci		return latency;
224462306a36Sopenharmony_ci	else
224562306a36Sopenharmony_ci		return latency + (line_fill_time - wm->active_time);
224662306a36Sopenharmony_ci
224762306a36Sopenharmony_ci}
224862306a36Sopenharmony_ci
224962306a36Sopenharmony_cistatic bool dce6_average_bandwidth_vs_dram_bandwidth_for_display(struct dce6_wm_params *wm)
225062306a36Sopenharmony_ci{
225162306a36Sopenharmony_ci	if (dce6_average_bandwidth(wm) <=
225262306a36Sopenharmony_ci	    (dce6_dram_bandwidth_for_display(wm) / wm->num_heads))
225362306a36Sopenharmony_ci		return true;
225462306a36Sopenharmony_ci	else
225562306a36Sopenharmony_ci		return false;
225662306a36Sopenharmony_ci};
225762306a36Sopenharmony_ci
225862306a36Sopenharmony_cistatic bool dce6_average_bandwidth_vs_available_bandwidth(struct dce6_wm_params *wm)
225962306a36Sopenharmony_ci{
226062306a36Sopenharmony_ci	if (dce6_average_bandwidth(wm) <=
226162306a36Sopenharmony_ci	    (dce6_available_bandwidth(wm) / wm->num_heads))
226262306a36Sopenharmony_ci		return true;
226362306a36Sopenharmony_ci	else
226462306a36Sopenharmony_ci		return false;
226562306a36Sopenharmony_ci};
226662306a36Sopenharmony_ci
226762306a36Sopenharmony_cistatic bool dce6_check_latency_hiding(struct dce6_wm_params *wm)
226862306a36Sopenharmony_ci{
226962306a36Sopenharmony_ci	u32 lb_partitions = wm->lb_size / wm->src_width;
227062306a36Sopenharmony_ci	u32 line_time = wm->active_time + wm->blank_time;
227162306a36Sopenharmony_ci	u32 latency_tolerant_lines;
227262306a36Sopenharmony_ci	u32 latency_hiding;
227362306a36Sopenharmony_ci	fixed20_12 a;
227462306a36Sopenharmony_ci
227562306a36Sopenharmony_ci	a.full = dfixed_const(1);
227662306a36Sopenharmony_ci	if (wm->vsc.full > a.full)
227762306a36Sopenharmony_ci		latency_tolerant_lines = 1;
227862306a36Sopenharmony_ci	else {
227962306a36Sopenharmony_ci		if (lb_partitions <= (wm->vtaps + 1))
228062306a36Sopenharmony_ci			latency_tolerant_lines = 1;
228162306a36Sopenharmony_ci		else
228262306a36Sopenharmony_ci			latency_tolerant_lines = 2;
228362306a36Sopenharmony_ci	}
228462306a36Sopenharmony_ci
228562306a36Sopenharmony_ci	latency_hiding = (latency_tolerant_lines * line_time + wm->blank_time);
228662306a36Sopenharmony_ci
228762306a36Sopenharmony_ci	if (dce6_latency_watermark(wm) <= latency_hiding)
228862306a36Sopenharmony_ci		return true;
228962306a36Sopenharmony_ci	else
229062306a36Sopenharmony_ci		return false;
229162306a36Sopenharmony_ci}
229262306a36Sopenharmony_ci
229362306a36Sopenharmony_cistatic void dce6_program_watermarks(struct radeon_device *rdev,
229462306a36Sopenharmony_ci					 struct radeon_crtc *radeon_crtc,
229562306a36Sopenharmony_ci					 u32 lb_size, u32 num_heads)
229662306a36Sopenharmony_ci{
229762306a36Sopenharmony_ci	struct drm_display_mode *mode = &radeon_crtc->base.mode;
229862306a36Sopenharmony_ci	struct dce6_wm_params wm_low, wm_high;
229962306a36Sopenharmony_ci	u32 dram_channels;
230062306a36Sopenharmony_ci	u32 active_time;
230162306a36Sopenharmony_ci	u32 line_time = 0;
230262306a36Sopenharmony_ci	u32 latency_watermark_a = 0, latency_watermark_b = 0;
230362306a36Sopenharmony_ci	u32 priority_a_mark = 0, priority_b_mark = 0;
230462306a36Sopenharmony_ci	u32 priority_a_cnt = PRIORITY_OFF;
230562306a36Sopenharmony_ci	u32 priority_b_cnt = PRIORITY_OFF;
230662306a36Sopenharmony_ci	u32 tmp, arb_control3;
230762306a36Sopenharmony_ci	fixed20_12 a, b, c;
230862306a36Sopenharmony_ci
230962306a36Sopenharmony_ci	if (radeon_crtc->base.enabled && num_heads && mode) {
231062306a36Sopenharmony_ci		active_time = (u32) div_u64((u64)mode->crtc_hdisplay * 1000000,
231162306a36Sopenharmony_ci					    (u32)mode->clock);
231262306a36Sopenharmony_ci		line_time = (u32) div_u64((u64)mode->crtc_htotal * 1000000,
231362306a36Sopenharmony_ci					  (u32)mode->clock);
231462306a36Sopenharmony_ci		line_time = min(line_time, (u32)65535);
231562306a36Sopenharmony_ci		priority_a_cnt = 0;
231662306a36Sopenharmony_ci		priority_b_cnt = 0;
231762306a36Sopenharmony_ci
231862306a36Sopenharmony_ci		if (rdev->family == CHIP_ARUBA)
231962306a36Sopenharmony_ci			dram_channels = evergreen_get_number_of_dram_channels(rdev);
232062306a36Sopenharmony_ci		else
232162306a36Sopenharmony_ci			dram_channels = si_get_number_of_dram_channels(rdev);
232262306a36Sopenharmony_ci
232362306a36Sopenharmony_ci		/* watermark for high clocks */
232462306a36Sopenharmony_ci		if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled) {
232562306a36Sopenharmony_ci			wm_high.yclk =
232662306a36Sopenharmony_ci				radeon_dpm_get_mclk(rdev, false) * 10;
232762306a36Sopenharmony_ci			wm_high.sclk =
232862306a36Sopenharmony_ci				radeon_dpm_get_sclk(rdev, false) * 10;
232962306a36Sopenharmony_ci		} else {
233062306a36Sopenharmony_ci			wm_high.yclk = rdev->pm.current_mclk * 10;
233162306a36Sopenharmony_ci			wm_high.sclk = rdev->pm.current_sclk * 10;
233262306a36Sopenharmony_ci		}
233362306a36Sopenharmony_ci
233462306a36Sopenharmony_ci		wm_high.disp_clk = mode->clock;
233562306a36Sopenharmony_ci		wm_high.src_width = mode->crtc_hdisplay;
233662306a36Sopenharmony_ci		wm_high.active_time = active_time;
233762306a36Sopenharmony_ci		wm_high.blank_time = line_time - wm_high.active_time;
233862306a36Sopenharmony_ci		wm_high.interlaced = false;
233962306a36Sopenharmony_ci		if (mode->flags & DRM_MODE_FLAG_INTERLACE)
234062306a36Sopenharmony_ci			wm_high.interlaced = true;
234162306a36Sopenharmony_ci		wm_high.vsc = radeon_crtc->vsc;
234262306a36Sopenharmony_ci		wm_high.vtaps = 1;
234362306a36Sopenharmony_ci		if (radeon_crtc->rmx_type != RMX_OFF)
234462306a36Sopenharmony_ci			wm_high.vtaps = 2;
234562306a36Sopenharmony_ci		wm_high.bytes_per_pixel = 4; /* XXX: get this from fb config */
234662306a36Sopenharmony_ci		wm_high.lb_size = lb_size;
234762306a36Sopenharmony_ci		wm_high.dram_channels = dram_channels;
234862306a36Sopenharmony_ci		wm_high.num_heads = num_heads;
234962306a36Sopenharmony_ci
235062306a36Sopenharmony_ci		/* watermark for low clocks */
235162306a36Sopenharmony_ci		if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled) {
235262306a36Sopenharmony_ci			wm_low.yclk =
235362306a36Sopenharmony_ci				radeon_dpm_get_mclk(rdev, true) * 10;
235462306a36Sopenharmony_ci			wm_low.sclk =
235562306a36Sopenharmony_ci				radeon_dpm_get_sclk(rdev, true) * 10;
235662306a36Sopenharmony_ci		} else {
235762306a36Sopenharmony_ci			wm_low.yclk = rdev->pm.current_mclk * 10;
235862306a36Sopenharmony_ci			wm_low.sclk = rdev->pm.current_sclk * 10;
235962306a36Sopenharmony_ci		}
236062306a36Sopenharmony_ci
236162306a36Sopenharmony_ci		wm_low.disp_clk = mode->clock;
236262306a36Sopenharmony_ci		wm_low.src_width = mode->crtc_hdisplay;
236362306a36Sopenharmony_ci		wm_low.active_time = active_time;
236462306a36Sopenharmony_ci		wm_low.blank_time = line_time - wm_low.active_time;
236562306a36Sopenharmony_ci		wm_low.interlaced = false;
236662306a36Sopenharmony_ci		if (mode->flags & DRM_MODE_FLAG_INTERLACE)
236762306a36Sopenharmony_ci			wm_low.interlaced = true;
236862306a36Sopenharmony_ci		wm_low.vsc = radeon_crtc->vsc;
236962306a36Sopenharmony_ci		wm_low.vtaps = 1;
237062306a36Sopenharmony_ci		if (radeon_crtc->rmx_type != RMX_OFF)
237162306a36Sopenharmony_ci			wm_low.vtaps = 2;
237262306a36Sopenharmony_ci		wm_low.bytes_per_pixel = 4; /* XXX: get this from fb config */
237362306a36Sopenharmony_ci		wm_low.lb_size = lb_size;
237462306a36Sopenharmony_ci		wm_low.dram_channels = dram_channels;
237562306a36Sopenharmony_ci		wm_low.num_heads = num_heads;
237662306a36Sopenharmony_ci
237762306a36Sopenharmony_ci		/* set for high clocks */
237862306a36Sopenharmony_ci		latency_watermark_a = min(dce6_latency_watermark(&wm_high), (u32)65535);
237962306a36Sopenharmony_ci		/* set for low clocks */
238062306a36Sopenharmony_ci		latency_watermark_b = min(dce6_latency_watermark(&wm_low), (u32)65535);
238162306a36Sopenharmony_ci
238262306a36Sopenharmony_ci		/* possibly force display priority to high */
238362306a36Sopenharmony_ci		/* should really do this at mode validation time... */
238462306a36Sopenharmony_ci		if (!dce6_average_bandwidth_vs_dram_bandwidth_for_display(&wm_high) ||
238562306a36Sopenharmony_ci		    !dce6_average_bandwidth_vs_available_bandwidth(&wm_high) ||
238662306a36Sopenharmony_ci		    !dce6_check_latency_hiding(&wm_high) ||
238762306a36Sopenharmony_ci		    (rdev->disp_priority == 2)) {
238862306a36Sopenharmony_ci			DRM_DEBUG_KMS("force priority to high\n");
238962306a36Sopenharmony_ci			priority_a_cnt |= PRIORITY_ALWAYS_ON;
239062306a36Sopenharmony_ci			priority_b_cnt |= PRIORITY_ALWAYS_ON;
239162306a36Sopenharmony_ci		}
239262306a36Sopenharmony_ci		if (!dce6_average_bandwidth_vs_dram_bandwidth_for_display(&wm_low) ||
239362306a36Sopenharmony_ci		    !dce6_average_bandwidth_vs_available_bandwidth(&wm_low) ||
239462306a36Sopenharmony_ci		    !dce6_check_latency_hiding(&wm_low) ||
239562306a36Sopenharmony_ci		    (rdev->disp_priority == 2)) {
239662306a36Sopenharmony_ci			DRM_DEBUG_KMS("force priority to high\n");
239762306a36Sopenharmony_ci			priority_a_cnt |= PRIORITY_ALWAYS_ON;
239862306a36Sopenharmony_ci			priority_b_cnt |= PRIORITY_ALWAYS_ON;
239962306a36Sopenharmony_ci		}
240062306a36Sopenharmony_ci
240162306a36Sopenharmony_ci		a.full = dfixed_const(1000);
240262306a36Sopenharmony_ci		b.full = dfixed_const(mode->clock);
240362306a36Sopenharmony_ci		b.full = dfixed_div(b, a);
240462306a36Sopenharmony_ci		c.full = dfixed_const(latency_watermark_a);
240562306a36Sopenharmony_ci		c.full = dfixed_mul(c, b);
240662306a36Sopenharmony_ci		c.full = dfixed_mul(c, radeon_crtc->hsc);
240762306a36Sopenharmony_ci		c.full = dfixed_div(c, a);
240862306a36Sopenharmony_ci		a.full = dfixed_const(16);
240962306a36Sopenharmony_ci		c.full = dfixed_div(c, a);
241062306a36Sopenharmony_ci		priority_a_mark = dfixed_trunc(c);
241162306a36Sopenharmony_ci		priority_a_cnt |= priority_a_mark & PRIORITY_MARK_MASK;
241262306a36Sopenharmony_ci
241362306a36Sopenharmony_ci		a.full = dfixed_const(1000);
241462306a36Sopenharmony_ci		b.full = dfixed_const(mode->clock);
241562306a36Sopenharmony_ci		b.full = dfixed_div(b, a);
241662306a36Sopenharmony_ci		c.full = dfixed_const(latency_watermark_b);
241762306a36Sopenharmony_ci		c.full = dfixed_mul(c, b);
241862306a36Sopenharmony_ci		c.full = dfixed_mul(c, radeon_crtc->hsc);
241962306a36Sopenharmony_ci		c.full = dfixed_div(c, a);
242062306a36Sopenharmony_ci		a.full = dfixed_const(16);
242162306a36Sopenharmony_ci		c.full = dfixed_div(c, a);
242262306a36Sopenharmony_ci		priority_b_mark = dfixed_trunc(c);
242362306a36Sopenharmony_ci		priority_b_cnt |= priority_b_mark & PRIORITY_MARK_MASK;
242462306a36Sopenharmony_ci
242562306a36Sopenharmony_ci		/* Save number of lines the linebuffer leads before the scanout */
242662306a36Sopenharmony_ci		radeon_crtc->lb_vblank_lead_lines = DIV_ROUND_UP(lb_size, mode->crtc_hdisplay);
242762306a36Sopenharmony_ci	}
242862306a36Sopenharmony_ci
242962306a36Sopenharmony_ci	/* select wm A */
243062306a36Sopenharmony_ci	arb_control3 = RREG32(DPG_PIPE_ARBITRATION_CONTROL3 + radeon_crtc->crtc_offset);
243162306a36Sopenharmony_ci	tmp = arb_control3;
243262306a36Sopenharmony_ci	tmp &= ~LATENCY_WATERMARK_MASK(3);
243362306a36Sopenharmony_ci	tmp |= LATENCY_WATERMARK_MASK(1);
243462306a36Sopenharmony_ci	WREG32(DPG_PIPE_ARBITRATION_CONTROL3 + radeon_crtc->crtc_offset, tmp);
243562306a36Sopenharmony_ci	WREG32(DPG_PIPE_LATENCY_CONTROL + radeon_crtc->crtc_offset,
243662306a36Sopenharmony_ci	       (LATENCY_LOW_WATERMARK(latency_watermark_a) |
243762306a36Sopenharmony_ci		LATENCY_HIGH_WATERMARK(line_time)));
243862306a36Sopenharmony_ci	/* select wm B */
243962306a36Sopenharmony_ci	tmp = RREG32(DPG_PIPE_ARBITRATION_CONTROL3 + radeon_crtc->crtc_offset);
244062306a36Sopenharmony_ci	tmp &= ~LATENCY_WATERMARK_MASK(3);
244162306a36Sopenharmony_ci	tmp |= LATENCY_WATERMARK_MASK(2);
244262306a36Sopenharmony_ci	WREG32(DPG_PIPE_ARBITRATION_CONTROL3 + radeon_crtc->crtc_offset, tmp);
244362306a36Sopenharmony_ci	WREG32(DPG_PIPE_LATENCY_CONTROL + radeon_crtc->crtc_offset,
244462306a36Sopenharmony_ci	       (LATENCY_LOW_WATERMARK(latency_watermark_b) |
244562306a36Sopenharmony_ci		LATENCY_HIGH_WATERMARK(line_time)));
244662306a36Sopenharmony_ci	/* restore original selection */
244762306a36Sopenharmony_ci	WREG32(DPG_PIPE_ARBITRATION_CONTROL3 + radeon_crtc->crtc_offset, arb_control3);
244862306a36Sopenharmony_ci
244962306a36Sopenharmony_ci	/* write the priority marks */
245062306a36Sopenharmony_ci	WREG32(PRIORITY_A_CNT + radeon_crtc->crtc_offset, priority_a_cnt);
245162306a36Sopenharmony_ci	WREG32(PRIORITY_B_CNT + radeon_crtc->crtc_offset, priority_b_cnt);
245262306a36Sopenharmony_ci
245362306a36Sopenharmony_ci	/* save values for DPM */
245462306a36Sopenharmony_ci	radeon_crtc->line_time = line_time;
245562306a36Sopenharmony_ci	radeon_crtc->wm_high = latency_watermark_a;
245662306a36Sopenharmony_ci	radeon_crtc->wm_low = latency_watermark_b;
245762306a36Sopenharmony_ci}
245862306a36Sopenharmony_ci
245962306a36Sopenharmony_civoid dce6_bandwidth_update(struct radeon_device *rdev)
246062306a36Sopenharmony_ci{
246162306a36Sopenharmony_ci	struct drm_display_mode *mode0 = NULL;
246262306a36Sopenharmony_ci	struct drm_display_mode *mode1 = NULL;
246362306a36Sopenharmony_ci	u32 num_heads = 0, lb_size;
246462306a36Sopenharmony_ci	int i;
246562306a36Sopenharmony_ci
246662306a36Sopenharmony_ci	if (!rdev->mode_info.mode_config_initialized)
246762306a36Sopenharmony_ci		return;
246862306a36Sopenharmony_ci
246962306a36Sopenharmony_ci	radeon_update_display_priority(rdev);
247062306a36Sopenharmony_ci
247162306a36Sopenharmony_ci	for (i = 0; i < rdev->num_crtc; i++) {
247262306a36Sopenharmony_ci		if (rdev->mode_info.crtcs[i]->base.enabled)
247362306a36Sopenharmony_ci			num_heads++;
247462306a36Sopenharmony_ci	}
247562306a36Sopenharmony_ci	for (i = 0; i < rdev->num_crtc; i += 2) {
247662306a36Sopenharmony_ci		mode0 = &rdev->mode_info.crtcs[i]->base.mode;
247762306a36Sopenharmony_ci		mode1 = &rdev->mode_info.crtcs[i+1]->base.mode;
247862306a36Sopenharmony_ci		lb_size = dce6_line_buffer_adjust(rdev, rdev->mode_info.crtcs[i], mode0, mode1);
247962306a36Sopenharmony_ci		dce6_program_watermarks(rdev, rdev->mode_info.crtcs[i], lb_size, num_heads);
248062306a36Sopenharmony_ci		lb_size = dce6_line_buffer_adjust(rdev, rdev->mode_info.crtcs[i+1], mode1, mode0);
248162306a36Sopenharmony_ci		dce6_program_watermarks(rdev, rdev->mode_info.crtcs[i+1], lb_size, num_heads);
248262306a36Sopenharmony_ci	}
248362306a36Sopenharmony_ci}
248462306a36Sopenharmony_ci
248562306a36Sopenharmony_ci/*
248662306a36Sopenharmony_ci * Core functions
248762306a36Sopenharmony_ci */
248862306a36Sopenharmony_cistatic void si_tiling_mode_table_init(struct radeon_device *rdev)
248962306a36Sopenharmony_ci{
249062306a36Sopenharmony_ci	u32 *tile = rdev->config.si.tile_mode_array;
249162306a36Sopenharmony_ci	const u32 num_tile_mode_states =
249262306a36Sopenharmony_ci			ARRAY_SIZE(rdev->config.si.tile_mode_array);
249362306a36Sopenharmony_ci	u32 reg_offset, split_equal_to_row_size;
249462306a36Sopenharmony_ci
249562306a36Sopenharmony_ci	switch (rdev->config.si.mem_row_size_in_kb) {
249662306a36Sopenharmony_ci	case 1:
249762306a36Sopenharmony_ci		split_equal_to_row_size = ADDR_SURF_TILE_SPLIT_1KB;
249862306a36Sopenharmony_ci		break;
249962306a36Sopenharmony_ci	case 2:
250062306a36Sopenharmony_ci	default:
250162306a36Sopenharmony_ci		split_equal_to_row_size = ADDR_SURF_TILE_SPLIT_2KB;
250262306a36Sopenharmony_ci		break;
250362306a36Sopenharmony_ci	case 4:
250462306a36Sopenharmony_ci		split_equal_to_row_size = ADDR_SURF_TILE_SPLIT_4KB;
250562306a36Sopenharmony_ci		break;
250662306a36Sopenharmony_ci	}
250762306a36Sopenharmony_ci
250862306a36Sopenharmony_ci	for (reg_offset = 0; reg_offset < num_tile_mode_states; reg_offset++)
250962306a36Sopenharmony_ci		tile[reg_offset] = 0;
251062306a36Sopenharmony_ci
251162306a36Sopenharmony_ci	switch(rdev->family) {
251262306a36Sopenharmony_ci	case CHIP_TAHITI:
251362306a36Sopenharmony_ci	case CHIP_PITCAIRN:
251462306a36Sopenharmony_ci		/* non-AA compressed depth or any compressed stencil */
251562306a36Sopenharmony_ci		tile[0] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
251662306a36Sopenharmony_ci			   MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
251762306a36Sopenharmony_ci			   PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
251862306a36Sopenharmony_ci			   TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) |
251962306a36Sopenharmony_ci			   NUM_BANKS(ADDR_SURF_16_BANK) |
252062306a36Sopenharmony_ci			   BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
252162306a36Sopenharmony_ci			   BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
252262306a36Sopenharmony_ci			   MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
252362306a36Sopenharmony_ci		/* 2xAA/4xAA compressed depth only */
252462306a36Sopenharmony_ci		tile[1] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
252562306a36Sopenharmony_ci			   MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
252662306a36Sopenharmony_ci			   PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
252762306a36Sopenharmony_ci			   TILE_SPLIT(ADDR_SURF_TILE_SPLIT_128B) |
252862306a36Sopenharmony_ci			   NUM_BANKS(ADDR_SURF_16_BANK) |
252962306a36Sopenharmony_ci			   BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
253062306a36Sopenharmony_ci			   BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
253162306a36Sopenharmony_ci			   MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
253262306a36Sopenharmony_ci		/* 8xAA compressed depth only */
253362306a36Sopenharmony_ci		tile[2] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
253462306a36Sopenharmony_ci			   MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
253562306a36Sopenharmony_ci			   PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
253662306a36Sopenharmony_ci			   TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
253762306a36Sopenharmony_ci			   NUM_BANKS(ADDR_SURF_16_BANK) |
253862306a36Sopenharmony_ci			   BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
253962306a36Sopenharmony_ci			   BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
254062306a36Sopenharmony_ci			   MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
254162306a36Sopenharmony_ci		/* 2xAA/4xAA compressed depth with stencil (for depth buffer) */
254262306a36Sopenharmony_ci		tile[3] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
254362306a36Sopenharmony_ci			   MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
254462306a36Sopenharmony_ci			   PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
254562306a36Sopenharmony_ci			   TILE_SPLIT(ADDR_SURF_TILE_SPLIT_128B) |
254662306a36Sopenharmony_ci			   NUM_BANKS(ADDR_SURF_16_BANK) |
254762306a36Sopenharmony_ci			   BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
254862306a36Sopenharmony_ci			   BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
254962306a36Sopenharmony_ci			   MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
255062306a36Sopenharmony_ci		/* Maps w/ a dimension less than the 2D macro-tile dimensions (for mipmapped depth textures) */
255162306a36Sopenharmony_ci		tile[4] = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
255262306a36Sopenharmony_ci			   MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
255362306a36Sopenharmony_ci			   PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
255462306a36Sopenharmony_ci			   TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) |
255562306a36Sopenharmony_ci			   NUM_BANKS(ADDR_SURF_16_BANK) |
255662306a36Sopenharmony_ci			   BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
255762306a36Sopenharmony_ci			   BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
255862306a36Sopenharmony_ci			   MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
255962306a36Sopenharmony_ci		/* Uncompressed 16bpp depth - and stencil buffer allocated with it */
256062306a36Sopenharmony_ci		tile[5] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
256162306a36Sopenharmony_ci			   MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
256262306a36Sopenharmony_ci			   PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
256362306a36Sopenharmony_ci			   TILE_SPLIT(split_equal_to_row_size) |
256462306a36Sopenharmony_ci			   NUM_BANKS(ADDR_SURF_16_BANK) |
256562306a36Sopenharmony_ci			   BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
256662306a36Sopenharmony_ci			   BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
256762306a36Sopenharmony_ci			   MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
256862306a36Sopenharmony_ci		/* Uncompressed 32bpp depth - and stencil buffer allocated with it */
256962306a36Sopenharmony_ci		tile[6] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
257062306a36Sopenharmony_ci			   MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
257162306a36Sopenharmony_ci			   PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
257262306a36Sopenharmony_ci			   TILE_SPLIT(split_equal_to_row_size) |
257362306a36Sopenharmony_ci			   NUM_BANKS(ADDR_SURF_16_BANK) |
257462306a36Sopenharmony_ci			   BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
257562306a36Sopenharmony_ci			   BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
257662306a36Sopenharmony_ci			   MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1));
257762306a36Sopenharmony_ci		/* Uncompressed 8bpp stencil without depth (drivers typically do not use) */
257862306a36Sopenharmony_ci		tile[7] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
257962306a36Sopenharmony_ci			   MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
258062306a36Sopenharmony_ci			   PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
258162306a36Sopenharmony_ci			   TILE_SPLIT(split_equal_to_row_size) |
258262306a36Sopenharmony_ci			   NUM_BANKS(ADDR_SURF_16_BANK) |
258362306a36Sopenharmony_ci			   BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
258462306a36Sopenharmony_ci			   BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
258562306a36Sopenharmony_ci			   MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
258662306a36Sopenharmony_ci		/* 1D and 1D Array Surfaces */
258762306a36Sopenharmony_ci		tile[8] = (ARRAY_MODE(ARRAY_LINEAR_ALIGNED) |
258862306a36Sopenharmony_ci			   MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) |
258962306a36Sopenharmony_ci			   PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
259062306a36Sopenharmony_ci			   TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) |
259162306a36Sopenharmony_ci			   NUM_BANKS(ADDR_SURF_16_BANK) |
259262306a36Sopenharmony_ci			   BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
259362306a36Sopenharmony_ci			   BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
259462306a36Sopenharmony_ci			   MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
259562306a36Sopenharmony_ci		/* Displayable maps. */
259662306a36Sopenharmony_ci		tile[9] = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
259762306a36Sopenharmony_ci			   MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) |
259862306a36Sopenharmony_ci			   PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
259962306a36Sopenharmony_ci			   TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) |
260062306a36Sopenharmony_ci			   NUM_BANKS(ADDR_SURF_16_BANK) |
260162306a36Sopenharmony_ci			   BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
260262306a36Sopenharmony_ci			   BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
260362306a36Sopenharmony_ci			   MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
260462306a36Sopenharmony_ci		/* Display 8bpp. */
260562306a36Sopenharmony_ci		tile[10] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
260662306a36Sopenharmony_ci			   MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) |
260762306a36Sopenharmony_ci			   PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
260862306a36Sopenharmony_ci			   TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
260962306a36Sopenharmony_ci			   NUM_BANKS(ADDR_SURF_16_BANK) |
261062306a36Sopenharmony_ci			   BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
261162306a36Sopenharmony_ci			   BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
261262306a36Sopenharmony_ci			   MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
261362306a36Sopenharmony_ci		/* Display 16bpp. */
261462306a36Sopenharmony_ci		tile[11] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
261562306a36Sopenharmony_ci			   MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) |
261662306a36Sopenharmony_ci			   PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
261762306a36Sopenharmony_ci			   TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
261862306a36Sopenharmony_ci			   NUM_BANKS(ADDR_SURF_16_BANK) |
261962306a36Sopenharmony_ci			   BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
262062306a36Sopenharmony_ci			   BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
262162306a36Sopenharmony_ci			   MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
262262306a36Sopenharmony_ci		/* Display 32bpp. */
262362306a36Sopenharmony_ci		tile[12] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
262462306a36Sopenharmony_ci			   MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) |
262562306a36Sopenharmony_ci			   PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
262662306a36Sopenharmony_ci			   TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) |
262762306a36Sopenharmony_ci			   NUM_BANKS(ADDR_SURF_16_BANK) |
262862306a36Sopenharmony_ci			   BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
262962306a36Sopenharmony_ci			   BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
263062306a36Sopenharmony_ci			   MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1));
263162306a36Sopenharmony_ci		/* Thin. */
263262306a36Sopenharmony_ci		tile[13] = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
263362306a36Sopenharmony_ci			   MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
263462306a36Sopenharmony_ci			   PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
263562306a36Sopenharmony_ci			   TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) |
263662306a36Sopenharmony_ci			   NUM_BANKS(ADDR_SURF_16_BANK) |
263762306a36Sopenharmony_ci			   BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
263862306a36Sopenharmony_ci			   BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
263962306a36Sopenharmony_ci			   MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
264062306a36Sopenharmony_ci		/* Thin 8 bpp. */
264162306a36Sopenharmony_ci		tile[14] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
264262306a36Sopenharmony_ci			   MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
264362306a36Sopenharmony_ci			   PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
264462306a36Sopenharmony_ci			   TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
264562306a36Sopenharmony_ci			   NUM_BANKS(ADDR_SURF_16_BANK) |
264662306a36Sopenharmony_ci			   BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
264762306a36Sopenharmony_ci			   BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
264862306a36Sopenharmony_ci			   MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1));
264962306a36Sopenharmony_ci		/* Thin 16 bpp. */
265062306a36Sopenharmony_ci		tile[15] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
265162306a36Sopenharmony_ci			   MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
265262306a36Sopenharmony_ci			   PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
265362306a36Sopenharmony_ci			   TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
265462306a36Sopenharmony_ci			   NUM_BANKS(ADDR_SURF_16_BANK) |
265562306a36Sopenharmony_ci			   BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
265662306a36Sopenharmony_ci			   BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
265762306a36Sopenharmony_ci			   MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1));
265862306a36Sopenharmony_ci		/* Thin 32 bpp. */
265962306a36Sopenharmony_ci		tile[16] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
266062306a36Sopenharmony_ci			   MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
266162306a36Sopenharmony_ci			   PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
266262306a36Sopenharmony_ci			   TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) |
266362306a36Sopenharmony_ci			   NUM_BANKS(ADDR_SURF_16_BANK) |
266462306a36Sopenharmony_ci			   BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
266562306a36Sopenharmony_ci			   BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
266662306a36Sopenharmony_ci			   MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1));
266762306a36Sopenharmony_ci		/* Thin 64 bpp. */
266862306a36Sopenharmony_ci		tile[17] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
266962306a36Sopenharmony_ci			   MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
267062306a36Sopenharmony_ci			   PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
267162306a36Sopenharmony_ci			   TILE_SPLIT(split_equal_to_row_size) |
267262306a36Sopenharmony_ci			   NUM_BANKS(ADDR_SURF_16_BANK) |
267362306a36Sopenharmony_ci			   BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
267462306a36Sopenharmony_ci			   BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
267562306a36Sopenharmony_ci			   MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1));
267662306a36Sopenharmony_ci		/* 8 bpp PRT. */
267762306a36Sopenharmony_ci		tile[21] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
267862306a36Sopenharmony_ci			   MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
267962306a36Sopenharmony_ci			   PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
268062306a36Sopenharmony_ci			   TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
268162306a36Sopenharmony_ci			   NUM_BANKS(ADDR_SURF_16_BANK) |
268262306a36Sopenharmony_ci			   BANK_WIDTH(ADDR_SURF_BANK_WIDTH_2) |
268362306a36Sopenharmony_ci			   BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
268462306a36Sopenharmony_ci			   MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
268562306a36Sopenharmony_ci		/* 16 bpp PRT */
268662306a36Sopenharmony_ci		tile[22] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
268762306a36Sopenharmony_ci			   MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
268862306a36Sopenharmony_ci			   PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
268962306a36Sopenharmony_ci			   TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
269062306a36Sopenharmony_ci			   NUM_BANKS(ADDR_SURF_16_BANK) |
269162306a36Sopenharmony_ci			   BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
269262306a36Sopenharmony_ci			   BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
269362306a36Sopenharmony_ci			   MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4));
269462306a36Sopenharmony_ci		/* 32 bpp PRT */
269562306a36Sopenharmony_ci		tile[23] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
269662306a36Sopenharmony_ci			   MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
269762306a36Sopenharmony_ci			   PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
269862306a36Sopenharmony_ci			   TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
269962306a36Sopenharmony_ci			   NUM_BANKS(ADDR_SURF_16_BANK) |
270062306a36Sopenharmony_ci			   BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
270162306a36Sopenharmony_ci			   BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
270262306a36Sopenharmony_ci			   MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
270362306a36Sopenharmony_ci		/* 64 bpp PRT */
270462306a36Sopenharmony_ci		tile[24] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
270562306a36Sopenharmony_ci			   MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
270662306a36Sopenharmony_ci			   PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
270762306a36Sopenharmony_ci			   TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) |
270862306a36Sopenharmony_ci			   NUM_BANKS(ADDR_SURF_16_BANK) |
270962306a36Sopenharmony_ci			   BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
271062306a36Sopenharmony_ci			   BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
271162306a36Sopenharmony_ci			   MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
271262306a36Sopenharmony_ci		/* 128 bpp PRT */
271362306a36Sopenharmony_ci		tile[25] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
271462306a36Sopenharmony_ci			   MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
271562306a36Sopenharmony_ci			   PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
271662306a36Sopenharmony_ci			   TILE_SPLIT(ADDR_SURF_TILE_SPLIT_1KB) |
271762306a36Sopenharmony_ci			   NUM_BANKS(ADDR_SURF_8_BANK) |
271862306a36Sopenharmony_ci			   BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
271962306a36Sopenharmony_ci			   BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
272062306a36Sopenharmony_ci			   MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1));
272162306a36Sopenharmony_ci
272262306a36Sopenharmony_ci		for (reg_offset = 0; reg_offset < num_tile_mode_states; reg_offset++)
272362306a36Sopenharmony_ci			WREG32(GB_TILE_MODE0 + (reg_offset * 4), tile[reg_offset]);
272462306a36Sopenharmony_ci		break;
272562306a36Sopenharmony_ci
272662306a36Sopenharmony_ci	case CHIP_VERDE:
272762306a36Sopenharmony_ci	case CHIP_OLAND:
272862306a36Sopenharmony_ci	case CHIP_HAINAN:
272962306a36Sopenharmony_ci		/* non-AA compressed depth or any compressed stencil */
273062306a36Sopenharmony_ci		tile[0] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
273162306a36Sopenharmony_ci			   MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
273262306a36Sopenharmony_ci			   PIPE_CONFIG(ADDR_SURF_P4_8x16) |
273362306a36Sopenharmony_ci			   TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) |
273462306a36Sopenharmony_ci			   NUM_BANKS(ADDR_SURF_16_BANK) |
273562306a36Sopenharmony_ci			   BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
273662306a36Sopenharmony_ci			   BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
273762306a36Sopenharmony_ci			   MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4));
273862306a36Sopenharmony_ci		/* 2xAA/4xAA compressed depth only */
273962306a36Sopenharmony_ci		tile[1] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
274062306a36Sopenharmony_ci			   MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
274162306a36Sopenharmony_ci			   PIPE_CONFIG(ADDR_SURF_P4_8x16) |
274262306a36Sopenharmony_ci			   TILE_SPLIT(ADDR_SURF_TILE_SPLIT_128B) |
274362306a36Sopenharmony_ci			   NUM_BANKS(ADDR_SURF_16_BANK) |
274462306a36Sopenharmony_ci			   BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
274562306a36Sopenharmony_ci			   BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
274662306a36Sopenharmony_ci			   MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4));
274762306a36Sopenharmony_ci		/* 8xAA compressed depth only */
274862306a36Sopenharmony_ci		tile[2] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
274962306a36Sopenharmony_ci			   MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
275062306a36Sopenharmony_ci			   PIPE_CONFIG(ADDR_SURF_P4_8x16) |
275162306a36Sopenharmony_ci			   TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
275262306a36Sopenharmony_ci			   NUM_BANKS(ADDR_SURF_16_BANK) |
275362306a36Sopenharmony_ci			   BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
275462306a36Sopenharmony_ci			   BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
275562306a36Sopenharmony_ci			   MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4));
275662306a36Sopenharmony_ci		/* 2xAA/4xAA compressed depth with stencil (for depth buffer) */
275762306a36Sopenharmony_ci		tile[3] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
275862306a36Sopenharmony_ci			   MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
275962306a36Sopenharmony_ci			   PIPE_CONFIG(ADDR_SURF_P4_8x16) |
276062306a36Sopenharmony_ci			   TILE_SPLIT(ADDR_SURF_TILE_SPLIT_128B) |
276162306a36Sopenharmony_ci			   NUM_BANKS(ADDR_SURF_16_BANK) |
276262306a36Sopenharmony_ci			   BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
276362306a36Sopenharmony_ci			   BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
276462306a36Sopenharmony_ci			   MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4));
276562306a36Sopenharmony_ci		/* Maps w/ a dimension less than the 2D macro-tile dimensions (for mipmapped depth textures) */
276662306a36Sopenharmony_ci		tile[4] = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
276762306a36Sopenharmony_ci			   MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
276862306a36Sopenharmony_ci			   PIPE_CONFIG(ADDR_SURF_P4_8x16) |
276962306a36Sopenharmony_ci			   TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) |
277062306a36Sopenharmony_ci			   NUM_BANKS(ADDR_SURF_16_BANK) |
277162306a36Sopenharmony_ci			   BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
277262306a36Sopenharmony_ci			   BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
277362306a36Sopenharmony_ci			   MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
277462306a36Sopenharmony_ci		/* Uncompressed 16bpp depth - and stencil buffer allocated with it */
277562306a36Sopenharmony_ci		tile[5] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
277662306a36Sopenharmony_ci			   MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
277762306a36Sopenharmony_ci			   PIPE_CONFIG(ADDR_SURF_P4_8x16) |
277862306a36Sopenharmony_ci			   TILE_SPLIT(split_equal_to_row_size) |
277962306a36Sopenharmony_ci			   NUM_BANKS(ADDR_SURF_16_BANK) |
278062306a36Sopenharmony_ci			   BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
278162306a36Sopenharmony_ci			   BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
278262306a36Sopenharmony_ci			   MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
278362306a36Sopenharmony_ci		/* Uncompressed 32bpp depth - and stencil buffer allocated with it */
278462306a36Sopenharmony_ci		tile[6] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
278562306a36Sopenharmony_ci			   MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
278662306a36Sopenharmony_ci			   PIPE_CONFIG(ADDR_SURF_P4_8x16) |
278762306a36Sopenharmony_ci			   TILE_SPLIT(split_equal_to_row_size) |
278862306a36Sopenharmony_ci			   NUM_BANKS(ADDR_SURF_16_BANK) |
278962306a36Sopenharmony_ci			   BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
279062306a36Sopenharmony_ci			   BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
279162306a36Sopenharmony_ci			   MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
279262306a36Sopenharmony_ci		/* Uncompressed 8bpp stencil without depth (drivers typically do not use) */
279362306a36Sopenharmony_ci		tile[7] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
279462306a36Sopenharmony_ci			   MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
279562306a36Sopenharmony_ci			   PIPE_CONFIG(ADDR_SURF_P4_8x16) |
279662306a36Sopenharmony_ci			   TILE_SPLIT(split_equal_to_row_size) |
279762306a36Sopenharmony_ci			   NUM_BANKS(ADDR_SURF_16_BANK) |
279862306a36Sopenharmony_ci			   BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
279962306a36Sopenharmony_ci			   BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
280062306a36Sopenharmony_ci			   MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4));
280162306a36Sopenharmony_ci		/* 1D and 1D Array Surfaces */
280262306a36Sopenharmony_ci		tile[8] = (ARRAY_MODE(ARRAY_LINEAR_ALIGNED) |
280362306a36Sopenharmony_ci			   MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) |
280462306a36Sopenharmony_ci			   PIPE_CONFIG(ADDR_SURF_P4_8x16) |
280562306a36Sopenharmony_ci			   TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) |
280662306a36Sopenharmony_ci			   NUM_BANKS(ADDR_SURF_16_BANK) |
280762306a36Sopenharmony_ci			   BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
280862306a36Sopenharmony_ci			   BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
280962306a36Sopenharmony_ci			   MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
281062306a36Sopenharmony_ci		/* Displayable maps. */
281162306a36Sopenharmony_ci		tile[9] = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
281262306a36Sopenharmony_ci			   MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) |
281362306a36Sopenharmony_ci			   PIPE_CONFIG(ADDR_SURF_P4_8x16) |
281462306a36Sopenharmony_ci			   TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) |
281562306a36Sopenharmony_ci			   NUM_BANKS(ADDR_SURF_16_BANK) |
281662306a36Sopenharmony_ci			   BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
281762306a36Sopenharmony_ci			   BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
281862306a36Sopenharmony_ci			   MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
281962306a36Sopenharmony_ci		/* Display 8bpp. */
282062306a36Sopenharmony_ci		tile[10] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
282162306a36Sopenharmony_ci			   MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) |
282262306a36Sopenharmony_ci			   PIPE_CONFIG(ADDR_SURF_P4_8x16) |
282362306a36Sopenharmony_ci			   TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
282462306a36Sopenharmony_ci			   NUM_BANKS(ADDR_SURF_16_BANK) |
282562306a36Sopenharmony_ci			   BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
282662306a36Sopenharmony_ci			   BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
282762306a36Sopenharmony_ci			   MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4));
282862306a36Sopenharmony_ci		/* Display 16bpp. */
282962306a36Sopenharmony_ci		tile[11] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
283062306a36Sopenharmony_ci			   MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) |
283162306a36Sopenharmony_ci			   PIPE_CONFIG(ADDR_SURF_P4_8x16) |
283262306a36Sopenharmony_ci			   TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
283362306a36Sopenharmony_ci			   NUM_BANKS(ADDR_SURF_16_BANK) |
283462306a36Sopenharmony_ci			   BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
283562306a36Sopenharmony_ci			   BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
283662306a36Sopenharmony_ci			   MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
283762306a36Sopenharmony_ci		/* Display 32bpp. */
283862306a36Sopenharmony_ci		tile[12] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
283962306a36Sopenharmony_ci			   MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) |
284062306a36Sopenharmony_ci			   PIPE_CONFIG(ADDR_SURF_P4_8x16) |
284162306a36Sopenharmony_ci			   TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) |
284262306a36Sopenharmony_ci			   NUM_BANKS(ADDR_SURF_16_BANK) |
284362306a36Sopenharmony_ci			   BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
284462306a36Sopenharmony_ci			   BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
284562306a36Sopenharmony_ci			   MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
284662306a36Sopenharmony_ci		/* Thin. */
284762306a36Sopenharmony_ci		tile[13] = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
284862306a36Sopenharmony_ci			   MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
284962306a36Sopenharmony_ci			   PIPE_CONFIG(ADDR_SURF_P4_8x16) |
285062306a36Sopenharmony_ci			   TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) |
285162306a36Sopenharmony_ci			   NUM_BANKS(ADDR_SURF_16_BANK) |
285262306a36Sopenharmony_ci			   BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
285362306a36Sopenharmony_ci			   BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
285462306a36Sopenharmony_ci			   MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
285562306a36Sopenharmony_ci		/* Thin 8 bpp. */
285662306a36Sopenharmony_ci		tile[14] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
285762306a36Sopenharmony_ci			   MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
285862306a36Sopenharmony_ci			   PIPE_CONFIG(ADDR_SURF_P4_8x16) |
285962306a36Sopenharmony_ci			   TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
286062306a36Sopenharmony_ci			   NUM_BANKS(ADDR_SURF_16_BANK) |
286162306a36Sopenharmony_ci			   BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
286262306a36Sopenharmony_ci			   BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
286362306a36Sopenharmony_ci			   MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
286462306a36Sopenharmony_ci		/* Thin 16 bpp. */
286562306a36Sopenharmony_ci		tile[15] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
286662306a36Sopenharmony_ci			   MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
286762306a36Sopenharmony_ci			   PIPE_CONFIG(ADDR_SURF_P4_8x16) |
286862306a36Sopenharmony_ci			   TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
286962306a36Sopenharmony_ci			   NUM_BANKS(ADDR_SURF_16_BANK) |
287062306a36Sopenharmony_ci			   BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
287162306a36Sopenharmony_ci			   BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
287262306a36Sopenharmony_ci			   MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
287362306a36Sopenharmony_ci		/* Thin 32 bpp. */
287462306a36Sopenharmony_ci		tile[16] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
287562306a36Sopenharmony_ci			   MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
287662306a36Sopenharmony_ci			   PIPE_CONFIG(ADDR_SURF_P4_8x16) |
287762306a36Sopenharmony_ci			   TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) |
287862306a36Sopenharmony_ci			   NUM_BANKS(ADDR_SURF_16_BANK) |
287962306a36Sopenharmony_ci			   BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
288062306a36Sopenharmony_ci			   BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
288162306a36Sopenharmony_ci			   MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
288262306a36Sopenharmony_ci		/* Thin 64 bpp. */
288362306a36Sopenharmony_ci		tile[17] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
288462306a36Sopenharmony_ci			   MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
288562306a36Sopenharmony_ci			   PIPE_CONFIG(ADDR_SURF_P4_8x16) |
288662306a36Sopenharmony_ci			   TILE_SPLIT(split_equal_to_row_size) |
288762306a36Sopenharmony_ci			   NUM_BANKS(ADDR_SURF_16_BANK) |
288862306a36Sopenharmony_ci			   BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
288962306a36Sopenharmony_ci			   BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
289062306a36Sopenharmony_ci			   MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
289162306a36Sopenharmony_ci		/* 8 bpp PRT. */
289262306a36Sopenharmony_ci		tile[21] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
289362306a36Sopenharmony_ci			   MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
289462306a36Sopenharmony_ci			   PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
289562306a36Sopenharmony_ci			   TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
289662306a36Sopenharmony_ci			   NUM_BANKS(ADDR_SURF_16_BANK) |
289762306a36Sopenharmony_ci			   BANK_WIDTH(ADDR_SURF_BANK_WIDTH_2) |
289862306a36Sopenharmony_ci			   BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
289962306a36Sopenharmony_ci			   MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
290062306a36Sopenharmony_ci		/* 16 bpp PRT */
290162306a36Sopenharmony_ci		tile[22] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
290262306a36Sopenharmony_ci			   MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
290362306a36Sopenharmony_ci			   PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
290462306a36Sopenharmony_ci			   TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
290562306a36Sopenharmony_ci			   NUM_BANKS(ADDR_SURF_16_BANK) |
290662306a36Sopenharmony_ci			   BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
290762306a36Sopenharmony_ci			   BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
290862306a36Sopenharmony_ci			   MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4));
290962306a36Sopenharmony_ci		/* 32 bpp PRT */
291062306a36Sopenharmony_ci		tile[23] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
291162306a36Sopenharmony_ci			   MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
291262306a36Sopenharmony_ci			   PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
291362306a36Sopenharmony_ci			   TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
291462306a36Sopenharmony_ci			   NUM_BANKS(ADDR_SURF_16_BANK) |
291562306a36Sopenharmony_ci			   BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
291662306a36Sopenharmony_ci			   BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
291762306a36Sopenharmony_ci			   MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
291862306a36Sopenharmony_ci		/* 64 bpp PRT */
291962306a36Sopenharmony_ci		tile[24] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
292062306a36Sopenharmony_ci			   MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
292162306a36Sopenharmony_ci			   PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
292262306a36Sopenharmony_ci			   TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) |
292362306a36Sopenharmony_ci			   NUM_BANKS(ADDR_SURF_16_BANK) |
292462306a36Sopenharmony_ci			   BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
292562306a36Sopenharmony_ci			   BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
292662306a36Sopenharmony_ci			   MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
292762306a36Sopenharmony_ci		/* 128 bpp PRT */
292862306a36Sopenharmony_ci		tile[25] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
292962306a36Sopenharmony_ci			   MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
293062306a36Sopenharmony_ci			   PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
293162306a36Sopenharmony_ci			   TILE_SPLIT(ADDR_SURF_TILE_SPLIT_1KB) |
293262306a36Sopenharmony_ci			   NUM_BANKS(ADDR_SURF_8_BANK) |
293362306a36Sopenharmony_ci			   BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
293462306a36Sopenharmony_ci			   BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
293562306a36Sopenharmony_ci			   MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1));
293662306a36Sopenharmony_ci
293762306a36Sopenharmony_ci		for (reg_offset = 0; reg_offset < num_tile_mode_states; reg_offset++)
293862306a36Sopenharmony_ci			WREG32(GB_TILE_MODE0 + (reg_offset * 4), tile[reg_offset]);
293962306a36Sopenharmony_ci		break;
294062306a36Sopenharmony_ci
294162306a36Sopenharmony_ci	default:
294262306a36Sopenharmony_ci		DRM_ERROR("unknown asic: 0x%x\n", rdev->family);
294362306a36Sopenharmony_ci	}
294462306a36Sopenharmony_ci}
294562306a36Sopenharmony_ci
294662306a36Sopenharmony_cistatic void si_select_se_sh(struct radeon_device *rdev,
294762306a36Sopenharmony_ci			    u32 se_num, u32 sh_num)
294862306a36Sopenharmony_ci{
294962306a36Sopenharmony_ci	u32 data = INSTANCE_BROADCAST_WRITES;
295062306a36Sopenharmony_ci
295162306a36Sopenharmony_ci	if ((se_num == 0xffffffff) && (sh_num == 0xffffffff))
295262306a36Sopenharmony_ci		data |= SH_BROADCAST_WRITES | SE_BROADCAST_WRITES;
295362306a36Sopenharmony_ci	else if (se_num == 0xffffffff)
295462306a36Sopenharmony_ci		data |= SE_BROADCAST_WRITES | SH_INDEX(sh_num);
295562306a36Sopenharmony_ci	else if (sh_num == 0xffffffff)
295662306a36Sopenharmony_ci		data |= SH_BROADCAST_WRITES | SE_INDEX(se_num);
295762306a36Sopenharmony_ci	else
295862306a36Sopenharmony_ci		data |= SH_INDEX(sh_num) | SE_INDEX(se_num);
295962306a36Sopenharmony_ci	WREG32(GRBM_GFX_INDEX, data);
296062306a36Sopenharmony_ci}
296162306a36Sopenharmony_ci
296262306a36Sopenharmony_cistatic u32 si_create_bitmask(u32 bit_width)
296362306a36Sopenharmony_ci{
296462306a36Sopenharmony_ci	u32 i, mask = 0;
296562306a36Sopenharmony_ci
296662306a36Sopenharmony_ci	for (i = 0; i < bit_width; i++) {
296762306a36Sopenharmony_ci		mask <<= 1;
296862306a36Sopenharmony_ci		mask |= 1;
296962306a36Sopenharmony_ci	}
297062306a36Sopenharmony_ci	return mask;
297162306a36Sopenharmony_ci}
297262306a36Sopenharmony_ci
297362306a36Sopenharmony_cistatic u32 si_get_cu_enabled(struct radeon_device *rdev, u32 cu_per_sh)
297462306a36Sopenharmony_ci{
297562306a36Sopenharmony_ci	u32 data, mask;
297662306a36Sopenharmony_ci
297762306a36Sopenharmony_ci	data = RREG32(CC_GC_SHADER_ARRAY_CONFIG);
297862306a36Sopenharmony_ci	if (data & 1)
297962306a36Sopenharmony_ci		data &= INACTIVE_CUS_MASK;
298062306a36Sopenharmony_ci	else
298162306a36Sopenharmony_ci		data = 0;
298262306a36Sopenharmony_ci	data |= RREG32(GC_USER_SHADER_ARRAY_CONFIG);
298362306a36Sopenharmony_ci
298462306a36Sopenharmony_ci	data >>= INACTIVE_CUS_SHIFT;
298562306a36Sopenharmony_ci
298662306a36Sopenharmony_ci	mask = si_create_bitmask(cu_per_sh);
298762306a36Sopenharmony_ci
298862306a36Sopenharmony_ci	return ~data & mask;
298962306a36Sopenharmony_ci}
299062306a36Sopenharmony_ci
299162306a36Sopenharmony_cistatic void si_setup_spi(struct radeon_device *rdev,
299262306a36Sopenharmony_ci			 u32 se_num, u32 sh_per_se,
299362306a36Sopenharmony_ci			 u32 cu_per_sh)
299462306a36Sopenharmony_ci{
299562306a36Sopenharmony_ci	int i, j, k;
299662306a36Sopenharmony_ci	u32 data, mask, active_cu;
299762306a36Sopenharmony_ci
299862306a36Sopenharmony_ci	for (i = 0; i < se_num; i++) {
299962306a36Sopenharmony_ci		for (j = 0; j < sh_per_se; j++) {
300062306a36Sopenharmony_ci			si_select_se_sh(rdev, i, j);
300162306a36Sopenharmony_ci			data = RREG32(SPI_STATIC_THREAD_MGMT_3);
300262306a36Sopenharmony_ci			active_cu = si_get_cu_enabled(rdev, cu_per_sh);
300362306a36Sopenharmony_ci
300462306a36Sopenharmony_ci			mask = 1;
300562306a36Sopenharmony_ci			for (k = 0; k < 16; k++) {
300662306a36Sopenharmony_ci				mask <<= k;
300762306a36Sopenharmony_ci				if (active_cu & mask) {
300862306a36Sopenharmony_ci					data &= ~mask;
300962306a36Sopenharmony_ci					WREG32(SPI_STATIC_THREAD_MGMT_3, data);
301062306a36Sopenharmony_ci					break;
301162306a36Sopenharmony_ci				}
301262306a36Sopenharmony_ci			}
301362306a36Sopenharmony_ci		}
301462306a36Sopenharmony_ci	}
301562306a36Sopenharmony_ci	si_select_se_sh(rdev, 0xffffffff, 0xffffffff);
301662306a36Sopenharmony_ci}
301762306a36Sopenharmony_ci
301862306a36Sopenharmony_cistatic u32 si_get_rb_disabled(struct radeon_device *rdev,
301962306a36Sopenharmony_ci			      u32 max_rb_num_per_se,
302062306a36Sopenharmony_ci			      u32 sh_per_se)
302162306a36Sopenharmony_ci{
302262306a36Sopenharmony_ci	u32 data, mask;
302362306a36Sopenharmony_ci
302462306a36Sopenharmony_ci	data = RREG32(CC_RB_BACKEND_DISABLE);
302562306a36Sopenharmony_ci	if (data & 1)
302662306a36Sopenharmony_ci		data &= BACKEND_DISABLE_MASK;
302762306a36Sopenharmony_ci	else
302862306a36Sopenharmony_ci		data = 0;
302962306a36Sopenharmony_ci	data |= RREG32(GC_USER_RB_BACKEND_DISABLE);
303062306a36Sopenharmony_ci
303162306a36Sopenharmony_ci	data >>= BACKEND_DISABLE_SHIFT;
303262306a36Sopenharmony_ci
303362306a36Sopenharmony_ci	mask = si_create_bitmask(max_rb_num_per_se / sh_per_se);
303462306a36Sopenharmony_ci
303562306a36Sopenharmony_ci	return data & mask;
303662306a36Sopenharmony_ci}
303762306a36Sopenharmony_ci
303862306a36Sopenharmony_cistatic void si_setup_rb(struct radeon_device *rdev,
303962306a36Sopenharmony_ci			u32 se_num, u32 sh_per_se,
304062306a36Sopenharmony_ci			u32 max_rb_num_per_se)
304162306a36Sopenharmony_ci{
304262306a36Sopenharmony_ci	int i, j;
304362306a36Sopenharmony_ci	u32 data, mask;
304462306a36Sopenharmony_ci	u32 disabled_rbs = 0;
304562306a36Sopenharmony_ci	u32 enabled_rbs = 0;
304662306a36Sopenharmony_ci
304762306a36Sopenharmony_ci	for (i = 0; i < se_num; i++) {
304862306a36Sopenharmony_ci		for (j = 0; j < sh_per_se; j++) {
304962306a36Sopenharmony_ci			si_select_se_sh(rdev, i, j);
305062306a36Sopenharmony_ci			data = si_get_rb_disabled(rdev, max_rb_num_per_se, sh_per_se);
305162306a36Sopenharmony_ci			disabled_rbs |= data << ((i * sh_per_se + j) * TAHITI_RB_BITMAP_WIDTH_PER_SH);
305262306a36Sopenharmony_ci		}
305362306a36Sopenharmony_ci	}
305462306a36Sopenharmony_ci	si_select_se_sh(rdev, 0xffffffff, 0xffffffff);
305562306a36Sopenharmony_ci
305662306a36Sopenharmony_ci	mask = 1;
305762306a36Sopenharmony_ci	for (i = 0; i < max_rb_num_per_se * se_num; i++) {
305862306a36Sopenharmony_ci		if (!(disabled_rbs & mask))
305962306a36Sopenharmony_ci			enabled_rbs |= mask;
306062306a36Sopenharmony_ci		mask <<= 1;
306162306a36Sopenharmony_ci	}
306262306a36Sopenharmony_ci
306362306a36Sopenharmony_ci	rdev->config.si.backend_enable_mask = enabled_rbs;
306462306a36Sopenharmony_ci
306562306a36Sopenharmony_ci	for (i = 0; i < se_num; i++) {
306662306a36Sopenharmony_ci		si_select_se_sh(rdev, i, 0xffffffff);
306762306a36Sopenharmony_ci		data = 0;
306862306a36Sopenharmony_ci		for (j = 0; j < sh_per_se; j++) {
306962306a36Sopenharmony_ci			switch (enabled_rbs & 3) {
307062306a36Sopenharmony_ci			case 1:
307162306a36Sopenharmony_ci				data |= (RASTER_CONFIG_RB_MAP_0 << (i * sh_per_se + j) * 2);
307262306a36Sopenharmony_ci				break;
307362306a36Sopenharmony_ci			case 2:
307462306a36Sopenharmony_ci				data |= (RASTER_CONFIG_RB_MAP_3 << (i * sh_per_se + j) * 2);
307562306a36Sopenharmony_ci				break;
307662306a36Sopenharmony_ci			case 3:
307762306a36Sopenharmony_ci			default:
307862306a36Sopenharmony_ci				data |= (RASTER_CONFIG_RB_MAP_2 << (i * sh_per_se + j) * 2);
307962306a36Sopenharmony_ci				break;
308062306a36Sopenharmony_ci			}
308162306a36Sopenharmony_ci			enabled_rbs >>= 2;
308262306a36Sopenharmony_ci		}
308362306a36Sopenharmony_ci		WREG32(PA_SC_RASTER_CONFIG, data);
308462306a36Sopenharmony_ci	}
308562306a36Sopenharmony_ci	si_select_se_sh(rdev, 0xffffffff, 0xffffffff);
308662306a36Sopenharmony_ci}
308762306a36Sopenharmony_ci
308862306a36Sopenharmony_cistatic void si_gpu_init(struct radeon_device *rdev)
308962306a36Sopenharmony_ci{
309062306a36Sopenharmony_ci	u32 gb_addr_config = 0;
309162306a36Sopenharmony_ci	u32 mc_arb_ramcfg;
309262306a36Sopenharmony_ci	u32 sx_debug_1;
309362306a36Sopenharmony_ci	u32 hdp_host_path_cntl;
309462306a36Sopenharmony_ci	u32 tmp;
309562306a36Sopenharmony_ci	int i, j;
309662306a36Sopenharmony_ci
309762306a36Sopenharmony_ci	switch (rdev->family) {
309862306a36Sopenharmony_ci	case CHIP_TAHITI:
309962306a36Sopenharmony_ci		rdev->config.si.max_shader_engines = 2;
310062306a36Sopenharmony_ci		rdev->config.si.max_tile_pipes = 12;
310162306a36Sopenharmony_ci		rdev->config.si.max_cu_per_sh = 8;
310262306a36Sopenharmony_ci		rdev->config.si.max_sh_per_se = 2;
310362306a36Sopenharmony_ci		rdev->config.si.max_backends_per_se = 4;
310462306a36Sopenharmony_ci		rdev->config.si.max_texture_channel_caches = 12;
310562306a36Sopenharmony_ci		rdev->config.si.max_gprs = 256;
310662306a36Sopenharmony_ci		rdev->config.si.max_gs_threads = 32;
310762306a36Sopenharmony_ci		rdev->config.si.max_hw_contexts = 8;
310862306a36Sopenharmony_ci
310962306a36Sopenharmony_ci		rdev->config.si.sc_prim_fifo_size_frontend = 0x20;
311062306a36Sopenharmony_ci		rdev->config.si.sc_prim_fifo_size_backend = 0x100;
311162306a36Sopenharmony_ci		rdev->config.si.sc_hiz_tile_fifo_size = 0x30;
311262306a36Sopenharmony_ci		rdev->config.si.sc_earlyz_tile_fifo_size = 0x130;
311362306a36Sopenharmony_ci		gb_addr_config = TAHITI_GB_ADDR_CONFIG_GOLDEN;
311462306a36Sopenharmony_ci		break;
311562306a36Sopenharmony_ci	case CHIP_PITCAIRN:
311662306a36Sopenharmony_ci		rdev->config.si.max_shader_engines = 2;
311762306a36Sopenharmony_ci		rdev->config.si.max_tile_pipes = 8;
311862306a36Sopenharmony_ci		rdev->config.si.max_cu_per_sh = 5;
311962306a36Sopenharmony_ci		rdev->config.si.max_sh_per_se = 2;
312062306a36Sopenharmony_ci		rdev->config.si.max_backends_per_se = 4;
312162306a36Sopenharmony_ci		rdev->config.si.max_texture_channel_caches = 8;
312262306a36Sopenharmony_ci		rdev->config.si.max_gprs = 256;
312362306a36Sopenharmony_ci		rdev->config.si.max_gs_threads = 32;
312462306a36Sopenharmony_ci		rdev->config.si.max_hw_contexts = 8;
312562306a36Sopenharmony_ci
312662306a36Sopenharmony_ci		rdev->config.si.sc_prim_fifo_size_frontend = 0x20;
312762306a36Sopenharmony_ci		rdev->config.si.sc_prim_fifo_size_backend = 0x100;
312862306a36Sopenharmony_ci		rdev->config.si.sc_hiz_tile_fifo_size = 0x30;
312962306a36Sopenharmony_ci		rdev->config.si.sc_earlyz_tile_fifo_size = 0x130;
313062306a36Sopenharmony_ci		gb_addr_config = TAHITI_GB_ADDR_CONFIG_GOLDEN;
313162306a36Sopenharmony_ci		break;
313262306a36Sopenharmony_ci	case CHIP_VERDE:
313362306a36Sopenharmony_ci	default:
313462306a36Sopenharmony_ci		rdev->config.si.max_shader_engines = 1;
313562306a36Sopenharmony_ci		rdev->config.si.max_tile_pipes = 4;
313662306a36Sopenharmony_ci		rdev->config.si.max_cu_per_sh = 5;
313762306a36Sopenharmony_ci		rdev->config.si.max_sh_per_se = 2;
313862306a36Sopenharmony_ci		rdev->config.si.max_backends_per_se = 4;
313962306a36Sopenharmony_ci		rdev->config.si.max_texture_channel_caches = 4;
314062306a36Sopenharmony_ci		rdev->config.si.max_gprs = 256;
314162306a36Sopenharmony_ci		rdev->config.si.max_gs_threads = 32;
314262306a36Sopenharmony_ci		rdev->config.si.max_hw_contexts = 8;
314362306a36Sopenharmony_ci
314462306a36Sopenharmony_ci		rdev->config.si.sc_prim_fifo_size_frontend = 0x20;
314562306a36Sopenharmony_ci		rdev->config.si.sc_prim_fifo_size_backend = 0x40;
314662306a36Sopenharmony_ci		rdev->config.si.sc_hiz_tile_fifo_size = 0x30;
314762306a36Sopenharmony_ci		rdev->config.si.sc_earlyz_tile_fifo_size = 0x130;
314862306a36Sopenharmony_ci		gb_addr_config = VERDE_GB_ADDR_CONFIG_GOLDEN;
314962306a36Sopenharmony_ci		break;
315062306a36Sopenharmony_ci	case CHIP_OLAND:
315162306a36Sopenharmony_ci		rdev->config.si.max_shader_engines = 1;
315262306a36Sopenharmony_ci		rdev->config.si.max_tile_pipes = 4;
315362306a36Sopenharmony_ci		rdev->config.si.max_cu_per_sh = 6;
315462306a36Sopenharmony_ci		rdev->config.si.max_sh_per_se = 1;
315562306a36Sopenharmony_ci		rdev->config.si.max_backends_per_se = 2;
315662306a36Sopenharmony_ci		rdev->config.si.max_texture_channel_caches = 4;
315762306a36Sopenharmony_ci		rdev->config.si.max_gprs = 256;
315862306a36Sopenharmony_ci		rdev->config.si.max_gs_threads = 16;
315962306a36Sopenharmony_ci		rdev->config.si.max_hw_contexts = 8;
316062306a36Sopenharmony_ci
316162306a36Sopenharmony_ci		rdev->config.si.sc_prim_fifo_size_frontend = 0x20;
316262306a36Sopenharmony_ci		rdev->config.si.sc_prim_fifo_size_backend = 0x40;
316362306a36Sopenharmony_ci		rdev->config.si.sc_hiz_tile_fifo_size = 0x30;
316462306a36Sopenharmony_ci		rdev->config.si.sc_earlyz_tile_fifo_size = 0x130;
316562306a36Sopenharmony_ci		gb_addr_config = VERDE_GB_ADDR_CONFIG_GOLDEN;
316662306a36Sopenharmony_ci		break;
316762306a36Sopenharmony_ci	case CHIP_HAINAN:
316862306a36Sopenharmony_ci		rdev->config.si.max_shader_engines = 1;
316962306a36Sopenharmony_ci		rdev->config.si.max_tile_pipes = 4;
317062306a36Sopenharmony_ci		rdev->config.si.max_cu_per_sh = 5;
317162306a36Sopenharmony_ci		rdev->config.si.max_sh_per_se = 1;
317262306a36Sopenharmony_ci		rdev->config.si.max_backends_per_se = 1;
317362306a36Sopenharmony_ci		rdev->config.si.max_texture_channel_caches = 2;
317462306a36Sopenharmony_ci		rdev->config.si.max_gprs = 256;
317562306a36Sopenharmony_ci		rdev->config.si.max_gs_threads = 16;
317662306a36Sopenharmony_ci		rdev->config.si.max_hw_contexts = 8;
317762306a36Sopenharmony_ci
317862306a36Sopenharmony_ci		rdev->config.si.sc_prim_fifo_size_frontend = 0x20;
317962306a36Sopenharmony_ci		rdev->config.si.sc_prim_fifo_size_backend = 0x40;
318062306a36Sopenharmony_ci		rdev->config.si.sc_hiz_tile_fifo_size = 0x30;
318162306a36Sopenharmony_ci		rdev->config.si.sc_earlyz_tile_fifo_size = 0x130;
318262306a36Sopenharmony_ci		gb_addr_config = HAINAN_GB_ADDR_CONFIG_GOLDEN;
318362306a36Sopenharmony_ci		break;
318462306a36Sopenharmony_ci	}
318562306a36Sopenharmony_ci
318662306a36Sopenharmony_ci	/* Initialize HDP */
318762306a36Sopenharmony_ci	for (i = 0, j = 0; i < 32; i++, j += 0x18) {
318862306a36Sopenharmony_ci		WREG32((0x2c14 + j), 0x00000000);
318962306a36Sopenharmony_ci		WREG32((0x2c18 + j), 0x00000000);
319062306a36Sopenharmony_ci		WREG32((0x2c1c + j), 0x00000000);
319162306a36Sopenharmony_ci		WREG32((0x2c20 + j), 0x00000000);
319262306a36Sopenharmony_ci		WREG32((0x2c24 + j), 0x00000000);
319362306a36Sopenharmony_ci	}
319462306a36Sopenharmony_ci
319562306a36Sopenharmony_ci	WREG32(GRBM_CNTL, GRBM_READ_TIMEOUT(0xff));
319662306a36Sopenharmony_ci	WREG32(SRBM_INT_CNTL, 1);
319762306a36Sopenharmony_ci	WREG32(SRBM_INT_ACK, 1);
319862306a36Sopenharmony_ci
319962306a36Sopenharmony_ci	evergreen_fix_pci_max_read_req_size(rdev);
320062306a36Sopenharmony_ci
320162306a36Sopenharmony_ci	WREG32(BIF_FB_EN, FB_READ_EN | FB_WRITE_EN);
320262306a36Sopenharmony_ci
320362306a36Sopenharmony_ci	RREG32(MC_SHARED_CHMAP);
320462306a36Sopenharmony_ci	mc_arb_ramcfg = RREG32(MC_ARB_RAMCFG);
320562306a36Sopenharmony_ci
320662306a36Sopenharmony_ci	rdev->config.si.num_tile_pipes = rdev->config.si.max_tile_pipes;
320762306a36Sopenharmony_ci	rdev->config.si.mem_max_burst_length_bytes = 256;
320862306a36Sopenharmony_ci	tmp = (mc_arb_ramcfg & NOOFCOLS_MASK) >> NOOFCOLS_SHIFT;
320962306a36Sopenharmony_ci	rdev->config.si.mem_row_size_in_kb = (4 * (1 << (8 + tmp))) / 1024;
321062306a36Sopenharmony_ci	if (rdev->config.si.mem_row_size_in_kb > 4)
321162306a36Sopenharmony_ci		rdev->config.si.mem_row_size_in_kb = 4;
321262306a36Sopenharmony_ci	/* XXX use MC settings? */
321362306a36Sopenharmony_ci	rdev->config.si.shader_engine_tile_size = 32;
321462306a36Sopenharmony_ci	rdev->config.si.num_gpus = 1;
321562306a36Sopenharmony_ci	rdev->config.si.multi_gpu_tile_size = 64;
321662306a36Sopenharmony_ci
321762306a36Sopenharmony_ci	/* fix up row size */
321862306a36Sopenharmony_ci	gb_addr_config &= ~ROW_SIZE_MASK;
321962306a36Sopenharmony_ci	switch (rdev->config.si.mem_row_size_in_kb) {
322062306a36Sopenharmony_ci	case 1:
322162306a36Sopenharmony_ci	default:
322262306a36Sopenharmony_ci		gb_addr_config |= ROW_SIZE(0);
322362306a36Sopenharmony_ci		break;
322462306a36Sopenharmony_ci	case 2:
322562306a36Sopenharmony_ci		gb_addr_config |= ROW_SIZE(1);
322662306a36Sopenharmony_ci		break;
322762306a36Sopenharmony_ci	case 4:
322862306a36Sopenharmony_ci		gb_addr_config |= ROW_SIZE(2);
322962306a36Sopenharmony_ci		break;
323062306a36Sopenharmony_ci	}
323162306a36Sopenharmony_ci
323262306a36Sopenharmony_ci	/* setup tiling info dword.  gb_addr_config is not adequate since it does
323362306a36Sopenharmony_ci	 * not have bank info, so create a custom tiling dword.
323462306a36Sopenharmony_ci	 * bits 3:0   num_pipes
323562306a36Sopenharmony_ci	 * bits 7:4   num_banks
323662306a36Sopenharmony_ci	 * bits 11:8  group_size
323762306a36Sopenharmony_ci	 * bits 15:12 row_size
323862306a36Sopenharmony_ci	 */
323962306a36Sopenharmony_ci	rdev->config.si.tile_config = 0;
324062306a36Sopenharmony_ci	switch (rdev->config.si.num_tile_pipes) {
324162306a36Sopenharmony_ci	case 1:
324262306a36Sopenharmony_ci		rdev->config.si.tile_config |= (0 << 0);
324362306a36Sopenharmony_ci		break;
324462306a36Sopenharmony_ci	case 2:
324562306a36Sopenharmony_ci		rdev->config.si.tile_config |= (1 << 0);
324662306a36Sopenharmony_ci		break;
324762306a36Sopenharmony_ci	case 4:
324862306a36Sopenharmony_ci		rdev->config.si.tile_config |= (2 << 0);
324962306a36Sopenharmony_ci		break;
325062306a36Sopenharmony_ci	case 8:
325162306a36Sopenharmony_ci	default:
325262306a36Sopenharmony_ci		/* XXX what about 12? */
325362306a36Sopenharmony_ci		rdev->config.si.tile_config |= (3 << 0);
325462306a36Sopenharmony_ci		break;
325562306a36Sopenharmony_ci	}
325662306a36Sopenharmony_ci	switch ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) {
325762306a36Sopenharmony_ci	case 0: /* four banks */
325862306a36Sopenharmony_ci		rdev->config.si.tile_config |= 0 << 4;
325962306a36Sopenharmony_ci		break;
326062306a36Sopenharmony_ci	case 1: /* eight banks */
326162306a36Sopenharmony_ci		rdev->config.si.tile_config |= 1 << 4;
326262306a36Sopenharmony_ci		break;
326362306a36Sopenharmony_ci	case 2: /* sixteen banks */
326462306a36Sopenharmony_ci	default:
326562306a36Sopenharmony_ci		rdev->config.si.tile_config |= 2 << 4;
326662306a36Sopenharmony_ci		break;
326762306a36Sopenharmony_ci	}
326862306a36Sopenharmony_ci	rdev->config.si.tile_config |=
326962306a36Sopenharmony_ci		((gb_addr_config & PIPE_INTERLEAVE_SIZE_MASK) >> PIPE_INTERLEAVE_SIZE_SHIFT) << 8;
327062306a36Sopenharmony_ci	rdev->config.si.tile_config |=
327162306a36Sopenharmony_ci		((gb_addr_config & ROW_SIZE_MASK) >> ROW_SIZE_SHIFT) << 12;
327262306a36Sopenharmony_ci
327362306a36Sopenharmony_ci	WREG32(GB_ADDR_CONFIG, gb_addr_config);
327462306a36Sopenharmony_ci	WREG32(DMIF_ADDR_CONFIG, gb_addr_config);
327562306a36Sopenharmony_ci	WREG32(DMIF_ADDR_CALC, gb_addr_config);
327662306a36Sopenharmony_ci	WREG32(HDP_ADDR_CONFIG, gb_addr_config);
327762306a36Sopenharmony_ci	WREG32(DMA_TILING_CONFIG + DMA0_REGISTER_OFFSET, gb_addr_config);
327862306a36Sopenharmony_ci	WREG32(DMA_TILING_CONFIG + DMA1_REGISTER_OFFSET, gb_addr_config);
327962306a36Sopenharmony_ci	if (rdev->has_uvd) {
328062306a36Sopenharmony_ci		WREG32(UVD_UDEC_ADDR_CONFIG, gb_addr_config);
328162306a36Sopenharmony_ci		WREG32(UVD_UDEC_DB_ADDR_CONFIG, gb_addr_config);
328262306a36Sopenharmony_ci		WREG32(UVD_UDEC_DBW_ADDR_CONFIG, gb_addr_config);
328362306a36Sopenharmony_ci	}
328462306a36Sopenharmony_ci
328562306a36Sopenharmony_ci	si_tiling_mode_table_init(rdev);
328662306a36Sopenharmony_ci
328762306a36Sopenharmony_ci	si_setup_rb(rdev, rdev->config.si.max_shader_engines,
328862306a36Sopenharmony_ci		    rdev->config.si.max_sh_per_se,
328962306a36Sopenharmony_ci		    rdev->config.si.max_backends_per_se);
329062306a36Sopenharmony_ci
329162306a36Sopenharmony_ci	si_setup_spi(rdev, rdev->config.si.max_shader_engines,
329262306a36Sopenharmony_ci		     rdev->config.si.max_sh_per_se,
329362306a36Sopenharmony_ci		     rdev->config.si.max_cu_per_sh);
329462306a36Sopenharmony_ci
329562306a36Sopenharmony_ci	rdev->config.si.active_cus = 0;
329662306a36Sopenharmony_ci	for (i = 0; i < rdev->config.si.max_shader_engines; i++) {
329762306a36Sopenharmony_ci		for (j = 0; j < rdev->config.si.max_sh_per_se; j++) {
329862306a36Sopenharmony_ci			rdev->config.si.active_cus +=
329962306a36Sopenharmony_ci				hweight32(si_get_cu_active_bitmap(rdev, i, j));
330062306a36Sopenharmony_ci		}
330162306a36Sopenharmony_ci	}
330262306a36Sopenharmony_ci
330362306a36Sopenharmony_ci	/* set HW defaults for 3D engine */
330462306a36Sopenharmony_ci	WREG32(CP_QUEUE_THRESHOLDS, (ROQ_IB1_START(0x16) |
330562306a36Sopenharmony_ci				     ROQ_IB2_START(0x2b)));
330662306a36Sopenharmony_ci	WREG32(CP_MEQ_THRESHOLDS, MEQ1_START(0x30) | MEQ2_START(0x60));
330762306a36Sopenharmony_ci
330862306a36Sopenharmony_ci	sx_debug_1 = RREG32(SX_DEBUG_1);
330962306a36Sopenharmony_ci	WREG32(SX_DEBUG_1, sx_debug_1);
331062306a36Sopenharmony_ci
331162306a36Sopenharmony_ci	WREG32(SPI_CONFIG_CNTL_1, VTX_DONE_DELAY(4));
331262306a36Sopenharmony_ci
331362306a36Sopenharmony_ci	WREG32(PA_SC_FIFO_SIZE, (SC_FRONTEND_PRIM_FIFO_SIZE(rdev->config.si.sc_prim_fifo_size_frontend) |
331462306a36Sopenharmony_ci				 SC_BACKEND_PRIM_FIFO_SIZE(rdev->config.si.sc_prim_fifo_size_backend) |
331562306a36Sopenharmony_ci				 SC_HIZ_TILE_FIFO_SIZE(rdev->config.si.sc_hiz_tile_fifo_size) |
331662306a36Sopenharmony_ci				 SC_EARLYZ_TILE_FIFO_SIZE(rdev->config.si.sc_earlyz_tile_fifo_size)));
331762306a36Sopenharmony_ci
331862306a36Sopenharmony_ci	WREG32(VGT_NUM_INSTANCES, 1);
331962306a36Sopenharmony_ci
332062306a36Sopenharmony_ci	WREG32(CP_PERFMON_CNTL, 0);
332162306a36Sopenharmony_ci
332262306a36Sopenharmony_ci	WREG32(SQ_CONFIG, 0);
332362306a36Sopenharmony_ci
332462306a36Sopenharmony_ci	WREG32(PA_SC_FORCE_EOV_MAX_CNTS, (FORCE_EOV_MAX_CLK_CNT(4095) |
332562306a36Sopenharmony_ci					  FORCE_EOV_MAX_REZ_CNT(255)));
332662306a36Sopenharmony_ci
332762306a36Sopenharmony_ci	WREG32(VGT_CACHE_INVALIDATION, CACHE_INVALIDATION(VC_AND_TC) |
332862306a36Sopenharmony_ci	       AUTO_INVLD_EN(ES_AND_GS_AUTO));
332962306a36Sopenharmony_ci
333062306a36Sopenharmony_ci	WREG32(VGT_GS_VERTEX_REUSE, 16);
333162306a36Sopenharmony_ci	WREG32(PA_SC_LINE_STIPPLE_STATE, 0);
333262306a36Sopenharmony_ci
333362306a36Sopenharmony_ci	WREG32(CB_PERFCOUNTER0_SELECT0, 0);
333462306a36Sopenharmony_ci	WREG32(CB_PERFCOUNTER0_SELECT1, 0);
333562306a36Sopenharmony_ci	WREG32(CB_PERFCOUNTER1_SELECT0, 0);
333662306a36Sopenharmony_ci	WREG32(CB_PERFCOUNTER1_SELECT1, 0);
333762306a36Sopenharmony_ci	WREG32(CB_PERFCOUNTER2_SELECT0, 0);
333862306a36Sopenharmony_ci	WREG32(CB_PERFCOUNTER2_SELECT1, 0);
333962306a36Sopenharmony_ci	WREG32(CB_PERFCOUNTER3_SELECT0, 0);
334062306a36Sopenharmony_ci	WREG32(CB_PERFCOUNTER3_SELECT1, 0);
334162306a36Sopenharmony_ci
334262306a36Sopenharmony_ci	tmp = RREG32(HDP_MISC_CNTL);
334362306a36Sopenharmony_ci	tmp |= HDP_FLUSH_INVALIDATE_CACHE;
334462306a36Sopenharmony_ci	WREG32(HDP_MISC_CNTL, tmp);
334562306a36Sopenharmony_ci
334662306a36Sopenharmony_ci	hdp_host_path_cntl = RREG32(HDP_HOST_PATH_CNTL);
334762306a36Sopenharmony_ci	WREG32(HDP_HOST_PATH_CNTL, hdp_host_path_cntl);
334862306a36Sopenharmony_ci
334962306a36Sopenharmony_ci	WREG32(PA_CL_ENHANCE, CLIP_VTX_REORDER_ENA | NUM_CLIP_SEQ(3));
335062306a36Sopenharmony_ci
335162306a36Sopenharmony_ci	udelay(50);
335262306a36Sopenharmony_ci}
335362306a36Sopenharmony_ci
335462306a36Sopenharmony_ci/*
335562306a36Sopenharmony_ci * GPU scratch registers helpers function.
335662306a36Sopenharmony_ci */
335762306a36Sopenharmony_cistatic void si_scratch_init(struct radeon_device *rdev)
335862306a36Sopenharmony_ci{
335962306a36Sopenharmony_ci	int i;
336062306a36Sopenharmony_ci
336162306a36Sopenharmony_ci	rdev->scratch.num_reg = 7;
336262306a36Sopenharmony_ci	rdev->scratch.reg_base = SCRATCH_REG0;
336362306a36Sopenharmony_ci	for (i = 0; i < rdev->scratch.num_reg; i++) {
336462306a36Sopenharmony_ci		rdev->scratch.free[i] = true;
336562306a36Sopenharmony_ci		rdev->scratch.reg[i] = rdev->scratch.reg_base + (i * 4);
336662306a36Sopenharmony_ci	}
336762306a36Sopenharmony_ci}
336862306a36Sopenharmony_ci
336962306a36Sopenharmony_civoid si_fence_ring_emit(struct radeon_device *rdev,
337062306a36Sopenharmony_ci			struct radeon_fence *fence)
337162306a36Sopenharmony_ci{
337262306a36Sopenharmony_ci	struct radeon_ring *ring = &rdev->ring[fence->ring];
337362306a36Sopenharmony_ci	u64 addr = rdev->fence_drv[fence->ring].gpu_addr;
337462306a36Sopenharmony_ci
337562306a36Sopenharmony_ci	/* flush read cache over gart */
337662306a36Sopenharmony_ci	radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1));
337762306a36Sopenharmony_ci	radeon_ring_write(ring, (CP_COHER_CNTL2 - PACKET3_SET_CONFIG_REG_START) >> 2);
337862306a36Sopenharmony_ci	radeon_ring_write(ring, 0);
337962306a36Sopenharmony_ci	radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3));
338062306a36Sopenharmony_ci	radeon_ring_write(ring, PACKET3_TCL1_ACTION_ENA |
338162306a36Sopenharmony_ci			  PACKET3_TC_ACTION_ENA |
338262306a36Sopenharmony_ci			  PACKET3_SH_KCACHE_ACTION_ENA |
338362306a36Sopenharmony_ci			  PACKET3_SH_ICACHE_ACTION_ENA);
338462306a36Sopenharmony_ci	radeon_ring_write(ring, 0xFFFFFFFF);
338562306a36Sopenharmony_ci	radeon_ring_write(ring, 0);
338662306a36Sopenharmony_ci	radeon_ring_write(ring, 10); /* poll interval */
338762306a36Sopenharmony_ci	/* EVENT_WRITE_EOP - flush caches, send int */
338862306a36Sopenharmony_ci	radeon_ring_write(ring, PACKET3(PACKET3_EVENT_WRITE_EOP, 4));
338962306a36Sopenharmony_ci	radeon_ring_write(ring, EVENT_TYPE(CACHE_FLUSH_AND_INV_TS_EVENT) | EVENT_INDEX(5));
339062306a36Sopenharmony_ci	radeon_ring_write(ring, lower_32_bits(addr));
339162306a36Sopenharmony_ci	radeon_ring_write(ring, (upper_32_bits(addr) & 0xff) | DATA_SEL(1) | INT_SEL(2));
339262306a36Sopenharmony_ci	radeon_ring_write(ring, fence->seq);
339362306a36Sopenharmony_ci	radeon_ring_write(ring, 0);
339462306a36Sopenharmony_ci}
339562306a36Sopenharmony_ci
339662306a36Sopenharmony_ci/*
339762306a36Sopenharmony_ci * IB stuff
339862306a36Sopenharmony_ci */
339962306a36Sopenharmony_civoid si_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib)
340062306a36Sopenharmony_ci{
340162306a36Sopenharmony_ci	struct radeon_ring *ring = &rdev->ring[ib->ring];
340262306a36Sopenharmony_ci	unsigned vm_id = ib->vm ? ib->vm->ids[ib->ring].id : 0;
340362306a36Sopenharmony_ci	u32 header;
340462306a36Sopenharmony_ci
340562306a36Sopenharmony_ci	if (ib->is_const_ib) {
340662306a36Sopenharmony_ci		/* set switch buffer packet before const IB */
340762306a36Sopenharmony_ci		radeon_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0));
340862306a36Sopenharmony_ci		radeon_ring_write(ring, 0);
340962306a36Sopenharmony_ci
341062306a36Sopenharmony_ci		header = PACKET3(PACKET3_INDIRECT_BUFFER_CONST, 2);
341162306a36Sopenharmony_ci	} else {
341262306a36Sopenharmony_ci		u32 next_rptr;
341362306a36Sopenharmony_ci		if (ring->rptr_save_reg) {
341462306a36Sopenharmony_ci			next_rptr = ring->wptr + 3 + 4 + 8;
341562306a36Sopenharmony_ci			radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1));
341662306a36Sopenharmony_ci			radeon_ring_write(ring, ((ring->rptr_save_reg -
341762306a36Sopenharmony_ci						  PACKET3_SET_CONFIG_REG_START) >> 2));
341862306a36Sopenharmony_ci			radeon_ring_write(ring, next_rptr);
341962306a36Sopenharmony_ci		} else if (rdev->wb.enabled) {
342062306a36Sopenharmony_ci			next_rptr = ring->wptr + 5 + 4 + 8;
342162306a36Sopenharmony_ci			radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
342262306a36Sopenharmony_ci			radeon_ring_write(ring, (1 << 8));
342362306a36Sopenharmony_ci			radeon_ring_write(ring, ring->next_rptr_gpu_addr & 0xfffffffc);
342462306a36Sopenharmony_ci			radeon_ring_write(ring, upper_32_bits(ring->next_rptr_gpu_addr));
342562306a36Sopenharmony_ci			radeon_ring_write(ring, next_rptr);
342662306a36Sopenharmony_ci		}
342762306a36Sopenharmony_ci
342862306a36Sopenharmony_ci		header = PACKET3(PACKET3_INDIRECT_BUFFER, 2);
342962306a36Sopenharmony_ci	}
343062306a36Sopenharmony_ci
343162306a36Sopenharmony_ci	radeon_ring_write(ring, header);
343262306a36Sopenharmony_ci	radeon_ring_write(ring,
343362306a36Sopenharmony_ci#ifdef __BIG_ENDIAN
343462306a36Sopenharmony_ci			  (2 << 0) |
343562306a36Sopenharmony_ci#endif
343662306a36Sopenharmony_ci			  (ib->gpu_addr & 0xFFFFFFFC));
343762306a36Sopenharmony_ci	radeon_ring_write(ring, upper_32_bits(ib->gpu_addr) & 0xFFFF);
343862306a36Sopenharmony_ci	radeon_ring_write(ring, ib->length_dw | (vm_id << 24));
343962306a36Sopenharmony_ci
344062306a36Sopenharmony_ci	if (!ib->is_const_ib) {
344162306a36Sopenharmony_ci		/* flush read cache over gart for this vmid */
344262306a36Sopenharmony_ci		radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1));
344362306a36Sopenharmony_ci		radeon_ring_write(ring, (CP_COHER_CNTL2 - PACKET3_SET_CONFIG_REG_START) >> 2);
344462306a36Sopenharmony_ci		radeon_ring_write(ring, vm_id);
344562306a36Sopenharmony_ci		radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3));
344662306a36Sopenharmony_ci		radeon_ring_write(ring, PACKET3_TCL1_ACTION_ENA |
344762306a36Sopenharmony_ci				  PACKET3_TC_ACTION_ENA |
344862306a36Sopenharmony_ci				  PACKET3_SH_KCACHE_ACTION_ENA |
344962306a36Sopenharmony_ci				  PACKET3_SH_ICACHE_ACTION_ENA);
345062306a36Sopenharmony_ci		radeon_ring_write(ring, 0xFFFFFFFF);
345162306a36Sopenharmony_ci		radeon_ring_write(ring, 0);
345262306a36Sopenharmony_ci		radeon_ring_write(ring, 10); /* poll interval */
345362306a36Sopenharmony_ci	}
345462306a36Sopenharmony_ci}
345562306a36Sopenharmony_ci
345662306a36Sopenharmony_ci/*
345762306a36Sopenharmony_ci * CP.
345862306a36Sopenharmony_ci */
345962306a36Sopenharmony_cistatic void si_cp_enable(struct radeon_device *rdev, bool enable)
346062306a36Sopenharmony_ci{
346162306a36Sopenharmony_ci	if (enable)
346262306a36Sopenharmony_ci		WREG32(CP_ME_CNTL, 0);
346362306a36Sopenharmony_ci	else {
346462306a36Sopenharmony_ci		if (rdev->asic->copy.copy_ring_index == RADEON_RING_TYPE_GFX_INDEX)
346562306a36Sopenharmony_ci			radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size);
346662306a36Sopenharmony_ci		WREG32(CP_ME_CNTL, (CP_ME_HALT | CP_PFP_HALT | CP_CE_HALT));
346762306a36Sopenharmony_ci		WREG32(SCRATCH_UMSK, 0);
346862306a36Sopenharmony_ci		rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false;
346962306a36Sopenharmony_ci		rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX].ready = false;
347062306a36Sopenharmony_ci		rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX].ready = false;
347162306a36Sopenharmony_ci	}
347262306a36Sopenharmony_ci	udelay(50);
347362306a36Sopenharmony_ci}
347462306a36Sopenharmony_ci
347562306a36Sopenharmony_cistatic int si_cp_load_microcode(struct radeon_device *rdev)
347662306a36Sopenharmony_ci{
347762306a36Sopenharmony_ci	int i;
347862306a36Sopenharmony_ci
347962306a36Sopenharmony_ci	if (!rdev->me_fw || !rdev->pfp_fw || !rdev->ce_fw)
348062306a36Sopenharmony_ci		return -EINVAL;
348162306a36Sopenharmony_ci
348262306a36Sopenharmony_ci	si_cp_enable(rdev, false);
348362306a36Sopenharmony_ci
348462306a36Sopenharmony_ci	if (rdev->new_fw) {
348562306a36Sopenharmony_ci		const struct gfx_firmware_header_v1_0 *pfp_hdr =
348662306a36Sopenharmony_ci			(const struct gfx_firmware_header_v1_0 *)rdev->pfp_fw->data;
348762306a36Sopenharmony_ci		const struct gfx_firmware_header_v1_0 *ce_hdr =
348862306a36Sopenharmony_ci			(const struct gfx_firmware_header_v1_0 *)rdev->ce_fw->data;
348962306a36Sopenharmony_ci		const struct gfx_firmware_header_v1_0 *me_hdr =
349062306a36Sopenharmony_ci			(const struct gfx_firmware_header_v1_0 *)rdev->me_fw->data;
349162306a36Sopenharmony_ci		const __le32 *fw_data;
349262306a36Sopenharmony_ci		u32 fw_size;
349362306a36Sopenharmony_ci
349462306a36Sopenharmony_ci		radeon_ucode_print_gfx_hdr(&pfp_hdr->header);
349562306a36Sopenharmony_ci		radeon_ucode_print_gfx_hdr(&ce_hdr->header);
349662306a36Sopenharmony_ci		radeon_ucode_print_gfx_hdr(&me_hdr->header);
349762306a36Sopenharmony_ci
349862306a36Sopenharmony_ci		/* PFP */
349962306a36Sopenharmony_ci		fw_data = (const __le32 *)
350062306a36Sopenharmony_ci			(rdev->pfp_fw->data + le32_to_cpu(pfp_hdr->header.ucode_array_offset_bytes));
350162306a36Sopenharmony_ci		fw_size = le32_to_cpu(pfp_hdr->header.ucode_size_bytes) / 4;
350262306a36Sopenharmony_ci		WREG32(CP_PFP_UCODE_ADDR, 0);
350362306a36Sopenharmony_ci		for (i = 0; i < fw_size; i++)
350462306a36Sopenharmony_ci			WREG32(CP_PFP_UCODE_DATA, le32_to_cpup(fw_data++));
350562306a36Sopenharmony_ci		WREG32(CP_PFP_UCODE_ADDR, 0);
350662306a36Sopenharmony_ci
350762306a36Sopenharmony_ci		/* CE */
350862306a36Sopenharmony_ci		fw_data = (const __le32 *)
350962306a36Sopenharmony_ci			(rdev->ce_fw->data + le32_to_cpu(ce_hdr->header.ucode_array_offset_bytes));
351062306a36Sopenharmony_ci		fw_size = le32_to_cpu(ce_hdr->header.ucode_size_bytes) / 4;
351162306a36Sopenharmony_ci		WREG32(CP_CE_UCODE_ADDR, 0);
351262306a36Sopenharmony_ci		for (i = 0; i < fw_size; i++)
351362306a36Sopenharmony_ci			WREG32(CP_CE_UCODE_DATA, le32_to_cpup(fw_data++));
351462306a36Sopenharmony_ci		WREG32(CP_CE_UCODE_ADDR, 0);
351562306a36Sopenharmony_ci
351662306a36Sopenharmony_ci		/* ME */
351762306a36Sopenharmony_ci		fw_data = (const __be32 *)
351862306a36Sopenharmony_ci			(rdev->me_fw->data + le32_to_cpu(me_hdr->header.ucode_array_offset_bytes));
351962306a36Sopenharmony_ci		fw_size = le32_to_cpu(me_hdr->header.ucode_size_bytes) / 4;
352062306a36Sopenharmony_ci		WREG32(CP_ME_RAM_WADDR, 0);
352162306a36Sopenharmony_ci		for (i = 0; i < fw_size; i++)
352262306a36Sopenharmony_ci			WREG32(CP_ME_RAM_DATA, le32_to_cpup(fw_data++));
352362306a36Sopenharmony_ci		WREG32(CP_ME_RAM_WADDR, 0);
352462306a36Sopenharmony_ci	} else {
352562306a36Sopenharmony_ci		const __be32 *fw_data;
352662306a36Sopenharmony_ci
352762306a36Sopenharmony_ci		/* PFP */
352862306a36Sopenharmony_ci		fw_data = (const __be32 *)rdev->pfp_fw->data;
352962306a36Sopenharmony_ci		WREG32(CP_PFP_UCODE_ADDR, 0);
353062306a36Sopenharmony_ci		for (i = 0; i < SI_PFP_UCODE_SIZE; i++)
353162306a36Sopenharmony_ci			WREG32(CP_PFP_UCODE_DATA, be32_to_cpup(fw_data++));
353262306a36Sopenharmony_ci		WREG32(CP_PFP_UCODE_ADDR, 0);
353362306a36Sopenharmony_ci
353462306a36Sopenharmony_ci		/* CE */
353562306a36Sopenharmony_ci		fw_data = (const __be32 *)rdev->ce_fw->data;
353662306a36Sopenharmony_ci		WREG32(CP_CE_UCODE_ADDR, 0);
353762306a36Sopenharmony_ci		for (i = 0; i < SI_CE_UCODE_SIZE; i++)
353862306a36Sopenharmony_ci			WREG32(CP_CE_UCODE_DATA, be32_to_cpup(fw_data++));
353962306a36Sopenharmony_ci		WREG32(CP_CE_UCODE_ADDR, 0);
354062306a36Sopenharmony_ci
354162306a36Sopenharmony_ci		/* ME */
354262306a36Sopenharmony_ci		fw_data = (const __be32 *)rdev->me_fw->data;
354362306a36Sopenharmony_ci		WREG32(CP_ME_RAM_WADDR, 0);
354462306a36Sopenharmony_ci		for (i = 0; i < SI_PM4_UCODE_SIZE; i++)
354562306a36Sopenharmony_ci			WREG32(CP_ME_RAM_DATA, be32_to_cpup(fw_data++));
354662306a36Sopenharmony_ci		WREG32(CP_ME_RAM_WADDR, 0);
354762306a36Sopenharmony_ci	}
354862306a36Sopenharmony_ci
354962306a36Sopenharmony_ci	WREG32(CP_PFP_UCODE_ADDR, 0);
355062306a36Sopenharmony_ci	WREG32(CP_CE_UCODE_ADDR, 0);
355162306a36Sopenharmony_ci	WREG32(CP_ME_RAM_WADDR, 0);
355262306a36Sopenharmony_ci	WREG32(CP_ME_RAM_RADDR, 0);
355362306a36Sopenharmony_ci	return 0;
355462306a36Sopenharmony_ci}
355562306a36Sopenharmony_ci
355662306a36Sopenharmony_cistatic int si_cp_start(struct radeon_device *rdev)
355762306a36Sopenharmony_ci{
355862306a36Sopenharmony_ci	struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
355962306a36Sopenharmony_ci	int r, i;
356062306a36Sopenharmony_ci
356162306a36Sopenharmony_ci	r = radeon_ring_lock(rdev, ring, 7 + 4);
356262306a36Sopenharmony_ci	if (r) {
356362306a36Sopenharmony_ci		DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r);
356462306a36Sopenharmony_ci		return r;
356562306a36Sopenharmony_ci	}
356662306a36Sopenharmony_ci	/* init the CP */
356762306a36Sopenharmony_ci	radeon_ring_write(ring, PACKET3(PACKET3_ME_INITIALIZE, 5));
356862306a36Sopenharmony_ci	radeon_ring_write(ring, 0x1);
356962306a36Sopenharmony_ci	radeon_ring_write(ring, 0x0);
357062306a36Sopenharmony_ci	radeon_ring_write(ring, rdev->config.si.max_hw_contexts - 1);
357162306a36Sopenharmony_ci	radeon_ring_write(ring, PACKET3_ME_INITIALIZE_DEVICE_ID(1));
357262306a36Sopenharmony_ci	radeon_ring_write(ring, 0);
357362306a36Sopenharmony_ci	radeon_ring_write(ring, 0);
357462306a36Sopenharmony_ci
357562306a36Sopenharmony_ci	/* init the CE partitions */
357662306a36Sopenharmony_ci	radeon_ring_write(ring, PACKET3(PACKET3_SET_BASE, 2));
357762306a36Sopenharmony_ci	radeon_ring_write(ring, PACKET3_BASE_INDEX(CE_PARTITION_BASE));
357862306a36Sopenharmony_ci	radeon_ring_write(ring, 0xc000);
357962306a36Sopenharmony_ci	radeon_ring_write(ring, 0xe000);
358062306a36Sopenharmony_ci	radeon_ring_unlock_commit(rdev, ring, false);
358162306a36Sopenharmony_ci
358262306a36Sopenharmony_ci	si_cp_enable(rdev, true);
358362306a36Sopenharmony_ci
358462306a36Sopenharmony_ci	r = radeon_ring_lock(rdev, ring, si_default_size + 10);
358562306a36Sopenharmony_ci	if (r) {
358662306a36Sopenharmony_ci		DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r);
358762306a36Sopenharmony_ci		return r;
358862306a36Sopenharmony_ci	}
358962306a36Sopenharmony_ci
359062306a36Sopenharmony_ci	/* setup clear context state */
359162306a36Sopenharmony_ci	radeon_ring_write(ring, PACKET3(PACKET3_PREAMBLE_CNTL, 0));
359262306a36Sopenharmony_ci	radeon_ring_write(ring, PACKET3_PREAMBLE_BEGIN_CLEAR_STATE);
359362306a36Sopenharmony_ci
359462306a36Sopenharmony_ci	for (i = 0; i < si_default_size; i++)
359562306a36Sopenharmony_ci		radeon_ring_write(ring, si_default_state[i]);
359662306a36Sopenharmony_ci
359762306a36Sopenharmony_ci	radeon_ring_write(ring, PACKET3(PACKET3_PREAMBLE_CNTL, 0));
359862306a36Sopenharmony_ci	radeon_ring_write(ring, PACKET3_PREAMBLE_END_CLEAR_STATE);
359962306a36Sopenharmony_ci
360062306a36Sopenharmony_ci	/* set clear context state */
360162306a36Sopenharmony_ci	radeon_ring_write(ring, PACKET3(PACKET3_CLEAR_STATE, 0));
360262306a36Sopenharmony_ci	radeon_ring_write(ring, 0);
360362306a36Sopenharmony_ci
360462306a36Sopenharmony_ci	radeon_ring_write(ring, PACKET3(PACKET3_SET_CONTEXT_REG, 2));
360562306a36Sopenharmony_ci	radeon_ring_write(ring, 0x00000316);
360662306a36Sopenharmony_ci	radeon_ring_write(ring, 0x0000000e); /* VGT_VERTEX_REUSE_BLOCK_CNTL */
360762306a36Sopenharmony_ci	radeon_ring_write(ring, 0x00000010); /* VGT_OUT_DEALLOC_CNTL */
360862306a36Sopenharmony_ci
360962306a36Sopenharmony_ci	radeon_ring_unlock_commit(rdev, ring, false);
361062306a36Sopenharmony_ci
361162306a36Sopenharmony_ci	for (i = RADEON_RING_TYPE_GFX_INDEX; i <= CAYMAN_RING_TYPE_CP2_INDEX; ++i) {
361262306a36Sopenharmony_ci		ring = &rdev->ring[i];
361362306a36Sopenharmony_ci		r = radeon_ring_lock(rdev, ring, 2);
361462306a36Sopenharmony_ci		if (r) {
361562306a36Sopenharmony_ci			DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r);
361662306a36Sopenharmony_ci			return r;
361762306a36Sopenharmony_ci		}
361862306a36Sopenharmony_ci
361962306a36Sopenharmony_ci		/* clear the compute context state */
362062306a36Sopenharmony_ci		radeon_ring_write(ring, PACKET3_COMPUTE(PACKET3_CLEAR_STATE, 0));
362162306a36Sopenharmony_ci		radeon_ring_write(ring, 0);
362262306a36Sopenharmony_ci
362362306a36Sopenharmony_ci		radeon_ring_unlock_commit(rdev, ring, false);
362462306a36Sopenharmony_ci	}
362562306a36Sopenharmony_ci
362662306a36Sopenharmony_ci	return 0;
362762306a36Sopenharmony_ci}
362862306a36Sopenharmony_ci
362962306a36Sopenharmony_cistatic void si_cp_fini(struct radeon_device *rdev)
363062306a36Sopenharmony_ci{
363162306a36Sopenharmony_ci	struct radeon_ring *ring;
363262306a36Sopenharmony_ci	si_cp_enable(rdev, false);
363362306a36Sopenharmony_ci
363462306a36Sopenharmony_ci	ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
363562306a36Sopenharmony_ci	radeon_ring_fini(rdev, ring);
363662306a36Sopenharmony_ci	radeon_scratch_free(rdev, ring->rptr_save_reg);
363762306a36Sopenharmony_ci
363862306a36Sopenharmony_ci	ring = &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX];
363962306a36Sopenharmony_ci	radeon_ring_fini(rdev, ring);
364062306a36Sopenharmony_ci	radeon_scratch_free(rdev, ring->rptr_save_reg);
364162306a36Sopenharmony_ci
364262306a36Sopenharmony_ci	ring = &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX];
364362306a36Sopenharmony_ci	radeon_ring_fini(rdev, ring);
364462306a36Sopenharmony_ci	radeon_scratch_free(rdev, ring->rptr_save_reg);
364562306a36Sopenharmony_ci}
364662306a36Sopenharmony_ci
364762306a36Sopenharmony_cistatic int si_cp_resume(struct radeon_device *rdev)
364862306a36Sopenharmony_ci{
364962306a36Sopenharmony_ci	struct radeon_ring *ring;
365062306a36Sopenharmony_ci	u32 tmp;
365162306a36Sopenharmony_ci	u32 rb_bufsz;
365262306a36Sopenharmony_ci	int r;
365362306a36Sopenharmony_ci
365462306a36Sopenharmony_ci	si_enable_gui_idle_interrupt(rdev, false);
365562306a36Sopenharmony_ci
365662306a36Sopenharmony_ci	WREG32(CP_SEM_WAIT_TIMER, 0x0);
365762306a36Sopenharmony_ci	WREG32(CP_SEM_INCOMPLETE_TIMER_CNTL, 0x0);
365862306a36Sopenharmony_ci
365962306a36Sopenharmony_ci	/* Set the write pointer delay */
366062306a36Sopenharmony_ci	WREG32(CP_RB_WPTR_DELAY, 0);
366162306a36Sopenharmony_ci
366262306a36Sopenharmony_ci	WREG32(CP_DEBUG, 0);
366362306a36Sopenharmony_ci	WREG32(SCRATCH_ADDR, ((rdev->wb.gpu_addr + RADEON_WB_SCRATCH_OFFSET) >> 8) & 0xFFFFFFFF);
366462306a36Sopenharmony_ci
366562306a36Sopenharmony_ci	/* ring 0 - compute and gfx */
366662306a36Sopenharmony_ci	/* Set ring buffer size */
366762306a36Sopenharmony_ci	ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
366862306a36Sopenharmony_ci	rb_bufsz = order_base_2(ring->ring_size / 8);
366962306a36Sopenharmony_ci	tmp = (order_base_2(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz;
367062306a36Sopenharmony_ci#ifdef __BIG_ENDIAN
367162306a36Sopenharmony_ci	tmp |= BUF_SWAP_32BIT;
367262306a36Sopenharmony_ci#endif
367362306a36Sopenharmony_ci	WREG32(CP_RB0_CNTL, tmp);
367462306a36Sopenharmony_ci
367562306a36Sopenharmony_ci	/* Initialize the ring buffer's read and write pointers */
367662306a36Sopenharmony_ci	WREG32(CP_RB0_CNTL, tmp | RB_RPTR_WR_ENA);
367762306a36Sopenharmony_ci	ring->wptr = 0;
367862306a36Sopenharmony_ci	WREG32(CP_RB0_WPTR, ring->wptr);
367962306a36Sopenharmony_ci
368062306a36Sopenharmony_ci	/* set the wb address whether it's enabled or not */
368162306a36Sopenharmony_ci	WREG32(CP_RB0_RPTR_ADDR, (rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFFFFFFFC);
368262306a36Sopenharmony_ci	WREG32(CP_RB0_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFF);
368362306a36Sopenharmony_ci
368462306a36Sopenharmony_ci	if (rdev->wb.enabled)
368562306a36Sopenharmony_ci		WREG32(SCRATCH_UMSK, 0xff);
368662306a36Sopenharmony_ci	else {
368762306a36Sopenharmony_ci		tmp |= RB_NO_UPDATE;
368862306a36Sopenharmony_ci		WREG32(SCRATCH_UMSK, 0);
368962306a36Sopenharmony_ci	}
369062306a36Sopenharmony_ci
369162306a36Sopenharmony_ci	mdelay(1);
369262306a36Sopenharmony_ci	WREG32(CP_RB0_CNTL, tmp);
369362306a36Sopenharmony_ci
369462306a36Sopenharmony_ci	WREG32(CP_RB0_BASE, ring->gpu_addr >> 8);
369562306a36Sopenharmony_ci
369662306a36Sopenharmony_ci	/* ring1  - compute only */
369762306a36Sopenharmony_ci	/* Set ring buffer size */
369862306a36Sopenharmony_ci	ring = &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX];
369962306a36Sopenharmony_ci	rb_bufsz = order_base_2(ring->ring_size / 8);
370062306a36Sopenharmony_ci	tmp = (order_base_2(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz;
370162306a36Sopenharmony_ci#ifdef __BIG_ENDIAN
370262306a36Sopenharmony_ci	tmp |= BUF_SWAP_32BIT;
370362306a36Sopenharmony_ci#endif
370462306a36Sopenharmony_ci	WREG32(CP_RB1_CNTL, tmp);
370562306a36Sopenharmony_ci
370662306a36Sopenharmony_ci	/* Initialize the ring buffer's read and write pointers */
370762306a36Sopenharmony_ci	WREG32(CP_RB1_CNTL, tmp | RB_RPTR_WR_ENA);
370862306a36Sopenharmony_ci	ring->wptr = 0;
370962306a36Sopenharmony_ci	WREG32(CP_RB1_WPTR, ring->wptr);
371062306a36Sopenharmony_ci
371162306a36Sopenharmony_ci	/* set the wb address whether it's enabled or not */
371262306a36Sopenharmony_ci	WREG32(CP_RB1_RPTR_ADDR, (rdev->wb.gpu_addr + RADEON_WB_CP1_RPTR_OFFSET) & 0xFFFFFFFC);
371362306a36Sopenharmony_ci	WREG32(CP_RB1_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP1_RPTR_OFFSET) & 0xFF);
371462306a36Sopenharmony_ci
371562306a36Sopenharmony_ci	mdelay(1);
371662306a36Sopenharmony_ci	WREG32(CP_RB1_CNTL, tmp);
371762306a36Sopenharmony_ci
371862306a36Sopenharmony_ci	WREG32(CP_RB1_BASE, ring->gpu_addr >> 8);
371962306a36Sopenharmony_ci
372062306a36Sopenharmony_ci	/* ring2 - compute only */
372162306a36Sopenharmony_ci	/* Set ring buffer size */
372262306a36Sopenharmony_ci	ring = &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX];
372362306a36Sopenharmony_ci	rb_bufsz = order_base_2(ring->ring_size / 8);
372462306a36Sopenharmony_ci	tmp = (order_base_2(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz;
372562306a36Sopenharmony_ci#ifdef __BIG_ENDIAN
372662306a36Sopenharmony_ci	tmp |= BUF_SWAP_32BIT;
372762306a36Sopenharmony_ci#endif
372862306a36Sopenharmony_ci	WREG32(CP_RB2_CNTL, tmp);
372962306a36Sopenharmony_ci
373062306a36Sopenharmony_ci	/* Initialize the ring buffer's read and write pointers */
373162306a36Sopenharmony_ci	WREG32(CP_RB2_CNTL, tmp | RB_RPTR_WR_ENA);
373262306a36Sopenharmony_ci	ring->wptr = 0;
373362306a36Sopenharmony_ci	WREG32(CP_RB2_WPTR, ring->wptr);
373462306a36Sopenharmony_ci
373562306a36Sopenharmony_ci	/* set the wb address whether it's enabled or not */
373662306a36Sopenharmony_ci	WREG32(CP_RB2_RPTR_ADDR, (rdev->wb.gpu_addr + RADEON_WB_CP2_RPTR_OFFSET) & 0xFFFFFFFC);
373762306a36Sopenharmony_ci	WREG32(CP_RB2_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP2_RPTR_OFFSET) & 0xFF);
373862306a36Sopenharmony_ci
373962306a36Sopenharmony_ci	mdelay(1);
374062306a36Sopenharmony_ci	WREG32(CP_RB2_CNTL, tmp);
374162306a36Sopenharmony_ci
374262306a36Sopenharmony_ci	WREG32(CP_RB2_BASE, ring->gpu_addr >> 8);
374362306a36Sopenharmony_ci
374462306a36Sopenharmony_ci	/* start the rings */
374562306a36Sopenharmony_ci	si_cp_start(rdev);
374662306a36Sopenharmony_ci	rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = true;
374762306a36Sopenharmony_ci	rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX].ready = true;
374862306a36Sopenharmony_ci	rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX].ready = true;
374962306a36Sopenharmony_ci	r = radeon_ring_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]);
375062306a36Sopenharmony_ci	if (r) {
375162306a36Sopenharmony_ci		rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false;
375262306a36Sopenharmony_ci		rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX].ready = false;
375362306a36Sopenharmony_ci		rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX].ready = false;
375462306a36Sopenharmony_ci		return r;
375562306a36Sopenharmony_ci	}
375662306a36Sopenharmony_ci	r = radeon_ring_test(rdev, CAYMAN_RING_TYPE_CP1_INDEX, &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX]);
375762306a36Sopenharmony_ci	if (r) {
375862306a36Sopenharmony_ci		rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX].ready = false;
375962306a36Sopenharmony_ci	}
376062306a36Sopenharmony_ci	r = radeon_ring_test(rdev, CAYMAN_RING_TYPE_CP2_INDEX, &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX]);
376162306a36Sopenharmony_ci	if (r) {
376262306a36Sopenharmony_ci		rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX].ready = false;
376362306a36Sopenharmony_ci	}
376462306a36Sopenharmony_ci
376562306a36Sopenharmony_ci	si_enable_gui_idle_interrupt(rdev, true);
376662306a36Sopenharmony_ci
376762306a36Sopenharmony_ci	if (rdev->asic->copy.copy_ring_index == RADEON_RING_TYPE_GFX_INDEX)
376862306a36Sopenharmony_ci		radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size);
376962306a36Sopenharmony_ci
377062306a36Sopenharmony_ci	return 0;
377162306a36Sopenharmony_ci}
377262306a36Sopenharmony_ci
377362306a36Sopenharmony_ciu32 si_gpu_check_soft_reset(struct radeon_device *rdev)
377462306a36Sopenharmony_ci{
377562306a36Sopenharmony_ci	u32 reset_mask = 0;
377662306a36Sopenharmony_ci	u32 tmp;
377762306a36Sopenharmony_ci
377862306a36Sopenharmony_ci	/* GRBM_STATUS */
377962306a36Sopenharmony_ci	tmp = RREG32(GRBM_STATUS);
378062306a36Sopenharmony_ci	if (tmp & (PA_BUSY | SC_BUSY |
378162306a36Sopenharmony_ci		   BCI_BUSY | SX_BUSY |
378262306a36Sopenharmony_ci		   TA_BUSY | VGT_BUSY |
378362306a36Sopenharmony_ci		   DB_BUSY | CB_BUSY |
378462306a36Sopenharmony_ci		   GDS_BUSY | SPI_BUSY |
378562306a36Sopenharmony_ci		   IA_BUSY | IA_BUSY_NO_DMA))
378662306a36Sopenharmony_ci		reset_mask |= RADEON_RESET_GFX;
378762306a36Sopenharmony_ci
378862306a36Sopenharmony_ci	if (tmp & (CF_RQ_PENDING | PF_RQ_PENDING |
378962306a36Sopenharmony_ci		   CP_BUSY | CP_COHERENCY_BUSY))
379062306a36Sopenharmony_ci		reset_mask |= RADEON_RESET_CP;
379162306a36Sopenharmony_ci
379262306a36Sopenharmony_ci	if (tmp & GRBM_EE_BUSY)
379362306a36Sopenharmony_ci		reset_mask |= RADEON_RESET_GRBM | RADEON_RESET_GFX | RADEON_RESET_CP;
379462306a36Sopenharmony_ci
379562306a36Sopenharmony_ci	/* GRBM_STATUS2 */
379662306a36Sopenharmony_ci	tmp = RREG32(GRBM_STATUS2);
379762306a36Sopenharmony_ci	if (tmp & (RLC_RQ_PENDING | RLC_BUSY))
379862306a36Sopenharmony_ci		reset_mask |= RADEON_RESET_RLC;
379962306a36Sopenharmony_ci
380062306a36Sopenharmony_ci	/* DMA_STATUS_REG 0 */
380162306a36Sopenharmony_ci	tmp = RREG32(DMA_STATUS_REG + DMA0_REGISTER_OFFSET);
380262306a36Sopenharmony_ci	if (!(tmp & DMA_IDLE))
380362306a36Sopenharmony_ci		reset_mask |= RADEON_RESET_DMA;
380462306a36Sopenharmony_ci
380562306a36Sopenharmony_ci	/* DMA_STATUS_REG 1 */
380662306a36Sopenharmony_ci	tmp = RREG32(DMA_STATUS_REG + DMA1_REGISTER_OFFSET);
380762306a36Sopenharmony_ci	if (!(tmp & DMA_IDLE))
380862306a36Sopenharmony_ci		reset_mask |= RADEON_RESET_DMA1;
380962306a36Sopenharmony_ci
381062306a36Sopenharmony_ci	/* SRBM_STATUS2 */
381162306a36Sopenharmony_ci	tmp = RREG32(SRBM_STATUS2);
381262306a36Sopenharmony_ci	if (tmp & DMA_BUSY)
381362306a36Sopenharmony_ci		reset_mask |= RADEON_RESET_DMA;
381462306a36Sopenharmony_ci
381562306a36Sopenharmony_ci	if (tmp & DMA1_BUSY)
381662306a36Sopenharmony_ci		reset_mask |= RADEON_RESET_DMA1;
381762306a36Sopenharmony_ci
381862306a36Sopenharmony_ci	/* SRBM_STATUS */
381962306a36Sopenharmony_ci	tmp = RREG32(SRBM_STATUS);
382062306a36Sopenharmony_ci
382162306a36Sopenharmony_ci	if (tmp & IH_BUSY)
382262306a36Sopenharmony_ci		reset_mask |= RADEON_RESET_IH;
382362306a36Sopenharmony_ci
382462306a36Sopenharmony_ci	if (tmp & SEM_BUSY)
382562306a36Sopenharmony_ci		reset_mask |= RADEON_RESET_SEM;
382662306a36Sopenharmony_ci
382762306a36Sopenharmony_ci	if (tmp & GRBM_RQ_PENDING)
382862306a36Sopenharmony_ci		reset_mask |= RADEON_RESET_GRBM;
382962306a36Sopenharmony_ci
383062306a36Sopenharmony_ci	if (tmp & VMC_BUSY)
383162306a36Sopenharmony_ci		reset_mask |= RADEON_RESET_VMC;
383262306a36Sopenharmony_ci
383362306a36Sopenharmony_ci	if (tmp & (MCB_BUSY | MCB_NON_DISPLAY_BUSY |
383462306a36Sopenharmony_ci		   MCC_BUSY | MCD_BUSY))
383562306a36Sopenharmony_ci		reset_mask |= RADEON_RESET_MC;
383662306a36Sopenharmony_ci
383762306a36Sopenharmony_ci	if (evergreen_is_display_hung(rdev))
383862306a36Sopenharmony_ci		reset_mask |= RADEON_RESET_DISPLAY;
383962306a36Sopenharmony_ci
384062306a36Sopenharmony_ci	/* VM_L2_STATUS */
384162306a36Sopenharmony_ci	tmp = RREG32(VM_L2_STATUS);
384262306a36Sopenharmony_ci	if (tmp & L2_BUSY)
384362306a36Sopenharmony_ci		reset_mask |= RADEON_RESET_VMC;
384462306a36Sopenharmony_ci
384562306a36Sopenharmony_ci	/* Skip MC reset as it's mostly likely not hung, just busy */
384662306a36Sopenharmony_ci	if (reset_mask & RADEON_RESET_MC) {
384762306a36Sopenharmony_ci		DRM_DEBUG("MC busy: 0x%08X, clearing.\n", reset_mask);
384862306a36Sopenharmony_ci		reset_mask &= ~RADEON_RESET_MC;
384962306a36Sopenharmony_ci	}
385062306a36Sopenharmony_ci
385162306a36Sopenharmony_ci	return reset_mask;
385262306a36Sopenharmony_ci}
385362306a36Sopenharmony_ci
385462306a36Sopenharmony_cistatic void si_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask)
385562306a36Sopenharmony_ci{
385662306a36Sopenharmony_ci	struct evergreen_mc_save save;
385762306a36Sopenharmony_ci	u32 grbm_soft_reset = 0, srbm_soft_reset = 0;
385862306a36Sopenharmony_ci	u32 tmp;
385962306a36Sopenharmony_ci
386062306a36Sopenharmony_ci	if (reset_mask == 0)
386162306a36Sopenharmony_ci		return;
386262306a36Sopenharmony_ci
386362306a36Sopenharmony_ci	dev_info(rdev->dev, "GPU softreset: 0x%08X\n", reset_mask);
386462306a36Sopenharmony_ci
386562306a36Sopenharmony_ci	evergreen_print_gpu_status_regs(rdev);
386662306a36Sopenharmony_ci	dev_info(rdev->dev, "  VM_CONTEXT1_PROTECTION_FAULT_ADDR   0x%08X\n",
386762306a36Sopenharmony_ci		 RREG32(VM_CONTEXT1_PROTECTION_FAULT_ADDR));
386862306a36Sopenharmony_ci	dev_info(rdev->dev, "  VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x%08X\n",
386962306a36Sopenharmony_ci		 RREG32(VM_CONTEXT1_PROTECTION_FAULT_STATUS));
387062306a36Sopenharmony_ci
387162306a36Sopenharmony_ci	/* disable PG/CG */
387262306a36Sopenharmony_ci	si_fini_pg(rdev);
387362306a36Sopenharmony_ci	si_fini_cg(rdev);
387462306a36Sopenharmony_ci
387562306a36Sopenharmony_ci	/* stop the rlc */
387662306a36Sopenharmony_ci	si_rlc_stop(rdev);
387762306a36Sopenharmony_ci
387862306a36Sopenharmony_ci	/* Disable CP parsing/prefetching */
387962306a36Sopenharmony_ci	WREG32(CP_ME_CNTL, CP_ME_HALT | CP_PFP_HALT | CP_CE_HALT);
388062306a36Sopenharmony_ci
388162306a36Sopenharmony_ci	if (reset_mask & RADEON_RESET_DMA) {
388262306a36Sopenharmony_ci		/* dma0 */
388362306a36Sopenharmony_ci		tmp = RREG32(DMA_RB_CNTL + DMA0_REGISTER_OFFSET);
388462306a36Sopenharmony_ci		tmp &= ~DMA_RB_ENABLE;
388562306a36Sopenharmony_ci		WREG32(DMA_RB_CNTL + DMA0_REGISTER_OFFSET, tmp);
388662306a36Sopenharmony_ci	}
388762306a36Sopenharmony_ci	if (reset_mask & RADEON_RESET_DMA1) {
388862306a36Sopenharmony_ci		/* dma1 */
388962306a36Sopenharmony_ci		tmp = RREG32(DMA_RB_CNTL + DMA1_REGISTER_OFFSET);
389062306a36Sopenharmony_ci		tmp &= ~DMA_RB_ENABLE;
389162306a36Sopenharmony_ci		WREG32(DMA_RB_CNTL + DMA1_REGISTER_OFFSET, tmp);
389262306a36Sopenharmony_ci	}
389362306a36Sopenharmony_ci
389462306a36Sopenharmony_ci	udelay(50);
389562306a36Sopenharmony_ci
389662306a36Sopenharmony_ci	evergreen_mc_stop(rdev, &save);
389762306a36Sopenharmony_ci	if (evergreen_mc_wait_for_idle(rdev)) {
389862306a36Sopenharmony_ci		dev_warn(rdev->dev, "Wait for MC idle timedout !\n");
389962306a36Sopenharmony_ci	}
390062306a36Sopenharmony_ci
390162306a36Sopenharmony_ci	if (reset_mask & (RADEON_RESET_GFX | RADEON_RESET_COMPUTE | RADEON_RESET_CP)) {
390262306a36Sopenharmony_ci		grbm_soft_reset = SOFT_RESET_CB |
390362306a36Sopenharmony_ci			SOFT_RESET_DB |
390462306a36Sopenharmony_ci			SOFT_RESET_GDS |
390562306a36Sopenharmony_ci			SOFT_RESET_PA |
390662306a36Sopenharmony_ci			SOFT_RESET_SC |
390762306a36Sopenharmony_ci			SOFT_RESET_BCI |
390862306a36Sopenharmony_ci			SOFT_RESET_SPI |
390962306a36Sopenharmony_ci			SOFT_RESET_SX |
391062306a36Sopenharmony_ci			SOFT_RESET_TC |
391162306a36Sopenharmony_ci			SOFT_RESET_TA |
391262306a36Sopenharmony_ci			SOFT_RESET_VGT |
391362306a36Sopenharmony_ci			SOFT_RESET_IA;
391462306a36Sopenharmony_ci	}
391562306a36Sopenharmony_ci
391662306a36Sopenharmony_ci	if (reset_mask & RADEON_RESET_CP) {
391762306a36Sopenharmony_ci		grbm_soft_reset |= SOFT_RESET_CP | SOFT_RESET_VGT;
391862306a36Sopenharmony_ci
391962306a36Sopenharmony_ci		srbm_soft_reset |= SOFT_RESET_GRBM;
392062306a36Sopenharmony_ci	}
392162306a36Sopenharmony_ci
392262306a36Sopenharmony_ci	if (reset_mask & RADEON_RESET_DMA)
392362306a36Sopenharmony_ci		srbm_soft_reset |= SOFT_RESET_DMA;
392462306a36Sopenharmony_ci
392562306a36Sopenharmony_ci	if (reset_mask & RADEON_RESET_DMA1)
392662306a36Sopenharmony_ci		srbm_soft_reset |= SOFT_RESET_DMA1;
392762306a36Sopenharmony_ci
392862306a36Sopenharmony_ci	if (reset_mask & RADEON_RESET_DISPLAY)
392962306a36Sopenharmony_ci		srbm_soft_reset |= SOFT_RESET_DC;
393062306a36Sopenharmony_ci
393162306a36Sopenharmony_ci	if (reset_mask & RADEON_RESET_RLC)
393262306a36Sopenharmony_ci		grbm_soft_reset |= SOFT_RESET_RLC;
393362306a36Sopenharmony_ci
393462306a36Sopenharmony_ci	if (reset_mask & RADEON_RESET_SEM)
393562306a36Sopenharmony_ci		srbm_soft_reset |= SOFT_RESET_SEM;
393662306a36Sopenharmony_ci
393762306a36Sopenharmony_ci	if (reset_mask & RADEON_RESET_IH)
393862306a36Sopenharmony_ci		srbm_soft_reset |= SOFT_RESET_IH;
393962306a36Sopenharmony_ci
394062306a36Sopenharmony_ci	if (reset_mask & RADEON_RESET_GRBM)
394162306a36Sopenharmony_ci		srbm_soft_reset |= SOFT_RESET_GRBM;
394262306a36Sopenharmony_ci
394362306a36Sopenharmony_ci	if (reset_mask & RADEON_RESET_VMC)
394462306a36Sopenharmony_ci		srbm_soft_reset |= SOFT_RESET_VMC;
394562306a36Sopenharmony_ci
394662306a36Sopenharmony_ci	if (reset_mask & RADEON_RESET_MC)
394762306a36Sopenharmony_ci		srbm_soft_reset |= SOFT_RESET_MC;
394862306a36Sopenharmony_ci
394962306a36Sopenharmony_ci	if (grbm_soft_reset) {
395062306a36Sopenharmony_ci		tmp = RREG32(GRBM_SOFT_RESET);
395162306a36Sopenharmony_ci		tmp |= grbm_soft_reset;
395262306a36Sopenharmony_ci		dev_info(rdev->dev, "GRBM_SOFT_RESET=0x%08X\n", tmp);
395362306a36Sopenharmony_ci		WREG32(GRBM_SOFT_RESET, tmp);
395462306a36Sopenharmony_ci		tmp = RREG32(GRBM_SOFT_RESET);
395562306a36Sopenharmony_ci
395662306a36Sopenharmony_ci		udelay(50);
395762306a36Sopenharmony_ci
395862306a36Sopenharmony_ci		tmp &= ~grbm_soft_reset;
395962306a36Sopenharmony_ci		WREG32(GRBM_SOFT_RESET, tmp);
396062306a36Sopenharmony_ci		tmp = RREG32(GRBM_SOFT_RESET);
396162306a36Sopenharmony_ci	}
396262306a36Sopenharmony_ci
396362306a36Sopenharmony_ci	if (srbm_soft_reset) {
396462306a36Sopenharmony_ci		tmp = RREG32(SRBM_SOFT_RESET);
396562306a36Sopenharmony_ci		tmp |= srbm_soft_reset;
396662306a36Sopenharmony_ci		dev_info(rdev->dev, "SRBM_SOFT_RESET=0x%08X\n", tmp);
396762306a36Sopenharmony_ci		WREG32(SRBM_SOFT_RESET, tmp);
396862306a36Sopenharmony_ci		tmp = RREG32(SRBM_SOFT_RESET);
396962306a36Sopenharmony_ci
397062306a36Sopenharmony_ci		udelay(50);
397162306a36Sopenharmony_ci
397262306a36Sopenharmony_ci		tmp &= ~srbm_soft_reset;
397362306a36Sopenharmony_ci		WREG32(SRBM_SOFT_RESET, tmp);
397462306a36Sopenharmony_ci		tmp = RREG32(SRBM_SOFT_RESET);
397562306a36Sopenharmony_ci	}
397662306a36Sopenharmony_ci
397762306a36Sopenharmony_ci	/* Wait a little for things to settle down */
397862306a36Sopenharmony_ci	udelay(50);
397962306a36Sopenharmony_ci
398062306a36Sopenharmony_ci	evergreen_mc_resume(rdev, &save);
398162306a36Sopenharmony_ci	udelay(50);
398262306a36Sopenharmony_ci
398362306a36Sopenharmony_ci	evergreen_print_gpu_status_regs(rdev);
398462306a36Sopenharmony_ci}
398562306a36Sopenharmony_ci
398662306a36Sopenharmony_cistatic void si_set_clk_bypass_mode(struct radeon_device *rdev)
398762306a36Sopenharmony_ci{
398862306a36Sopenharmony_ci	u32 tmp, i;
398962306a36Sopenharmony_ci
399062306a36Sopenharmony_ci	tmp = RREG32(CG_SPLL_FUNC_CNTL);
399162306a36Sopenharmony_ci	tmp |= SPLL_BYPASS_EN;
399262306a36Sopenharmony_ci	WREG32(CG_SPLL_FUNC_CNTL, tmp);
399362306a36Sopenharmony_ci
399462306a36Sopenharmony_ci	tmp = RREG32(CG_SPLL_FUNC_CNTL_2);
399562306a36Sopenharmony_ci	tmp |= SPLL_CTLREQ_CHG;
399662306a36Sopenharmony_ci	WREG32(CG_SPLL_FUNC_CNTL_2, tmp);
399762306a36Sopenharmony_ci
399862306a36Sopenharmony_ci	for (i = 0; i < rdev->usec_timeout; i++) {
399962306a36Sopenharmony_ci		if (RREG32(SPLL_STATUS) & SPLL_CHG_STATUS)
400062306a36Sopenharmony_ci			break;
400162306a36Sopenharmony_ci		udelay(1);
400262306a36Sopenharmony_ci	}
400362306a36Sopenharmony_ci
400462306a36Sopenharmony_ci	tmp = RREG32(CG_SPLL_FUNC_CNTL_2);
400562306a36Sopenharmony_ci	tmp &= ~(SPLL_CTLREQ_CHG | SCLK_MUX_UPDATE);
400662306a36Sopenharmony_ci	WREG32(CG_SPLL_FUNC_CNTL_2, tmp);
400762306a36Sopenharmony_ci
400862306a36Sopenharmony_ci	tmp = RREG32(MPLL_CNTL_MODE);
400962306a36Sopenharmony_ci	tmp &= ~MPLL_MCLK_SEL;
401062306a36Sopenharmony_ci	WREG32(MPLL_CNTL_MODE, tmp);
401162306a36Sopenharmony_ci}
401262306a36Sopenharmony_ci
401362306a36Sopenharmony_cistatic void si_spll_powerdown(struct radeon_device *rdev)
401462306a36Sopenharmony_ci{
401562306a36Sopenharmony_ci	u32 tmp;
401662306a36Sopenharmony_ci
401762306a36Sopenharmony_ci	tmp = RREG32(SPLL_CNTL_MODE);
401862306a36Sopenharmony_ci	tmp |= SPLL_SW_DIR_CONTROL;
401962306a36Sopenharmony_ci	WREG32(SPLL_CNTL_MODE, tmp);
402062306a36Sopenharmony_ci
402162306a36Sopenharmony_ci	tmp = RREG32(CG_SPLL_FUNC_CNTL);
402262306a36Sopenharmony_ci	tmp |= SPLL_RESET;
402362306a36Sopenharmony_ci	WREG32(CG_SPLL_FUNC_CNTL, tmp);
402462306a36Sopenharmony_ci
402562306a36Sopenharmony_ci	tmp = RREG32(CG_SPLL_FUNC_CNTL);
402662306a36Sopenharmony_ci	tmp |= SPLL_SLEEP;
402762306a36Sopenharmony_ci	WREG32(CG_SPLL_FUNC_CNTL, tmp);
402862306a36Sopenharmony_ci
402962306a36Sopenharmony_ci	tmp = RREG32(SPLL_CNTL_MODE);
403062306a36Sopenharmony_ci	tmp &= ~SPLL_SW_DIR_CONTROL;
403162306a36Sopenharmony_ci	WREG32(SPLL_CNTL_MODE, tmp);
403262306a36Sopenharmony_ci}
403362306a36Sopenharmony_ci
403462306a36Sopenharmony_cistatic void si_gpu_pci_config_reset(struct radeon_device *rdev)
403562306a36Sopenharmony_ci{
403662306a36Sopenharmony_ci	struct evergreen_mc_save save;
403762306a36Sopenharmony_ci	u32 tmp, i;
403862306a36Sopenharmony_ci
403962306a36Sopenharmony_ci	dev_info(rdev->dev, "GPU pci config reset\n");
404062306a36Sopenharmony_ci
404162306a36Sopenharmony_ci	/* disable dpm? */
404262306a36Sopenharmony_ci
404362306a36Sopenharmony_ci	/* disable cg/pg */
404462306a36Sopenharmony_ci	si_fini_pg(rdev);
404562306a36Sopenharmony_ci	si_fini_cg(rdev);
404662306a36Sopenharmony_ci
404762306a36Sopenharmony_ci	/* Disable CP parsing/prefetching */
404862306a36Sopenharmony_ci	WREG32(CP_ME_CNTL, CP_ME_HALT | CP_PFP_HALT | CP_CE_HALT);
404962306a36Sopenharmony_ci	/* dma0 */
405062306a36Sopenharmony_ci	tmp = RREG32(DMA_RB_CNTL + DMA0_REGISTER_OFFSET);
405162306a36Sopenharmony_ci	tmp &= ~DMA_RB_ENABLE;
405262306a36Sopenharmony_ci	WREG32(DMA_RB_CNTL + DMA0_REGISTER_OFFSET, tmp);
405362306a36Sopenharmony_ci	/* dma1 */
405462306a36Sopenharmony_ci	tmp = RREG32(DMA_RB_CNTL + DMA1_REGISTER_OFFSET);
405562306a36Sopenharmony_ci	tmp &= ~DMA_RB_ENABLE;
405662306a36Sopenharmony_ci	WREG32(DMA_RB_CNTL + DMA1_REGISTER_OFFSET, tmp);
405762306a36Sopenharmony_ci	/* XXX other engines? */
405862306a36Sopenharmony_ci
405962306a36Sopenharmony_ci	/* halt the rlc, disable cp internal ints */
406062306a36Sopenharmony_ci	si_rlc_stop(rdev);
406162306a36Sopenharmony_ci
406262306a36Sopenharmony_ci	udelay(50);
406362306a36Sopenharmony_ci
406462306a36Sopenharmony_ci	/* disable mem access */
406562306a36Sopenharmony_ci	evergreen_mc_stop(rdev, &save);
406662306a36Sopenharmony_ci	if (evergreen_mc_wait_for_idle(rdev)) {
406762306a36Sopenharmony_ci		dev_warn(rdev->dev, "Wait for MC idle timed out !\n");
406862306a36Sopenharmony_ci	}
406962306a36Sopenharmony_ci
407062306a36Sopenharmony_ci	/* set mclk/sclk to bypass */
407162306a36Sopenharmony_ci	si_set_clk_bypass_mode(rdev);
407262306a36Sopenharmony_ci	/* powerdown spll */
407362306a36Sopenharmony_ci	si_spll_powerdown(rdev);
407462306a36Sopenharmony_ci	/* disable BM */
407562306a36Sopenharmony_ci	pci_clear_master(rdev->pdev);
407662306a36Sopenharmony_ci	/* reset */
407762306a36Sopenharmony_ci	radeon_pci_config_reset(rdev);
407862306a36Sopenharmony_ci	/* wait for asic to come out of reset */
407962306a36Sopenharmony_ci	for (i = 0; i < rdev->usec_timeout; i++) {
408062306a36Sopenharmony_ci		if (RREG32(CONFIG_MEMSIZE) != 0xffffffff)
408162306a36Sopenharmony_ci			break;
408262306a36Sopenharmony_ci		udelay(1);
408362306a36Sopenharmony_ci	}
408462306a36Sopenharmony_ci}
408562306a36Sopenharmony_ci
408662306a36Sopenharmony_ciint si_asic_reset(struct radeon_device *rdev, bool hard)
408762306a36Sopenharmony_ci{
408862306a36Sopenharmony_ci	u32 reset_mask;
408962306a36Sopenharmony_ci
409062306a36Sopenharmony_ci	if (hard) {
409162306a36Sopenharmony_ci		si_gpu_pci_config_reset(rdev);
409262306a36Sopenharmony_ci		return 0;
409362306a36Sopenharmony_ci	}
409462306a36Sopenharmony_ci
409562306a36Sopenharmony_ci	reset_mask = si_gpu_check_soft_reset(rdev);
409662306a36Sopenharmony_ci
409762306a36Sopenharmony_ci	if (reset_mask)
409862306a36Sopenharmony_ci		r600_set_bios_scratch_engine_hung(rdev, true);
409962306a36Sopenharmony_ci
410062306a36Sopenharmony_ci	/* try soft reset */
410162306a36Sopenharmony_ci	si_gpu_soft_reset(rdev, reset_mask);
410262306a36Sopenharmony_ci
410362306a36Sopenharmony_ci	reset_mask = si_gpu_check_soft_reset(rdev);
410462306a36Sopenharmony_ci
410562306a36Sopenharmony_ci	/* try pci config reset */
410662306a36Sopenharmony_ci	if (reset_mask && radeon_hard_reset)
410762306a36Sopenharmony_ci		si_gpu_pci_config_reset(rdev);
410862306a36Sopenharmony_ci
410962306a36Sopenharmony_ci	reset_mask = si_gpu_check_soft_reset(rdev);
411062306a36Sopenharmony_ci
411162306a36Sopenharmony_ci	if (!reset_mask)
411262306a36Sopenharmony_ci		r600_set_bios_scratch_engine_hung(rdev, false);
411362306a36Sopenharmony_ci
411462306a36Sopenharmony_ci	return 0;
411562306a36Sopenharmony_ci}
411662306a36Sopenharmony_ci
411762306a36Sopenharmony_ci/**
411862306a36Sopenharmony_ci * si_gfx_is_lockup - Check if the GFX engine is locked up
411962306a36Sopenharmony_ci *
412062306a36Sopenharmony_ci * @rdev: radeon_device pointer
412162306a36Sopenharmony_ci * @ring: radeon_ring structure holding ring information
412262306a36Sopenharmony_ci *
412362306a36Sopenharmony_ci * Check if the GFX engine is locked up.
412462306a36Sopenharmony_ci * Returns true if the engine appears to be locked up, false if not.
412562306a36Sopenharmony_ci */
412662306a36Sopenharmony_cibool si_gfx_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring)
412762306a36Sopenharmony_ci{
412862306a36Sopenharmony_ci	u32 reset_mask = si_gpu_check_soft_reset(rdev);
412962306a36Sopenharmony_ci
413062306a36Sopenharmony_ci	if (!(reset_mask & (RADEON_RESET_GFX |
413162306a36Sopenharmony_ci			    RADEON_RESET_COMPUTE |
413262306a36Sopenharmony_ci			    RADEON_RESET_CP))) {
413362306a36Sopenharmony_ci		radeon_ring_lockup_update(rdev, ring);
413462306a36Sopenharmony_ci		return false;
413562306a36Sopenharmony_ci	}
413662306a36Sopenharmony_ci	return radeon_ring_test_lockup(rdev, ring);
413762306a36Sopenharmony_ci}
413862306a36Sopenharmony_ci
413962306a36Sopenharmony_ci/* MC */
414062306a36Sopenharmony_cistatic void si_mc_program(struct radeon_device *rdev)
414162306a36Sopenharmony_ci{
414262306a36Sopenharmony_ci	struct evergreen_mc_save save;
414362306a36Sopenharmony_ci	u32 tmp;
414462306a36Sopenharmony_ci	int i, j;
414562306a36Sopenharmony_ci
414662306a36Sopenharmony_ci	/* Initialize HDP */
414762306a36Sopenharmony_ci	for (i = 0, j = 0; i < 32; i++, j += 0x18) {
414862306a36Sopenharmony_ci		WREG32((0x2c14 + j), 0x00000000);
414962306a36Sopenharmony_ci		WREG32((0x2c18 + j), 0x00000000);
415062306a36Sopenharmony_ci		WREG32((0x2c1c + j), 0x00000000);
415162306a36Sopenharmony_ci		WREG32((0x2c20 + j), 0x00000000);
415262306a36Sopenharmony_ci		WREG32((0x2c24 + j), 0x00000000);
415362306a36Sopenharmony_ci	}
415462306a36Sopenharmony_ci	WREG32(HDP_REG_COHERENCY_FLUSH_CNTL, 0);
415562306a36Sopenharmony_ci
415662306a36Sopenharmony_ci	evergreen_mc_stop(rdev, &save);
415762306a36Sopenharmony_ci	if (radeon_mc_wait_for_idle(rdev)) {
415862306a36Sopenharmony_ci		dev_warn(rdev->dev, "Wait for MC idle timedout !\n");
415962306a36Sopenharmony_ci	}
416062306a36Sopenharmony_ci	if (!ASIC_IS_NODCE(rdev))
416162306a36Sopenharmony_ci		/* Lockout access through VGA aperture*/
416262306a36Sopenharmony_ci		WREG32(VGA_HDP_CONTROL, VGA_MEMORY_DISABLE);
416362306a36Sopenharmony_ci	/* Update configuration */
416462306a36Sopenharmony_ci	WREG32(MC_VM_SYSTEM_APERTURE_LOW_ADDR,
416562306a36Sopenharmony_ci	       rdev->mc.vram_start >> 12);
416662306a36Sopenharmony_ci	WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR,
416762306a36Sopenharmony_ci	       rdev->mc.vram_end >> 12);
416862306a36Sopenharmony_ci	WREG32(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR,
416962306a36Sopenharmony_ci	       rdev->vram_scratch.gpu_addr >> 12);
417062306a36Sopenharmony_ci	tmp = ((rdev->mc.vram_end >> 24) & 0xFFFF) << 16;
417162306a36Sopenharmony_ci	tmp |= ((rdev->mc.vram_start >> 24) & 0xFFFF);
417262306a36Sopenharmony_ci	WREG32(MC_VM_FB_LOCATION, tmp);
417362306a36Sopenharmony_ci	/* XXX double check these! */
417462306a36Sopenharmony_ci	WREG32(HDP_NONSURFACE_BASE, (rdev->mc.vram_start >> 8));
417562306a36Sopenharmony_ci	WREG32(HDP_NONSURFACE_INFO, (2 << 7) | (1 << 30));
417662306a36Sopenharmony_ci	WREG32(HDP_NONSURFACE_SIZE, 0x3FFFFFFF);
417762306a36Sopenharmony_ci	WREG32(MC_VM_AGP_BASE, 0);
417862306a36Sopenharmony_ci	WREG32(MC_VM_AGP_TOP, 0x0FFFFFFF);
417962306a36Sopenharmony_ci	WREG32(MC_VM_AGP_BOT, 0x0FFFFFFF);
418062306a36Sopenharmony_ci	if (radeon_mc_wait_for_idle(rdev)) {
418162306a36Sopenharmony_ci		dev_warn(rdev->dev, "Wait for MC idle timedout !\n");
418262306a36Sopenharmony_ci	}
418362306a36Sopenharmony_ci	evergreen_mc_resume(rdev, &save);
418462306a36Sopenharmony_ci	if (!ASIC_IS_NODCE(rdev)) {
418562306a36Sopenharmony_ci		/* we need to own VRAM, so turn off the VGA renderer here
418662306a36Sopenharmony_ci		 * to stop it overwriting our objects */
418762306a36Sopenharmony_ci		rv515_vga_render_disable(rdev);
418862306a36Sopenharmony_ci	}
418962306a36Sopenharmony_ci}
419062306a36Sopenharmony_ci
419162306a36Sopenharmony_civoid si_vram_gtt_location(struct radeon_device *rdev,
419262306a36Sopenharmony_ci			  struct radeon_mc *mc)
419362306a36Sopenharmony_ci{
419462306a36Sopenharmony_ci	if (mc->mc_vram_size > 0xFFC0000000ULL) {
419562306a36Sopenharmony_ci		/* leave room for at least 1024M GTT */
419662306a36Sopenharmony_ci		dev_warn(rdev->dev, "limiting VRAM\n");
419762306a36Sopenharmony_ci		mc->real_vram_size = 0xFFC0000000ULL;
419862306a36Sopenharmony_ci		mc->mc_vram_size = 0xFFC0000000ULL;
419962306a36Sopenharmony_ci	}
420062306a36Sopenharmony_ci	radeon_vram_location(rdev, &rdev->mc, 0);
420162306a36Sopenharmony_ci	rdev->mc.gtt_base_align = 0;
420262306a36Sopenharmony_ci	radeon_gtt_location(rdev, mc);
420362306a36Sopenharmony_ci}
420462306a36Sopenharmony_ci
420562306a36Sopenharmony_cistatic int si_mc_init(struct radeon_device *rdev)
420662306a36Sopenharmony_ci{
420762306a36Sopenharmony_ci	u32 tmp;
420862306a36Sopenharmony_ci	int chansize, numchan;
420962306a36Sopenharmony_ci
421062306a36Sopenharmony_ci	/* Get VRAM informations */
421162306a36Sopenharmony_ci	rdev->mc.vram_is_ddr = true;
421262306a36Sopenharmony_ci	tmp = RREG32(MC_ARB_RAMCFG);
421362306a36Sopenharmony_ci	if (tmp & CHANSIZE_OVERRIDE) {
421462306a36Sopenharmony_ci		chansize = 16;
421562306a36Sopenharmony_ci	} else if (tmp & CHANSIZE_MASK) {
421662306a36Sopenharmony_ci		chansize = 64;
421762306a36Sopenharmony_ci	} else {
421862306a36Sopenharmony_ci		chansize = 32;
421962306a36Sopenharmony_ci	}
422062306a36Sopenharmony_ci	tmp = RREG32(MC_SHARED_CHMAP);
422162306a36Sopenharmony_ci	switch ((tmp & NOOFCHAN_MASK) >> NOOFCHAN_SHIFT) {
422262306a36Sopenharmony_ci	case 0:
422362306a36Sopenharmony_ci	default:
422462306a36Sopenharmony_ci		numchan = 1;
422562306a36Sopenharmony_ci		break;
422662306a36Sopenharmony_ci	case 1:
422762306a36Sopenharmony_ci		numchan = 2;
422862306a36Sopenharmony_ci		break;
422962306a36Sopenharmony_ci	case 2:
423062306a36Sopenharmony_ci		numchan = 4;
423162306a36Sopenharmony_ci		break;
423262306a36Sopenharmony_ci	case 3:
423362306a36Sopenharmony_ci		numchan = 8;
423462306a36Sopenharmony_ci		break;
423562306a36Sopenharmony_ci	case 4:
423662306a36Sopenharmony_ci		numchan = 3;
423762306a36Sopenharmony_ci		break;
423862306a36Sopenharmony_ci	case 5:
423962306a36Sopenharmony_ci		numchan = 6;
424062306a36Sopenharmony_ci		break;
424162306a36Sopenharmony_ci	case 6:
424262306a36Sopenharmony_ci		numchan = 10;
424362306a36Sopenharmony_ci		break;
424462306a36Sopenharmony_ci	case 7:
424562306a36Sopenharmony_ci		numchan = 12;
424662306a36Sopenharmony_ci		break;
424762306a36Sopenharmony_ci	case 8:
424862306a36Sopenharmony_ci		numchan = 16;
424962306a36Sopenharmony_ci		break;
425062306a36Sopenharmony_ci	}
425162306a36Sopenharmony_ci	rdev->mc.vram_width = numchan * chansize;
425262306a36Sopenharmony_ci	/* Could aper size report 0 ? */
425362306a36Sopenharmony_ci	rdev->mc.aper_base = pci_resource_start(rdev->pdev, 0);
425462306a36Sopenharmony_ci	rdev->mc.aper_size = pci_resource_len(rdev->pdev, 0);
425562306a36Sopenharmony_ci	/* size in MB on si */
425662306a36Sopenharmony_ci	tmp = RREG32(CONFIG_MEMSIZE);
425762306a36Sopenharmony_ci	/* some boards may have garbage in the upper 16 bits */
425862306a36Sopenharmony_ci	if (tmp & 0xffff0000) {
425962306a36Sopenharmony_ci		DRM_INFO("Probable bad vram size: 0x%08x\n", tmp);
426062306a36Sopenharmony_ci		if (tmp & 0xffff)
426162306a36Sopenharmony_ci			tmp &= 0xffff;
426262306a36Sopenharmony_ci	}
426362306a36Sopenharmony_ci	rdev->mc.mc_vram_size = tmp * 1024ULL * 1024ULL;
426462306a36Sopenharmony_ci	rdev->mc.real_vram_size = rdev->mc.mc_vram_size;
426562306a36Sopenharmony_ci	rdev->mc.visible_vram_size = rdev->mc.aper_size;
426662306a36Sopenharmony_ci	si_vram_gtt_location(rdev, &rdev->mc);
426762306a36Sopenharmony_ci	radeon_update_bandwidth_info(rdev);
426862306a36Sopenharmony_ci
426962306a36Sopenharmony_ci	return 0;
427062306a36Sopenharmony_ci}
427162306a36Sopenharmony_ci
427262306a36Sopenharmony_ci/*
427362306a36Sopenharmony_ci * GART
427462306a36Sopenharmony_ci */
427562306a36Sopenharmony_civoid si_pcie_gart_tlb_flush(struct radeon_device *rdev)
427662306a36Sopenharmony_ci{
427762306a36Sopenharmony_ci	/* flush hdp cache */
427862306a36Sopenharmony_ci	WREG32(HDP_MEM_COHERENCY_FLUSH_CNTL, 0x1);
427962306a36Sopenharmony_ci
428062306a36Sopenharmony_ci	/* bits 0-15 are the VM contexts0-15 */
428162306a36Sopenharmony_ci	WREG32(VM_INVALIDATE_REQUEST, 1);
428262306a36Sopenharmony_ci}
428362306a36Sopenharmony_ci
428462306a36Sopenharmony_cistatic int si_pcie_gart_enable(struct radeon_device *rdev)
428562306a36Sopenharmony_ci{
428662306a36Sopenharmony_ci	int r, i;
428762306a36Sopenharmony_ci
428862306a36Sopenharmony_ci	if (rdev->gart.robj == NULL) {
428962306a36Sopenharmony_ci		dev_err(rdev->dev, "No VRAM object for PCIE GART.\n");
429062306a36Sopenharmony_ci		return -EINVAL;
429162306a36Sopenharmony_ci	}
429262306a36Sopenharmony_ci	r = radeon_gart_table_vram_pin(rdev);
429362306a36Sopenharmony_ci	if (r)
429462306a36Sopenharmony_ci		return r;
429562306a36Sopenharmony_ci	/* Setup TLB control */
429662306a36Sopenharmony_ci	WREG32(MC_VM_MX_L1_TLB_CNTL,
429762306a36Sopenharmony_ci	       (0xA << 7) |
429862306a36Sopenharmony_ci	       ENABLE_L1_TLB |
429962306a36Sopenharmony_ci	       ENABLE_L1_FRAGMENT_PROCESSING |
430062306a36Sopenharmony_ci	       SYSTEM_ACCESS_MODE_NOT_IN_SYS |
430162306a36Sopenharmony_ci	       ENABLE_ADVANCED_DRIVER_MODEL |
430262306a36Sopenharmony_ci	       SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU);
430362306a36Sopenharmony_ci	/* Setup L2 cache */
430462306a36Sopenharmony_ci	WREG32(VM_L2_CNTL, ENABLE_L2_CACHE |
430562306a36Sopenharmony_ci	       ENABLE_L2_FRAGMENT_PROCESSING |
430662306a36Sopenharmony_ci	       ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE |
430762306a36Sopenharmony_ci	       ENABLE_L2_PDE0_CACHE_LRU_UPDATE_BY_WRITE |
430862306a36Sopenharmony_ci	       EFFECTIVE_L2_QUEUE_SIZE(7) |
430962306a36Sopenharmony_ci	       CONTEXT1_IDENTITY_ACCESS_MODE(1));
431062306a36Sopenharmony_ci	WREG32(VM_L2_CNTL2, INVALIDATE_ALL_L1_TLBS | INVALIDATE_L2_CACHE);
431162306a36Sopenharmony_ci	WREG32(VM_L2_CNTL3, L2_CACHE_BIGK_ASSOCIATIVITY |
431262306a36Sopenharmony_ci	       BANK_SELECT(4) |
431362306a36Sopenharmony_ci	       L2_CACHE_BIGK_FRAGMENT_SIZE(4));
431462306a36Sopenharmony_ci	/* setup context0 */
431562306a36Sopenharmony_ci	WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR, rdev->mc.gtt_start >> 12);
431662306a36Sopenharmony_ci	WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR, rdev->mc.gtt_end >> 12);
431762306a36Sopenharmony_ci	WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR, rdev->gart.table_addr >> 12);
431862306a36Sopenharmony_ci	WREG32(VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR,
431962306a36Sopenharmony_ci			(u32)(rdev->dummy_page.addr >> 12));
432062306a36Sopenharmony_ci	WREG32(VM_CONTEXT0_CNTL2, 0);
432162306a36Sopenharmony_ci	WREG32(VM_CONTEXT0_CNTL, (ENABLE_CONTEXT | PAGE_TABLE_DEPTH(0) |
432262306a36Sopenharmony_ci				  RANGE_PROTECTION_FAULT_ENABLE_DEFAULT));
432362306a36Sopenharmony_ci
432462306a36Sopenharmony_ci	WREG32(0x15D4, 0);
432562306a36Sopenharmony_ci	WREG32(0x15D8, 0);
432662306a36Sopenharmony_ci	WREG32(0x15DC, 0);
432762306a36Sopenharmony_ci
432862306a36Sopenharmony_ci	/* empty context1-15 */
432962306a36Sopenharmony_ci	/* set vm size, must be a multiple of 4 */
433062306a36Sopenharmony_ci	WREG32(VM_CONTEXT1_PAGE_TABLE_START_ADDR, 0);
433162306a36Sopenharmony_ci	WREG32(VM_CONTEXT1_PAGE_TABLE_END_ADDR, rdev->vm_manager.max_pfn - 1);
433262306a36Sopenharmony_ci	/* Assign the pt base to something valid for now; the pts used for
433362306a36Sopenharmony_ci	 * the VMs are determined by the application and setup and assigned
433462306a36Sopenharmony_ci	 * on the fly in the vm part of radeon_gart.c
433562306a36Sopenharmony_ci	 */
433662306a36Sopenharmony_ci	for (i = 1; i < 16; i++) {
433762306a36Sopenharmony_ci		if (i < 8)
433862306a36Sopenharmony_ci			WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (i << 2),
433962306a36Sopenharmony_ci			       rdev->vm_manager.saved_table_addr[i]);
434062306a36Sopenharmony_ci		else
434162306a36Sopenharmony_ci			WREG32(VM_CONTEXT8_PAGE_TABLE_BASE_ADDR + ((i - 8) << 2),
434262306a36Sopenharmony_ci			       rdev->vm_manager.saved_table_addr[i]);
434362306a36Sopenharmony_ci	}
434462306a36Sopenharmony_ci
434562306a36Sopenharmony_ci	/* enable context1-15 */
434662306a36Sopenharmony_ci	WREG32(VM_CONTEXT1_PROTECTION_FAULT_DEFAULT_ADDR,
434762306a36Sopenharmony_ci	       (u32)(rdev->dummy_page.addr >> 12));
434862306a36Sopenharmony_ci	WREG32(VM_CONTEXT1_CNTL2, 4);
434962306a36Sopenharmony_ci	WREG32(VM_CONTEXT1_CNTL, ENABLE_CONTEXT | PAGE_TABLE_DEPTH(1) |
435062306a36Sopenharmony_ci				PAGE_TABLE_BLOCK_SIZE(radeon_vm_block_size - 9) |
435162306a36Sopenharmony_ci				RANGE_PROTECTION_FAULT_ENABLE_INTERRUPT |
435262306a36Sopenharmony_ci				RANGE_PROTECTION_FAULT_ENABLE_DEFAULT |
435362306a36Sopenharmony_ci				DUMMY_PAGE_PROTECTION_FAULT_ENABLE_INTERRUPT |
435462306a36Sopenharmony_ci				DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT |
435562306a36Sopenharmony_ci				PDE0_PROTECTION_FAULT_ENABLE_INTERRUPT |
435662306a36Sopenharmony_ci				PDE0_PROTECTION_FAULT_ENABLE_DEFAULT |
435762306a36Sopenharmony_ci				VALID_PROTECTION_FAULT_ENABLE_INTERRUPT |
435862306a36Sopenharmony_ci				VALID_PROTECTION_FAULT_ENABLE_DEFAULT |
435962306a36Sopenharmony_ci				READ_PROTECTION_FAULT_ENABLE_INTERRUPT |
436062306a36Sopenharmony_ci				READ_PROTECTION_FAULT_ENABLE_DEFAULT |
436162306a36Sopenharmony_ci				WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT |
436262306a36Sopenharmony_ci				WRITE_PROTECTION_FAULT_ENABLE_DEFAULT);
436362306a36Sopenharmony_ci
436462306a36Sopenharmony_ci	si_pcie_gart_tlb_flush(rdev);
436562306a36Sopenharmony_ci	DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n",
436662306a36Sopenharmony_ci		 (unsigned)(rdev->mc.gtt_size >> 20),
436762306a36Sopenharmony_ci		 (unsigned long long)rdev->gart.table_addr);
436862306a36Sopenharmony_ci	rdev->gart.ready = true;
436962306a36Sopenharmony_ci	return 0;
437062306a36Sopenharmony_ci}
437162306a36Sopenharmony_ci
437262306a36Sopenharmony_cistatic void si_pcie_gart_disable(struct radeon_device *rdev)
437362306a36Sopenharmony_ci{
437462306a36Sopenharmony_ci	unsigned i;
437562306a36Sopenharmony_ci
437662306a36Sopenharmony_ci	for (i = 1; i < 16; ++i) {
437762306a36Sopenharmony_ci		uint32_t reg;
437862306a36Sopenharmony_ci		if (i < 8)
437962306a36Sopenharmony_ci			reg = VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (i << 2);
438062306a36Sopenharmony_ci		else
438162306a36Sopenharmony_ci			reg = VM_CONTEXT8_PAGE_TABLE_BASE_ADDR + ((i - 8) << 2);
438262306a36Sopenharmony_ci		rdev->vm_manager.saved_table_addr[i] = RREG32(reg);
438362306a36Sopenharmony_ci	}
438462306a36Sopenharmony_ci
438562306a36Sopenharmony_ci	/* Disable all tables */
438662306a36Sopenharmony_ci	WREG32(VM_CONTEXT0_CNTL, 0);
438762306a36Sopenharmony_ci	WREG32(VM_CONTEXT1_CNTL, 0);
438862306a36Sopenharmony_ci	/* Setup TLB control */
438962306a36Sopenharmony_ci	WREG32(MC_VM_MX_L1_TLB_CNTL, SYSTEM_ACCESS_MODE_NOT_IN_SYS |
439062306a36Sopenharmony_ci	       SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU);
439162306a36Sopenharmony_ci	/* Setup L2 cache */
439262306a36Sopenharmony_ci	WREG32(VM_L2_CNTL, ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE |
439362306a36Sopenharmony_ci	       ENABLE_L2_PDE0_CACHE_LRU_UPDATE_BY_WRITE |
439462306a36Sopenharmony_ci	       EFFECTIVE_L2_QUEUE_SIZE(7) |
439562306a36Sopenharmony_ci	       CONTEXT1_IDENTITY_ACCESS_MODE(1));
439662306a36Sopenharmony_ci	WREG32(VM_L2_CNTL2, 0);
439762306a36Sopenharmony_ci	WREG32(VM_L2_CNTL3, L2_CACHE_BIGK_ASSOCIATIVITY |
439862306a36Sopenharmony_ci	       L2_CACHE_BIGK_FRAGMENT_SIZE(0));
439962306a36Sopenharmony_ci	radeon_gart_table_vram_unpin(rdev);
440062306a36Sopenharmony_ci}
440162306a36Sopenharmony_ci
440262306a36Sopenharmony_cistatic void si_pcie_gart_fini(struct radeon_device *rdev)
440362306a36Sopenharmony_ci{
440462306a36Sopenharmony_ci	si_pcie_gart_disable(rdev);
440562306a36Sopenharmony_ci	radeon_gart_table_vram_free(rdev);
440662306a36Sopenharmony_ci	radeon_gart_fini(rdev);
440762306a36Sopenharmony_ci}
440862306a36Sopenharmony_ci
440962306a36Sopenharmony_ci/* vm parser */
441062306a36Sopenharmony_cistatic bool si_vm_reg_valid(u32 reg)
441162306a36Sopenharmony_ci{
441262306a36Sopenharmony_ci	/* context regs are fine */
441362306a36Sopenharmony_ci	if (reg >= 0x28000)
441462306a36Sopenharmony_ci		return true;
441562306a36Sopenharmony_ci
441662306a36Sopenharmony_ci	/* shader regs are also fine */
441762306a36Sopenharmony_ci	if (reg >= 0xB000 && reg < 0xC000)
441862306a36Sopenharmony_ci		return true;
441962306a36Sopenharmony_ci
442062306a36Sopenharmony_ci	/* check config regs */
442162306a36Sopenharmony_ci	switch (reg) {
442262306a36Sopenharmony_ci	case GRBM_GFX_INDEX:
442362306a36Sopenharmony_ci	case CP_STRMOUT_CNTL:
442462306a36Sopenharmony_ci	case VGT_VTX_VECT_EJECT_REG:
442562306a36Sopenharmony_ci	case VGT_CACHE_INVALIDATION:
442662306a36Sopenharmony_ci	case VGT_ESGS_RING_SIZE:
442762306a36Sopenharmony_ci	case VGT_GSVS_RING_SIZE:
442862306a36Sopenharmony_ci	case VGT_GS_VERTEX_REUSE:
442962306a36Sopenharmony_ci	case VGT_PRIMITIVE_TYPE:
443062306a36Sopenharmony_ci	case VGT_INDEX_TYPE:
443162306a36Sopenharmony_ci	case VGT_NUM_INDICES:
443262306a36Sopenharmony_ci	case VGT_NUM_INSTANCES:
443362306a36Sopenharmony_ci	case VGT_TF_RING_SIZE:
443462306a36Sopenharmony_ci	case VGT_HS_OFFCHIP_PARAM:
443562306a36Sopenharmony_ci	case VGT_TF_MEMORY_BASE:
443662306a36Sopenharmony_ci	case PA_CL_ENHANCE:
443762306a36Sopenharmony_ci	case PA_SU_LINE_STIPPLE_VALUE:
443862306a36Sopenharmony_ci	case PA_SC_LINE_STIPPLE_STATE:
443962306a36Sopenharmony_ci	case PA_SC_ENHANCE:
444062306a36Sopenharmony_ci	case SQC_CACHES:
444162306a36Sopenharmony_ci	case SPI_STATIC_THREAD_MGMT_1:
444262306a36Sopenharmony_ci	case SPI_STATIC_THREAD_MGMT_2:
444362306a36Sopenharmony_ci	case SPI_STATIC_THREAD_MGMT_3:
444462306a36Sopenharmony_ci	case SPI_PS_MAX_WAVE_ID:
444562306a36Sopenharmony_ci	case SPI_CONFIG_CNTL:
444662306a36Sopenharmony_ci	case SPI_CONFIG_CNTL_1:
444762306a36Sopenharmony_ci	case TA_CNTL_AUX:
444862306a36Sopenharmony_ci	case TA_CS_BC_BASE_ADDR:
444962306a36Sopenharmony_ci		return true;
445062306a36Sopenharmony_ci	default:
445162306a36Sopenharmony_ci		DRM_ERROR("Invalid register 0x%x in CS\n", reg);
445262306a36Sopenharmony_ci		return false;
445362306a36Sopenharmony_ci	}
445462306a36Sopenharmony_ci}
445562306a36Sopenharmony_ci
445662306a36Sopenharmony_cistatic int si_vm_packet3_ce_check(struct radeon_device *rdev,
445762306a36Sopenharmony_ci				  u32 *ib, struct radeon_cs_packet *pkt)
445862306a36Sopenharmony_ci{
445962306a36Sopenharmony_ci	switch (pkt->opcode) {
446062306a36Sopenharmony_ci	case PACKET3_NOP:
446162306a36Sopenharmony_ci	case PACKET3_SET_BASE:
446262306a36Sopenharmony_ci	case PACKET3_SET_CE_DE_COUNTERS:
446362306a36Sopenharmony_ci	case PACKET3_LOAD_CONST_RAM:
446462306a36Sopenharmony_ci	case PACKET3_WRITE_CONST_RAM:
446562306a36Sopenharmony_ci	case PACKET3_WRITE_CONST_RAM_OFFSET:
446662306a36Sopenharmony_ci	case PACKET3_DUMP_CONST_RAM:
446762306a36Sopenharmony_ci	case PACKET3_INCREMENT_CE_COUNTER:
446862306a36Sopenharmony_ci	case PACKET3_WAIT_ON_DE_COUNTER:
446962306a36Sopenharmony_ci	case PACKET3_CE_WRITE:
447062306a36Sopenharmony_ci		break;
447162306a36Sopenharmony_ci	default:
447262306a36Sopenharmony_ci		DRM_ERROR("Invalid CE packet3: 0x%x\n", pkt->opcode);
447362306a36Sopenharmony_ci		return -EINVAL;
447462306a36Sopenharmony_ci	}
447562306a36Sopenharmony_ci	return 0;
447662306a36Sopenharmony_ci}
447762306a36Sopenharmony_ci
447862306a36Sopenharmony_cistatic int si_vm_packet3_cp_dma_check(u32 *ib, u32 idx)
447962306a36Sopenharmony_ci{
448062306a36Sopenharmony_ci	u32 start_reg, reg, i;
448162306a36Sopenharmony_ci	u32 command = ib[idx + 4];
448262306a36Sopenharmony_ci	u32 info = ib[idx + 1];
448362306a36Sopenharmony_ci	u32 idx_value = ib[idx];
448462306a36Sopenharmony_ci	if (command & PACKET3_CP_DMA_CMD_SAS) {
448562306a36Sopenharmony_ci		/* src address space is register */
448662306a36Sopenharmony_ci		if (((info & 0x60000000) >> 29) == 0) {
448762306a36Sopenharmony_ci			start_reg = idx_value << 2;
448862306a36Sopenharmony_ci			if (command & PACKET3_CP_DMA_CMD_SAIC) {
448962306a36Sopenharmony_ci				reg = start_reg;
449062306a36Sopenharmony_ci				if (!si_vm_reg_valid(reg)) {
449162306a36Sopenharmony_ci					DRM_ERROR("CP DMA Bad SRC register\n");
449262306a36Sopenharmony_ci					return -EINVAL;
449362306a36Sopenharmony_ci				}
449462306a36Sopenharmony_ci			} else {
449562306a36Sopenharmony_ci				for (i = 0; i < (command & 0x1fffff); i++) {
449662306a36Sopenharmony_ci					reg = start_reg + (4 * i);
449762306a36Sopenharmony_ci					if (!si_vm_reg_valid(reg)) {
449862306a36Sopenharmony_ci						DRM_ERROR("CP DMA Bad SRC register\n");
449962306a36Sopenharmony_ci						return -EINVAL;
450062306a36Sopenharmony_ci					}
450162306a36Sopenharmony_ci				}
450262306a36Sopenharmony_ci			}
450362306a36Sopenharmony_ci		}
450462306a36Sopenharmony_ci	}
450562306a36Sopenharmony_ci	if (command & PACKET3_CP_DMA_CMD_DAS) {
450662306a36Sopenharmony_ci		/* dst address space is register */
450762306a36Sopenharmony_ci		if (((info & 0x00300000) >> 20) == 0) {
450862306a36Sopenharmony_ci			start_reg = ib[idx + 2];
450962306a36Sopenharmony_ci			if (command & PACKET3_CP_DMA_CMD_DAIC) {
451062306a36Sopenharmony_ci				reg = start_reg;
451162306a36Sopenharmony_ci				if (!si_vm_reg_valid(reg)) {
451262306a36Sopenharmony_ci					DRM_ERROR("CP DMA Bad DST register\n");
451362306a36Sopenharmony_ci					return -EINVAL;
451462306a36Sopenharmony_ci				}
451562306a36Sopenharmony_ci			} else {
451662306a36Sopenharmony_ci				for (i = 0; i < (command & 0x1fffff); i++) {
451762306a36Sopenharmony_ci					reg = start_reg + (4 * i);
451862306a36Sopenharmony_ci					if (!si_vm_reg_valid(reg)) {
451962306a36Sopenharmony_ci						DRM_ERROR("CP DMA Bad DST register\n");
452062306a36Sopenharmony_ci						return -EINVAL;
452162306a36Sopenharmony_ci					}
452262306a36Sopenharmony_ci				}
452362306a36Sopenharmony_ci			}
452462306a36Sopenharmony_ci		}
452562306a36Sopenharmony_ci	}
452662306a36Sopenharmony_ci	return 0;
452762306a36Sopenharmony_ci}
452862306a36Sopenharmony_ci
452962306a36Sopenharmony_cistatic int si_vm_packet3_gfx_check(struct radeon_device *rdev,
453062306a36Sopenharmony_ci				   u32 *ib, struct radeon_cs_packet *pkt)
453162306a36Sopenharmony_ci{
453262306a36Sopenharmony_ci	int r;
453362306a36Sopenharmony_ci	u32 idx = pkt->idx + 1;
453462306a36Sopenharmony_ci	u32 idx_value = ib[idx];
453562306a36Sopenharmony_ci	u32 start_reg, end_reg, reg, i;
453662306a36Sopenharmony_ci
453762306a36Sopenharmony_ci	switch (pkt->opcode) {
453862306a36Sopenharmony_ci	case PACKET3_NOP:
453962306a36Sopenharmony_ci	case PACKET3_SET_BASE:
454062306a36Sopenharmony_ci	case PACKET3_CLEAR_STATE:
454162306a36Sopenharmony_ci	case PACKET3_INDEX_BUFFER_SIZE:
454262306a36Sopenharmony_ci	case PACKET3_DISPATCH_DIRECT:
454362306a36Sopenharmony_ci	case PACKET3_DISPATCH_INDIRECT:
454462306a36Sopenharmony_ci	case PACKET3_ALLOC_GDS:
454562306a36Sopenharmony_ci	case PACKET3_WRITE_GDS_RAM:
454662306a36Sopenharmony_ci	case PACKET3_ATOMIC_GDS:
454762306a36Sopenharmony_ci	case PACKET3_ATOMIC:
454862306a36Sopenharmony_ci	case PACKET3_OCCLUSION_QUERY:
454962306a36Sopenharmony_ci	case PACKET3_SET_PREDICATION:
455062306a36Sopenharmony_ci	case PACKET3_COND_EXEC:
455162306a36Sopenharmony_ci	case PACKET3_PRED_EXEC:
455262306a36Sopenharmony_ci	case PACKET3_DRAW_INDIRECT:
455362306a36Sopenharmony_ci	case PACKET3_DRAW_INDEX_INDIRECT:
455462306a36Sopenharmony_ci	case PACKET3_INDEX_BASE:
455562306a36Sopenharmony_ci	case PACKET3_DRAW_INDEX_2:
455662306a36Sopenharmony_ci	case PACKET3_CONTEXT_CONTROL:
455762306a36Sopenharmony_ci	case PACKET3_INDEX_TYPE:
455862306a36Sopenharmony_ci	case PACKET3_DRAW_INDIRECT_MULTI:
455962306a36Sopenharmony_ci	case PACKET3_DRAW_INDEX_AUTO:
456062306a36Sopenharmony_ci	case PACKET3_DRAW_INDEX_IMMD:
456162306a36Sopenharmony_ci	case PACKET3_NUM_INSTANCES:
456262306a36Sopenharmony_ci	case PACKET3_DRAW_INDEX_MULTI_AUTO:
456362306a36Sopenharmony_ci	case PACKET3_STRMOUT_BUFFER_UPDATE:
456462306a36Sopenharmony_ci	case PACKET3_DRAW_INDEX_OFFSET_2:
456562306a36Sopenharmony_ci	case PACKET3_DRAW_INDEX_MULTI_ELEMENT:
456662306a36Sopenharmony_ci	case PACKET3_DRAW_INDEX_INDIRECT_MULTI:
456762306a36Sopenharmony_ci	case PACKET3_MPEG_INDEX:
456862306a36Sopenharmony_ci	case PACKET3_WAIT_REG_MEM:
456962306a36Sopenharmony_ci	case PACKET3_MEM_WRITE:
457062306a36Sopenharmony_ci	case PACKET3_PFP_SYNC_ME:
457162306a36Sopenharmony_ci	case PACKET3_SURFACE_SYNC:
457262306a36Sopenharmony_ci	case PACKET3_EVENT_WRITE:
457362306a36Sopenharmony_ci	case PACKET3_EVENT_WRITE_EOP:
457462306a36Sopenharmony_ci	case PACKET3_EVENT_WRITE_EOS:
457562306a36Sopenharmony_ci	case PACKET3_SET_CONTEXT_REG:
457662306a36Sopenharmony_ci	case PACKET3_SET_CONTEXT_REG_INDIRECT:
457762306a36Sopenharmony_ci	case PACKET3_SET_SH_REG:
457862306a36Sopenharmony_ci	case PACKET3_SET_SH_REG_OFFSET:
457962306a36Sopenharmony_ci	case PACKET3_INCREMENT_DE_COUNTER:
458062306a36Sopenharmony_ci	case PACKET3_WAIT_ON_CE_COUNTER:
458162306a36Sopenharmony_ci	case PACKET3_WAIT_ON_AVAIL_BUFFER:
458262306a36Sopenharmony_ci	case PACKET3_ME_WRITE:
458362306a36Sopenharmony_ci		break;
458462306a36Sopenharmony_ci	case PACKET3_COPY_DATA:
458562306a36Sopenharmony_ci		if ((idx_value & 0xf00) == 0) {
458662306a36Sopenharmony_ci			reg = ib[idx + 3] * 4;
458762306a36Sopenharmony_ci			if (!si_vm_reg_valid(reg))
458862306a36Sopenharmony_ci				return -EINVAL;
458962306a36Sopenharmony_ci		}
459062306a36Sopenharmony_ci		break;
459162306a36Sopenharmony_ci	case PACKET3_WRITE_DATA:
459262306a36Sopenharmony_ci		if ((idx_value & 0xf00) == 0) {
459362306a36Sopenharmony_ci			start_reg = ib[idx + 1] * 4;
459462306a36Sopenharmony_ci			if (idx_value & 0x10000) {
459562306a36Sopenharmony_ci				if (!si_vm_reg_valid(start_reg))
459662306a36Sopenharmony_ci					return -EINVAL;
459762306a36Sopenharmony_ci			} else {
459862306a36Sopenharmony_ci				for (i = 0; i < (pkt->count - 2); i++) {
459962306a36Sopenharmony_ci					reg = start_reg + (4 * i);
460062306a36Sopenharmony_ci					if (!si_vm_reg_valid(reg))
460162306a36Sopenharmony_ci						return -EINVAL;
460262306a36Sopenharmony_ci				}
460362306a36Sopenharmony_ci			}
460462306a36Sopenharmony_ci		}
460562306a36Sopenharmony_ci		break;
460662306a36Sopenharmony_ci	case PACKET3_COND_WRITE:
460762306a36Sopenharmony_ci		if (idx_value & 0x100) {
460862306a36Sopenharmony_ci			reg = ib[idx + 5] * 4;
460962306a36Sopenharmony_ci			if (!si_vm_reg_valid(reg))
461062306a36Sopenharmony_ci				return -EINVAL;
461162306a36Sopenharmony_ci		}
461262306a36Sopenharmony_ci		break;
461362306a36Sopenharmony_ci	case PACKET3_COPY_DW:
461462306a36Sopenharmony_ci		if (idx_value & 0x2) {
461562306a36Sopenharmony_ci			reg = ib[idx + 3] * 4;
461662306a36Sopenharmony_ci			if (!si_vm_reg_valid(reg))
461762306a36Sopenharmony_ci				return -EINVAL;
461862306a36Sopenharmony_ci		}
461962306a36Sopenharmony_ci		break;
462062306a36Sopenharmony_ci	case PACKET3_SET_CONFIG_REG:
462162306a36Sopenharmony_ci		start_reg = (idx_value << 2) + PACKET3_SET_CONFIG_REG_START;
462262306a36Sopenharmony_ci		end_reg = 4 * pkt->count + start_reg - 4;
462362306a36Sopenharmony_ci		if ((start_reg < PACKET3_SET_CONFIG_REG_START) ||
462462306a36Sopenharmony_ci		    (start_reg >= PACKET3_SET_CONFIG_REG_END) ||
462562306a36Sopenharmony_ci		    (end_reg >= PACKET3_SET_CONFIG_REG_END)) {
462662306a36Sopenharmony_ci			DRM_ERROR("bad PACKET3_SET_CONFIG_REG\n");
462762306a36Sopenharmony_ci			return -EINVAL;
462862306a36Sopenharmony_ci		}
462962306a36Sopenharmony_ci		for (i = 0; i < pkt->count; i++) {
463062306a36Sopenharmony_ci			reg = start_reg + (4 * i);
463162306a36Sopenharmony_ci			if (!si_vm_reg_valid(reg))
463262306a36Sopenharmony_ci				return -EINVAL;
463362306a36Sopenharmony_ci		}
463462306a36Sopenharmony_ci		break;
463562306a36Sopenharmony_ci	case PACKET3_CP_DMA:
463662306a36Sopenharmony_ci		r = si_vm_packet3_cp_dma_check(ib, idx);
463762306a36Sopenharmony_ci		if (r)
463862306a36Sopenharmony_ci			return r;
463962306a36Sopenharmony_ci		break;
464062306a36Sopenharmony_ci	default:
464162306a36Sopenharmony_ci		DRM_ERROR("Invalid GFX packet3: 0x%x\n", pkt->opcode);
464262306a36Sopenharmony_ci		return -EINVAL;
464362306a36Sopenharmony_ci	}
464462306a36Sopenharmony_ci	return 0;
464562306a36Sopenharmony_ci}
464662306a36Sopenharmony_ci
464762306a36Sopenharmony_cistatic int si_vm_packet3_compute_check(struct radeon_device *rdev,
464862306a36Sopenharmony_ci				       u32 *ib, struct radeon_cs_packet *pkt)
464962306a36Sopenharmony_ci{
465062306a36Sopenharmony_ci	int r;
465162306a36Sopenharmony_ci	u32 idx = pkt->idx + 1;
465262306a36Sopenharmony_ci	u32 idx_value = ib[idx];
465362306a36Sopenharmony_ci	u32 start_reg, reg, i;
465462306a36Sopenharmony_ci
465562306a36Sopenharmony_ci	switch (pkt->opcode) {
465662306a36Sopenharmony_ci	case PACKET3_NOP:
465762306a36Sopenharmony_ci	case PACKET3_SET_BASE:
465862306a36Sopenharmony_ci	case PACKET3_CLEAR_STATE:
465962306a36Sopenharmony_ci	case PACKET3_DISPATCH_DIRECT:
466062306a36Sopenharmony_ci	case PACKET3_DISPATCH_INDIRECT:
466162306a36Sopenharmony_ci	case PACKET3_ALLOC_GDS:
466262306a36Sopenharmony_ci	case PACKET3_WRITE_GDS_RAM:
466362306a36Sopenharmony_ci	case PACKET3_ATOMIC_GDS:
466462306a36Sopenharmony_ci	case PACKET3_ATOMIC:
466562306a36Sopenharmony_ci	case PACKET3_OCCLUSION_QUERY:
466662306a36Sopenharmony_ci	case PACKET3_SET_PREDICATION:
466762306a36Sopenharmony_ci	case PACKET3_COND_EXEC:
466862306a36Sopenharmony_ci	case PACKET3_PRED_EXEC:
466962306a36Sopenharmony_ci	case PACKET3_CONTEXT_CONTROL:
467062306a36Sopenharmony_ci	case PACKET3_STRMOUT_BUFFER_UPDATE:
467162306a36Sopenharmony_ci	case PACKET3_WAIT_REG_MEM:
467262306a36Sopenharmony_ci	case PACKET3_MEM_WRITE:
467362306a36Sopenharmony_ci	case PACKET3_PFP_SYNC_ME:
467462306a36Sopenharmony_ci	case PACKET3_SURFACE_SYNC:
467562306a36Sopenharmony_ci	case PACKET3_EVENT_WRITE:
467662306a36Sopenharmony_ci	case PACKET3_EVENT_WRITE_EOP:
467762306a36Sopenharmony_ci	case PACKET3_EVENT_WRITE_EOS:
467862306a36Sopenharmony_ci	case PACKET3_SET_CONTEXT_REG:
467962306a36Sopenharmony_ci	case PACKET3_SET_CONTEXT_REG_INDIRECT:
468062306a36Sopenharmony_ci	case PACKET3_SET_SH_REG:
468162306a36Sopenharmony_ci	case PACKET3_SET_SH_REG_OFFSET:
468262306a36Sopenharmony_ci	case PACKET3_INCREMENT_DE_COUNTER:
468362306a36Sopenharmony_ci	case PACKET3_WAIT_ON_CE_COUNTER:
468462306a36Sopenharmony_ci	case PACKET3_WAIT_ON_AVAIL_BUFFER:
468562306a36Sopenharmony_ci	case PACKET3_ME_WRITE:
468662306a36Sopenharmony_ci		break;
468762306a36Sopenharmony_ci	case PACKET3_COPY_DATA:
468862306a36Sopenharmony_ci		if ((idx_value & 0xf00) == 0) {
468962306a36Sopenharmony_ci			reg = ib[idx + 3] * 4;
469062306a36Sopenharmony_ci			if (!si_vm_reg_valid(reg))
469162306a36Sopenharmony_ci				return -EINVAL;
469262306a36Sopenharmony_ci		}
469362306a36Sopenharmony_ci		break;
469462306a36Sopenharmony_ci	case PACKET3_WRITE_DATA:
469562306a36Sopenharmony_ci		if ((idx_value & 0xf00) == 0) {
469662306a36Sopenharmony_ci			start_reg = ib[idx + 1] * 4;
469762306a36Sopenharmony_ci			if (idx_value & 0x10000) {
469862306a36Sopenharmony_ci				if (!si_vm_reg_valid(start_reg))
469962306a36Sopenharmony_ci					return -EINVAL;
470062306a36Sopenharmony_ci			} else {
470162306a36Sopenharmony_ci				for (i = 0; i < (pkt->count - 2); i++) {
470262306a36Sopenharmony_ci					reg = start_reg + (4 * i);
470362306a36Sopenharmony_ci					if (!si_vm_reg_valid(reg))
470462306a36Sopenharmony_ci						return -EINVAL;
470562306a36Sopenharmony_ci				}
470662306a36Sopenharmony_ci			}
470762306a36Sopenharmony_ci		}
470862306a36Sopenharmony_ci		break;
470962306a36Sopenharmony_ci	case PACKET3_COND_WRITE:
471062306a36Sopenharmony_ci		if (idx_value & 0x100) {
471162306a36Sopenharmony_ci			reg = ib[idx + 5] * 4;
471262306a36Sopenharmony_ci			if (!si_vm_reg_valid(reg))
471362306a36Sopenharmony_ci				return -EINVAL;
471462306a36Sopenharmony_ci		}
471562306a36Sopenharmony_ci		break;
471662306a36Sopenharmony_ci	case PACKET3_COPY_DW:
471762306a36Sopenharmony_ci		if (idx_value & 0x2) {
471862306a36Sopenharmony_ci			reg = ib[idx + 3] * 4;
471962306a36Sopenharmony_ci			if (!si_vm_reg_valid(reg))
472062306a36Sopenharmony_ci				return -EINVAL;
472162306a36Sopenharmony_ci		}
472262306a36Sopenharmony_ci		break;
472362306a36Sopenharmony_ci	case PACKET3_CP_DMA:
472462306a36Sopenharmony_ci		r = si_vm_packet3_cp_dma_check(ib, idx);
472562306a36Sopenharmony_ci		if (r)
472662306a36Sopenharmony_ci			return r;
472762306a36Sopenharmony_ci		break;
472862306a36Sopenharmony_ci	default:
472962306a36Sopenharmony_ci		DRM_ERROR("Invalid Compute packet3: 0x%x\n", pkt->opcode);
473062306a36Sopenharmony_ci		return -EINVAL;
473162306a36Sopenharmony_ci	}
473262306a36Sopenharmony_ci	return 0;
473362306a36Sopenharmony_ci}
473462306a36Sopenharmony_ci
473562306a36Sopenharmony_ciint si_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib)
473662306a36Sopenharmony_ci{
473762306a36Sopenharmony_ci	int ret = 0;
473862306a36Sopenharmony_ci	u32 idx = 0, i;
473962306a36Sopenharmony_ci	struct radeon_cs_packet pkt;
474062306a36Sopenharmony_ci
474162306a36Sopenharmony_ci	do {
474262306a36Sopenharmony_ci		pkt.idx = idx;
474362306a36Sopenharmony_ci		pkt.type = RADEON_CP_PACKET_GET_TYPE(ib->ptr[idx]);
474462306a36Sopenharmony_ci		pkt.count = RADEON_CP_PACKET_GET_COUNT(ib->ptr[idx]);
474562306a36Sopenharmony_ci		pkt.one_reg_wr = 0;
474662306a36Sopenharmony_ci		switch (pkt.type) {
474762306a36Sopenharmony_ci		case RADEON_PACKET_TYPE0:
474862306a36Sopenharmony_ci			dev_err(rdev->dev, "Packet0 not allowed!\n");
474962306a36Sopenharmony_ci			ret = -EINVAL;
475062306a36Sopenharmony_ci			break;
475162306a36Sopenharmony_ci		case RADEON_PACKET_TYPE2:
475262306a36Sopenharmony_ci			idx += 1;
475362306a36Sopenharmony_ci			break;
475462306a36Sopenharmony_ci		case RADEON_PACKET_TYPE3:
475562306a36Sopenharmony_ci			pkt.opcode = RADEON_CP_PACKET3_GET_OPCODE(ib->ptr[idx]);
475662306a36Sopenharmony_ci			if (ib->is_const_ib)
475762306a36Sopenharmony_ci				ret = si_vm_packet3_ce_check(rdev, ib->ptr, &pkt);
475862306a36Sopenharmony_ci			else {
475962306a36Sopenharmony_ci				switch (ib->ring) {
476062306a36Sopenharmony_ci				case RADEON_RING_TYPE_GFX_INDEX:
476162306a36Sopenharmony_ci					ret = si_vm_packet3_gfx_check(rdev, ib->ptr, &pkt);
476262306a36Sopenharmony_ci					break;
476362306a36Sopenharmony_ci				case CAYMAN_RING_TYPE_CP1_INDEX:
476462306a36Sopenharmony_ci				case CAYMAN_RING_TYPE_CP2_INDEX:
476562306a36Sopenharmony_ci					ret = si_vm_packet3_compute_check(rdev, ib->ptr, &pkt);
476662306a36Sopenharmony_ci					break;
476762306a36Sopenharmony_ci				default:
476862306a36Sopenharmony_ci					dev_err(rdev->dev, "Non-PM4 ring %d !\n", ib->ring);
476962306a36Sopenharmony_ci					ret = -EINVAL;
477062306a36Sopenharmony_ci					break;
477162306a36Sopenharmony_ci				}
477262306a36Sopenharmony_ci			}
477362306a36Sopenharmony_ci			idx += pkt.count + 2;
477462306a36Sopenharmony_ci			break;
477562306a36Sopenharmony_ci		default:
477662306a36Sopenharmony_ci			dev_err(rdev->dev, "Unknown packet type %d !\n", pkt.type);
477762306a36Sopenharmony_ci			ret = -EINVAL;
477862306a36Sopenharmony_ci			break;
477962306a36Sopenharmony_ci		}
478062306a36Sopenharmony_ci		if (ret) {
478162306a36Sopenharmony_ci			for (i = 0; i < ib->length_dw; i++) {
478262306a36Sopenharmony_ci				if (i == idx)
478362306a36Sopenharmony_ci					printk("\t0x%08x <---\n", ib->ptr[i]);
478462306a36Sopenharmony_ci				else
478562306a36Sopenharmony_ci					printk("\t0x%08x\n", ib->ptr[i]);
478662306a36Sopenharmony_ci			}
478762306a36Sopenharmony_ci			break;
478862306a36Sopenharmony_ci		}
478962306a36Sopenharmony_ci	} while (idx < ib->length_dw);
479062306a36Sopenharmony_ci
479162306a36Sopenharmony_ci	return ret;
479262306a36Sopenharmony_ci}
479362306a36Sopenharmony_ci
479462306a36Sopenharmony_ci/*
479562306a36Sopenharmony_ci * vm
479662306a36Sopenharmony_ci */
479762306a36Sopenharmony_ciint si_vm_init(struct radeon_device *rdev)
479862306a36Sopenharmony_ci{
479962306a36Sopenharmony_ci	/* number of VMs */
480062306a36Sopenharmony_ci	rdev->vm_manager.nvm = 16;
480162306a36Sopenharmony_ci	/* base offset of vram pages */
480262306a36Sopenharmony_ci	rdev->vm_manager.vram_base_offset = 0;
480362306a36Sopenharmony_ci
480462306a36Sopenharmony_ci	return 0;
480562306a36Sopenharmony_ci}
480662306a36Sopenharmony_ci
480762306a36Sopenharmony_civoid si_vm_fini(struct radeon_device *rdev)
480862306a36Sopenharmony_ci{
480962306a36Sopenharmony_ci}
481062306a36Sopenharmony_ci
481162306a36Sopenharmony_ci/**
481262306a36Sopenharmony_ci * si_vm_decode_fault - print human readable fault info
481362306a36Sopenharmony_ci *
481462306a36Sopenharmony_ci * @rdev: radeon_device pointer
481562306a36Sopenharmony_ci * @status: VM_CONTEXT1_PROTECTION_FAULT_STATUS register value
481662306a36Sopenharmony_ci * @addr: VM_CONTEXT1_PROTECTION_FAULT_ADDR register value
481762306a36Sopenharmony_ci *
481862306a36Sopenharmony_ci * Print human readable fault information (SI).
481962306a36Sopenharmony_ci */
482062306a36Sopenharmony_cistatic void si_vm_decode_fault(struct radeon_device *rdev,
482162306a36Sopenharmony_ci			       u32 status, u32 addr)
482262306a36Sopenharmony_ci{
482362306a36Sopenharmony_ci	u32 mc_id = (status & MEMORY_CLIENT_ID_MASK) >> MEMORY_CLIENT_ID_SHIFT;
482462306a36Sopenharmony_ci	u32 vmid = (status & FAULT_VMID_MASK) >> FAULT_VMID_SHIFT;
482562306a36Sopenharmony_ci	u32 protections = (status & PROTECTIONS_MASK) >> PROTECTIONS_SHIFT;
482662306a36Sopenharmony_ci	char *block;
482762306a36Sopenharmony_ci
482862306a36Sopenharmony_ci	if (rdev->family == CHIP_TAHITI) {
482962306a36Sopenharmony_ci		switch (mc_id) {
483062306a36Sopenharmony_ci		case 160:
483162306a36Sopenharmony_ci		case 144:
483262306a36Sopenharmony_ci		case 96:
483362306a36Sopenharmony_ci		case 80:
483462306a36Sopenharmony_ci		case 224:
483562306a36Sopenharmony_ci		case 208:
483662306a36Sopenharmony_ci		case 32:
483762306a36Sopenharmony_ci		case 16:
483862306a36Sopenharmony_ci			block = "CB";
483962306a36Sopenharmony_ci			break;
484062306a36Sopenharmony_ci		case 161:
484162306a36Sopenharmony_ci		case 145:
484262306a36Sopenharmony_ci		case 97:
484362306a36Sopenharmony_ci		case 81:
484462306a36Sopenharmony_ci		case 225:
484562306a36Sopenharmony_ci		case 209:
484662306a36Sopenharmony_ci		case 33:
484762306a36Sopenharmony_ci		case 17:
484862306a36Sopenharmony_ci			block = "CB_FMASK";
484962306a36Sopenharmony_ci			break;
485062306a36Sopenharmony_ci		case 162:
485162306a36Sopenharmony_ci		case 146:
485262306a36Sopenharmony_ci		case 98:
485362306a36Sopenharmony_ci		case 82:
485462306a36Sopenharmony_ci		case 226:
485562306a36Sopenharmony_ci		case 210:
485662306a36Sopenharmony_ci		case 34:
485762306a36Sopenharmony_ci		case 18:
485862306a36Sopenharmony_ci			block = "CB_CMASK";
485962306a36Sopenharmony_ci			break;
486062306a36Sopenharmony_ci		case 163:
486162306a36Sopenharmony_ci		case 147:
486262306a36Sopenharmony_ci		case 99:
486362306a36Sopenharmony_ci		case 83:
486462306a36Sopenharmony_ci		case 227:
486562306a36Sopenharmony_ci		case 211:
486662306a36Sopenharmony_ci		case 35:
486762306a36Sopenharmony_ci		case 19:
486862306a36Sopenharmony_ci			block = "CB_IMMED";
486962306a36Sopenharmony_ci			break;
487062306a36Sopenharmony_ci		case 164:
487162306a36Sopenharmony_ci		case 148:
487262306a36Sopenharmony_ci		case 100:
487362306a36Sopenharmony_ci		case 84:
487462306a36Sopenharmony_ci		case 228:
487562306a36Sopenharmony_ci		case 212:
487662306a36Sopenharmony_ci		case 36:
487762306a36Sopenharmony_ci		case 20:
487862306a36Sopenharmony_ci			block = "DB";
487962306a36Sopenharmony_ci			break;
488062306a36Sopenharmony_ci		case 165:
488162306a36Sopenharmony_ci		case 149:
488262306a36Sopenharmony_ci		case 101:
488362306a36Sopenharmony_ci		case 85:
488462306a36Sopenharmony_ci		case 229:
488562306a36Sopenharmony_ci		case 213:
488662306a36Sopenharmony_ci		case 37:
488762306a36Sopenharmony_ci		case 21:
488862306a36Sopenharmony_ci			block = "DB_HTILE";
488962306a36Sopenharmony_ci			break;
489062306a36Sopenharmony_ci		case 167:
489162306a36Sopenharmony_ci		case 151:
489262306a36Sopenharmony_ci		case 103:
489362306a36Sopenharmony_ci		case 87:
489462306a36Sopenharmony_ci		case 231:
489562306a36Sopenharmony_ci		case 215:
489662306a36Sopenharmony_ci		case 39:
489762306a36Sopenharmony_ci		case 23:
489862306a36Sopenharmony_ci			block = "DB_STEN";
489962306a36Sopenharmony_ci			break;
490062306a36Sopenharmony_ci		case 72:
490162306a36Sopenharmony_ci		case 68:
490262306a36Sopenharmony_ci		case 64:
490362306a36Sopenharmony_ci		case 8:
490462306a36Sopenharmony_ci		case 4:
490562306a36Sopenharmony_ci		case 0:
490662306a36Sopenharmony_ci		case 136:
490762306a36Sopenharmony_ci		case 132:
490862306a36Sopenharmony_ci		case 128:
490962306a36Sopenharmony_ci		case 200:
491062306a36Sopenharmony_ci		case 196:
491162306a36Sopenharmony_ci		case 192:
491262306a36Sopenharmony_ci			block = "TC";
491362306a36Sopenharmony_ci			break;
491462306a36Sopenharmony_ci		case 112:
491562306a36Sopenharmony_ci		case 48:
491662306a36Sopenharmony_ci			block = "CP";
491762306a36Sopenharmony_ci			break;
491862306a36Sopenharmony_ci		case 49:
491962306a36Sopenharmony_ci		case 177:
492062306a36Sopenharmony_ci		case 50:
492162306a36Sopenharmony_ci		case 178:
492262306a36Sopenharmony_ci			block = "SH";
492362306a36Sopenharmony_ci			break;
492462306a36Sopenharmony_ci		case 53:
492562306a36Sopenharmony_ci		case 190:
492662306a36Sopenharmony_ci			block = "VGT";
492762306a36Sopenharmony_ci			break;
492862306a36Sopenharmony_ci		case 117:
492962306a36Sopenharmony_ci			block = "IH";
493062306a36Sopenharmony_ci			break;
493162306a36Sopenharmony_ci		case 51:
493262306a36Sopenharmony_ci		case 115:
493362306a36Sopenharmony_ci			block = "RLC";
493462306a36Sopenharmony_ci			break;
493562306a36Sopenharmony_ci		case 119:
493662306a36Sopenharmony_ci		case 183:
493762306a36Sopenharmony_ci			block = "DMA0";
493862306a36Sopenharmony_ci			break;
493962306a36Sopenharmony_ci		case 61:
494062306a36Sopenharmony_ci			block = "DMA1";
494162306a36Sopenharmony_ci			break;
494262306a36Sopenharmony_ci		case 248:
494362306a36Sopenharmony_ci		case 120:
494462306a36Sopenharmony_ci			block = "HDP";
494562306a36Sopenharmony_ci			break;
494662306a36Sopenharmony_ci		default:
494762306a36Sopenharmony_ci			block = "unknown";
494862306a36Sopenharmony_ci			break;
494962306a36Sopenharmony_ci		}
495062306a36Sopenharmony_ci	} else {
495162306a36Sopenharmony_ci		switch (mc_id) {
495262306a36Sopenharmony_ci		case 32:
495362306a36Sopenharmony_ci		case 16:
495462306a36Sopenharmony_ci		case 96:
495562306a36Sopenharmony_ci		case 80:
495662306a36Sopenharmony_ci		case 160:
495762306a36Sopenharmony_ci		case 144:
495862306a36Sopenharmony_ci		case 224:
495962306a36Sopenharmony_ci		case 208:
496062306a36Sopenharmony_ci			block = "CB";
496162306a36Sopenharmony_ci			break;
496262306a36Sopenharmony_ci		case 33:
496362306a36Sopenharmony_ci		case 17:
496462306a36Sopenharmony_ci		case 97:
496562306a36Sopenharmony_ci		case 81:
496662306a36Sopenharmony_ci		case 161:
496762306a36Sopenharmony_ci		case 145:
496862306a36Sopenharmony_ci		case 225:
496962306a36Sopenharmony_ci		case 209:
497062306a36Sopenharmony_ci			block = "CB_FMASK";
497162306a36Sopenharmony_ci			break;
497262306a36Sopenharmony_ci		case 34:
497362306a36Sopenharmony_ci		case 18:
497462306a36Sopenharmony_ci		case 98:
497562306a36Sopenharmony_ci		case 82:
497662306a36Sopenharmony_ci		case 162:
497762306a36Sopenharmony_ci		case 146:
497862306a36Sopenharmony_ci		case 226:
497962306a36Sopenharmony_ci		case 210:
498062306a36Sopenharmony_ci			block = "CB_CMASK";
498162306a36Sopenharmony_ci			break;
498262306a36Sopenharmony_ci		case 35:
498362306a36Sopenharmony_ci		case 19:
498462306a36Sopenharmony_ci		case 99:
498562306a36Sopenharmony_ci		case 83:
498662306a36Sopenharmony_ci		case 163:
498762306a36Sopenharmony_ci		case 147:
498862306a36Sopenharmony_ci		case 227:
498962306a36Sopenharmony_ci		case 211:
499062306a36Sopenharmony_ci			block = "CB_IMMED";
499162306a36Sopenharmony_ci			break;
499262306a36Sopenharmony_ci		case 36:
499362306a36Sopenharmony_ci		case 20:
499462306a36Sopenharmony_ci		case 100:
499562306a36Sopenharmony_ci		case 84:
499662306a36Sopenharmony_ci		case 164:
499762306a36Sopenharmony_ci		case 148:
499862306a36Sopenharmony_ci		case 228:
499962306a36Sopenharmony_ci		case 212:
500062306a36Sopenharmony_ci			block = "DB";
500162306a36Sopenharmony_ci			break;
500262306a36Sopenharmony_ci		case 37:
500362306a36Sopenharmony_ci		case 21:
500462306a36Sopenharmony_ci		case 101:
500562306a36Sopenharmony_ci		case 85:
500662306a36Sopenharmony_ci		case 165:
500762306a36Sopenharmony_ci		case 149:
500862306a36Sopenharmony_ci		case 229:
500962306a36Sopenharmony_ci		case 213:
501062306a36Sopenharmony_ci			block = "DB_HTILE";
501162306a36Sopenharmony_ci			break;
501262306a36Sopenharmony_ci		case 39:
501362306a36Sopenharmony_ci		case 23:
501462306a36Sopenharmony_ci		case 103:
501562306a36Sopenharmony_ci		case 87:
501662306a36Sopenharmony_ci		case 167:
501762306a36Sopenharmony_ci		case 151:
501862306a36Sopenharmony_ci		case 231:
501962306a36Sopenharmony_ci		case 215:
502062306a36Sopenharmony_ci			block = "DB_STEN";
502162306a36Sopenharmony_ci			break;
502262306a36Sopenharmony_ci		case 72:
502362306a36Sopenharmony_ci		case 68:
502462306a36Sopenharmony_ci		case 8:
502562306a36Sopenharmony_ci		case 4:
502662306a36Sopenharmony_ci		case 136:
502762306a36Sopenharmony_ci		case 132:
502862306a36Sopenharmony_ci		case 200:
502962306a36Sopenharmony_ci		case 196:
503062306a36Sopenharmony_ci			block = "TC";
503162306a36Sopenharmony_ci			break;
503262306a36Sopenharmony_ci		case 112:
503362306a36Sopenharmony_ci		case 48:
503462306a36Sopenharmony_ci			block = "CP";
503562306a36Sopenharmony_ci			break;
503662306a36Sopenharmony_ci		case 49:
503762306a36Sopenharmony_ci		case 177:
503862306a36Sopenharmony_ci		case 50:
503962306a36Sopenharmony_ci		case 178:
504062306a36Sopenharmony_ci			block = "SH";
504162306a36Sopenharmony_ci			break;
504262306a36Sopenharmony_ci		case 53:
504362306a36Sopenharmony_ci			block = "VGT";
504462306a36Sopenharmony_ci			break;
504562306a36Sopenharmony_ci		case 117:
504662306a36Sopenharmony_ci			block = "IH";
504762306a36Sopenharmony_ci			break;
504862306a36Sopenharmony_ci		case 51:
504962306a36Sopenharmony_ci		case 115:
505062306a36Sopenharmony_ci			block = "RLC";
505162306a36Sopenharmony_ci			break;
505262306a36Sopenharmony_ci		case 119:
505362306a36Sopenharmony_ci		case 183:
505462306a36Sopenharmony_ci			block = "DMA0";
505562306a36Sopenharmony_ci			break;
505662306a36Sopenharmony_ci		case 61:
505762306a36Sopenharmony_ci			block = "DMA1";
505862306a36Sopenharmony_ci			break;
505962306a36Sopenharmony_ci		case 248:
506062306a36Sopenharmony_ci		case 120:
506162306a36Sopenharmony_ci			block = "HDP";
506262306a36Sopenharmony_ci			break;
506362306a36Sopenharmony_ci		default:
506462306a36Sopenharmony_ci			block = "unknown";
506562306a36Sopenharmony_ci			break;
506662306a36Sopenharmony_ci		}
506762306a36Sopenharmony_ci	}
506862306a36Sopenharmony_ci
506962306a36Sopenharmony_ci	printk("VM fault (0x%02x, vmid %d) at page %u, %s from %s (%d)\n",
507062306a36Sopenharmony_ci	       protections, vmid, addr,
507162306a36Sopenharmony_ci	       (status & MEMORY_CLIENT_RW_MASK) ? "write" : "read",
507262306a36Sopenharmony_ci	       block, mc_id);
507362306a36Sopenharmony_ci}
507462306a36Sopenharmony_ci
507562306a36Sopenharmony_civoid si_vm_flush(struct radeon_device *rdev, struct radeon_ring *ring,
507662306a36Sopenharmony_ci		 unsigned vm_id, uint64_t pd_addr)
507762306a36Sopenharmony_ci{
507862306a36Sopenharmony_ci	/* write new base address */
507962306a36Sopenharmony_ci	radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
508062306a36Sopenharmony_ci	radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(1) |
508162306a36Sopenharmony_ci				 WRITE_DATA_DST_SEL(0)));
508262306a36Sopenharmony_ci
508362306a36Sopenharmony_ci	if (vm_id < 8) {
508462306a36Sopenharmony_ci		radeon_ring_write(ring,
508562306a36Sopenharmony_ci				  (VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (vm_id << 2)) >> 2);
508662306a36Sopenharmony_ci	} else {
508762306a36Sopenharmony_ci		radeon_ring_write(ring,
508862306a36Sopenharmony_ci				  (VM_CONTEXT8_PAGE_TABLE_BASE_ADDR + ((vm_id - 8) << 2)) >> 2);
508962306a36Sopenharmony_ci	}
509062306a36Sopenharmony_ci	radeon_ring_write(ring, 0);
509162306a36Sopenharmony_ci	radeon_ring_write(ring, pd_addr >> 12);
509262306a36Sopenharmony_ci
509362306a36Sopenharmony_ci	/* flush hdp cache */
509462306a36Sopenharmony_ci	radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
509562306a36Sopenharmony_ci	radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(1) |
509662306a36Sopenharmony_ci				 WRITE_DATA_DST_SEL(0)));
509762306a36Sopenharmony_ci	radeon_ring_write(ring, HDP_MEM_COHERENCY_FLUSH_CNTL >> 2);
509862306a36Sopenharmony_ci	radeon_ring_write(ring, 0);
509962306a36Sopenharmony_ci	radeon_ring_write(ring, 0x1);
510062306a36Sopenharmony_ci
510162306a36Sopenharmony_ci	/* bits 0-15 are the VM contexts0-15 */
510262306a36Sopenharmony_ci	radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
510362306a36Sopenharmony_ci	radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(1) |
510462306a36Sopenharmony_ci				 WRITE_DATA_DST_SEL(0)));
510562306a36Sopenharmony_ci	radeon_ring_write(ring, VM_INVALIDATE_REQUEST >> 2);
510662306a36Sopenharmony_ci	radeon_ring_write(ring, 0);
510762306a36Sopenharmony_ci	radeon_ring_write(ring, 1 << vm_id);
510862306a36Sopenharmony_ci
510962306a36Sopenharmony_ci	/* wait for the invalidate to complete */
511062306a36Sopenharmony_ci	radeon_ring_write(ring, PACKET3(PACKET3_WAIT_REG_MEM, 5));
511162306a36Sopenharmony_ci	radeon_ring_write(ring, (WAIT_REG_MEM_FUNCTION(0) |  /* always */
511262306a36Sopenharmony_ci				 WAIT_REG_MEM_ENGINE(0))); /* me */
511362306a36Sopenharmony_ci	radeon_ring_write(ring, VM_INVALIDATE_REQUEST >> 2);
511462306a36Sopenharmony_ci	radeon_ring_write(ring, 0);
511562306a36Sopenharmony_ci	radeon_ring_write(ring, 0); /* ref */
511662306a36Sopenharmony_ci	radeon_ring_write(ring, 0); /* mask */
511762306a36Sopenharmony_ci	radeon_ring_write(ring, 0x20); /* poll interval */
511862306a36Sopenharmony_ci
511962306a36Sopenharmony_ci	/* sync PFP to ME, otherwise we might get invalid PFP reads */
512062306a36Sopenharmony_ci	radeon_ring_write(ring, PACKET3(PACKET3_PFP_SYNC_ME, 0));
512162306a36Sopenharmony_ci	radeon_ring_write(ring, 0x0);
512262306a36Sopenharmony_ci}
512362306a36Sopenharmony_ci
512462306a36Sopenharmony_ci/*
512562306a36Sopenharmony_ci *  Power and clock gating
512662306a36Sopenharmony_ci */
512762306a36Sopenharmony_cistatic void si_wait_for_rlc_serdes(struct radeon_device *rdev)
512862306a36Sopenharmony_ci{
512962306a36Sopenharmony_ci	int i;
513062306a36Sopenharmony_ci
513162306a36Sopenharmony_ci	for (i = 0; i < rdev->usec_timeout; i++) {
513262306a36Sopenharmony_ci		if (RREG32(RLC_SERDES_MASTER_BUSY_0) == 0)
513362306a36Sopenharmony_ci			break;
513462306a36Sopenharmony_ci		udelay(1);
513562306a36Sopenharmony_ci	}
513662306a36Sopenharmony_ci
513762306a36Sopenharmony_ci	for (i = 0; i < rdev->usec_timeout; i++) {
513862306a36Sopenharmony_ci		if (RREG32(RLC_SERDES_MASTER_BUSY_1) == 0)
513962306a36Sopenharmony_ci			break;
514062306a36Sopenharmony_ci		udelay(1);
514162306a36Sopenharmony_ci	}
514262306a36Sopenharmony_ci}
514362306a36Sopenharmony_ci
514462306a36Sopenharmony_cistatic void si_enable_gui_idle_interrupt(struct radeon_device *rdev,
514562306a36Sopenharmony_ci					 bool enable)
514662306a36Sopenharmony_ci{
514762306a36Sopenharmony_ci	u32 tmp = RREG32(CP_INT_CNTL_RING0);
514862306a36Sopenharmony_ci	u32 mask;
514962306a36Sopenharmony_ci	int i;
515062306a36Sopenharmony_ci
515162306a36Sopenharmony_ci	if (enable)
515262306a36Sopenharmony_ci		tmp |= (CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE);
515362306a36Sopenharmony_ci	else
515462306a36Sopenharmony_ci		tmp &= ~(CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE);
515562306a36Sopenharmony_ci	WREG32(CP_INT_CNTL_RING0, tmp);
515662306a36Sopenharmony_ci
515762306a36Sopenharmony_ci	if (!enable) {
515862306a36Sopenharmony_ci		/* read a gfx register */
515962306a36Sopenharmony_ci		tmp = RREG32(DB_DEPTH_INFO);
516062306a36Sopenharmony_ci
516162306a36Sopenharmony_ci		mask = RLC_BUSY_STATUS | GFX_POWER_STATUS | GFX_CLOCK_STATUS | GFX_LS_STATUS;
516262306a36Sopenharmony_ci		for (i = 0; i < rdev->usec_timeout; i++) {
516362306a36Sopenharmony_ci			if ((RREG32(RLC_STAT) & mask) == (GFX_CLOCK_STATUS | GFX_POWER_STATUS))
516462306a36Sopenharmony_ci				break;
516562306a36Sopenharmony_ci			udelay(1);
516662306a36Sopenharmony_ci		}
516762306a36Sopenharmony_ci	}
516862306a36Sopenharmony_ci}
516962306a36Sopenharmony_ci
517062306a36Sopenharmony_cistatic void si_set_uvd_dcm(struct radeon_device *rdev,
517162306a36Sopenharmony_ci			   bool sw_mode)
517262306a36Sopenharmony_ci{
517362306a36Sopenharmony_ci	u32 tmp, tmp2;
517462306a36Sopenharmony_ci
517562306a36Sopenharmony_ci	tmp = RREG32(UVD_CGC_CTRL);
517662306a36Sopenharmony_ci	tmp &= ~(CLK_OD_MASK | CG_DT_MASK);
517762306a36Sopenharmony_ci	tmp |= DCM | CG_DT(1) | CLK_OD(4);
517862306a36Sopenharmony_ci
517962306a36Sopenharmony_ci	if (sw_mode) {
518062306a36Sopenharmony_ci		tmp &= ~0x7ffff800;
518162306a36Sopenharmony_ci		tmp2 = DYN_OR_EN | DYN_RR_EN | G_DIV_ID(7);
518262306a36Sopenharmony_ci	} else {
518362306a36Sopenharmony_ci		tmp |= 0x7ffff800;
518462306a36Sopenharmony_ci		tmp2 = 0;
518562306a36Sopenharmony_ci	}
518662306a36Sopenharmony_ci
518762306a36Sopenharmony_ci	WREG32(UVD_CGC_CTRL, tmp);
518862306a36Sopenharmony_ci	WREG32_UVD_CTX(UVD_CGC_CTRL2, tmp2);
518962306a36Sopenharmony_ci}
519062306a36Sopenharmony_ci
519162306a36Sopenharmony_civoid si_init_uvd_internal_cg(struct radeon_device *rdev)
519262306a36Sopenharmony_ci{
519362306a36Sopenharmony_ci	bool hw_mode = true;
519462306a36Sopenharmony_ci
519562306a36Sopenharmony_ci	if (hw_mode) {
519662306a36Sopenharmony_ci		si_set_uvd_dcm(rdev, false);
519762306a36Sopenharmony_ci	} else {
519862306a36Sopenharmony_ci		u32 tmp = RREG32(UVD_CGC_CTRL);
519962306a36Sopenharmony_ci		tmp &= ~DCM;
520062306a36Sopenharmony_ci		WREG32(UVD_CGC_CTRL, tmp);
520162306a36Sopenharmony_ci	}
520262306a36Sopenharmony_ci}
520362306a36Sopenharmony_ci
520462306a36Sopenharmony_cistatic u32 si_halt_rlc(struct radeon_device *rdev)
520562306a36Sopenharmony_ci{
520662306a36Sopenharmony_ci	u32 data, orig;
520762306a36Sopenharmony_ci
520862306a36Sopenharmony_ci	orig = data = RREG32(RLC_CNTL);
520962306a36Sopenharmony_ci
521062306a36Sopenharmony_ci	if (data & RLC_ENABLE) {
521162306a36Sopenharmony_ci		data &= ~RLC_ENABLE;
521262306a36Sopenharmony_ci		WREG32(RLC_CNTL, data);
521362306a36Sopenharmony_ci
521462306a36Sopenharmony_ci		si_wait_for_rlc_serdes(rdev);
521562306a36Sopenharmony_ci	}
521662306a36Sopenharmony_ci
521762306a36Sopenharmony_ci	return orig;
521862306a36Sopenharmony_ci}
521962306a36Sopenharmony_ci
522062306a36Sopenharmony_cistatic void si_update_rlc(struct radeon_device *rdev, u32 rlc)
522162306a36Sopenharmony_ci{
522262306a36Sopenharmony_ci	u32 tmp;
522362306a36Sopenharmony_ci
522462306a36Sopenharmony_ci	tmp = RREG32(RLC_CNTL);
522562306a36Sopenharmony_ci	if (tmp != rlc)
522662306a36Sopenharmony_ci		WREG32(RLC_CNTL, rlc);
522762306a36Sopenharmony_ci}
522862306a36Sopenharmony_ci
522962306a36Sopenharmony_cistatic void si_enable_dma_pg(struct radeon_device *rdev, bool enable)
523062306a36Sopenharmony_ci{
523162306a36Sopenharmony_ci	u32 data, orig;
523262306a36Sopenharmony_ci
523362306a36Sopenharmony_ci	orig = data = RREG32(DMA_PG);
523462306a36Sopenharmony_ci	if (enable && (rdev->pg_flags & RADEON_PG_SUPPORT_SDMA))
523562306a36Sopenharmony_ci		data |= PG_CNTL_ENABLE;
523662306a36Sopenharmony_ci	else
523762306a36Sopenharmony_ci		data &= ~PG_CNTL_ENABLE;
523862306a36Sopenharmony_ci	if (orig != data)
523962306a36Sopenharmony_ci		WREG32(DMA_PG, data);
524062306a36Sopenharmony_ci}
524162306a36Sopenharmony_ci
524262306a36Sopenharmony_cistatic void si_init_dma_pg(struct radeon_device *rdev)
524362306a36Sopenharmony_ci{
524462306a36Sopenharmony_ci	u32 tmp;
524562306a36Sopenharmony_ci
524662306a36Sopenharmony_ci	WREG32(DMA_PGFSM_WRITE,  0x00002000);
524762306a36Sopenharmony_ci	WREG32(DMA_PGFSM_CONFIG, 0x100010ff);
524862306a36Sopenharmony_ci
524962306a36Sopenharmony_ci	for (tmp = 0; tmp < 5; tmp++)
525062306a36Sopenharmony_ci		WREG32(DMA_PGFSM_WRITE, 0);
525162306a36Sopenharmony_ci}
525262306a36Sopenharmony_ci
525362306a36Sopenharmony_cistatic void si_enable_gfx_cgpg(struct radeon_device *rdev,
525462306a36Sopenharmony_ci			       bool enable)
525562306a36Sopenharmony_ci{
525662306a36Sopenharmony_ci	u32 tmp;
525762306a36Sopenharmony_ci
525862306a36Sopenharmony_ci	if (enable && (rdev->pg_flags & RADEON_PG_SUPPORT_GFX_PG)) {
525962306a36Sopenharmony_ci		tmp = RLC_PUD(0x10) | RLC_PDD(0x10) | RLC_TTPD(0x10) | RLC_MSD(0x10);
526062306a36Sopenharmony_ci		WREG32(RLC_TTOP_D, tmp);
526162306a36Sopenharmony_ci
526262306a36Sopenharmony_ci		tmp = RREG32(RLC_PG_CNTL);
526362306a36Sopenharmony_ci		tmp |= GFX_PG_ENABLE;
526462306a36Sopenharmony_ci		WREG32(RLC_PG_CNTL, tmp);
526562306a36Sopenharmony_ci
526662306a36Sopenharmony_ci		tmp = RREG32(RLC_AUTO_PG_CTRL);
526762306a36Sopenharmony_ci		tmp |= AUTO_PG_EN;
526862306a36Sopenharmony_ci		WREG32(RLC_AUTO_PG_CTRL, tmp);
526962306a36Sopenharmony_ci	} else {
527062306a36Sopenharmony_ci		tmp = RREG32(RLC_AUTO_PG_CTRL);
527162306a36Sopenharmony_ci		tmp &= ~AUTO_PG_EN;
527262306a36Sopenharmony_ci		WREG32(RLC_AUTO_PG_CTRL, tmp);
527362306a36Sopenharmony_ci
527462306a36Sopenharmony_ci		tmp = RREG32(DB_RENDER_CONTROL);
527562306a36Sopenharmony_ci	}
527662306a36Sopenharmony_ci}
527762306a36Sopenharmony_ci
527862306a36Sopenharmony_cistatic void si_init_gfx_cgpg(struct radeon_device *rdev)
527962306a36Sopenharmony_ci{
528062306a36Sopenharmony_ci	u32 tmp;
528162306a36Sopenharmony_ci
528262306a36Sopenharmony_ci	WREG32(RLC_SAVE_AND_RESTORE_BASE, rdev->rlc.save_restore_gpu_addr >> 8);
528362306a36Sopenharmony_ci
528462306a36Sopenharmony_ci	tmp = RREG32(RLC_PG_CNTL);
528562306a36Sopenharmony_ci	tmp |= GFX_PG_SRC;
528662306a36Sopenharmony_ci	WREG32(RLC_PG_CNTL, tmp);
528762306a36Sopenharmony_ci
528862306a36Sopenharmony_ci	WREG32(RLC_CLEAR_STATE_RESTORE_BASE, rdev->rlc.clear_state_gpu_addr >> 8);
528962306a36Sopenharmony_ci
529062306a36Sopenharmony_ci	tmp = RREG32(RLC_AUTO_PG_CTRL);
529162306a36Sopenharmony_ci
529262306a36Sopenharmony_ci	tmp &= ~GRBM_REG_SGIT_MASK;
529362306a36Sopenharmony_ci	tmp |= GRBM_REG_SGIT(0x700);
529462306a36Sopenharmony_ci	tmp &= ~PG_AFTER_GRBM_REG_ST_MASK;
529562306a36Sopenharmony_ci	WREG32(RLC_AUTO_PG_CTRL, tmp);
529662306a36Sopenharmony_ci}
529762306a36Sopenharmony_ci
529862306a36Sopenharmony_cistatic u32 si_get_cu_active_bitmap(struct radeon_device *rdev, u32 se, u32 sh)
529962306a36Sopenharmony_ci{
530062306a36Sopenharmony_ci	u32 mask = 0, tmp, tmp1;
530162306a36Sopenharmony_ci	int i;
530262306a36Sopenharmony_ci
530362306a36Sopenharmony_ci	si_select_se_sh(rdev, se, sh);
530462306a36Sopenharmony_ci	tmp = RREG32(CC_GC_SHADER_ARRAY_CONFIG);
530562306a36Sopenharmony_ci	tmp1 = RREG32(GC_USER_SHADER_ARRAY_CONFIG);
530662306a36Sopenharmony_ci	si_select_se_sh(rdev, 0xffffffff, 0xffffffff);
530762306a36Sopenharmony_ci
530862306a36Sopenharmony_ci	tmp &= 0xffff0000;
530962306a36Sopenharmony_ci
531062306a36Sopenharmony_ci	tmp |= tmp1;
531162306a36Sopenharmony_ci	tmp >>= 16;
531262306a36Sopenharmony_ci
531362306a36Sopenharmony_ci	for (i = 0; i < rdev->config.si.max_cu_per_sh; i ++) {
531462306a36Sopenharmony_ci		mask <<= 1;
531562306a36Sopenharmony_ci		mask |= 1;
531662306a36Sopenharmony_ci	}
531762306a36Sopenharmony_ci
531862306a36Sopenharmony_ci	return (~tmp) & mask;
531962306a36Sopenharmony_ci}
532062306a36Sopenharmony_ci
532162306a36Sopenharmony_cistatic void si_init_ao_cu_mask(struct radeon_device *rdev)
532262306a36Sopenharmony_ci{
532362306a36Sopenharmony_ci	u32 i, j, k, active_cu_number = 0;
532462306a36Sopenharmony_ci	u32 mask, counter, cu_bitmap;
532562306a36Sopenharmony_ci	u32 tmp = 0;
532662306a36Sopenharmony_ci
532762306a36Sopenharmony_ci	for (i = 0; i < rdev->config.si.max_shader_engines; i++) {
532862306a36Sopenharmony_ci		for (j = 0; j < rdev->config.si.max_sh_per_se; j++) {
532962306a36Sopenharmony_ci			mask = 1;
533062306a36Sopenharmony_ci			cu_bitmap = 0;
533162306a36Sopenharmony_ci			counter  = 0;
533262306a36Sopenharmony_ci			for (k = 0; k < rdev->config.si.max_cu_per_sh; k++) {
533362306a36Sopenharmony_ci				if (si_get_cu_active_bitmap(rdev, i, j) & mask) {
533462306a36Sopenharmony_ci					if (counter < 2)
533562306a36Sopenharmony_ci						cu_bitmap |= mask;
533662306a36Sopenharmony_ci					counter++;
533762306a36Sopenharmony_ci				}
533862306a36Sopenharmony_ci				mask <<= 1;
533962306a36Sopenharmony_ci			}
534062306a36Sopenharmony_ci
534162306a36Sopenharmony_ci			active_cu_number += counter;
534262306a36Sopenharmony_ci			tmp |= (cu_bitmap << (i * 16 + j * 8));
534362306a36Sopenharmony_ci		}
534462306a36Sopenharmony_ci	}
534562306a36Sopenharmony_ci
534662306a36Sopenharmony_ci	WREG32(RLC_PG_AO_CU_MASK, tmp);
534762306a36Sopenharmony_ci
534862306a36Sopenharmony_ci	tmp = RREG32(RLC_MAX_PG_CU);
534962306a36Sopenharmony_ci	tmp &= ~MAX_PU_CU_MASK;
535062306a36Sopenharmony_ci	tmp |= MAX_PU_CU(active_cu_number);
535162306a36Sopenharmony_ci	WREG32(RLC_MAX_PG_CU, tmp);
535262306a36Sopenharmony_ci}
535362306a36Sopenharmony_ci
535462306a36Sopenharmony_cistatic void si_enable_cgcg(struct radeon_device *rdev,
535562306a36Sopenharmony_ci			   bool enable)
535662306a36Sopenharmony_ci{
535762306a36Sopenharmony_ci	u32 data, orig, tmp;
535862306a36Sopenharmony_ci
535962306a36Sopenharmony_ci	orig = data = RREG32(RLC_CGCG_CGLS_CTRL);
536062306a36Sopenharmony_ci
536162306a36Sopenharmony_ci	if (enable && (rdev->cg_flags & RADEON_CG_SUPPORT_GFX_CGCG)) {
536262306a36Sopenharmony_ci		si_enable_gui_idle_interrupt(rdev, true);
536362306a36Sopenharmony_ci
536462306a36Sopenharmony_ci		WREG32(RLC_GCPM_GENERAL_3, 0x00000080);
536562306a36Sopenharmony_ci
536662306a36Sopenharmony_ci		tmp = si_halt_rlc(rdev);
536762306a36Sopenharmony_ci
536862306a36Sopenharmony_ci		WREG32(RLC_SERDES_WR_MASTER_MASK_0, 0xffffffff);
536962306a36Sopenharmony_ci		WREG32(RLC_SERDES_WR_MASTER_MASK_1, 0xffffffff);
537062306a36Sopenharmony_ci		WREG32(RLC_SERDES_WR_CTRL, 0x00b000ff);
537162306a36Sopenharmony_ci
537262306a36Sopenharmony_ci		si_wait_for_rlc_serdes(rdev);
537362306a36Sopenharmony_ci
537462306a36Sopenharmony_ci		si_update_rlc(rdev, tmp);
537562306a36Sopenharmony_ci
537662306a36Sopenharmony_ci		WREG32(RLC_SERDES_WR_CTRL, 0x007000ff);
537762306a36Sopenharmony_ci
537862306a36Sopenharmony_ci		data |= CGCG_EN | CGLS_EN;
537962306a36Sopenharmony_ci	} else {
538062306a36Sopenharmony_ci		si_enable_gui_idle_interrupt(rdev, false);
538162306a36Sopenharmony_ci
538262306a36Sopenharmony_ci		RREG32(CB_CGTT_SCLK_CTRL);
538362306a36Sopenharmony_ci		RREG32(CB_CGTT_SCLK_CTRL);
538462306a36Sopenharmony_ci		RREG32(CB_CGTT_SCLK_CTRL);
538562306a36Sopenharmony_ci		RREG32(CB_CGTT_SCLK_CTRL);
538662306a36Sopenharmony_ci
538762306a36Sopenharmony_ci		data &= ~(CGCG_EN | CGLS_EN);
538862306a36Sopenharmony_ci	}
538962306a36Sopenharmony_ci
539062306a36Sopenharmony_ci	if (orig != data)
539162306a36Sopenharmony_ci		WREG32(RLC_CGCG_CGLS_CTRL, data);
539262306a36Sopenharmony_ci}
539362306a36Sopenharmony_ci
539462306a36Sopenharmony_cistatic void si_enable_mgcg(struct radeon_device *rdev,
539562306a36Sopenharmony_ci			   bool enable)
539662306a36Sopenharmony_ci{
539762306a36Sopenharmony_ci	u32 data, orig, tmp = 0;
539862306a36Sopenharmony_ci
539962306a36Sopenharmony_ci	if (enable && (rdev->cg_flags & RADEON_CG_SUPPORT_GFX_MGCG)) {
540062306a36Sopenharmony_ci		orig = data = RREG32(CGTS_SM_CTRL_REG);
540162306a36Sopenharmony_ci		data = 0x96940200;
540262306a36Sopenharmony_ci		if (orig != data)
540362306a36Sopenharmony_ci			WREG32(CGTS_SM_CTRL_REG, data);
540462306a36Sopenharmony_ci
540562306a36Sopenharmony_ci		if (rdev->cg_flags & RADEON_CG_SUPPORT_GFX_CP_LS) {
540662306a36Sopenharmony_ci			orig = data = RREG32(CP_MEM_SLP_CNTL);
540762306a36Sopenharmony_ci			data |= CP_MEM_LS_EN;
540862306a36Sopenharmony_ci			if (orig != data)
540962306a36Sopenharmony_ci				WREG32(CP_MEM_SLP_CNTL, data);
541062306a36Sopenharmony_ci		}
541162306a36Sopenharmony_ci
541262306a36Sopenharmony_ci		orig = data = RREG32(RLC_CGTT_MGCG_OVERRIDE);
541362306a36Sopenharmony_ci		data &= 0xffffffc0;
541462306a36Sopenharmony_ci		if (orig != data)
541562306a36Sopenharmony_ci			WREG32(RLC_CGTT_MGCG_OVERRIDE, data);
541662306a36Sopenharmony_ci
541762306a36Sopenharmony_ci		tmp = si_halt_rlc(rdev);
541862306a36Sopenharmony_ci
541962306a36Sopenharmony_ci		WREG32(RLC_SERDES_WR_MASTER_MASK_0, 0xffffffff);
542062306a36Sopenharmony_ci		WREG32(RLC_SERDES_WR_MASTER_MASK_1, 0xffffffff);
542162306a36Sopenharmony_ci		WREG32(RLC_SERDES_WR_CTRL, 0x00d000ff);
542262306a36Sopenharmony_ci
542362306a36Sopenharmony_ci		si_update_rlc(rdev, tmp);
542462306a36Sopenharmony_ci	} else {
542562306a36Sopenharmony_ci		orig = data = RREG32(RLC_CGTT_MGCG_OVERRIDE);
542662306a36Sopenharmony_ci		data |= 0x00000003;
542762306a36Sopenharmony_ci		if (orig != data)
542862306a36Sopenharmony_ci			WREG32(RLC_CGTT_MGCG_OVERRIDE, data);
542962306a36Sopenharmony_ci
543062306a36Sopenharmony_ci		data = RREG32(CP_MEM_SLP_CNTL);
543162306a36Sopenharmony_ci		if (data & CP_MEM_LS_EN) {
543262306a36Sopenharmony_ci			data &= ~CP_MEM_LS_EN;
543362306a36Sopenharmony_ci			WREG32(CP_MEM_SLP_CNTL, data);
543462306a36Sopenharmony_ci		}
543562306a36Sopenharmony_ci		orig = data = RREG32(CGTS_SM_CTRL_REG);
543662306a36Sopenharmony_ci		data |= LS_OVERRIDE | OVERRIDE;
543762306a36Sopenharmony_ci		if (orig != data)
543862306a36Sopenharmony_ci			WREG32(CGTS_SM_CTRL_REG, data);
543962306a36Sopenharmony_ci
544062306a36Sopenharmony_ci		tmp = si_halt_rlc(rdev);
544162306a36Sopenharmony_ci
544262306a36Sopenharmony_ci		WREG32(RLC_SERDES_WR_MASTER_MASK_0, 0xffffffff);
544362306a36Sopenharmony_ci		WREG32(RLC_SERDES_WR_MASTER_MASK_1, 0xffffffff);
544462306a36Sopenharmony_ci		WREG32(RLC_SERDES_WR_CTRL, 0x00e000ff);
544562306a36Sopenharmony_ci
544662306a36Sopenharmony_ci		si_update_rlc(rdev, tmp);
544762306a36Sopenharmony_ci	}
544862306a36Sopenharmony_ci}
544962306a36Sopenharmony_ci
545062306a36Sopenharmony_cistatic void si_enable_uvd_mgcg(struct radeon_device *rdev,
545162306a36Sopenharmony_ci			       bool enable)
545262306a36Sopenharmony_ci{
545362306a36Sopenharmony_ci	u32 orig, data, tmp;
545462306a36Sopenharmony_ci
545562306a36Sopenharmony_ci	if (enable && (rdev->cg_flags & RADEON_CG_SUPPORT_UVD_MGCG)) {
545662306a36Sopenharmony_ci		tmp = RREG32_UVD_CTX(UVD_CGC_MEM_CTRL);
545762306a36Sopenharmony_ci		tmp |= 0x3fff;
545862306a36Sopenharmony_ci		WREG32_UVD_CTX(UVD_CGC_MEM_CTRL, tmp);
545962306a36Sopenharmony_ci
546062306a36Sopenharmony_ci		orig = data = RREG32(UVD_CGC_CTRL);
546162306a36Sopenharmony_ci		data |= DCM;
546262306a36Sopenharmony_ci		if (orig != data)
546362306a36Sopenharmony_ci			WREG32(UVD_CGC_CTRL, data);
546462306a36Sopenharmony_ci
546562306a36Sopenharmony_ci		WREG32_SMC(SMC_CG_IND_START + CG_CGTT_LOCAL_0, 0);
546662306a36Sopenharmony_ci		WREG32_SMC(SMC_CG_IND_START + CG_CGTT_LOCAL_1, 0);
546762306a36Sopenharmony_ci	} else {
546862306a36Sopenharmony_ci		tmp = RREG32_UVD_CTX(UVD_CGC_MEM_CTRL);
546962306a36Sopenharmony_ci		tmp &= ~0x3fff;
547062306a36Sopenharmony_ci		WREG32_UVD_CTX(UVD_CGC_MEM_CTRL, tmp);
547162306a36Sopenharmony_ci
547262306a36Sopenharmony_ci		orig = data = RREG32(UVD_CGC_CTRL);
547362306a36Sopenharmony_ci		data &= ~DCM;
547462306a36Sopenharmony_ci		if (orig != data)
547562306a36Sopenharmony_ci			WREG32(UVD_CGC_CTRL, data);
547662306a36Sopenharmony_ci
547762306a36Sopenharmony_ci		WREG32_SMC(SMC_CG_IND_START + CG_CGTT_LOCAL_0, 0xffffffff);
547862306a36Sopenharmony_ci		WREG32_SMC(SMC_CG_IND_START + CG_CGTT_LOCAL_1, 0xffffffff);
547962306a36Sopenharmony_ci	}
548062306a36Sopenharmony_ci}
548162306a36Sopenharmony_ci
548262306a36Sopenharmony_cistatic const u32 mc_cg_registers[] =
548362306a36Sopenharmony_ci{
548462306a36Sopenharmony_ci	MC_HUB_MISC_HUB_CG,
548562306a36Sopenharmony_ci	MC_HUB_MISC_SIP_CG,
548662306a36Sopenharmony_ci	MC_HUB_MISC_VM_CG,
548762306a36Sopenharmony_ci	MC_XPB_CLK_GAT,
548862306a36Sopenharmony_ci	ATC_MISC_CG,
548962306a36Sopenharmony_ci	MC_CITF_MISC_WR_CG,
549062306a36Sopenharmony_ci	MC_CITF_MISC_RD_CG,
549162306a36Sopenharmony_ci	MC_CITF_MISC_VM_CG,
549262306a36Sopenharmony_ci	VM_L2_CG,
549362306a36Sopenharmony_ci};
549462306a36Sopenharmony_ci
549562306a36Sopenharmony_cistatic void si_enable_mc_ls(struct radeon_device *rdev,
549662306a36Sopenharmony_ci			    bool enable)
549762306a36Sopenharmony_ci{
549862306a36Sopenharmony_ci	int i;
549962306a36Sopenharmony_ci	u32 orig, data;
550062306a36Sopenharmony_ci
550162306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(mc_cg_registers); i++) {
550262306a36Sopenharmony_ci		orig = data = RREG32(mc_cg_registers[i]);
550362306a36Sopenharmony_ci		if (enable && (rdev->cg_flags & RADEON_CG_SUPPORT_MC_LS))
550462306a36Sopenharmony_ci			data |= MC_LS_ENABLE;
550562306a36Sopenharmony_ci		else
550662306a36Sopenharmony_ci			data &= ~MC_LS_ENABLE;
550762306a36Sopenharmony_ci		if (data != orig)
550862306a36Sopenharmony_ci			WREG32(mc_cg_registers[i], data);
550962306a36Sopenharmony_ci	}
551062306a36Sopenharmony_ci}
551162306a36Sopenharmony_ci
551262306a36Sopenharmony_cistatic void si_enable_mc_mgcg(struct radeon_device *rdev,
551362306a36Sopenharmony_ci			       bool enable)
551462306a36Sopenharmony_ci{
551562306a36Sopenharmony_ci	int i;
551662306a36Sopenharmony_ci	u32 orig, data;
551762306a36Sopenharmony_ci
551862306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(mc_cg_registers); i++) {
551962306a36Sopenharmony_ci		orig = data = RREG32(mc_cg_registers[i]);
552062306a36Sopenharmony_ci		if (enable && (rdev->cg_flags & RADEON_CG_SUPPORT_MC_MGCG))
552162306a36Sopenharmony_ci			data |= MC_CG_ENABLE;
552262306a36Sopenharmony_ci		else
552362306a36Sopenharmony_ci			data &= ~MC_CG_ENABLE;
552462306a36Sopenharmony_ci		if (data != orig)
552562306a36Sopenharmony_ci			WREG32(mc_cg_registers[i], data);
552662306a36Sopenharmony_ci	}
552762306a36Sopenharmony_ci}
552862306a36Sopenharmony_ci
552962306a36Sopenharmony_cistatic void si_enable_dma_mgcg(struct radeon_device *rdev,
553062306a36Sopenharmony_ci			       bool enable)
553162306a36Sopenharmony_ci{
553262306a36Sopenharmony_ci	u32 orig, data, offset;
553362306a36Sopenharmony_ci	int i;
553462306a36Sopenharmony_ci
553562306a36Sopenharmony_ci	if (enable && (rdev->cg_flags & RADEON_CG_SUPPORT_SDMA_MGCG)) {
553662306a36Sopenharmony_ci		for (i = 0; i < 2; i++) {
553762306a36Sopenharmony_ci			if (i == 0)
553862306a36Sopenharmony_ci				offset = DMA0_REGISTER_OFFSET;
553962306a36Sopenharmony_ci			else
554062306a36Sopenharmony_ci				offset = DMA1_REGISTER_OFFSET;
554162306a36Sopenharmony_ci			orig = data = RREG32(DMA_POWER_CNTL + offset);
554262306a36Sopenharmony_ci			data &= ~MEM_POWER_OVERRIDE;
554362306a36Sopenharmony_ci			if (data != orig)
554462306a36Sopenharmony_ci				WREG32(DMA_POWER_CNTL + offset, data);
554562306a36Sopenharmony_ci			WREG32(DMA_CLK_CTRL + offset, 0x00000100);
554662306a36Sopenharmony_ci		}
554762306a36Sopenharmony_ci	} else {
554862306a36Sopenharmony_ci		for (i = 0; i < 2; i++) {
554962306a36Sopenharmony_ci			if (i == 0)
555062306a36Sopenharmony_ci				offset = DMA0_REGISTER_OFFSET;
555162306a36Sopenharmony_ci			else
555262306a36Sopenharmony_ci				offset = DMA1_REGISTER_OFFSET;
555362306a36Sopenharmony_ci			orig = data = RREG32(DMA_POWER_CNTL + offset);
555462306a36Sopenharmony_ci			data |= MEM_POWER_OVERRIDE;
555562306a36Sopenharmony_ci			if (data != orig)
555662306a36Sopenharmony_ci				WREG32(DMA_POWER_CNTL + offset, data);
555762306a36Sopenharmony_ci
555862306a36Sopenharmony_ci			orig = data = RREG32(DMA_CLK_CTRL + offset);
555962306a36Sopenharmony_ci			data = 0xff000000;
556062306a36Sopenharmony_ci			if (data != orig)
556162306a36Sopenharmony_ci				WREG32(DMA_CLK_CTRL + offset, data);
556262306a36Sopenharmony_ci		}
556362306a36Sopenharmony_ci	}
556462306a36Sopenharmony_ci}
556562306a36Sopenharmony_ci
556662306a36Sopenharmony_cistatic void si_enable_bif_mgls(struct radeon_device *rdev,
556762306a36Sopenharmony_ci			       bool enable)
556862306a36Sopenharmony_ci{
556962306a36Sopenharmony_ci	u32 orig, data;
557062306a36Sopenharmony_ci
557162306a36Sopenharmony_ci	orig = data = RREG32_PCIE(PCIE_CNTL2);
557262306a36Sopenharmony_ci
557362306a36Sopenharmony_ci	if (enable && (rdev->cg_flags & RADEON_CG_SUPPORT_BIF_LS))
557462306a36Sopenharmony_ci		data |= SLV_MEM_LS_EN | MST_MEM_LS_EN |
557562306a36Sopenharmony_ci			REPLAY_MEM_LS_EN | SLV_MEM_AGGRESSIVE_LS_EN;
557662306a36Sopenharmony_ci	else
557762306a36Sopenharmony_ci		data &= ~(SLV_MEM_LS_EN | MST_MEM_LS_EN |
557862306a36Sopenharmony_ci			  REPLAY_MEM_LS_EN | SLV_MEM_AGGRESSIVE_LS_EN);
557962306a36Sopenharmony_ci
558062306a36Sopenharmony_ci	if (orig != data)
558162306a36Sopenharmony_ci		WREG32_PCIE(PCIE_CNTL2, data);
558262306a36Sopenharmony_ci}
558362306a36Sopenharmony_ci
558462306a36Sopenharmony_cistatic void si_enable_hdp_mgcg(struct radeon_device *rdev,
558562306a36Sopenharmony_ci			       bool enable)
558662306a36Sopenharmony_ci{
558762306a36Sopenharmony_ci	u32 orig, data;
558862306a36Sopenharmony_ci
558962306a36Sopenharmony_ci	orig = data = RREG32(HDP_HOST_PATH_CNTL);
559062306a36Sopenharmony_ci
559162306a36Sopenharmony_ci	if (enable && (rdev->cg_flags & RADEON_CG_SUPPORT_HDP_MGCG))
559262306a36Sopenharmony_ci		data &= ~CLOCK_GATING_DIS;
559362306a36Sopenharmony_ci	else
559462306a36Sopenharmony_ci		data |= CLOCK_GATING_DIS;
559562306a36Sopenharmony_ci
559662306a36Sopenharmony_ci	if (orig != data)
559762306a36Sopenharmony_ci		WREG32(HDP_HOST_PATH_CNTL, data);
559862306a36Sopenharmony_ci}
559962306a36Sopenharmony_ci
560062306a36Sopenharmony_cistatic void si_enable_hdp_ls(struct radeon_device *rdev,
560162306a36Sopenharmony_ci			     bool enable)
560262306a36Sopenharmony_ci{
560362306a36Sopenharmony_ci	u32 orig, data;
560462306a36Sopenharmony_ci
560562306a36Sopenharmony_ci	orig = data = RREG32(HDP_MEM_POWER_LS);
560662306a36Sopenharmony_ci
560762306a36Sopenharmony_ci	if (enable && (rdev->cg_flags & RADEON_CG_SUPPORT_HDP_LS))
560862306a36Sopenharmony_ci		data |= HDP_LS_ENABLE;
560962306a36Sopenharmony_ci	else
561062306a36Sopenharmony_ci		data &= ~HDP_LS_ENABLE;
561162306a36Sopenharmony_ci
561262306a36Sopenharmony_ci	if (orig != data)
561362306a36Sopenharmony_ci		WREG32(HDP_MEM_POWER_LS, data);
561462306a36Sopenharmony_ci}
561562306a36Sopenharmony_ci
561662306a36Sopenharmony_cistatic void si_update_cg(struct radeon_device *rdev,
561762306a36Sopenharmony_ci			 u32 block, bool enable)
561862306a36Sopenharmony_ci{
561962306a36Sopenharmony_ci	if (block & RADEON_CG_BLOCK_GFX) {
562062306a36Sopenharmony_ci		si_enable_gui_idle_interrupt(rdev, false);
562162306a36Sopenharmony_ci		/* order matters! */
562262306a36Sopenharmony_ci		if (enable) {
562362306a36Sopenharmony_ci			si_enable_mgcg(rdev, true);
562462306a36Sopenharmony_ci			si_enable_cgcg(rdev, true);
562562306a36Sopenharmony_ci		} else {
562662306a36Sopenharmony_ci			si_enable_cgcg(rdev, false);
562762306a36Sopenharmony_ci			si_enable_mgcg(rdev, false);
562862306a36Sopenharmony_ci		}
562962306a36Sopenharmony_ci		si_enable_gui_idle_interrupt(rdev, true);
563062306a36Sopenharmony_ci	}
563162306a36Sopenharmony_ci
563262306a36Sopenharmony_ci	if (block & RADEON_CG_BLOCK_MC) {
563362306a36Sopenharmony_ci		si_enable_mc_mgcg(rdev, enable);
563462306a36Sopenharmony_ci		si_enable_mc_ls(rdev, enable);
563562306a36Sopenharmony_ci	}
563662306a36Sopenharmony_ci
563762306a36Sopenharmony_ci	if (block & RADEON_CG_BLOCK_SDMA) {
563862306a36Sopenharmony_ci		si_enable_dma_mgcg(rdev, enable);
563962306a36Sopenharmony_ci	}
564062306a36Sopenharmony_ci
564162306a36Sopenharmony_ci	if (block & RADEON_CG_BLOCK_BIF) {
564262306a36Sopenharmony_ci		si_enable_bif_mgls(rdev, enable);
564362306a36Sopenharmony_ci	}
564462306a36Sopenharmony_ci
564562306a36Sopenharmony_ci	if (block & RADEON_CG_BLOCK_UVD) {
564662306a36Sopenharmony_ci		if (rdev->has_uvd) {
564762306a36Sopenharmony_ci			si_enable_uvd_mgcg(rdev, enable);
564862306a36Sopenharmony_ci		}
564962306a36Sopenharmony_ci	}
565062306a36Sopenharmony_ci
565162306a36Sopenharmony_ci	if (block & RADEON_CG_BLOCK_HDP) {
565262306a36Sopenharmony_ci		si_enable_hdp_mgcg(rdev, enable);
565362306a36Sopenharmony_ci		si_enable_hdp_ls(rdev, enable);
565462306a36Sopenharmony_ci	}
565562306a36Sopenharmony_ci}
565662306a36Sopenharmony_ci
565762306a36Sopenharmony_cistatic void si_init_cg(struct radeon_device *rdev)
565862306a36Sopenharmony_ci{
565962306a36Sopenharmony_ci	si_update_cg(rdev, (RADEON_CG_BLOCK_GFX |
566062306a36Sopenharmony_ci			    RADEON_CG_BLOCK_MC |
566162306a36Sopenharmony_ci			    RADEON_CG_BLOCK_SDMA |
566262306a36Sopenharmony_ci			    RADEON_CG_BLOCK_BIF |
566362306a36Sopenharmony_ci			    RADEON_CG_BLOCK_HDP), true);
566462306a36Sopenharmony_ci	if (rdev->has_uvd) {
566562306a36Sopenharmony_ci		si_update_cg(rdev, RADEON_CG_BLOCK_UVD, true);
566662306a36Sopenharmony_ci		si_init_uvd_internal_cg(rdev);
566762306a36Sopenharmony_ci	}
566862306a36Sopenharmony_ci}
566962306a36Sopenharmony_ci
567062306a36Sopenharmony_cistatic void si_fini_cg(struct radeon_device *rdev)
567162306a36Sopenharmony_ci{
567262306a36Sopenharmony_ci	if (rdev->has_uvd) {
567362306a36Sopenharmony_ci		si_update_cg(rdev, RADEON_CG_BLOCK_UVD, false);
567462306a36Sopenharmony_ci	}
567562306a36Sopenharmony_ci	si_update_cg(rdev, (RADEON_CG_BLOCK_GFX |
567662306a36Sopenharmony_ci			    RADEON_CG_BLOCK_MC |
567762306a36Sopenharmony_ci			    RADEON_CG_BLOCK_SDMA |
567862306a36Sopenharmony_ci			    RADEON_CG_BLOCK_BIF |
567962306a36Sopenharmony_ci			    RADEON_CG_BLOCK_HDP), false);
568062306a36Sopenharmony_ci}
568162306a36Sopenharmony_ci
568262306a36Sopenharmony_ciu32 si_get_csb_size(struct radeon_device *rdev)
568362306a36Sopenharmony_ci{
568462306a36Sopenharmony_ci	u32 count = 0;
568562306a36Sopenharmony_ci	const struct cs_section_def *sect = NULL;
568662306a36Sopenharmony_ci	const struct cs_extent_def *ext = NULL;
568762306a36Sopenharmony_ci
568862306a36Sopenharmony_ci	if (rdev->rlc.cs_data == NULL)
568962306a36Sopenharmony_ci		return 0;
569062306a36Sopenharmony_ci
569162306a36Sopenharmony_ci	/* begin clear state */
569262306a36Sopenharmony_ci	count += 2;
569362306a36Sopenharmony_ci	/* context control state */
569462306a36Sopenharmony_ci	count += 3;
569562306a36Sopenharmony_ci
569662306a36Sopenharmony_ci	for (sect = rdev->rlc.cs_data; sect->section != NULL; ++sect) {
569762306a36Sopenharmony_ci		for (ext = sect->section; ext->extent != NULL; ++ext) {
569862306a36Sopenharmony_ci			if (sect->id == SECT_CONTEXT)
569962306a36Sopenharmony_ci				count += 2 + ext->reg_count;
570062306a36Sopenharmony_ci			else
570162306a36Sopenharmony_ci				return 0;
570262306a36Sopenharmony_ci		}
570362306a36Sopenharmony_ci	}
570462306a36Sopenharmony_ci	/* pa_sc_raster_config */
570562306a36Sopenharmony_ci	count += 3;
570662306a36Sopenharmony_ci	/* end clear state */
570762306a36Sopenharmony_ci	count += 2;
570862306a36Sopenharmony_ci	/* clear state */
570962306a36Sopenharmony_ci	count += 2;
571062306a36Sopenharmony_ci
571162306a36Sopenharmony_ci	return count;
571262306a36Sopenharmony_ci}
571362306a36Sopenharmony_ci
571462306a36Sopenharmony_civoid si_get_csb_buffer(struct radeon_device *rdev, volatile u32 *buffer)
571562306a36Sopenharmony_ci{
571662306a36Sopenharmony_ci	u32 count = 0, i;
571762306a36Sopenharmony_ci	const struct cs_section_def *sect = NULL;
571862306a36Sopenharmony_ci	const struct cs_extent_def *ext = NULL;
571962306a36Sopenharmony_ci
572062306a36Sopenharmony_ci	if (rdev->rlc.cs_data == NULL)
572162306a36Sopenharmony_ci		return;
572262306a36Sopenharmony_ci	if (buffer == NULL)
572362306a36Sopenharmony_ci		return;
572462306a36Sopenharmony_ci
572562306a36Sopenharmony_ci	buffer[count++] = cpu_to_le32(PACKET3(PACKET3_PREAMBLE_CNTL, 0));
572662306a36Sopenharmony_ci	buffer[count++] = cpu_to_le32(PACKET3_PREAMBLE_BEGIN_CLEAR_STATE);
572762306a36Sopenharmony_ci
572862306a36Sopenharmony_ci	buffer[count++] = cpu_to_le32(PACKET3(PACKET3_CONTEXT_CONTROL, 1));
572962306a36Sopenharmony_ci	buffer[count++] = cpu_to_le32(0x80000000);
573062306a36Sopenharmony_ci	buffer[count++] = cpu_to_le32(0x80000000);
573162306a36Sopenharmony_ci
573262306a36Sopenharmony_ci	for (sect = rdev->rlc.cs_data; sect->section != NULL; ++sect) {
573362306a36Sopenharmony_ci		for (ext = sect->section; ext->extent != NULL; ++ext) {
573462306a36Sopenharmony_ci			if (sect->id == SECT_CONTEXT) {
573562306a36Sopenharmony_ci				buffer[count++] =
573662306a36Sopenharmony_ci					cpu_to_le32(PACKET3(PACKET3_SET_CONTEXT_REG, ext->reg_count));
573762306a36Sopenharmony_ci				buffer[count++] = cpu_to_le32(ext->reg_index - 0xa000);
573862306a36Sopenharmony_ci				for (i = 0; i < ext->reg_count; i++)
573962306a36Sopenharmony_ci					buffer[count++] = cpu_to_le32(ext->extent[i]);
574062306a36Sopenharmony_ci			} else {
574162306a36Sopenharmony_ci				return;
574262306a36Sopenharmony_ci			}
574362306a36Sopenharmony_ci		}
574462306a36Sopenharmony_ci	}
574562306a36Sopenharmony_ci
574662306a36Sopenharmony_ci	buffer[count++] = cpu_to_le32(PACKET3(PACKET3_SET_CONTEXT_REG, 1));
574762306a36Sopenharmony_ci	buffer[count++] = cpu_to_le32(PA_SC_RASTER_CONFIG - PACKET3_SET_CONTEXT_REG_START);
574862306a36Sopenharmony_ci	switch (rdev->family) {
574962306a36Sopenharmony_ci	case CHIP_TAHITI:
575062306a36Sopenharmony_ci	case CHIP_PITCAIRN:
575162306a36Sopenharmony_ci		buffer[count++] = cpu_to_le32(0x2a00126a);
575262306a36Sopenharmony_ci		break;
575362306a36Sopenharmony_ci	case CHIP_VERDE:
575462306a36Sopenharmony_ci		buffer[count++] = cpu_to_le32(0x0000124a);
575562306a36Sopenharmony_ci		break;
575662306a36Sopenharmony_ci	case CHIP_OLAND:
575762306a36Sopenharmony_ci		buffer[count++] = cpu_to_le32(0x00000082);
575862306a36Sopenharmony_ci		break;
575962306a36Sopenharmony_ci	case CHIP_HAINAN:
576062306a36Sopenharmony_ci		buffer[count++] = cpu_to_le32(0x00000000);
576162306a36Sopenharmony_ci		break;
576262306a36Sopenharmony_ci	default:
576362306a36Sopenharmony_ci		buffer[count++] = cpu_to_le32(0x00000000);
576462306a36Sopenharmony_ci		break;
576562306a36Sopenharmony_ci	}
576662306a36Sopenharmony_ci
576762306a36Sopenharmony_ci	buffer[count++] = cpu_to_le32(PACKET3(PACKET3_PREAMBLE_CNTL, 0));
576862306a36Sopenharmony_ci	buffer[count++] = cpu_to_le32(PACKET3_PREAMBLE_END_CLEAR_STATE);
576962306a36Sopenharmony_ci
577062306a36Sopenharmony_ci	buffer[count++] = cpu_to_le32(PACKET3(PACKET3_CLEAR_STATE, 0));
577162306a36Sopenharmony_ci	buffer[count++] = cpu_to_le32(0);
577262306a36Sopenharmony_ci}
577362306a36Sopenharmony_ci
577462306a36Sopenharmony_cistatic void si_init_pg(struct radeon_device *rdev)
577562306a36Sopenharmony_ci{
577662306a36Sopenharmony_ci	if (rdev->pg_flags) {
577762306a36Sopenharmony_ci		if (rdev->pg_flags & RADEON_PG_SUPPORT_SDMA) {
577862306a36Sopenharmony_ci			si_init_dma_pg(rdev);
577962306a36Sopenharmony_ci		}
578062306a36Sopenharmony_ci		si_init_ao_cu_mask(rdev);
578162306a36Sopenharmony_ci		if (rdev->pg_flags & RADEON_PG_SUPPORT_GFX_PG) {
578262306a36Sopenharmony_ci			si_init_gfx_cgpg(rdev);
578362306a36Sopenharmony_ci		} else {
578462306a36Sopenharmony_ci			WREG32(RLC_SAVE_AND_RESTORE_BASE, rdev->rlc.save_restore_gpu_addr >> 8);
578562306a36Sopenharmony_ci			WREG32(RLC_CLEAR_STATE_RESTORE_BASE, rdev->rlc.clear_state_gpu_addr >> 8);
578662306a36Sopenharmony_ci		}
578762306a36Sopenharmony_ci		si_enable_dma_pg(rdev, true);
578862306a36Sopenharmony_ci		si_enable_gfx_cgpg(rdev, true);
578962306a36Sopenharmony_ci	} else {
579062306a36Sopenharmony_ci		WREG32(RLC_SAVE_AND_RESTORE_BASE, rdev->rlc.save_restore_gpu_addr >> 8);
579162306a36Sopenharmony_ci		WREG32(RLC_CLEAR_STATE_RESTORE_BASE, rdev->rlc.clear_state_gpu_addr >> 8);
579262306a36Sopenharmony_ci	}
579362306a36Sopenharmony_ci}
579462306a36Sopenharmony_ci
579562306a36Sopenharmony_cistatic void si_fini_pg(struct radeon_device *rdev)
579662306a36Sopenharmony_ci{
579762306a36Sopenharmony_ci	if (rdev->pg_flags) {
579862306a36Sopenharmony_ci		si_enable_dma_pg(rdev, false);
579962306a36Sopenharmony_ci		si_enable_gfx_cgpg(rdev, false);
580062306a36Sopenharmony_ci	}
580162306a36Sopenharmony_ci}
580262306a36Sopenharmony_ci
580362306a36Sopenharmony_ci/*
580462306a36Sopenharmony_ci * RLC
580562306a36Sopenharmony_ci */
580662306a36Sopenharmony_civoid si_rlc_reset(struct radeon_device *rdev)
580762306a36Sopenharmony_ci{
580862306a36Sopenharmony_ci	u32 tmp = RREG32(GRBM_SOFT_RESET);
580962306a36Sopenharmony_ci
581062306a36Sopenharmony_ci	tmp |= SOFT_RESET_RLC;
581162306a36Sopenharmony_ci	WREG32(GRBM_SOFT_RESET, tmp);
581262306a36Sopenharmony_ci	udelay(50);
581362306a36Sopenharmony_ci	tmp &= ~SOFT_RESET_RLC;
581462306a36Sopenharmony_ci	WREG32(GRBM_SOFT_RESET, tmp);
581562306a36Sopenharmony_ci	udelay(50);
581662306a36Sopenharmony_ci}
581762306a36Sopenharmony_ci
581862306a36Sopenharmony_cistatic void si_rlc_stop(struct radeon_device *rdev)
581962306a36Sopenharmony_ci{
582062306a36Sopenharmony_ci	WREG32(RLC_CNTL, 0);
582162306a36Sopenharmony_ci
582262306a36Sopenharmony_ci	si_enable_gui_idle_interrupt(rdev, false);
582362306a36Sopenharmony_ci
582462306a36Sopenharmony_ci	si_wait_for_rlc_serdes(rdev);
582562306a36Sopenharmony_ci}
582662306a36Sopenharmony_ci
582762306a36Sopenharmony_cistatic void si_rlc_start(struct radeon_device *rdev)
582862306a36Sopenharmony_ci{
582962306a36Sopenharmony_ci	WREG32(RLC_CNTL, RLC_ENABLE);
583062306a36Sopenharmony_ci
583162306a36Sopenharmony_ci	si_enable_gui_idle_interrupt(rdev, true);
583262306a36Sopenharmony_ci
583362306a36Sopenharmony_ci	udelay(50);
583462306a36Sopenharmony_ci}
583562306a36Sopenharmony_ci
583662306a36Sopenharmony_cistatic bool si_lbpw_supported(struct radeon_device *rdev)
583762306a36Sopenharmony_ci{
583862306a36Sopenharmony_ci	u32 tmp;
583962306a36Sopenharmony_ci
584062306a36Sopenharmony_ci	/* Enable LBPW only for DDR3 */
584162306a36Sopenharmony_ci	tmp = RREG32(MC_SEQ_MISC0);
584262306a36Sopenharmony_ci	if ((tmp & 0xF0000000) == 0xB0000000)
584362306a36Sopenharmony_ci		return true;
584462306a36Sopenharmony_ci	return false;
584562306a36Sopenharmony_ci}
584662306a36Sopenharmony_ci
584762306a36Sopenharmony_cistatic void si_enable_lbpw(struct radeon_device *rdev, bool enable)
584862306a36Sopenharmony_ci{
584962306a36Sopenharmony_ci	u32 tmp;
585062306a36Sopenharmony_ci
585162306a36Sopenharmony_ci	tmp = RREG32(RLC_LB_CNTL);
585262306a36Sopenharmony_ci	if (enable)
585362306a36Sopenharmony_ci		tmp |= LOAD_BALANCE_ENABLE;
585462306a36Sopenharmony_ci	else
585562306a36Sopenharmony_ci		tmp &= ~LOAD_BALANCE_ENABLE;
585662306a36Sopenharmony_ci	WREG32(RLC_LB_CNTL, tmp);
585762306a36Sopenharmony_ci
585862306a36Sopenharmony_ci	if (!enable) {
585962306a36Sopenharmony_ci		si_select_se_sh(rdev, 0xffffffff, 0xffffffff);
586062306a36Sopenharmony_ci		WREG32(SPI_LB_CU_MASK, 0x00ff);
586162306a36Sopenharmony_ci	}
586262306a36Sopenharmony_ci}
586362306a36Sopenharmony_ci
586462306a36Sopenharmony_cistatic int si_rlc_resume(struct radeon_device *rdev)
586562306a36Sopenharmony_ci{
586662306a36Sopenharmony_ci	u32 i;
586762306a36Sopenharmony_ci
586862306a36Sopenharmony_ci	if (!rdev->rlc_fw)
586962306a36Sopenharmony_ci		return -EINVAL;
587062306a36Sopenharmony_ci
587162306a36Sopenharmony_ci	si_rlc_stop(rdev);
587262306a36Sopenharmony_ci
587362306a36Sopenharmony_ci	si_rlc_reset(rdev);
587462306a36Sopenharmony_ci
587562306a36Sopenharmony_ci	si_init_pg(rdev);
587662306a36Sopenharmony_ci
587762306a36Sopenharmony_ci	si_init_cg(rdev);
587862306a36Sopenharmony_ci
587962306a36Sopenharmony_ci	WREG32(RLC_RL_BASE, 0);
588062306a36Sopenharmony_ci	WREG32(RLC_RL_SIZE, 0);
588162306a36Sopenharmony_ci	WREG32(RLC_LB_CNTL, 0);
588262306a36Sopenharmony_ci	WREG32(RLC_LB_CNTR_MAX, 0xffffffff);
588362306a36Sopenharmony_ci	WREG32(RLC_LB_CNTR_INIT, 0);
588462306a36Sopenharmony_ci	WREG32(RLC_LB_INIT_CU_MASK, 0xffffffff);
588562306a36Sopenharmony_ci
588662306a36Sopenharmony_ci	WREG32(RLC_MC_CNTL, 0);
588762306a36Sopenharmony_ci	WREG32(RLC_UCODE_CNTL, 0);
588862306a36Sopenharmony_ci
588962306a36Sopenharmony_ci	if (rdev->new_fw) {
589062306a36Sopenharmony_ci		const struct rlc_firmware_header_v1_0 *hdr =
589162306a36Sopenharmony_ci			(const struct rlc_firmware_header_v1_0 *)rdev->rlc_fw->data;
589262306a36Sopenharmony_ci		u32 fw_size = le32_to_cpu(hdr->header.ucode_size_bytes) / 4;
589362306a36Sopenharmony_ci		const __le32 *fw_data = (const __le32 *)
589462306a36Sopenharmony_ci			(rdev->rlc_fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes));
589562306a36Sopenharmony_ci
589662306a36Sopenharmony_ci		radeon_ucode_print_rlc_hdr(&hdr->header);
589762306a36Sopenharmony_ci
589862306a36Sopenharmony_ci		for (i = 0; i < fw_size; i++) {
589962306a36Sopenharmony_ci			WREG32(RLC_UCODE_ADDR, i);
590062306a36Sopenharmony_ci			WREG32(RLC_UCODE_DATA, le32_to_cpup(fw_data++));
590162306a36Sopenharmony_ci		}
590262306a36Sopenharmony_ci	} else {
590362306a36Sopenharmony_ci		const __be32 *fw_data =
590462306a36Sopenharmony_ci			(const __be32 *)rdev->rlc_fw->data;
590562306a36Sopenharmony_ci		for (i = 0; i < SI_RLC_UCODE_SIZE; i++) {
590662306a36Sopenharmony_ci			WREG32(RLC_UCODE_ADDR, i);
590762306a36Sopenharmony_ci			WREG32(RLC_UCODE_DATA, be32_to_cpup(fw_data++));
590862306a36Sopenharmony_ci		}
590962306a36Sopenharmony_ci	}
591062306a36Sopenharmony_ci	WREG32(RLC_UCODE_ADDR, 0);
591162306a36Sopenharmony_ci
591262306a36Sopenharmony_ci	si_enable_lbpw(rdev, si_lbpw_supported(rdev));
591362306a36Sopenharmony_ci
591462306a36Sopenharmony_ci	si_rlc_start(rdev);
591562306a36Sopenharmony_ci
591662306a36Sopenharmony_ci	return 0;
591762306a36Sopenharmony_ci}
591862306a36Sopenharmony_ci
591962306a36Sopenharmony_cistatic void si_enable_interrupts(struct radeon_device *rdev)
592062306a36Sopenharmony_ci{
592162306a36Sopenharmony_ci	u32 ih_cntl = RREG32(IH_CNTL);
592262306a36Sopenharmony_ci	u32 ih_rb_cntl = RREG32(IH_RB_CNTL);
592362306a36Sopenharmony_ci
592462306a36Sopenharmony_ci	ih_cntl |= ENABLE_INTR;
592562306a36Sopenharmony_ci	ih_rb_cntl |= IH_RB_ENABLE;
592662306a36Sopenharmony_ci	WREG32(IH_CNTL, ih_cntl);
592762306a36Sopenharmony_ci	WREG32(IH_RB_CNTL, ih_rb_cntl);
592862306a36Sopenharmony_ci	rdev->ih.enabled = true;
592962306a36Sopenharmony_ci}
593062306a36Sopenharmony_ci
593162306a36Sopenharmony_cistatic void si_disable_interrupts(struct radeon_device *rdev)
593262306a36Sopenharmony_ci{
593362306a36Sopenharmony_ci	u32 ih_rb_cntl = RREG32(IH_RB_CNTL);
593462306a36Sopenharmony_ci	u32 ih_cntl = RREG32(IH_CNTL);
593562306a36Sopenharmony_ci
593662306a36Sopenharmony_ci	ih_rb_cntl &= ~IH_RB_ENABLE;
593762306a36Sopenharmony_ci	ih_cntl &= ~ENABLE_INTR;
593862306a36Sopenharmony_ci	WREG32(IH_RB_CNTL, ih_rb_cntl);
593962306a36Sopenharmony_ci	WREG32(IH_CNTL, ih_cntl);
594062306a36Sopenharmony_ci	/* set rptr, wptr to 0 */
594162306a36Sopenharmony_ci	WREG32(IH_RB_RPTR, 0);
594262306a36Sopenharmony_ci	WREG32(IH_RB_WPTR, 0);
594362306a36Sopenharmony_ci	rdev->ih.enabled = false;
594462306a36Sopenharmony_ci	rdev->ih.rptr = 0;
594562306a36Sopenharmony_ci}
594662306a36Sopenharmony_ci
594762306a36Sopenharmony_cistatic void si_disable_interrupt_state(struct radeon_device *rdev)
594862306a36Sopenharmony_ci{
594962306a36Sopenharmony_ci	int i;
595062306a36Sopenharmony_ci	u32 tmp;
595162306a36Sopenharmony_ci
595262306a36Sopenharmony_ci	tmp = RREG32(CP_INT_CNTL_RING0) &
595362306a36Sopenharmony_ci		(CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE);
595462306a36Sopenharmony_ci	WREG32(CP_INT_CNTL_RING0, tmp);
595562306a36Sopenharmony_ci	WREG32(CP_INT_CNTL_RING1, 0);
595662306a36Sopenharmony_ci	WREG32(CP_INT_CNTL_RING2, 0);
595762306a36Sopenharmony_ci	tmp = RREG32(DMA_CNTL + DMA0_REGISTER_OFFSET) & ~TRAP_ENABLE;
595862306a36Sopenharmony_ci	WREG32(DMA_CNTL + DMA0_REGISTER_OFFSET, tmp);
595962306a36Sopenharmony_ci	tmp = RREG32(DMA_CNTL + DMA1_REGISTER_OFFSET) & ~TRAP_ENABLE;
596062306a36Sopenharmony_ci	WREG32(DMA_CNTL + DMA1_REGISTER_OFFSET, tmp);
596162306a36Sopenharmony_ci	WREG32(GRBM_INT_CNTL, 0);
596262306a36Sopenharmony_ci	WREG32(SRBM_INT_CNTL, 0);
596362306a36Sopenharmony_ci	for (i = 0; i < rdev->num_crtc; i++)
596462306a36Sopenharmony_ci		WREG32(INT_MASK + crtc_offsets[i], 0);
596562306a36Sopenharmony_ci	for (i = 0; i < rdev->num_crtc; i++)
596662306a36Sopenharmony_ci		WREG32(GRPH_INT_CONTROL + crtc_offsets[i], 0);
596762306a36Sopenharmony_ci
596862306a36Sopenharmony_ci	if (!ASIC_IS_NODCE(rdev)) {
596962306a36Sopenharmony_ci		WREG32(DAC_AUTODETECT_INT_CONTROL, 0);
597062306a36Sopenharmony_ci
597162306a36Sopenharmony_ci		for (i = 0; i < 6; i++)
597262306a36Sopenharmony_ci			WREG32_AND(DC_HPDx_INT_CONTROL(i),
597362306a36Sopenharmony_ci				   DC_HPDx_INT_POLARITY);
597462306a36Sopenharmony_ci	}
597562306a36Sopenharmony_ci}
597662306a36Sopenharmony_ci
597762306a36Sopenharmony_cistatic int si_irq_init(struct radeon_device *rdev)
597862306a36Sopenharmony_ci{
597962306a36Sopenharmony_ci	int ret = 0;
598062306a36Sopenharmony_ci	int rb_bufsz;
598162306a36Sopenharmony_ci	u32 interrupt_cntl, ih_cntl, ih_rb_cntl;
598262306a36Sopenharmony_ci
598362306a36Sopenharmony_ci	/* allocate ring */
598462306a36Sopenharmony_ci	ret = r600_ih_ring_alloc(rdev);
598562306a36Sopenharmony_ci	if (ret)
598662306a36Sopenharmony_ci		return ret;
598762306a36Sopenharmony_ci
598862306a36Sopenharmony_ci	/* disable irqs */
598962306a36Sopenharmony_ci	si_disable_interrupts(rdev);
599062306a36Sopenharmony_ci
599162306a36Sopenharmony_ci	/* init rlc */
599262306a36Sopenharmony_ci	ret = si_rlc_resume(rdev);
599362306a36Sopenharmony_ci	if (ret) {
599462306a36Sopenharmony_ci		r600_ih_ring_fini(rdev);
599562306a36Sopenharmony_ci		return ret;
599662306a36Sopenharmony_ci	}
599762306a36Sopenharmony_ci
599862306a36Sopenharmony_ci	/* setup interrupt control */
599962306a36Sopenharmony_ci	/* set dummy read address to dummy page address */
600062306a36Sopenharmony_ci	WREG32(INTERRUPT_CNTL2, rdev->dummy_page.addr >> 8);
600162306a36Sopenharmony_ci	interrupt_cntl = RREG32(INTERRUPT_CNTL);
600262306a36Sopenharmony_ci	/* IH_DUMMY_RD_OVERRIDE=0 - dummy read disabled with msi, enabled without msi
600362306a36Sopenharmony_ci	 * IH_DUMMY_RD_OVERRIDE=1 - dummy read controlled by IH_DUMMY_RD_EN
600462306a36Sopenharmony_ci	 */
600562306a36Sopenharmony_ci	interrupt_cntl &= ~IH_DUMMY_RD_OVERRIDE;
600662306a36Sopenharmony_ci	/* IH_REQ_NONSNOOP_EN=1 if ring is in non-cacheable memory, e.g., vram */
600762306a36Sopenharmony_ci	interrupt_cntl &= ~IH_REQ_NONSNOOP_EN;
600862306a36Sopenharmony_ci	WREG32(INTERRUPT_CNTL, interrupt_cntl);
600962306a36Sopenharmony_ci
601062306a36Sopenharmony_ci	WREG32(IH_RB_BASE, rdev->ih.gpu_addr >> 8);
601162306a36Sopenharmony_ci	rb_bufsz = order_base_2(rdev->ih.ring_size / 4);
601262306a36Sopenharmony_ci
601362306a36Sopenharmony_ci	ih_rb_cntl = (IH_WPTR_OVERFLOW_ENABLE |
601462306a36Sopenharmony_ci		      IH_WPTR_OVERFLOW_CLEAR |
601562306a36Sopenharmony_ci		      (rb_bufsz << 1));
601662306a36Sopenharmony_ci
601762306a36Sopenharmony_ci	if (rdev->wb.enabled)
601862306a36Sopenharmony_ci		ih_rb_cntl |= IH_WPTR_WRITEBACK_ENABLE;
601962306a36Sopenharmony_ci
602062306a36Sopenharmony_ci	/* set the writeback address whether it's enabled or not */
602162306a36Sopenharmony_ci	WREG32(IH_RB_WPTR_ADDR_LO, (rdev->wb.gpu_addr + R600_WB_IH_WPTR_OFFSET) & 0xFFFFFFFC);
602262306a36Sopenharmony_ci	WREG32(IH_RB_WPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + R600_WB_IH_WPTR_OFFSET) & 0xFF);
602362306a36Sopenharmony_ci
602462306a36Sopenharmony_ci	WREG32(IH_RB_CNTL, ih_rb_cntl);
602562306a36Sopenharmony_ci
602662306a36Sopenharmony_ci	/* set rptr, wptr to 0 */
602762306a36Sopenharmony_ci	WREG32(IH_RB_RPTR, 0);
602862306a36Sopenharmony_ci	WREG32(IH_RB_WPTR, 0);
602962306a36Sopenharmony_ci
603062306a36Sopenharmony_ci	/* Default settings for IH_CNTL (disabled at first) */
603162306a36Sopenharmony_ci	ih_cntl = MC_WRREQ_CREDIT(0x10) | MC_WR_CLEAN_CNT(0x10) | MC_VMID(0);
603262306a36Sopenharmony_ci	/* RPTR_REARM only works if msi's are enabled */
603362306a36Sopenharmony_ci	if (rdev->msi_enabled)
603462306a36Sopenharmony_ci		ih_cntl |= RPTR_REARM;
603562306a36Sopenharmony_ci	WREG32(IH_CNTL, ih_cntl);
603662306a36Sopenharmony_ci
603762306a36Sopenharmony_ci	/* force the active interrupt state to all disabled */
603862306a36Sopenharmony_ci	si_disable_interrupt_state(rdev);
603962306a36Sopenharmony_ci
604062306a36Sopenharmony_ci	pci_set_master(rdev->pdev);
604162306a36Sopenharmony_ci
604262306a36Sopenharmony_ci	/* enable irqs */
604362306a36Sopenharmony_ci	si_enable_interrupts(rdev);
604462306a36Sopenharmony_ci
604562306a36Sopenharmony_ci	return ret;
604662306a36Sopenharmony_ci}
604762306a36Sopenharmony_ci
604862306a36Sopenharmony_ci/* The order we write back each register here is important */
604962306a36Sopenharmony_ciint si_irq_set(struct radeon_device *rdev)
605062306a36Sopenharmony_ci{
605162306a36Sopenharmony_ci	int i;
605262306a36Sopenharmony_ci	u32 cp_int_cntl;
605362306a36Sopenharmony_ci	u32 cp_int_cntl1 = 0, cp_int_cntl2 = 0;
605462306a36Sopenharmony_ci	u32 grbm_int_cntl = 0;
605562306a36Sopenharmony_ci	u32 dma_cntl, dma_cntl1;
605662306a36Sopenharmony_ci	u32 thermal_int = 0;
605762306a36Sopenharmony_ci
605862306a36Sopenharmony_ci	if (!rdev->irq.installed) {
605962306a36Sopenharmony_ci		WARN(1, "Can't enable IRQ/MSI because no handler is installed\n");
606062306a36Sopenharmony_ci		return -EINVAL;
606162306a36Sopenharmony_ci	}
606262306a36Sopenharmony_ci	/* don't enable anything if the ih is disabled */
606362306a36Sopenharmony_ci	if (!rdev->ih.enabled) {
606462306a36Sopenharmony_ci		si_disable_interrupts(rdev);
606562306a36Sopenharmony_ci		/* force the active interrupt state to all disabled */
606662306a36Sopenharmony_ci		si_disable_interrupt_state(rdev);
606762306a36Sopenharmony_ci		return 0;
606862306a36Sopenharmony_ci	}
606962306a36Sopenharmony_ci
607062306a36Sopenharmony_ci	cp_int_cntl = RREG32(CP_INT_CNTL_RING0) &
607162306a36Sopenharmony_ci		(CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE);
607262306a36Sopenharmony_ci
607362306a36Sopenharmony_ci	dma_cntl = RREG32(DMA_CNTL + DMA0_REGISTER_OFFSET) & ~TRAP_ENABLE;
607462306a36Sopenharmony_ci	dma_cntl1 = RREG32(DMA_CNTL + DMA1_REGISTER_OFFSET) & ~TRAP_ENABLE;
607562306a36Sopenharmony_ci
607662306a36Sopenharmony_ci	thermal_int = RREG32(CG_THERMAL_INT) &
607762306a36Sopenharmony_ci		~(THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW);
607862306a36Sopenharmony_ci
607962306a36Sopenharmony_ci	/* enable CP interrupts on all rings */
608062306a36Sopenharmony_ci	if (atomic_read(&rdev->irq.ring_int[RADEON_RING_TYPE_GFX_INDEX])) {
608162306a36Sopenharmony_ci		DRM_DEBUG("si_irq_set: sw int gfx\n");
608262306a36Sopenharmony_ci		cp_int_cntl |= TIME_STAMP_INT_ENABLE;
608362306a36Sopenharmony_ci	}
608462306a36Sopenharmony_ci	if (atomic_read(&rdev->irq.ring_int[CAYMAN_RING_TYPE_CP1_INDEX])) {
608562306a36Sopenharmony_ci		DRM_DEBUG("si_irq_set: sw int cp1\n");
608662306a36Sopenharmony_ci		cp_int_cntl1 |= TIME_STAMP_INT_ENABLE;
608762306a36Sopenharmony_ci	}
608862306a36Sopenharmony_ci	if (atomic_read(&rdev->irq.ring_int[CAYMAN_RING_TYPE_CP2_INDEX])) {
608962306a36Sopenharmony_ci		DRM_DEBUG("si_irq_set: sw int cp2\n");
609062306a36Sopenharmony_ci		cp_int_cntl2 |= TIME_STAMP_INT_ENABLE;
609162306a36Sopenharmony_ci	}
609262306a36Sopenharmony_ci	if (atomic_read(&rdev->irq.ring_int[R600_RING_TYPE_DMA_INDEX])) {
609362306a36Sopenharmony_ci		DRM_DEBUG("si_irq_set: sw int dma\n");
609462306a36Sopenharmony_ci		dma_cntl |= TRAP_ENABLE;
609562306a36Sopenharmony_ci	}
609662306a36Sopenharmony_ci
609762306a36Sopenharmony_ci	if (atomic_read(&rdev->irq.ring_int[CAYMAN_RING_TYPE_DMA1_INDEX])) {
609862306a36Sopenharmony_ci		DRM_DEBUG("si_irq_set: sw int dma1\n");
609962306a36Sopenharmony_ci		dma_cntl1 |= TRAP_ENABLE;
610062306a36Sopenharmony_ci	}
610162306a36Sopenharmony_ci
610262306a36Sopenharmony_ci	WREG32(CP_INT_CNTL_RING0, cp_int_cntl);
610362306a36Sopenharmony_ci	WREG32(CP_INT_CNTL_RING1, cp_int_cntl1);
610462306a36Sopenharmony_ci	WREG32(CP_INT_CNTL_RING2, cp_int_cntl2);
610562306a36Sopenharmony_ci
610662306a36Sopenharmony_ci	WREG32(DMA_CNTL + DMA0_REGISTER_OFFSET, dma_cntl);
610762306a36Sopenharmony_ci	WREG32(DMA_CNTL + DMA1_REGISTER_OFFSET, dma_cntl1);
610862306a36Sopenharmony_ci
610962306a36Sopenharmony_ci	WREG32(GRBM_INT_CNTL, grbm_int_cntl);
611062306a36Sopenharmony_ci
611162306a36Sopenharmony_ci	if (rdev->irq.dpm_thermal) {
611262306a36Sopenharmony_ci		DRM_DEBUG("dpm thermal\n");
611362306a36Sopenharmony_ci		thermal_int |= THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW;
611462306a36Sopenharmony_ci	}
611562306a36Sopenharmony_ci
611662306a36Sopenharmony_ci	for (i = 0; i < rdev->num_crtc; i++) {
611762306a36Sopenharmony_ci		radeon_irq_kms_set_irq_n_enabled(
611862306a36Sopenharmony_ci		    rdev, INT_MASK + crtc_offsets[i], VBLANK_INT_MASK,
611962306a36Sopenharmony_ci		    rdev->irq.crtc_vblank_int[i] ||
612062306a36Sopenharmony_ci		    atomic_read(&rdev->irq.pflip[i]), "vblank", i);
612162306a36Sopenharmony_ci	}
612262306a36Sopenharmony_ci
612362306a36Sopenharmony_ci	for (i = 0; i < rdev->num_crtc; i++)
612462306a36Sopenharmony_ci		WREG32(GRPH_INT_CONTROL + crtc_offsets[i], GRPH_PFLIP_INT_MASK);
612562306a36Sopenharmony_ci
612662306a36Sopenharmony_ci	if (!ASIC_IS_NODCE(rdev)) {
612762306a36Sopenharmony_ci		for (i = 0; i < 6; i++) {
612862306a36Sopenharmony_ci			radeon_irq_kms_set_irq_n_enabled(
612962306a36Sopenharmony_ci			    rdev, DC_HPDx_INT_CONTROL(i),
613062306a36Sopenharmony_ci			    DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN,
613162306a36Sopenharmony_ci			    rdev->irq.hpd[i], "HPD", i);
613262306a36Sopenharmony_ci		}
613362306a36Sopenharmony_ci	}
613462306a36Sopenharmony_ci
613562306a36Sopenharmony_ci	WREG32(CG_THERMAL_INT, thermal_int);
613662306a36Sopenharmony_ci
613762306a36Sopenharmony_ci	/* posting read */
613862306a36Sopenharmony_ci	RREG32(SRBM_STATUS);
613962306a36Sopenharmony_ci
614062306a36Sopenharmony_ci	return 0;
614162306a36Sopenharmony_ci}
614262306a36Sopenharmony_ci
614362306a36Sopenharmony_ci/* The order we write back each register here is important */
614462306a36Sopenharmony_cistatic inline void si_irq_ack(struct radeon_device *rdev)
614562306a36Sopenharmony_ci{
614662306a36Sopenharmony_ci	int i, j;
614762306a36Sopenharmony_ci	u32 *disp_int = rdev->irq.stat_regs.evergreen.disp_int;
614862306a36Sopenharmony_ci	u32 *grph_int = rdev->irq.stat_regs.evergreen.grph_int;
614962306a36Sopenharmony_ci
615062306a36Sopenharmony_ci	if (ASIC_IS_NODCE(rdev))
615162306a36Sopenharmony_ci		return;
615262306a36Sopenharmony_ci
615362306a36Sopenharmony_ci	for (i = 0; i < 6; i++) {
615462306a36Sopenharmony_ci		disp_int[i] = RREG32(si_disp_int_status[i]);
615562306a36Sopenharmony_ci		if (i < rdev->num_crtc)
615662306a36Sopenharmony_ci			grph_int[i] = RREG32(GRPH_INT_STATUS + crtc_offsets[i]);
615762306a36Sopenharmony_ci	}
615862306a36Sopenharmony_ci
615962306a36Sopenharmony_ci	/* We write back each interrupt register in pairs of two */
616062306a36Sopenharmony_ci	for (i = 0; i < rdev->num_crtc; i += 2) {
616162306a36Sopenharmony_ci		for (j = i; j < (i + 2); j++) {
616262306a36Sopenharmony_ci			if (grph_int[j] & GRPH_PFLIP_INT_OCCURRED)
616362306a36Sopenharmony_ci				WREG32(GRPH_INT_STATUS + crtc_offsets[j],
616462306a36Sopenharmony_ci				       GRPH_PFLIP_INT_CLEAR);
616562306a36Sopenharmony_ci		}
616662306a36Sopenharmony_ci
616762306a36Sopenharmony_ci		for (j = i; j < (i + 2); j++) {
616862306a36Sopenharmony_ci			if (disp_int[j] & LB_D1_VBLANK_INTERRUPT)
616962306a36Sopenharmony_ci				WREG32(VBLANK_STATUS + crtc_offsets[j],
617062306a36Sopenharmony_ci				       VBLANK_ACK);
617162306a36Sopenharmony_ci			if (disp_int[j] & LB_D1_VLINE_INTERRUPT)
617262306a36Sopenharmony_ci				WREG32(VLINE_STATUS + crtc_offsets[j],
617362306a36Sopenharmony_ci				       VLINE_ACK);
617462306a36Sopenharmony_ci		}
617562306a36Sopenharmony_ci	}
617662306a36Sopenharmony_ci
617762306a36Sopenharmony_ci	for (i = 0; i < 6; i++) {
617862306a36Sopenharmony_ci		if (disp_int[i] & DC_HPD1_INTERRUPT)
617962306a36Sopenharmony_ci			WREG32_OR(DC_HPDx_INT_CONTROL(i), DC_HPDx_INT_ACK);
618062306a36Sopenharmony_ci	}
618162306a36Sopenharmony_ci
618262306a36Sopenharmony_ci	for (i = 0; i < 6; i++) {
618362306a36Sopenharmony_ci		if (disp_int[i] & DC_HPD1_RX_INTERRUPT)
618462306a36Sopenharmony_ci			WREG32_OR(DC_HPDx_INT_CONTROL(i), DC_HPDx_RX_INT_ACK);
618562306a36Sopenharmony_ci	}
618662306a36Sopenharmony_ci}
618762306a36Sopenharmony_ci
618862306a36Sopenharmony_cistatic void si_irq_disable(struct radeon_device *rdev)
618962306a36Sopenharmony_ci{
619062306a36Sopenharmony_ci	si_disable_interrupts(rdev);
619162306a36Sopenharmony_ci	/* Wait and acknowledge irq */
619262306a36Sopenharmony_ci	mdelay(1);
619362306a36Sopenharmony_ci	si_irq_ack(rdev);
619462306a36Sopenharmony_ci	si_disable_interrupt_state(rdev);
619562306a36Sopenharmony_ci}
619662306a36Sopenharmony_ci
619762306a36Sopenharmony_cistatic void si_irq_suspend(struct radeon_device *rdev)
619862306a36Sopenharmony_ci{
619962306a36Sopenharmony_ci	si_irq_disable(rdev);
620062306a36Sopenharmony_ci	si_rlc_stop(rdev);
620162306a36Sopenharmony_ci}
620262306a36Sopenharmony_ci
620362306a36Sopenharmony_cistatic void si_irq_fini(struct radeon_device *rdev)
620462306a36Sopenharmony_ci{
620562306a36Sopenharmony_ci	si_irq_suspend(rdev);
620662306a36Sopenharmony_ci	r600_ih_ring_fini(rdev);
620762306a36Sopenharmony_ci}
620862306a36Sopenharmony_ci
620962306a36Sopenharmony_cistatic inline u32 si_get_ih_wptr(struct radeon_device *rdev)
621062306a36Sopenharmony_ci{
621162306a36Sopenharmony_ci	u32 wptr, tmp;
621262306a36Sopenharmony_ci
621362306a36Sopenharmony_ci	if (rdev->wb.enabled)
621462306a36Sopenharmony_ci		wptr = le32_to_cpu(rdev->wb.wb[R600_WB_IH_WPTR_OFFSET/4]);
621562306a36Sopenharmony_ci	else
621662306a36Sopenharmony_ci		wptr = RREG32(IH_RB_WPTR);
621762306a36Sopenharmony_ci
621862306a36Sopenharmony_ci	if (wptr & RB_OVERFLOW) {
621962306a36Sopenharmony_ci		wptr &= ~RB_OVERFLOW;
622062306a36Sopenharmony_ci		/* When a ring buffer overflow happen start parsing interrupt
622162306a36Sopenharmony_ci		 * from the last not overwritten vector (wptr + 16). Hopefully
622262306a36Sopenharmony_ci		 * this should allow us to catchup.
622362306a36Sopenharmony_ci		 */
622462306a36Sopenharmony_ci		dev_warn(rdev->dev, "IH ring buffer overflow (0x%08X, 0x%08X, 0x%08X)\n",
622562306a36Sopenharmony_ci			 wptr, rdev->ih.rptr, (wptr + 16) & rdev->ih.ptr_mask);
622662306a36Sopenharmony_ci		rdev->ih.rptr = (wptr + 16) & rdev->ih.ptr_mask;
622762306a36Sopenharmony_ci		tmp = RREG32(IH_RB_CNTL);
622862306a36Sopenharmony_ci		tmp |= IH_WPTR_OVERFLOW_CLEAR;
622962306a36Sopenharmony_ci		WREG32(IH_RB_CNTL, tmp);
623062306a36Sopenharmony_ci	}
623162306a36Sopenharmony_ci	return (wptr & rdev->ih.ptr_mask);
623262306a36Sopenharmony_ci}
623362306a36Sopenharmony_ci
623462306a36Sopenharmony_ci/*        SI IV Ring
623562306a36Sopenharmony_ci * Each IV ring entry is 128 bits:
623662306a36Sopenharmony_ci * [7:0]    - interrupt source id
623762306a36Sopenharmony_ci * [31:8]   - reserved
623862306a36Sopenharmony_ci * [59:32]  - interrupt source data
623962306a36Sopenharmony_ci * [63:60]  - reserved
624062306a36Sopenharmony_ci * [71:64]  - RINGID
624162306a36Sopenharmony_ci * [79:72]  - VMID
624262306a36Sopenharmony_ci * [127:80] - reserved
624362306a36Sopenharmony_ci */
624462306a36Sopenharmony_ciint si_irq_process(struct radeon_device *rdev)
624562306a36Sopenharmony_ci{
624662306a36Sopenharmony_ci	u32 *disp_int = rdev->irq.stat_regs.evergreen.disp_int;
624762306a36Sopenharmony_ci	u32 crtc_idx, hpd_idx;
624862306a36Sopenharmony_ci	u32 mask;
624962306a36Sopenharmony_ci	u32 wptr;
625062306a36Sopenharmony_ci	u32 rptr;
625162306a36Sopenharmony_ci	u32 src_id, src_data, ring_id;
625262306a36Sopenharmony_ci	u32 ring_index;
625362306a36Sopenharmony_ci	bool queue_hotplug = false;
625462306a36Sopenharmony_ci	bool queue_dp = false;
625562306a36Sopenharmony_ci	bool queue_thermal = false;
625662306a36Sopenharmony_ci	u32 status, addr;
625762306a36Sopenharmony_ci	const char *event_name;
625862306a36Sopenharmony_ci
625962306a36Sopenharmony_ci	if (!rdev->ih.enabled || rdev->shutdown)
626062306a36Sopenharmony_ci		return IRQ_NONE;
626162306a36Sopenharmony_ci
626262306a36Sopenharmony_ci	wptr = si_get_ih_wptr(rdev);
626362306a36Sopenharmony_ci
626462306a36Sopenharmony_cirestart_ih:
626562306a36Sopenharmony_ci	/* is somebody else already processing irqs? */
626662306a36Sopenharmony_ci	if (atomic_xchg(&rdev->ih.lock, 1))
626762306a36Sopenharmony_ci		return IRQ_NONE;
626862306a36Sopenharmony_ci
626962306a36Sopenharmony_ci	rptr = rdev->ih.rptr;
627062306a36Sopenharmony_ci	DRM_DEBUG("si_irq_process start: rptr %d, wptr %d\n", rptr, wptr);
627162306a36Sopenharmony_ci
627262306a36Sopenharmony_ci	/* Order reading of wptr vs. reading of IH ring data */
627362306a36Sopenharmony_ci	rmb();
627462306a36Sopenharmony_ci
627562306a36Sopenharmony_ci	/* display interrupts */
627662306a36Sopenharmony_ci	si_irq_ack(rdev);
627762306a36Sopenharmony_ci
627862306a36Sopenharmony_ci	while (rptr != wptr) {
627962306a36Sopenharmony_ci		/* wptr/rptr are in bytes! */
628062306a36Sopenharmony_ci		ring_index = rptr / 4;
628162306a36Sopenharmony_ci		src_id =  le32_to_cpu(rdev->ih.ring[ring_index]) & 0xff;
628262306a36Sopenharmony_ci		src_data = le32_to_cpu(rdev->ih.ring[ring_index + 1]) & 0xfffffff;
628362306a36Sopenharmony_ci		ring_id = le32_to_cpu(rdev->ih.ring[ring_index + 2]) & 0xff;
628462306a36Sopenharmony_ci
628562306a36Sopenharmony_ci		switch (src_id) {
628662306a36Sopenharmony_ci		case 1: /* D1 vblank/vline */
628762306a36Sopenharmony_ci		case 2: /* D2 vblank/vline */
628862306a36Sopenharmony_ci		case 3: /* D3 vblank/vline */
628962306a36Sopenharmony_ci		case 4: /* D4 vblank/vline */
629062306a36Sopenharmony_ci		case 5: /* D5 vblank/vline */
629162306a36Sopenharmony_ci		case 6: /* D6 vblank/vline */
629262306a36Sopenharmony_ci			crtc_idx = src_id - 1;
629362306a36Sopenharmony_ci
629462306a36Sopenharmony_ci			if (src_data == 0) { /* vblank */
629562306a36Sopenharmony_ci				mask = LB_D1_VBLANK_INTERRUPT;
629662306a36Sopenharmony_ci				event_name = "vblank";
629762306a36Sopenharmony_ci
629862306a36Sopenharmony_ci				if (rdev->irq.crtc_vblank_int[crtc_idx]) {
629962306a36Sopenharmony_ci					drm_handle_vblank(rdev->ddev, crtc_idx);
630062306a36Sopenharmony_ci					rdev->pm.vblank_sync = true;
630162306a36Sopenharmony_ci					wake_up(&rdev->irq.vblank_queue);
630262306a36Sopenharmony_ci				}
630362306a36Sopenharmony_ci				if (atomic_read(&rdev->irq.pflip[crtc_idx])) {
630462306a36Sopenharmony_ci					radeon_crtc_handle_vblank(rdev,
630562306a36Sopenharmony_ci								  crtc_idx);
630662306a36Sopenharmony_ci				}
630762306a36Sopenharmony_ci
630862306a36Sopenharmony_ci			} else if (src_data == 1) { /* vline */
630962306a36Sopenharmony_ci				mask = LB_D1_VLINE_INTERRUPT;
631062306a36Sopenharmony_ci				event_name = "vline";
631162306a36Sopenharmony_ci			} else {
631262306a36Sopenharmony_ci				DRM_DEBUG("Unhandled interrupt: %d %d\n",
631362306a36Sopenharmony_ci					  src_id, src_data);
631462306a36Sopenharmony_ci				break;
631562306a36Sopenharmony_ci			}
631662306a36Sopenharmony_ci
631762306a36Sopenharmony_ci			if (!(disp_int[crtc_idx] & mask)) {
631862306a36Sopenharmony_ci				DRM_DEBUG("IH: D%d %s - IH event w/o asserted irq bit?\n",
631962306a36Sopenharmony_ci					  crtc_idx + 1, event_name);
632062306a36Sopenharmony_ci			}
632162306a36Sopenharmony_ci
632262306a36Sopenharmony_ci			disp_int[crtc_idx] &= ~mask;
632362306a36Sopenharmony_ci			DRM_DEBUG("IH: D%d %s\n", crtc_idx + 1, event_name);
632462306a36Sopenharmony_ci
632562306a36Sopenharmony_ci			break;
632662306a36Sopenharmony_ci		case 8: /* D1 page flip */
632762306a36Sopenharmony_ci		case 10: /* D2 page flip */
632862306a36Sopenharmony_ci		case 12: /* D3 page flip */
632962306a36Sopenharmony_ci		case 14: /* D4 page flip */
633062306a36Sopenharmony_ci		case 16: /* D5 page flip */
633162306a36Sopenharmony_ci		case 18: /* D6 page flip */
633262306a36Sopenharmony_ci			DRM_DEBUG("IH: D%d flip\n", ((src_id - 8) >> 1) + 1);
633362306a36Sopenharmony_ci			if (radeon_use_pflipirq > 0)
633462306a36Sopenharmony_ci				radeon_crtc_handle_flip(rdev, (src_id - 8) >> 1);
633562306a36Sopenharmony_ci			break;
633662306a36Sopenharmony_ci		case 42: /* HPD hotplug */
633762306a36Sopenharmony_ci			if (src_data <= 5) {
633862306a36Sopenharmony_ci				hpd_idx = src_data;
633962306a36Sopenharmony_ci				mask = DC_HPD1_INTERRUPT;
634062306a36Sopenharmony_ci				queue_hotplug = true;
634162306a36Sopenharmony_ci				event_name = "HPD";
634262306a36Sopenharmony_ci
634362306a36Sopenharmony_ci			} else if (src_data <= 11) {
634462306a36Sopenharmony_ci				hpd_idx = src_data - 6;
634562306a36Sopenharmony_ci				mask = DC_HPD1_RX_INTERRUPT;
634662306a36Sopenharmony_ci				queue_dp = true;
634762306a36Sopenharmony_ci				event_name = "HPD_RX";
634862306a36Sopenharmony_ci
634962306a36Sopenharmony_ci			} else {
635062306a36Sopenharmony_ci				DRM_DEBUG("Unhandled interrupt: %d %d\n",
635162306a36Sopenharmony_ci					  src_id, src_data);
635262306a36Sopenharmony_ci				break;
635362306a36Sopenharmony_ci			}
635462306a36Sopenharmony_ci
635562306a36Sopenharmony_ci			if (!(disp_int[hpd_idx] & mask))
635662306a36Sopenharmony_ci				DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
635762306a36Sopenharmony_ci
635862306a36Sopenharmony_ci			disp_int[hpd_idx] &= ~mask;
635962306a36Sopenharmony_ci			DRM_DEBUG("IH: %s%d\n", event_name, hpd_idx + 1);
636062306a36Sopenharmony_ci			break;
636162306a36Sopenharmony_ci		case 96:
636262306a36Sopenharmony_ci			DRM_ERROR("SRBM_READ_ERROR: 0x%x\n", RREG32(SRBM_READ_ERROR));
636362306a36Sopenharmony_ci			WREG32(SRBM_INT_ACK, 0x1);
636462306a36Sopenharmony_ci			break;
636562306a36Sopenharmony_ci		case 124: /* UVD */
636662306a36Sopenharmony_ci			DRM_DEBUG("IH: UVD int: 0x%08x\n", src_data);
636762306a36Sopenharmony_ci			radeon_fence_process(rdev, R600_RING_TYPE_UVD_INDEX);
636862306a36Sopenharmony_ci			break;
636962306a36Sopenharmony_ci		case 146:
637062306a36Sopenharmony_ci		case 147:
637162306a36Sopenharmony_ci			addr = RREG32(VM_CONTEXT1_PROTECTION_FAULT_ADDR);
637262306a36Sopenharmony_ci			status = RREG32(VM_CONTEXT1_PROTECTION_FAULT_STATUS);
637362306a36Sopenharmony_ci			/* reset addr and status */
637462306a36Sopenharmony_ci			WREG32_P(VM_CONTEXT1_CNTL2, 1, ~1);
637562306a36Sopenharmony_ci			if (addr == 0x0 && status == 0x0)
637662306a36Sopenharmony_ci				break;
637762306a36Sopenharmony_ci			dev_err(rdev->dev, "GPU fault detected: %d 0x%08x\n", src_id, src_data);
637862306a36Sopenharmony_ci			dev_err(rdev->dev, "  VM_CONTEXT1_PROTECTION_FAULT_ADDR   0x%08X\n",
637962306a36Sopenharmony_ci				addr);
638062306a36Sopenharmony_ci			dev_err(rdev->dev, "  VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x%08X\n",
638162306a36Sopenharmony_ci				status);
638262306a36Sopenharmony_ci			si_vm_decode_fault(rdev, status, addr);
638362306a36Sopenharmony_ci			break;
638462306a36Sopenharmony_ci		case 176: /* RINGID0 CP_INT */
638562306a36Sopenharmony_ci			radeon_fence_process(rdev, RADEON_RING_TYPE_GFX_INDEX);
638662306a36Sopenharmony_ci			break;
638762306a36Sopenharmony_ci		case 177: /* RINGID1 CP_INT */
638862306a36Sopenharmony_ci			radeon_fence_process(rdev, CAYMAN_RING_TYPE_CP1_INDEX);
638962306a36Sopenharmony_ci			break;
639062306a36Sopenharmony_ci		case 178: /* RINGID2 CP_INT */
639162306a36Sopenharmony_ci			radeon_fence_process(rdev, CAYMAN_RING_TYPE_CP2_INDEX);
639262306a36Sopenharmony_ci			break;
639362306a36Sopenharmony_ci		case 181: /* CP EOP event */
639462306a36Sopenharmony_ci			DRM_DEBUG("IH: CP EOP\n");
639562306a36Sopenharmony_ci			switch (ring_id) {
639662306a36Sopenharmony_ci			case 0:
639762306a36Sopenharmony_ci				radeon_fence_process(rdev, RADEON_RING_TYPE_GFX_INDEX);
639862306a36Sopenharmony_ci				break;
639962306a36Sopenharmony_ci			case 1:
640062306a36Sopenharmony_ci				radeon_fence_process(rdev, CAYMAN_RING_TYPE_CP1_INDEX);
640162306a36Sopenharmony_ci				break;
640262306a36Sopenharmony_ci			case 2:
640362306a36Sopenharmony_ci				radeon_fence_process(rdev, CAYMAN_RING_TYPE_CP2_INDEX);
640462306a36Sopenharmony_ci				break;
640562306a36Sopenharmony_ci			}
640662306a36Sopenharmony_ci			break;
640762306a36Sopenharmony_ci		case 224: /* DMA trap event */
640862306a36Sopenharmony_ci			DRM_DEBUG("IH: DMA trap\n");
640962306a36Sopenharmony_ci			radeon_fence_process(rdev, R600_RING_TYPE_DMA_INDEX);
641062306a36Sopenharmony_ci			break;
641162306a36Sopenharmony_ci		case 230: /* thermal low to high */
641262306a36Sopenharmony_ci			DRM_DEBUG("IH: thermal low to high\n");
641362306a36Sopenharmony_ci			rdev->pm.dpm.thermal.high_to_low = false;
641462306a36Sopenharmony_ci			queue_thermal = true;
641562306a36Sopenharmony_ci			break;
641662306a36Sopenharmony_ci		case 231: /* thermal high to low */
641762306a36Sopenharmony_ci			DRM_DEBUG("IH: thermal high to low\n");
641862306a36Sopenharmony_ci			rdev->pm.dpm.thermal.high_to_low = true;
641962306a36Sopenharmony_ci			queue_thermal = true;
642062306a36Sopenharmony_ci			break;
642162306a36Sopenharmony_ci		case 233: /* GUI IDLE */
642262306a36Sopenharmony_ci			DRM_DEBUG("IH: GUI idle\n");
642362306a36Sopenharmony_ci			break;
642462306a36Sopenharmony_ci		case 244: /* DMA trap event */
642562306a36Sopenharmony_ci			DRM_DEBUG("IH: DMA1 trap\n");
642662306a36Sopenharmony_ci			radeon_fence_process(rdev, CAYMAN_RING_TYPE_DMA1_INDEX);
642762306a36Sopenharmony_ci			break;
642862306a36Sopenharmony_ci		default:
642962306a36Sopenharmony_ci			DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data);
643062306a36Sopenharmony_ci			break;
643162306a36Sopenharmony_ci		}
643262306a36Sopenharmony_ci
643362306a36Sopenharmony_ci		/* wptr/rptr are in bytes! */
643462306a36Sopenharmony_ci		rptr += 16;
643562306a36Sopenharmony_ci		rptr &= rdev->ih.ptr_mask;
643662306a36Sopenharmony_ci		WREG32(IH_RB_RPTR, rptr);
643762306a36Sopenharmony_ci	}
643862306a36Sopenharmony_ci	if (queue_dp)
643962306a36Sopenharmony_ci		schedule_work(&rdev->dp_work);
644062306a36Sopenharmony_ci	if (queue_hotplug)
644162306a36Sopenharmony_ci		schedule_delayed_work(&rdev->hotplug_work, 0);
644262306a36Sopenharmony_ci	if (queue_thermal && rdev->pm.dpm_enabled)
644362306a36Sopenharmony_ci		schedule_work(&rdev->pm.dpm.thermal.work);
644462306a36Sopenharmony_ci	rdev->ih.rptr = rptr;
644562306a36Sopenharmony_ci	atomic_set(&rdev->ih.lock, 0);
644662306a36Sopenharmony_ci
644762306a36Sopenharmony_ci	/* make sure wptr hasn't changed while processing */
644862306a36Sopenharmony_ci	wptr = si_get_ih_wptr(rdev);
644962306a36Sopenharmony_ci	if (wptr != rptr)
645062306a36Sopenharmony_ci		goto restart_ih;
645162306a36Sopenharmony_ci
645262306a36Sopenharmony_ci	return IRQ_HANDLED;
645362306a36Sopenharmony_ci}
645462306a36Sopenharmony_ci
645562306a36Sopenharmony_ci/*
645662306a36Sopenharmony_ci * startup/shutdown callbacks
645762306a36Sopenharmony_ci */
645862306a36Sopenharmony_cistatic void si_uvd_init(struct radeon_device *rdev)
645962306a36Sopenharmony_ci{
646062306a36Sopenharmony_ci	int r;
646162306a36Sopenharmony_ci
646262306a36Sopenharmony_ci	if (!rdev->has_uvd)
646362306a36Sopenharmony_ci		return;
646462306a36Sopenharmony_ci
646562306a36Sopenharmony_ci	r = radeon_uvd_init(rdev);
646662306a36Sopenharmony_ci	if (r) {
646762306a36Sopenharmony_ci		dev_err(rdev->dev, "failed UVD (%d) init.\n", r);
646862306a36Sopenharmony_ci		/*
646962306a36Sopenharmony_ci		 * At this point rdev->uvd.vcpu_bo is NULL which trickles down
647062306a36Sopenharmony_ci		 * to early fails uvd_v2_2_resume() and thus nothing happens
647162306a36Sopenharmony_ci		 * there. So it is pointless to try to go through that code
647262306a36Sopenharmony_ci		 * hence why we disable uvd here.
647362306a36Sopenharmony_ci		 */
647462306a36Sopenharmony_ci		rdev->has_uvd = false;
647562306a36Sopenharmony_ci		return;
647662306a36Sopenharmony_ci	}
647762306a36Sopenharmony_ci	rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_obj = NULL;
647862306a36Sopenharmony_ci	r600_ring_init(rdev, &rdev->ring[R600_RING_TYPE_UVD_INDEX], 4096);
647962306a36Sopenharmony_ci}
648062306a36Sopenharmony_ci
648162306a36Sopenharmony_cistatic void si_uvd_start(struct radeon_device *rdev)
648262306a36Sopenharmony_ci{
648362306a36Sopenharmony_ci	int r;
648462306a36Sopenharmony_ci
648562306a36Sopenharmony_ci	if (!rdev->has_uvd)
648662306a36Sopenharmony_ci		return;
648762306a36Sopenharmony_ci
648862306a36Sopenharmony_ci	r = uvd_v2_2_resume(rdev);
648962306a36Sopenharmony_ci	if (r) {
649062306a36Sopenharmony_ci		dev_err(rdev->dev, "failed UVD resume (%d).\n", r);
649162306a36Sopenharmony_ci		goto error;
649262306a36Sopenharmony_ci	}
649362306a36Sopenharmony_ci	r = radeon_fence_driver_start_ring(rdev, R600_RING_TYPE_UVD_INDEX);
649462306a36Sopenharmony_ci	if (r) {
649562306a36Sopenharmony_ci		dev_err(rdev->dev, "failed initializing UVD fences (%d).\n", r);
649662306a36Sopenharmony_ci		goto error;
649762306a36Sopenharmony_ci	}
649862306a36Sopenharmony_ci	return;
649962306a36Sopenharmony_ci
650062306a36Sopenharmony_cierror:
650162306a36Sopenharmony_ci	rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;
650262306a36Sopenharmony_ci}
650362306a36Sopenharmony_ci
650462306a36Sopenharmony_cistatic void si_uvd_resume(struct radeon_device *rdev)
650562306a36Sopenharmony_ci{
650662306a36Sopenharmony_ci	struct radeon_ring *ring;
650762306a36Sopenharmony_ci	int r;
650862306a36Sopenharmony_ci
650962306a36Sopenharmony_ci	if (!rdev->has_uvd || !rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size)
651062306a36Sopenharmony_ci		return;
651162306a36Sopenharmony_ci
651262306a36Sopenharmony_ci	ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
651362306a36Sopenharmony_ci	r = radeon_ring_init(rdev, ring, ring->ring_size, 0, PACKET0(UVD_NO_OP, 0));
651462306a36Sopenharmony_ci	if (r) {
651562306a36Sopenharmony_ci		dev_err(rdev->dev, "failed initializing UVD ring (%d).\n", r);
651662306a36Sopenharmony_ci		return;
651762306a36Sopenharmony_ci	}
651862306a36Sopenharmony_ci	r = uvd_v1_0_init(rdev);
651962306a36Sopenharmony_ci	if (r) {
652062306a36Sopenharmony_ci		dev_err(rdev->dev, "failed initializing UVD (%d).\n", r);
652162306a36Sopenharmony_ci		return;
652262306a36Sopenharmony_ci	}
652362306a36Sopenharmony_ci}
652462306a36Sopenharmony_ci
652562306a36Sopenharmony_cistatic void si_vce_init(struct radeon_device *rdev)
652662306a36Sopenharmony_ci{
652762306a36Sopenharmony_ci	int r;
652862306a36Sopenharmony_ci
652962306a36Sopenharmony_ci	if (!rdev->has_vce)
653062306a36Sopenharmony_ci		return;
653162306a36Sopenharmony_ci
653262306a36Sopenharmony_ci	r = radeon_vce_init(rdev);
653362306a36Sopenharmony_ci	if (r) {
653462306a36Sopenharmony_ci		dev_err(rdev->dev, "failed VCE (%d) init.\n", r);
653562306a36Sopenharmony_ci		/*
653662306a36Sopenharmony_ci		 * At this point rdev->vce.vcpu_bo is NULL which trickles down
653762306a36Sopenharmony_ci		 * to early fails si_vce_start() and thus nothing happens
653862306a36Sopenharmony_ci		 * there. So it is pointless to try to go through that code
653962306a36Sopenharmony_ci		 * hence why we disable vce here.
654062306a36Sopenharmony_ci		 */
654162306a36Sopenharmony_ci		rdev->has_vce = false;
654262306a36Sopenharmony_ci		return;
654362306a36Sopenharmony_ci	}
654462306a36Sopenharmony_ci	rdev->ring[TN_RING_TYPE_VCE1_INDEX].ring_obj = NULL;
654562306a36Sopenharmony_ci	r600_ring_init(rdev, &rdev->ring[TN_RING_TYPE_VCE1_INDEX], 4096);
654662306a36Sopenharmony_ci	rdev->ring[TN_RING_TYPE_VCE2_INDEX].ring_obj = NULL;
654762306a36Sopenharmony_ci	r600_ring_init(rdev, &rdev->ring[TN_RING_TYPE_VCE2_INDEX], 4096);
654862306a36Sopenharmony_ci}
654962306a36Sopenharmony_ci
655062306a36Sopenharmony_cistatic void si_vce_start(struct radeon_device *rdev)
655162306a36Sopenharmony_ci{
655262306a36Sopenharmony_ci	int r;
655362306a36Sopenharmony_ci
655462306a36Sopenharmony_ci	if (!rdev->has_vce)
655562306a36Sopenharmony_ci		return;
655662306a36Sopenharmony_ci
655762306a36Sopenharmony_ci	r = radeon_vce_resume(rdev);
655862306a36Sopenharmony_ci	if (r) {
655962306a36Sopenharmony_ci		dev_err(rdev->dev, "failed VCE resume (%d).\n", r);
656062306a36Sopenharmony_ci		goto error;
656162306a36Sopenharmony_ci	}
656262306a36Sopenharmony_ci	r = vce_v1_0_resume(rdev);
656362306a36Sopenharmony_ci	if (r) {
656462306a36Sopenharmony_ci		dev_err(rdev->dev, "failed VCE resume (%d).\n", r);
656562306a36Sopenharmony_ci		goto error;
656662306a36Sopenharmony_ci	}
656762306a36Sopenharmony_ci	r = radeon_fence_driver_start_ring(rdev, TN_RING_TYPE_VCE1_INDEX);
656862306a36Sopenharmony_ci	if (r) {
656962306a36Sopenharmony_ci		dev_err(rdev->dev, "failed initializing VCE1 fences (%d).\n", r);
657062306a36Sopenharmony_ci		goto error;
657162306a36Sopenharmony_ci	}
657262306a36Sopenharmony_ci	r = radeon_fence_driver_start_ring(rdev, TN_RING_TYPE_VCE2_INDEX);
657362306a36Sopenharmony_ci	if (r) {
657462306a36Sopenharmony_ci		dev_err(rdev->dev, "failed initializing VCE2 fences (%d).\n", r);
657562306a36Sopenharmony_ci		goto error;
657662306a36Sopenharmony_ci	}
657762306a36Sopenharmony_ci	return;
657862306a36Sopenharmony_ci
657962306a36Sopenharmony_cierror:
658062306a36Sopenharmony_ci	rdev->ring[TN_RING_TYPE_VCE1_INDEX].ring_size = 0;
658162306a36Sopenharmony_ci	rdev->ring[TN_RING_TYPE_VCE2_INDEX].ring_size = 0;
658262306a36Sopenharmony_ci}
658362306a36Sopenharmony_ci
658462306a36Sopenharmony_cistatic void si_vce_resume(struct radeon_device *rdev)
658562306a36Sopenharmony_ci{
658662306a36Sopenharmony_ci	struct radeon_ring *ring;
658762306a36Sopenharmony_ci	int r;
658862306a36Sopenharmony_ci
658962306a36Sopenharmony_ci	if (!rdev->has_vce || !rdev->ring[TN_RING_TYPE_VCE1_INDEX].ring_size)
659062306a36Sopenharmony_ci		return;
659162306a36Sopenharmony_ci
659262306a36Sopenharmony_ci	ring = &rdev->ring[TN_RING_TYPE_VCE1_INDEX];
659362306a36Sopenharmony_ci	r = radeon_ring_init(rdev, ring, ring->ring_size, 0, VCE_CMD_NO_OP);
659462306a36Sopenharmony_ci	if (r) {
659562306a36Sopenharmony_ci		dev_err(rdev->dev, "failed initializing VCE1 ring (%d).\n", r);
659662306a36Sopenharmony_ci		return;
659762306a36Sopenharmony_ci	}
659862306a36Sopenharmony_ci	ring = &rdev->ring[TN_RING_TYPE_VCE2_INDEX];
659962306a36Sopenharmony_ci	r = radeon_ring_init(rdev, ring, ring->ring_size, 0, VCE_CMD_NO_OP);
660062306a36Sopenharmony_ci	if (r) {
660162306a36Sopenharmony_ci		dev_err(rdev->dev, "failed initializing VCE1 ring (%d).\n", r);
660262306a36Sopenharmony_ci		return;
660362306a36Sopenharmony_ci	}
660462306a36Sopenharmony_ci	r = vce_v1_0_init(rdev);
660562306a36Sopenharmony_ci	if (r) {
660662306a36Sopenharmony_ci		dev_err(rdev->dev, "failed initializing VCE (%d).\n", r);
660762306a36Sopenharmony_ci		return;
660862306a36Sopenharmony_ci	}
660962306a36Sopenharmony_ci}
661062306a36Sopenharmony_ci
661162306a36Sopenharmony_cistatic int si_startup(struct radeon_device *rdev)
661262306a36Sopenharmony_ci{
661362306a36Sopenharmony_ci	struct radeon_ring *ring;
661462306a36Sopenharmony_ci	int r;
661562306a36Sopenharmony_ci
661662306a36Sopenharmony_ci	/* enable pcie gen2/3 link */
661762306a36Sopenharmony_ci	si_pcie_gen3_enable(rdev);
661862306a36Sopenharmony_ci	/* enable aspm */
661962306a36Sopenharmony_ci	si_program_aspm(rdev);
662062306a36Sopenharmony_ci
662162306a36Sopenharmony_ci	/* scratch needs to be initialized before MC */
662262306a36Sopenharmony_ci	r = r600_vram_scratch_init(rdev);
662362306a36Sopenharmony_ci	if (r)
662462306a36Sopenharmony_ci		return r;
662562306a36Sopenharmony_ci
662662306a36Sopenharmony_ci	si_mc_program(rdev);
662762306a36Sopenharmony_ci
662862306a36Sopenharmony_ci	if (!rdev->pm.dpm_enabled) {
662962306a36Sopenharmony_ci		r = si_mc_load_microcode(rdev);
663062306a36Sopenharmony_ci		if (r) {
663162306a36Sopenharmony_ci			DRM_ERROR("Failed to load MC firmware!\n");
663262306a36Sopenharmony_ci			return r;
663362306a36Sopenharmony_ci		}
663462306a36Sopenharmony_ci	}
663562306a36Sopenharmony_ci
663662306a36Sopenharmony_ci	r = si_pcie_gart_enable(rdev);
663762306a36Sopenharmony_ci	if (r)
663862306a36Sopenharmony_ci		return r;
663962306a36Sopenharmony_ci	si_gpu_init(rdev);
664062306a36Sopenharmony_ci
664162306a36Sopenharmony_ci	/* allocate rlc buffers */
664262306a36Sopenharmony_ci	if (rdev->family == CHIP_VERDE) {
664362306a36Sopenharmony_ci		rdev->rlc.reg_list = verde_rlc_save_restore_register_list;
664462306a36Sopenharmony_ci		rdev->rlc.reg_list_size =
664562306a36Sopenharmony_ci			(u32)ARRAY_SIZE(verde_rlc_save_restore_register_list);
664662306a36Sopenharmony_ci	}
664762306a36Sopenharmony_ci	rdev->rlc.cs_data = si_cs_data;
664862306a36Sopenharmony_ci	r = sumo_rlc_init(rdev);
664962306a36Sopenharmony_ci	if (r) {
665062306a36Sopenharmony_ci		DRM_ERROR("Failed to init rlc BOs!\n");
665162306a36Sopenharmony_ci		return r;
665262306a36Sopenharmony_ci	}
665362306a36Sopenharmony_ci
665462306a36Sopenharmony_ci	/* allocate wb buffer */
665562306a36Sopenharmony_ci	r = radeon_wb_init(rdev);
665662306a36Sopenharmony_ci	if (r)
665762306a36Sopenharmony_ci		return r;
665862306a36Sopenharmony_ci
665962306a36Sopenharmony_ci	r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX);
666062306a36Sopenharmony_ci	if (r) {
666162306a36Sopenharmony_ci		dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r);
666262306a36Sopenharmony_ci		return r;
666362306a36Sopenharmony_ci	}
666462306a36Sopenharmony_ci
666562306a36Sopenharmony_ci	r = radeon_fence_driver_start_ring(rdev, CAYMAN_RING_TYPE_CP1_INDEX);
666662306a36Sopenharmony_ci	if (r) {
666762306a36Sopenharmony_ci		dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r);
666862306a36Sopenharmony_ci		return r;
666962306a36Sopenharmony_ci	}
667062306a36Sopenharmony_ci
667162306a36Sopenharmony_ci	r = radeon_fence_driver_start_ring(rdev, CAYMAN_RING_TYPE_CP2_INDEX);
667262306a36Sopenharmony_ci	if (r) {
667362306a36Sopenharmony_ci		dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r);
667462306a36Sopenharmony_ci		return r;
667562306a36Sopenharmony_ci	}
667662306a36Sopenharmony_ci
667762306a36Sopenharmony_ci	r = radeon_fence_driver_start_ring(rdev, R600_RING_TYPE_DMA_INDEX);
667862306a36Sopenharmony_ci	if (r) {
667962306a36Sopenharmony_ci		dev_err(rdev->dev, "failed initializing DMA fences (%d).\n", r);
668062306a36Sopenharmony_ci		return r;
668162306a36Sopenharmony_ci	}
668262306a36Sopenharmony_ci
668362306a36Sopenharmony_ci	r = radeon_fence_driver_start_ring(rdev, CAYMAN_RING_TYPE_DMA1_INDEX);
668462306a36Sopenharmony_ci	if (r) {
668562306a36Sopenharmony_ci		dev_err(rdev->dev, "failed initializing DMA fences (%d).\n", r);
668662306a36Sopenharmony_ci		return r;
668762306a36Sopenharmony_ci	}
668862306a36Sopenharmony_ci
668962306a36Sopenharmony_ci	si_uvd_start(rdev);
669062306a36Sopenharmony_ci	si_vce_start(rdev);
669162306a36Sopenharmony_ci
669262306a36Sopenharmony_ci	/* Enable IRQ */
669362306a36Sopenharmony_ci	if (!rdev->irq.installed) {
669462306a36Sopenharmony_ci		r = radeon_irq_kms_init(rdev);
669562306a36Sopenharmony_ci		if (r)
669662306a36Sopenharmony_ci			return r;
669762306a36Sopenharmony_ci	}
669862306a36Sopenharmony_ci
669962306a36Sopenharmony_ci	r = si_irq_init(rdev);
670062306a36Sopenharmony_ci	if (r) {
670162306a36Sopenharmony_ci		DRM_ERROR("radeon: IH init failed (%d).\n", r);
670262306a36Sopenharmony_ci		radeon_irq_kms_fini(rdev);
670362306a36Sopenharmony_ci		return r;
670462306a36Sopenharmony_ci	}
670562306a36Sopenharmony_ci	si_irq_set(rdev);
670662306a36Sopenharmony_ci
670762306a36Sopenharmony_ci	ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
670862306a36Sopenharmony_ci	r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET,
670962306a36Sopenharmony_ci			     RADEON_CP_PACKET2);
671062306a36Sopenharmony_ci	if (r)
671162306a36Sopenharmony_ci		return r;
671262306a36Sopenharmony_ci
671362306a36Sopenharmony_ci	ring = &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX];
671462306a36Sopenharmony_ci	r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP1_RPTR_OFFSET,
671562306a36Sopenharmony_ci			     RADEON_CP_PACKET2);
671662306a36Sopenharmony_ci	if (r)
671762306a36Sopenharmony_ci		return r;
671862306a36Sopenharmony_ci
671962306a36Sopenharmony_ci	ring = &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX];
672062306a36Sopenharmony_ci	r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP2_RPTR_OFFSET,
672162306a36Sopenharmony_ci			     RADEON_CP_PACKET2);
672262306a36Sopenharmony_ci	if (r)
672362306a36Sopenharmony_ci		return r;
672462306a36Sopenharmony_ci
672562306a36Sopenharmony_ci	ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX];
672662306a36Sopenharmony_ci	r = radeon_ring_init(rdev, ring, ring->ring_size, R600_WB_DMA_RPTR_OFFSET,
672762306a36Sopenharmony_ci			     DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0, 0));
672862306a36Sopenharmony_ci	if (r)
672962306a36Sopenharmony_ci		return r;
673062306a36Sopenharmony_ci
673162306a36Sopenharmony_ci	ring = &rdev->ring[CAYMAN_RING_TYPE_DMA1_INDEX];
673262306a36Sopenharmony_ci	r = radeon_ring_init(rdev, ring, ring->ring_size, CAYMAN_WB_DMA1_RPTR_OFFSET,
673362306a36Sopenharmony_ci			     DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0, 0));
673462306a36Sopenharmony_ci	if (r)
673562306a36Sopenharmony_ci		return r;
673662306a36Sopenharmony_ci
673762306a36Sopenharmony_ci	r = si_cp_load_microcode(rdev);
673862306a36Sopenharmony_ci	if (r)
673962306a36Sopenharmony_ci		return r;
674062306a36Sopenharmony_ci	r = si_cp_resume(rdev);
674162306a36Sopenharmony_ci	if (r)
674262306a36Sopenharmony_ci		return r;
674362306a36Sopenharmony_ci
674462306a36Sopenharmony_ci	r = cayman_dma_resume(rdev);
674562306a36Sopenharmony_ci	if (r)
674662306a36Sopenharmony_ci		return r;
674762306a36Sopenharmony_ci
674862306a36Sopenharmony_ci	si_uvd_resume(rdev);
674962306a36Sopenharmony_ci	si_vce_resume(rdev);
675062306a36Sopenharmony_ci
675162306a36Sopenharmony_ci	r = radeon_ib_pool_init(rdev);
675262306a36Sopenharmony_ci	if (r) {
675362306a36Sopenharmony_ci		dev_err(rdev->dev, "IB initialization failed (%d).\n", r);
675462306a36Sopenharmony_ci		return r;
675562306a36Sopenharmony_ci	}
675662306a36Sopenharmony_ci
675762306a36Sopenharmony_ci	r = radeon_vm_manager_init(rdev);
675862306a36Sopenharmony_ci	if (r) {
675962306a36Sopenharmony_ci		dev_err(rdev->dev, "vm manager initialization failed (%d).\n", r);
676062306a36Sopenharmony_ci		return r;
676162306a36Sopenharmony_ci	}
676262306a36Sopenharmony_ci
676362306a36Sopenharmony_ci	r = radeon_audio_init(rdev);
676462306a36Sopenharmony_ci	if (r)
676562306a36Sopenharmony_ci		return r;
676662306a36Sopenharmony_ci
676762306a36Sopenharmony_ci	return 0;
676862306a36Sopenharmony_ci}
676962306a36Sopenharmony_ci
677062306a36Sopenharmony_ciint si_resume(struct radeon_device *rdev)
677162306a36Sopenharmony_ci{
677262306a36Sopenharmony_ci	int r;
677362306a36Sopenharmony_ci
677462306a36Sopenharmony_ci	/* Do not reset GPU before posting, on rv770 hw unlike on r500 hw,
677562306a36Sopenharmony_ci	 * posting will perform necessary task to bring back GPU into good
677662306a36Sopenharmony_ci	 * shape.
677762306a36Sopenharmony_ci	 */
677862306a36Sopenharmony_ci	/* post card */
677962306a36Sopenharmony_ci	atom_asic_init(rdev->mode_info.atom_context);
678062306a36Sopenharmony_ci
678162306a36Sopenharmony_ci	/* init golden registers */
678262306a36Sopenharmony_ci	si_init_golden_registers(rdev);
678362306a36Sopenharmony_ci
678462306a36Sopenharmony_ci	if (rdev->pm.pm_method == PM_METHOD_DPM)
678562306a36Sopenharmony_ci		radeon_pm_resume(rdev);
678662306a36Sopenharmony_ci
678762306a36Sopenharmony_ci	rdev->accel_working = true;
678862306a36Sopenharmony_ci	r = si_startup(rdev);
678962306a36Sopenharmony_ci	if (r) {
679062306a36Sopenharmony_ci		DRM_ERROR("si startup failed on resume\n");
679162306a36Sopenharmony_ci		rdev->accel_working = false;
679262306a36Sopenharmony_ci		return r;
679362306a36Sopenharmony_ci	}
679462306a36Sopenharmony_ci
679562306a36Sopenharmony_ci	return r;
679662306a36Sopenharmony_ci
679762306a36Sopenharmony_ci}
679862306a36Sopenharmony_ci
679962306a36Sopenharmony_ciint si_suspend(struct radeon_device *rdev)
680062306a36Sopenharmony_ci{
680162306a36Sopenharmony_ci	radeon_pm_suspend(rdev);
680262306a36Sopenharmony_ci	radeon_audio_fini(rdev);
680362306a36Sopenharmony_ci	radeon_vm_manager_fini(rdev);
680462306a36Sopenharmony_ci	si_cp_enable(rdev, false);
680562306a36Sopenharmony_ci	cayman_dma_stop(rdev);
680662306a36Sopenharmony_ci	if (rdev->has_uvd) {
680762306a36Sopenharmony_ci		radeon_uvd_suspend(rdev);
680862306a36Sopenharmony_ci		uvd_v1_0_fini(rdev);
680962306a36Sopenharmony_ci	}
681062306a36Sopenharmony_ci	if (rdev->has_vce)
681162306a36Sopenharmony_ci		radeon_vce_suspend(rdev);
681262306a36Sopenharmony_ci	si_fini_pg(rdev);
681362306a36Sopenharmony_ci	si_fini_cg(rdev);
681462306a36Sopenharmony_ci	si_irq_suspend(rdev);
681562306a36Sopenharmony_ci	radeon_wb_disable(rdev);
681662306a36Sopenharmony_ci	si_pcie_gart_disable(rdev);
681762306a36Sopenharmony_ci	return 0;
681862306a36Sopenharmony_ci}
681962306a36Sopenharmony_ci
682062306a36Sopenharmony_ci/* Plan is to move initialization in that function and use
682162306a36Sopenharmony_ci * helper function so that radeon_device_init pretty much
682262306a36Sopenharmony_ci * do nothing more than calling asic specific function. This
682362306a36Sopenharmony_ci * should also allow to remove a bunch of callback function
682462306a36Sopenharmony_ci * like vram_info.
682562306a36Sopenharmony_ci */
682662306a36Sopenharmony_ciint si_init(struct radeon_device *rdev)
682762306a36Sopenharmony_ci{
682862306a36Sopenharmony_ci	struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
682962306a36Sopenharmony_ci	int r;
683062306a36Sopenharmony_ci
683162306a36Sopenharmony_ci	/* Read BIOS */
683262306a36Sopenharmony_ci	if (!radeon_get_bios(rdev)) {
683362306a36Sopenharmony_ci		if (ASIC_IS_AVIVO(rdev))
683462306a36Sopenharmony_ci			return -EINVAL;
683562306a36Sopenharmony_ci	}
683662306a36Sopenharmony_ci	/* Must be an ATOMBIOS */
683762306a36Sopenharmony_ci	if (!rdev->is_atom_bios) {
683862306a36Sopenharmony_ci		dev_err(rdev->dev, "Expecting atombios for cayman GPU\n");
683962306a36Sopenharmony_ci		return -EINVAL;
684062306a36Sopenharmony_ci	}
684162306a36Sopenharmony_ci	r = radeon_atombios_init(rdev);
684262306a36Sopenharmony_ci	if (r)
684362306a36Sopenharmony_ci		return r;
684462306a36Sopenharmony_ci
684562306a36Sopenharmony_ci	/* Post card if necessary */
684662306a36Sopenharmony_ci	if (!radeon_card_posted(rdev)) {
684762306a36Sopenharmony_ci		if (!rdev->bios) {
684862306a36Sopenharmony_ci			dev_err(rdev->dev, "Card not posted and no BIOS - ignoring\n");
684962306a36Sopenharmony_ci			return -EINVAL;
685062306a36Sopenharmony_ci		}
685162306a36Sopenharmony_ci		DRM_INFO("GPU not posted. posting now...\n");
685262306a36Sopenharmony_ci		atom_asic_init(rdev->mode_info.atom_context);
685362306a36Sopenharmony_ci	}
685462306a36Sopenharmony_ci	/* init golden registers */
685562306a36Sopenharmony_ci	si_init_golden_registers(rdev);
685662306a36Sopenharmony_ci	/* Initialize scratch registers */
685762306a36Sopenharmony_ci	si_scratch_init(rdev);
685862306a36Sopenharmony_ci	/* Initialize surface registers */
685962306a36Sopenharmony_ci	radeon_surface_init(rdev);
686062306a36Sopenharmony_ci	/* Initialize clocks */
686162306a36Sopenharmony_ci	radeon_get_clock_info(rdev->ddev);
686262306a36Sopenharmony_ci
686362306a36Sopenharmony_ci	/* Fence driver */
686462306a36Sopenharmony_ci	radeon_fence_driver_init(rdev);
686562306a36Sopenharmony_ci
686662306a36Sopenharmony_ci	/* initialize memory controller */
686762306a36Sopenharmony_ci	r = si_mc_init(rdev);
686862306a36Sopenharmony_ci	if (r)
686962306a36Sopenharmony_ci		return r;
687062306a36Sopenharmony_ci	/* Memory manager */
687162306a36Sopenharmony_ci	r = radeon_bo_init(rdev);
687262306a36Sopenharmony_ci	if (r)
687362306a36Sopenharmony_ci		return r;
687462306a36Sopenharmony_ci
687562306a36Sopenharmony_ci	if (!rdev->me_fw || !rdev->pfp_fw || !rdev->ce_fw ||
687662306a36Sopenharmony_ci	    !rdev->rlc_fw || !rdev->mc_fw) {
687762306a36Sopenharmony_ci		r = si_init_microcode(rdev);
687862306a36Sopenharmony_ci		if (r) {
687962306a36Sopenharmony_ci			DRM_ERROR("Failed to load firmware!\n");
688062306a36Sopenharmony_ci			return r;
688162306a36Sopenharmony_ci		}
688262306a36Sopenharmony_ci	}
688362306a36Sopenharmony_ci
688462306a36Sopenharmony_ci	/* Initialize power management */
688562306a36Sopenharmony_ci	radeon_pm_init(rdev);
688662306a36Sopenharmony_ci
688762306a36Sopenharmony_ci	ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
688862306a36Sopenharmony_ci	ring->ring_obj = NULL;
688962306a36Sopenharmony_ci	r600_ring_init(rdev, ring, 1024 * 1024);
689062306a36Sopenharmony_ci
689162306a36Sopenharmony_ci	ring = &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX];
689262306a36Sopenharmony_ci	ring->ring_obj = NULL;
689362306a36Sopenharmony_ci	r600_ring_init(rdev, ring, 1024 * 1024);
689462306a36Sopenharmony_ci
689562306a36Sopenharmony_ci	ring = &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX];
689662306a36Sopenharmony_ci	ring->ring_obj = NULL;
689762306a36Sopenharmony_ci	r600_ring_init(rdev, ring, 1024 * 1024);
689862306a36Sopenharmony_ci
689962306a36Sopenharmony_ci	ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX];
690062306a36Sopenharmony_ci	ring->ring_obj = NULL;
690162306a36Sopenharmony_ci	r600_ring_init(rdev, ring, 64 * 1024);
690262306a36Sopenharmony_ci
690362306a36Sopenharmony_ci	ring = &rdev->ring[CAYMAN_RING_TYPE_DMA1_INDEX];
690462306a36Sopenharmony_ci	ring->ring_obj = NULL;
690562306a36Sopenharmony_ci	r600_ring_init(rdev, ring, 64 * 1024);
690662306a36Sopenharmony_ci
690762306a36Sopenharmony_ci	si_uvd_init(rdev);
690862306a36Sopenharmony_ci	si_vce_init(rdev);
690962306a36Sopenharmony_ci
691062306a36Sopenharmony_ci	rdev->ih.ring_obj = NULL;
691162306a36Sopenharmony_ci	r600_ih_ring_init(rdev, 64 * 1024);
691262306a36Sopenharmony_ci
691362306a36Sopenharmony_ci	r = r600_pcie_gart_init(rdev);
691462306a36Sopenharmony_ci	if (r)
691562306a36Sopenharmony_ci		return r;
691662306a36Sopenharmony_ci
691762306a36Sopenharmony_ci	rdev->accel_working = true;
691862306a36Sopenharmony_ci	r = si_startup(rdev);
691962306a36Sopenharmony_ci	if (r) {
692062306a36Sopenharmony_ci		dev_err(rdev->dev, "disabling GPU acceleration\n");
692162306a36Sopenharmony_ci		si_cp_fini(rdev);
692262306a36Sopenharmony_ci		cayman_dma_fini(rdev);
692362306a36Sopenharmony_ci		si_irq_fini(rdev);
692462306a36Sopenharmony_ci		sumo_rlc_fini(rdev);
692562306a36Sopenharmony_ci		radeon_wb_fini(rdev);
692662306a36Sopenharmony_ci		radeon_ib_pool_fini(rdev);
692762306a36Sopenharmony_ci		radeon_vm_manager_fini(rdev);
692862306a36Sopenharmony_ci		radeon_irq_kms_fini(rdev);
692962306a36Sopenharmony_ci		si_pcie_gart_fini(rdev);
693062306a36Sopenharmony_ci		rdev->accel_working = false;
693162306a36Sopenharmony_ci	}
693262306a36Sopenharmony_ci
693362306a36Sopenharmony_ci	/* Don't start up if the MC ucode is missing.
693462306a36Sopenharmony_ci	 * The default clocks and voltages before the MC ucode
693562306a36Sopenharmony_ci	 * is loaded are not suffient for advanced operations.
693662306a36Sopenharmony_ci	 */
693762306a36Sopenharmony_ci	if (!rdev->mc_fw) {
693862306a36Sopenharmony_ci		DRM_ERROR("radeon: MC ucode required for NI+.\n");
693962306a36Sopenharmony_ci		return -EINVAL;
694062306a36Sopenharmony_ci	}
694162306a36Sopenharmony_ci
694262306a36Sopenharmony_ci	return 0;
694362306a36Sopenharmony_ci}
694462306a36Sopenharmony_ci
694562306a36Sopenharmony_civoid si_fini(struct radeon_device *rdev)
694662306a36Sopenharmony_ci{
694762306a36Sopenharmony_ci	radeon_pm_fini(rdev);
694862306a36Sopenharmony_ci	si_cp_fini(rdev);
694962306a36Sopenharmony_ci	cayman_dma_fini(rdev);
695062306a36Sopenharmony_ci	si_fini_pg(rdev);
695162306a36Sopenharmony_ci	si_fini_cg(rdev);
695262306a36Sopenharmony_ci	si_irq_fini(rdev);
695362306a36Sopenharmony_ci	sumo_rlc_fini(rdev);
695462306a36Sopenharmony_ci	radeon_wb_fini(rdev);
695562306a36Sopenharmony_ci	radeon_vm_manager_fini(rdev);
695662306a36Sopenharmony_ci	radeon_ib_pool_fini(rdev);
695762306a36Sopenharmony_ci	radeon_irq_kms_fini(rdev);
695862306a36Sopenharmony_ci	if (rdev->has_uvd) {
695962306a36Sopenharmony_ci		uvd_v1_0_fini(rdev);
696062306a36Sopenharmony_ci		radeon_uvd_fini(rdev);
696162306a36Sopenharmony_ci	}
696262306a36Sopenharmony_ci	if (rdev->has_vce)
696362306a36Sopenharmony_ci		radeon_vce_fini(rdev);
696462306a36Sopenharmony_ci	si_pcie_gart_fini(rdev);
696562306a36Sopenharmony_ci	r600_vram_scratch_fini(rdev);
696662306a36Sopenharmony_ci	radeon_gem_fini(rdev);
696762306a36Sopenharmony_ci	radeon_fence_driver_fini(rdev);
696862306a36Sopenharmony_ci	radeon_bo_fini(rdev);
696962306a36Sopenharmony_ci	radeon_atombios_fini(rdev);
697062306a36Sopenharmony_ci	kfree(rdev->bios);
697162306a36Sopenharmony_ci	rdev->bios = NULL;
697262306a36Sopenharmony_ci}
697362306a36Sopenharmony_ci
697462306a36Sopenharmony_ci/**
697562306a36Sopenharmony_ci * si_get_gpu_clock_counter - return GPU clock counter snapshot
697662306a36Sopenharmony_ci *
697762306a36Sopenharmony_ci * @rdev: radeon_device pointer
697862306a36Sopenharmony_ci *
697962306a36Sopenharmony_ci * Fetches a GPU clock counter snapshot (SI).
698062306a36Sopenharmony_ci * Returns the 64 bit clock counter snapshot.
698162306a36Sopenharmony_ci */
698262306a36Sopenharmony_ciuint64_t si_get_gpu_clock_counter(struct radeon_device *rdev)
698362306a36Sopenharmony_ci{
698462306a36Sopenharmony_ci	uint64_t clock;
698562306a36Sopenharmony_ci
698662306a36Sopenharmony_ci	mutex_lock(&rdev->gpu_clock_mutex);
698762306a36Sopenharmony_ci	WREG32(RLC_CAPTURE_GPU_CLOCK_COUNT, 1);
698862306a36Sopenharmony_ci	clock = (uint64_t)RREG32(RLC_GPU_CLOCK_COUNT_LSB) |
698962306a36Sopenharmony_ci		((uint64_t)RREG32(RLC_GPU_CLOCK_COUNT_MSB) << 32ULL);
699062306a36Sopenharmony_ci	mutex_unlock(&rdev->gpu_clock_mutex);
699162306a36Sopenharmony_ci	return clock;
699262306a36Sopenharmony_ci}
699362306a36Sopenharmony_ci
699462306a36Sopenharmony_ciint si_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk)
699562306a36Sopenharmony_ci{
699662306a36Sopenharmony_ci	unsigned fb_div = 0, vclk_div = 0, dclk_div = 0;
699762306a36Sopenharmony_ci	int r;
699862306a36Sopenharmony_ci
699962306a36Sopenharmony_ci	/* bypass vclk and dclk with bclk */
700062306a36Sopenharmony_ci	WREG32_P(CG_UPLL_FUNC_CNTL_2,
700162306a36Sopenharmony_ci		VCLK_SRC_SEL(1) | DCLK_SRC_SEL(1),
700262306a36Sopenharmony_ci		~(VCLK_SRC_SEL_MASK | DCLK_SRC_SEL_MASK));
700362306a36Sopenharmony_ci
700462306a36Sopenharmony_ci	/* put PLL in bypass mode */
700562306a36Sopenharmony_ci	WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_BYPASS_EN_MASK, ~UPLL_BYPASS_EN_MASK);
700662306a36Sopenharmony_ci
700762306a36Sopenharmony_ci	if (!vclk || !dclk) {
700862306a36Sopenharmony_ci		/* keep the Bypass mode */
700962306a36Sopenharmony_ci		return 0;
701062306a36Sopenharmony_ci	}
701162306a36Sopenharmony_ci
701262306a36Sopenharmony_ci	r = radeon_uvd_calc_upll_dividers(rdev, vclk, dclk, 125000, 250000,
701362306a36Sopenharmony_ci					  16384, 0x03FFFFFF, 0, 128, 5,
701462306a36Sopenharmony_ci					  &fb_div, &vclk_div, &dclk_div);
701562306a36Sopenharmony_ci	if (r)
701662306a36Sopenharmony_ci		return r;
701762306a36Sopenharmony_ci
701862306a36Sopenharmony_ci	/* set RESET_ANTI_MUX to 0 */
701962306a36Sopenharmony_ci	WREG32_P(CG_UPLL_FUNC_CNTL_5, 0, ~RESET_ANTI_MUX_MASK);
702062306a36Sopenharmony_ci
702162306a36Sopenharmony_ci	/* set VCO_MODE to 1 */
702262306a36Sopenharmony_ci	WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_VCO_MODE_MASK, ~UPLL_VCO_MODE_MASK);
702362306a36Sopenharmony_ci
702462306a36Sopenharmony_ci	/* disable sleep mode */
702562306a36Sopenharmony_ci	WREG32_P(CG_UPLL_FUNC_CNTL, 0, ~UPLL_SLEEP_MASK);
702662306a36Sopenharmony_ci
702762306a36Sopenharmony_ci	/* deassert UPLL_RESET */
702862306a36Sopenharmony_ci	WREG32_P(CG_UPLL_FUNC_CNTL, 0, ~UPLL_RESET_MASK);
702962306a36Sopenharmony_ci
703062306a36Sopenharmony_ci	mdelay(1);
703162306a36Sopenharmony_ci
703262306a36Sopenharmony_ci	r = radeon_uvd_send_upll_ctlreq(rdev, CG_UPLL_FUNC_CNTL);
703362306a36Sopenharmony_ci	if (r)
703462306a36Sopenharmony_ci		return r;
703562306a36Sopenharmony_ci
703662306a36Sopenharmony_ci	/* assert UPLL_RESET again */
703762306a36Sopenharmony_ci	WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_RESET_MASK, ~UPLL_RESET_MASK);
703862306a36Sopenharmony_ci
703962306a36Sopenharmony_ci	/* disable spread spectrum. */
704062306a36Sopenharmony_ci	WREG32_P(CG_UPLL_SPREAD_SPECTRUM, 0, ~SSEN_MASK);
704162306a36Sopenharmony_ci
704262306a36Sopenharmony_ci	/* set feedback divider */
704362306a36Sopenharmony_ci	WREG32_P(CG_UPLL_FUNC_CNTL_3, UPLL_FB_DIV(fb_div), ~UPLL_FB_DIV_MASK);
704462306a36Sopenharmony_ci
704562306a36Sopenharmony_ci	/* set ref divider to 0 */
704662306a36Sopenharmony_ci	WREG32_P(CG_UPLL_FUNC_CNTL, 0, ~UPLL_REF_DIV_MASK);
704762306a36Sopenharmony_ci
704862306a36Sopenharmony_ci	if (fb_div < 307200)
704962306a36Sopenharmony_ci		WREG32_P(CG_UPLL_FUNC_CNTL_4, 0, ~UPLL_SPARE_ISPARE9);
705062306a36Sopenharmony_ci	else
705162306a36Sopenharmony_ci		WREG32_P(CG_UPLL_FUNC_CNTL_4, UPLL_SPARE_ISPARE9, ~UPLL_SPARE_ISPARE9);
705262306a36Sopenharmony_ci
705362306a36Sopenharmony_ci	/* set PDIV_A and PDIV_B */
705462306a36Sopenharmony_ci	WREG32_P(CG_UPLL_FUNC_CNTL_2,
705562306a36Sopenharmony_ci		UPLL_PDIV_A(vclk_div) | UPLL_PDIV_B(dclk_div),
705662306a36Sopenharmony_ci		~(UPLL_PDIV_A_MASK | UPLL_PDIV_B_MASK));
705762306a36Sopenharmony_ci
705862306a36Sopenharmony_ci	/* give the PLL some time to settle */
705962306a36Sopenharmony_ci	mdelay(15);
706062306a36Sopenharmony_ci
706162306a36Sopenharmony_ci	/* deassert PLL_RESET */
706262306a36Sopenharmony_ci	WREG32_P(CG_UPLL_FUNC_CNTL, 0, ~UPLL_RESET_MASK);
706362306a36Sopenharmony_ci
706462306a36Sopenharmony_ci	mdelay(15);
706562306a36Sopenharmony_ci
706662306a36Sopenharmony_ci	/* switch from bypass mode to normal mode */
706762306a36Sopenharmony_ci	WREG32_P(CG_UPLL_FUNC_CNTL, 0, ~UPLL_BYPASS_EN_MASK);
706862306a36Sopenharmony_ci
706962306a36Sopenharmony_ci	r = radeon_uvd_send_upll_ctlreq(rdev, CG_UPLL_FUNC_CNTL);
707062306a36Sopenharmony_ci	if (r)
707162306a36Sopenharmony_ci		return r;
707262306a36Sopenharmony_ci
707362306a36Sopenharmony_ci	/* switch VCLK and DCLK selection */
707462306a36Sopenharmony_ci	WREG32_P(CG_UPLL_FUNC_CNTL_2,
707562306a36Sopenharmony_ci		VCLK_SRC_SEL(2) | DCLK_SRC_SEL(2),
707662306a36Sopenharmony_ci		~(VCLK_SRC_SEL_MASK | DCLK_SRC_SEL_MASK));
707762306a36Sopenharmony_ci
707862306a36Sopenharmony_ci	mdelay(100);
707962306a36Sopenharmony_ci
708062306a36Sopenharmony_ci	return 0;
708162306a36Sopenharmony_ci}
708262306a36Sopenharmony_ci
708362306a36Sopenharmony_cistatic void si_pcie_gen3_enable(struct radeon_device *rdev)
708462306a36Sopenharmony_ci{
708562306a36Sopenharmony_ci	struct pci_dev *root = rdev->pdev->bus->self;
708662306a36Sopenharmony_ci	enum pci_bus_speed speed_cap;
708762306a36Sopenharmony_ci	u32 speed_cntl, current_data_rate;
708862306a36Sopenharmony_ci	int i;
708962306a36Sopenharmony_ci	u16 tmp16;
709062306a36Sopenharmony_ci
709162306a36Sopenharmony_ci	if (pci_is_root_bus(rdev->pdev->bus))
709262306a36Sopenharmony_ci		return;
709362306a36Sopenharmony_ci
709462306a36Sopenharmony_ci	if (radeon_pcie_gen2 == 0)
709562306a36Sopenharmony_ci		return;
709662306a36Sopenharmony_ci
709762306a36Sopenharmony_ci	if (rdev->flags & RADEON_IS_IGP)
709862306a36Sopenharmony_ci		return;
709962306a36Sopenharmony_ci
710062306a36Sopenharmony_ci	if (!(rdev->flags & RADEON_IS_PCIE))
710162306a36Sopenharmony_ci		return;
710262306a36Sopenharmony_ci
710362306a36Sopenharmony_ci	speed_cap = pcie_get_speed_cap(root);
710462306a36Sopenharmony_ci	if (speed_cap == PCI_SPEED_UNKNOWN)
710562306a36Sopenharmony_ci		return;
710662306a36Sopenharmony_ci
710762306a36Sopenharmony_ci	if ((speed_cap != PCIE_SPEED_8_0GT) &&
710862306a36Sopenharmony_ci	    (speed_cap != PCIE_SPEED_5_0GT))
710962306a36Sopenharmony_ci		return;
711062306a36Sopenharmony_ci
711162306a36Sopenharmony_ci	speed_cntl = RREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL);
711262306a36Sopenharmony_ci	current_data_rate = (speed_cntl & LC_CURRENT_DATA_RATE_MASK) >>
711362306a36Sopenharmony_ci		LC_CURRENT_DATA_RATE_SHIFT;
711462306a36Sopenharmony_ci	if (speed_cap == PCIE_SPEED_8_0GT) {
711562306a36Sopenharmony_ci		if (current_data_rate == 2) {
711662306a36Sopenharmony_ci			DRM_INFO("PCIE gen 3 link speeds already enabled\n");
711762306a36Sopenharmony_ci			return;
711862306a36Sopenharmony_ci		}
711962306a36Sopenharmony_ci		DRM_INFO("enabling PCIE gen 3 link speeds, disable with radeon.pcie_gen2=0\n");
712062306a36Sopenharmony_ci	} else if (speed_cap == PCIE_SPEED_5_0GT) {
712162306a36Sopenharmony_ci		if (current_data_rate == 1) {
712262306a36Sopenharmony_ci			DRM_INFO("PCIE gen 2 link speeds already enabled\n");
712362306a36Sopenharmony_ci			return;
712462306a36Sopenharmony_ci		}
712562306a36Sopenharmony_ci		DRM_INFO("enabling PCIE gen 2 link speeds, disable with radeon.pcie_gen2=0\n");
712662306a36Sopenharmony_ci	}
712762306a36Sopenharmony_ci
712862306a36Sopenharmony_ci	if (!pci_is_pcie(root) || !pci_is_pcie(rdev->pdev))
712962306a36Sopenharmony_ci		return;
713062306a36Sopenharmony_ci
713162306a36Sopenharmony_ci	if (speed_cap == PCIE_SPEED_8_0GT) {
713262306a36Sopenharmony_ci		/* re-try equalization if gen3 is not already enabled */
713362306a36Sopenharmony_ci		if (current_data_rate != 2) {
713462306a36Sopenharmony_ci			u16 bridge_cfg, gpu_cfg;
713562306a36Sopenharmony_ci			u16 bridge_cfg2, gpu_cfg2;
713662306a36Sopenharmony_ci			u32 max_lw, current_lw, tmp;
713762306a36Sopenharmony_ci
713862306a36Sopenharmony_ci			pcie_capability_set_word(root, PCI_EXP_LNKCTL, PCI_EXP_LNKCTL_HAWD);
713962306a36Sopenharmony_ci			pcie_capability_set_word(rdev->pdev, PCI_EXP_LNKCTL, PCI_EXP_LNKCTL_HAWD);
714062306a36Sopenharmony_ci
714162306a36Sopenharmony_ci			tmp = RREG32_PCIE(PCIE_LC_STATUS1);
714262306a36Sopenharmony_ci			max_lw = (tmp & LC_DETECTED_LINK_WIDTH_MASK) >> LC_DETECTED_LINK_WIDTH_SHIFT;
714362306a36Sopenharmony_ci			current_lw = (tmp & LC_OPERATING_LINK_WIDTH_MASK) >> LC_OPERATING_LINK_WIDTH_SHIFT;
714462306a36Sopenharmony_ci
714562306a36Sopenharmony_ci			if (current_lw < max_lw) {
714662306a36Sopenharmony_ci				tmp = RREG32_PCIE_PORT(PCIE_LC_LINK_WIDTH_CNTL);
714762306a36Sopenharmony_ci				if (tmp & LC_RENEGOTIATION_SUPPORT) {
714862306a36Sopenharmony_ci					tmp &= ~(LC_LINK_WIDTH_MASK | LC_UPCONFIGURE_DIS);
714962306a36Sopenharmony_ci					tmp |= (max_lw << LC_LINK_WIDTH_SHIFT);
715062306a36Sopenharmony_ci					tmp |= LC_UPCONFIGURE_SUPPORT | LC_RENEGOTIATE_EN | LC_RECONFIG_NOW;
715162306a36Sopenharmony_ci					WREG32_PCIE_PORT(PCIE_LC_LINK_WIDTH_CNTL, tmp);
715262306a36Sopenharmony_ci				}
715362306a36Sopenharmony_ci			}
715462306a36Sopenharmony_ci
715562306a36Sopenharmony_ci			for (i = 0; i < 10; i++) {
715662306a36Sopenharmony_ci				/* check status */
715762306a36Sopenharmony_ci				pcie_capability_read_word(rdev->pdev,
715862306a36Sopenharmony_ci							  PCI_EXP_DEVSTA,
715962306a36Sopenharmony_ci							  &tmp16);
716062306a36Sopenharmony_ci				if (tmp16 & PCI_EXP_DEVSTA_TRPND)
716162306a36Sopenharmony_ci					break;
716262306a36Sopenharmony_ci
716362306a36Sopenharmony_ci				pcie_capability_read_word(root, PCI_EXP_LNKCTL,
716462306a36Sopenharmony_ci							  &bridge_cfg);
716562306a36Sopenharmony_ci				pcie_capability_read_word(rdev->pdev,
716662306a36Sopenharmony_ci							  PCI_EXP_LNKCTL,
716762306a36Sopenharmony_ci							  &gpu_cfg);
716862306a36Sopenharmony_ci
716962306a36Sopenharmony_ci				pcie_capability_read_word(root, PCI_EXP_LNKCTL2,
717062306a36Sopenharmony_ci							  &bridge_cfg2);
717162306a36Sopenharmony_ci				pcie_capability_read_word(rdev->pdev,
717262306a36Sopenharmony_ci							  PCI_EXP_LNKCTL2,
717362306a36Sopenharmony_ci							  &gpu_cfg2);
717462306a36Sopenharmony_ci
717562306a36Sopenharmony_ci				tmp = RREG32_PCIE_PORT(PCIE_LC_CNTL4);
717662306a36Sopenharmony_ci				tmp |= LC_SET_QUIESCE;
717762306a36Sopenharmony_ci				WREG32_PCIE_PORT(PCIE_LC_CNTL4, tmp);
717862306a36Sopenharmony_ci
717962306a36Sopenharmony_ci				tmp = RREG32_PCIE_PORT(PCIE_LC_CNTL4);
718062306a36Sopenharmony_ci				tmp |= LC_REDO_EQ;
718162306a36Sopenharmony_ci				WREG32_PCIE_PORT(PCIE_LC_CNTL4, tmp);
718262306a36Sopenharmony_ci
718362306a36Sopenharmony_ci				msleep(100);
718462306a36Sopenharmony_ci
718562306a36Sopenharmony_ci				/* linkctl */
718662306a36Sopenharmony_ci				pcie_capability_clear_and_set_word(root, PCI_EXP_LNKCTL,
718762306a36Sopenharmony_ci								   PCI_EXP_LNKCTL_HAWD,
718862306a36Sopenharmony_ci								   bridge_cfg &
718962306a36Sopenharmony_ci								   PCI_EXP_LNKCTL_HAWD);
719062306a36Sopenharmony_ci				pcie_capability_clear_and_set_word(rdev->pdev, PCI_EXP_LNKCTL,
719162306a36Sopenharmony_ci								   PCI_EXP_LNKCTL_HAWD,
719262306a36Sopenharmony_ci								   gpu_cfg &
719362306a36Sopenharmony_ci								   PCI_EXP_LNKCTL_HAWD);
719462306a36Sopenharmony_ci
719562306a36Sopenharmony_ci				/* linkctl2 */
719662306a36Sopenharmony_ci				pcie_capability_read_word(root, PCI_EXP_LNKCTL2,
719762306a36Sopenharmony_ci							  &tmp16);
719862306a36Sopenharmony_ci				tmp16 &= ~(PCI_EXP_LNKCTL2_ENTER_COMP |
719962306a36Sopenharmony_ci					   PCI_EXP_LNKCTL2_TX_MARGIN);
720062306a36Sopenharmony_ci				tmp16 |= (bridge_cfg2 &
720162306a36Sopenharmony_ci					  (PCI_EXP_LNKCTL2_ENTER_COMP |
720262306a36Sopenharmony_ci					   PCI_EXP_LNKCTL2_TX_MARGIN));
720362306a36Sopenharmony_ci				pcie_capability_write_word(root,
720462306a36Sopenharmony_ci							   PCI_EXP_LNKCTL2,
720562306a36Sopenharmony_ci							   tmp16);
720662306a36Sopenharmony_ci
720762306a36Sopenharmony_ci				pcie_capability_read_word(rdev->pdev,
720862306a36Sopenharmony_ci							  PCI_EXP_LNKCTL2,
720962306a36Sopenharmony_ci							  &tmp16);
721062306a36Sopenharmony_ci				tmp16 &= ~(PCI_EXP_LNKCTL2_ENTER_COMP |
721162306a36Sopenharmony_ci					   PCI_EXP_LNKCTL2_TX_MARGIN);
721262306a36Sopenharmony_ci				tmp16 |= (gpu_cfg2 &
721362306a36Sopenharmony_ci					  (PCI_EXP_LNKCTL2_ENTER_COMP |
721462306a36Sopenharmony_ci					   PCI_EXP_LNKCTL2_TX_MARGIN));
721562306a36Sopenharmony_ci				pcie_capability_write_word(rdev->pdev,
721662306a36Sopenharmony_ci							   PCI_EXP_LNKCTL2,
721762306a36Sopenharmony_ci							   tmp16);
721862306a36Sopenharmony_ci
721962306a36Sopenharmony_ci				tmp = RREG32_PCIE_PORT(PCIE_LC_CNTL4);
722062306a36Sopenharmony_ci				tmp &= ~LC_SET_QUIESCE;
722162306a36Sopenharmony_ci				WREG32_PCIE_PORT(PCIE_LC_CNTL4, tmp);
722262306a36Sopenharmony_ci			}
722362306a36Sopenharmony_ci		}
722462306a36Sopenharmony_ci	}
722562306a36Sopenharmony_ci
722662306a36Sopenharmony_ci	/* set the link speed */
722762306a36Sopenharmony_ci	speed_cntl |= LC_FORCE_EN_SW_SPEED_CHANGE | LC_FORCE_DIS_HW_SPEED_CHANGE;
722862306a36Sopenharmony_ci	speed_cntl &= ~LC_FORCE_DIS_SW_SPEED_CHANGE;
722962306a36Sopenharmony_ci	WREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL, speed_cntl);
723062306a36Sopenharmony_ci
723162306a36Sopenharmony_ci	pcie_capability_read_word(rdev->pdev, PCI_EXP_LNKCTL2, &tmp16);
723262306a36Sopenharmony_ci	tmp16 &= ~PCI_EXP_LNKCTL2_TLS;
723362306a36Sopenharmony_ci	if (speed_cap == PCIE_SPEED_8_0GT)
723462306a36Sopenharmony_ci		tmp16 |= PCI_EXP_LNKCTL2_TLS_8_0GT; /* gen3 */
723562306a36Sopenharmony_ci	else if (speed_cap == PCIE_SPEED_5_0GT)
723662306a36Sopenharmony_ci		tmp16 |= PCI_EXP_LNKCTL2_TLS_5_0GT; /* gen2 */
723762306a36Sopenharmony_ci	else
723862306a36Sopenharmony_ci		tmp16 |= PCI_EXP_LNKCTL2_TLS_2_5GT; /* gen1 */
723962306a36Sopenharmony_ci	pcie_capability_write_word(rdev->pdev, PCI_EXP_LNKCTL2, tmp16);
724062306a36Sopenharmony_ci
724162306a36Sopenharmony_ci	speed_cntl = RREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL);
724262306a36Sopenharmony_ci	speed_cntl |= LC_INITIATE_LINK_SPEED_CHANGE;
724362306a36Sopenharmony_ci	WREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL, speed_cntl);
724462306a36Sopenharmony_ci
724562306a36Sopenharmony_ci	for (i = 0; i < rdev->usec_timeout; i++) {
724662306a36Sopenharmony_ci		speed_cntl = RREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL);
724762306a36Sopenharmony_ci		if ((speed_cntl & LC_INITIATE_LINK_SPEED_CHANGE) == 0)
724862306a36Sopenharmony_ci			break;
724962306a36Sopenharmony_ci		udelay(1);
725062306a36Sopenharmony_ci	}
725162306a36Sopenharmony_ci}
725262306a36Sopenharmony_ci
725362306a36Sopenharmony_cistatic void si_program_aspm(struct radeon_device *rdev)
725462306a36Sopenharmony_ci{
725562306a36Sopenharmony_ci	u32 data, orig;
725662306a36Sopenharmony_ci	bool disable_l0s = false, disable_l1 = false, disable_plloff_in_l1 = false;
725762306a36Sopenharmony_ci	bool disable_clkreq = false;
725862306a36Sopenharmony_ci
725962306a36Sopenharmony_ci	if (radeon_aspm == 0)
726062306a36Sopenharmony_ci		return;
726162306a36Sopenharmony_ci
726262306a36Sopenharmony_ci	if (!(rdev->flags & RADEON_IS_PCIE))
726362306a36Sopenharmony_ci		return;
726462306a36Sopenharmony_ci
726562306a36Sopenharmony_ci	orig = data = RREG32_PCIE_PORT(PCIE_LC_N_FTS_CNTL);
726662306a36Sopenharmony_ci	data &= ~LC_XMIT_N_FTS_MASK;
726762306a36Sopenharmony_ci	data |= LC_XMIT_N_FTS(0x24) | LC_XMIT_N_FTS_OVERRIDE_EN;
726862306a36Sopenharmony_ci	if (orig != data)
726962306a36Sopenharmony_ci		WREG32_PCIE_PORT(PCIE_LC_N_FTS_CNTL, data);
727062306a36Sopenharmony_ci
727162306a36Sopenharmony_ci	orig = data = RREG32_PCIE_PORT(PCIE_LC_CNTL3);
727262306a36Sopenharmony_ci	data |= LC_GO_TO_RECOVERY;
727362306a36Sopenharmony_ci	if (orig != data)
727462306a36Sopenharmony_ci		WREG32_PCIE_PORT(PCIE_LC_CNTL3, data);
727562306a36Sopenharmony_ci
727662306a36Sopenharmony_ci	orig = data = RREG32_PCIE(PCIE_P_CNTL);
727762306a36Sopenharmony_ci	data |= P_IGNORE_EDB_ERR;
727862306a36Sopenharmony_ci	if (orig != data)
727962306a36Sopenharmony_ci		WREG32_PCIE(PCIE_P_CNTL, data);
728062306a36Sopenharmony_ci
728162306a36Sopenharmony_ci	orig = data = RREG32_PCIE_PORT(PCIE_LC_CNTL);
728262306a36Sopenharmony_ci	data &= ~(LC_L0S_INACTIVITY_MASK | LC_L1_INACTIVITY_MASK);
728362306a36Sopenharmony_ci	data |= LC_PMI_TO_L1_DIS;
728462306a36Sopenharmony_ci	if (!disable_l0s)
728562306a36Sopenharmony_ci		data |= LC_L0S_INACTIVITY(7);
728662306a36Sopenharmony_ci
728762306a36Sopenharmony_ci	if (!disable_l1) {
728862306a36Sopenharmony_ci		data |= LC_L1_INACTIVITY(7);
728962306a36Sopenharmony_ci		data &= ~LC_PMI_TO_L1_DIS;
729062306a36Sopenharmony_ci		if (orig != data)
729162306a36Sopenharmony_ci			WREG32_PCIE_PORT(PCIE_LC_CNTL, data);
729262306a36Sopenharmony_ci
729362306a36Sopenharmony_ci		if (!disable_plloff_in_l1) {
729462306a36Sopenharmony_ci			bool clk_req_support;
729562306a36Sopenharmony_ci
729662306a36Sopenharmony_ci			orig = data = RREG32_PIF_PHY0(PB0_PIF_PWRDOWN_0);
729762306a36Sopenharmony_ci			data &= ~(PLL_POWER_STATE_IN_OFF_0_MASK | PLL_POWER_STATE_IN_TXS2_0_MASK);
729862306a36Sopenharmony_ci			data |= PLL_POWER_STATE_IN_OFF_0(7) | PLL_POWER_STATE_IN_TXS2_0(7);
729962306a36Sopenharmony_ci			if (orig != data)
730062306a36Sopenharmony_ci				WREG32_PIF_PHY0(PB0_PIF_PWRDOWN_0, data);
730162306a36Sopenharmony_ci
730262306a36Sopenharmony_ci			orig = data = RREG32_PIF_PHY0(PB0_PIF_PWRDOWN_1);
730362306a36Sopenharmony_ci			data &= ~(PLL_POWER_STATE_IN_OFF_1_MASK | PLL_POWER_STATE_IN_TXS2_1_MASK);
730462306a36Sopenharmony_ci			data |= PLL_POWER_STATE_IN_OFF_1(7) | PLL_POWER_STATE_IN_TXS2_1(7);
730562306a36Sopenharmony_ci			if (orig != data)
730662306a36Sopenharmony_ci				WREG32_PIF_PHY0(PB0_PIF_PWRDOWN_1, data);
730762306a36Sopenharmony_ci
730862306a36Sopenharmony_ci			orig = data = RREG32_PIF_PHY1(PB1_PIF_PWRDOWN_0);
730962306a36Sopenharmony_ci			data &= ~(PLL_POWER_STATE_IN_OFF_0_MASK | PLL_POWER_STATE_IN_TXS2_0_MASK);
731062306a36Sopenharmony_ci			data |= PLL_POWER_STATE_IN_OFF_0(7) | PLL_POWER_STATE_IN_TXS2_0(7);
731162306a36Sopenharmony_ci			if (orig != data)
731262306a36Sopenharmony_ci				WREG32_PIF_PHY1(PB1_PIF_PWRDOWN_0, data);
731362306a36Sopenharmony_ci
731462306a36Sopenharmony_ci			orig = data = RREG32_PIF_PHY1(PB1_PIF_PWRDOWN_1);
731562306a36Sopenharmony_ci			data &= ~(PLL_POWER_STATE_IN_OFF_1_MASK | PLL_POWER_STATE_IN_TXS2_1_MASK);
731662306a36Sopenharmony_ci			data |= PLL_POWER_STATE_IN_OFF_1(7) | PLL_POWER_STATE_IN_TXS2_1(7);
731762306a36Sopenharmony_ci			if (orig != data)
731862306a36Sopenharmony_ci				WREG32_PIF_PHY1(PB1_PIF_PWRDOWN_1, data);
731962306a36Sopenharmony_ci
732062306a36Sopenharmony_ci			if ((rdev->family != CHIP_OLAND) && (rdev->family != CHIP_HAINAN)) {
732162306a36Sopenharmony_ci				orig = data = RREG32_PIF_PHY0(PB0_PIF_PWRDOWN_0);
732262306a36Sopenharmony_ci				data &= ~PLL_RAMP_UP_TIME_0_MASK;
732362306a36Sopenharmony_ci				if (orig != data)
732462306a36Sopenharmony_ci					WREG32_PIF_PHY0(PB0_PIF_PWRDOWN_0, data);
732562306a36Sopenharmony_ci
732662306a36Sopenharmony_ci				orig = data = RREG32_PIF_PHY0(PB0_PIF_PWRDOWN_1);
732762306a36Sopenharmony_ci				data &= ~PLL_RAMP_UP_TIME_1_MASK;
732862306a36Sopenharmony_ci				if (orig != data)
732962306a36Sopenharmony_ci					WREG32_PIF_PHY0(PB0_PIF_PWRDOWN_1, data);
733062306a36Sopenharmony_ci
733162306a36Sopenharmony_ci				orig = data = RREG32_PIF_PHY0(PB0_PIF_PWRDOWN_2);
733262306a36Sopenharmony_ci				data &= ~PLL_RAMP_UP_TIME_2_MASK;
733362306a36Sopenharmony_ci				if (orig != data)
733462306a36Sopenharmony_ci					WREG32_PIF_PHY0(PB0_PIF_PWRDOWN_2, data);
733562306a36Sopenharmony_ci
733662306a36Sopenharmony_ci				orig = data = RREG32_PIF_PHY0(PB0_PIF_PWRDOWN_3);
733762306a36Sopenharmony_ci				data &= ~PLL_RAMP_UP_TIME_3_MASK;
733862306a36Sopenharmony_ci				if (orig != data)
733962306a36Sopenharmony_ci					WREG32_PIF_PHY0(PB0_PIF_PWRDOWN_3, data);
734062306a36Sopenharmony_ci
734162306a36Sopenharmony_ci				orig = data = RREG32_PIF_PHY1(PB1_PIF_PWRDOWN_0);
734262306a36Sopenharmony_ci				data &= ~PLL_RAMP_UP_TIME_0_MASK;
734362306a36Sopenharmony_ci				if (orig != data)
734462306a36Sopenharmony_ci					WREG32_PIF_PHY1(PB1_PIF_PWRDOWN_0, data);
734562306a36Sopenharmony_ci
734662306a36Sopenharmony_ci				orig = data = RREG32_PIF_PHY1(PB1_PIF_PWRDOWN_1);
734762306a36Sopenharmony_ci				data &= ~PLL_RAMP_UP_TIME_1_MASK;
734862306a36Sopenharmony_ci				if (orig != data)
734962306a36Sopenharmony_ci					WREG32_PIF_PHY1(PB1_PIF_PWRDOWN_1, data);
735062306a36Sopenharmony_ci
735162306a36Sopenharmony_ci				orig = data = RREG32_PIF_PHY1(PB1_PIF_PWRDOWN_2);
735262306a36Sopenharmony_ci				data &= ~PLL_RAMP_UP_TIME_2_MASK;
735362306a36Sopenharmony_ci				if (orig != data)
735462306a36Sopenharmony_ci					WREG32_PIF_PHY1(PB1_PIF_PWRDOWN_2, data);
735562306a36Sopenharmony_ci
735662306a36Sopenharmony_ci				orig = data = RREG32_PIF_PHY1(PB1_PIF_PWRDOWN_3);
735762306a36Sopenharmony_ci				data &= ~PLL_RAMP_UP_TIME_3_MASK;
735862306a36Sopenharmony_ci				if (orig != data)
735962306a36Sopenharmony_ci					WREG32_PIF_PHY1(PB1_PIF_PWRDOWN_3, data);
736062306a36Sopenharmony_ci			}
736162306a36Sopenharmony_ci			orig = data = RREG32_PCIE_PORT(PCIE_LC_LINK_WIDTH_CNTL);
736262306a36Sopenharmony_ci			data &= ~LC_DYN_LANES_PWR_STATE_MASK;
736362306a36Sopenharmony_ci			data |= LC_DYN_LANES_PWR_STATE(3);
736462306a36Sopenharmony_ci			if (orig != data)
736562306a36Sopenharmony_ci				WREG32_PCIE_PORT(PCIE_LC_LINK_WIDTH_CNTL, data);
736662306a36Sopenharmony_ci
736762306a36Sopenharmony_ci			orig = data = RREG32_PIF_PHY0(PB0_PIF_CNTL);
736862306a36Sopenharmony_ci			data &= ~LS2_EXIT_TIME_MASK;
736962306a36Sopenharmony_ci			if ((rdev->family == CHIP_OLAND) || (rdev->family == CHIP_HAINAN))
737062306a36Sopenharmony_ci				data |= LS2_EXIT_TIME(5);
737162306a36Sopenharmony_ci			if (orig != data)
737262306a36Sopenharmony_ci				WREG32_PIF_PHY0(PB0_PIF_CNTL, data);
737362306a36Sopenharmony_ci
737462306a36Sopenharmony_ci			orig = data = RREG32_PIF_PHY1(PB1_PIF_CNTL);
737562306a36Sopenharmony_ci			data &= ~LS2_EXIT_TIME_MASK;
737662306a36Sopenharmony_ci			if ((rdev->family == CHIP_OLAND) || (rdev->family == CHIP_HAINAN))
737762306a36Sopenharmony_ci				data |= LS2_EXIT_TIME(5);
737862306a36Sopenharmony_ci			if (orig != data)
737962306a36Sopenharmony_ci				WREG32_PIF_PHY1(PB1_PIF_CNTL, data);
738062306a36Sopenharmony_ci
738162306a36Sopenharmony_ci			if (!disable_clkreq &&
738262306a36Sopenharmony_ci			    !pci_is_root_bus(rdev->pdev->bus)) {
738362306a36Sopenharmony_ci				struct pci_dev *root = rdev->pdev->bus->self;
738462306a36Sopenharmony_ci				u32 lnkcap;
738562306a36Sopenharmony_ci
738662306a36Sopenharmony_ci				clk_req_support = false;
738762306a36Sopenharmony_ci				pcie_capability_read_dword(root, PCI_EXP_LNKCAP, &lnkcap);
738862306a36Sopenharmony_ci				if (lnkcap & PCI_EXP_LNKCAP_CLKPM)
738962306a36Sopenharmony_ci					clk_req_support = true;
739062306a36Sopenharmony_ci			} else {
739162306a36Sopenharmony_ci				clk_req_support = false;
739262306a36Sopenharmony_ci			}
739362306a36Sopenharmony_ci
739462306a36Sopenharmony_ci			if (clk_req_support) {
739562306a36Sopenharmony_ci				orig = data = RREG32_PCIE_PORT(PCIE_LC_CNTL2);
739662306a36Sopenharmony_ci				data |= LC_ALLOW_PDWN_IN_L1 | LC_ALLOW_PDWN_IN_L23;
739762306a36Sopenharmony_ci				if (orig != data)
739862306a36Sopenharmony_ci					WREG32_PCIE_PORT(PCIE_LC_CNTL2, data);
739962306a36Sopenharmony_ci
740062306a36Sopenharmony_ci				orig = data = RREG32(THM_CLK_CNTL);
740162306a36Sopenharmony_ci				data &= ~(CMON_CLK_SEL_MASK | TMON_CLK_SEL_MASK);
740262306a36Sopenharmony_ci				data |= CMON_CLK_SEL(1) | TMON_CLK_SEL(1);
740362306a36Sopenharmony_ci				if (orig != data)
740462306a36Sopenharmony_ci					WREG32(THM_CLK_CNTL, data);
740562306a36Sopenharmony_ci
740662306a36Sopenharmony_ci				orig = data = RREG32(MISC_CLK_CNTL);
740762306a36Sopenharmony_ci				data &= ~(DEEP_SLEEP_CLK_SEL_MASK | ZCLK_SEL_MASK);
740862306a36Sopenharmony_ci				data |= DEEP_SLEEP_CLK_SEL(1) | ZCLK_SEL(1);
740962306a36Sopenharmony_ci				if (orig != data)
741062306a36Sopenharmony_ci					WREG32(MISC_CLK_CNTL, data);
741162306a36Sopenharmony_ci
741262306a36Sopenharmony_ci				orig = data = RREG32(CG_CLKPIN_CNTL);
741362306a36Sopenharmony_ci				data &= ~BCLK_AS_XCLK;
741462306a36Sopenharmony_ci				if (orig != data)
741562306a36Sopenharmony_ci					WREG32(CG_CLKPIN_CNTL, data);
741662306a36Sopenharmony_ci
741762306a36Sopenharmony_ci				orig = data = RREG32(CG_CLKPIN_CNTL_2);
741862306a36Sopenharmony_ci				data &= ~FORCE_BIF_REFCLK_EN;
741962306a36Sopenharmony_ci				if (orig != data)
742062306a36Sopenharmony_ci					WREG32(CG_CLKPIN_CNTL_2, data);
742162306a36Sopenharmony_ci
742262306a36Sopenharmony_ci				orig = data = RREG32(MPLL_BYPASSCLK_SEL);
742362306a36Sopenharmony_ci				data &= ~MPLL_CLKOUT_SEL_MASK;
742462306a36Sopenharmony_ci				data |= MPLL_CLKOUT_SEL(4);
742562306a36Sopenharmony_ci				if (orig != data)
742662306a36Sopenharmony_ci					WREG32(MPLL_BYPASSCLK_SEL, data);
742762306a36Sopenharmony_ci
742862306a36Sopenharmony_ci				orig = data = RREG32(SPLL_CNTL_MODE);
742962306a36Sopenharmony_ci				data &= ~SPLL_REFCLK_SEL_MASK;
743062306a36Sopenharmony_ci				if (orig != data)
743162306a36Sopenharmony_ci					WREG32(SPLL_CNTL_MODE, data);
743262306a36Sopenharmony_ci			}
743362306a36Sopenharmony_ci		}
743462306a36Sopenharmony_ci	} else {
743562306a36Sopenharmony_ci		if (orig != data)
743662306a36Sopenharmony_ci			WREG32_PCIE_PORT(PCIE_LC_CNTL, data);
743762306a36Sopenharmony_ci	}
743862306a36Sopenharmony_ci
743962306a36Sopenharmony_ci	orig = data = RREG32_PCIE(PCIE_CNTL2);
744062306a36Sopenharmony_ci	data |= SLV_MEM_LS_EN | MST_MEM_LS_EN | REPLAY_MEM_LS_EN;
744162306a36Sopenharmony_ci	if (orig != data)
744262306a36Sopenharmony_ci		WREG32_PCIE(PCIE_CNTL2, data);
744362306a36Sopenharmony_ci
744462306a36Sopenharmony_ci	if (!disable_l0s) {
744562306a36Sopenharmony_ci		data = RREG32_PCIE_PORT(PCIE_LC_N_FTS_CNTL);
744662306a36Sopenharmony_ci		if((data & LC_N_FTS_MASK) == LC_N_FTS_MASK) {
744762306a36Sopenharmony_ci			data = RREG32_PCIE(PCIE_LC_STATUS1);
744862306a36Sopenharmony_ci			if ((data & LC_REVERSE_XMIT) && (data & LC_REVERSE_RCVR)) {
744962306a36Sopenharmony_ci				orig = data = RREG32_PCIE_PORT(PCIE_LC_CNTL);
745062306a36Sopenharmony_ci				data &= ~LC_L0S_INACTIVITY_MASK;
745162306a36Sopenharmony_ci				if (orig != data)
745262306a36Sopenharmony_ci					WREG32_PCIE_PORT(PCIE_LC_CNTL, data);
745362306a36Sopenharmony_ci			}
745462306a36Sopenharmony_ci		}
745562306a36Sopenharmony_ci	}
745662306a36Sopenharmony_ci}
745762306a36Sopenharmony_ci
745862306a36Sopenharmony_cistatic int si_vce_send_vcepll_ctlreq(struct radeon_device *rdev)
745962306a36Sopenharmony_ci{
746062306a36Sopenharmony_ci	unsigned i;
746162306a36Sopenharmony_ci
746262306a36Sopenharmony_ci	/* make sure VCEPLL_CTLREQ is deasserted */
746362306a36Sopenharmony_ci	WREG32_SMC_P(CG_VCEPLL_FUNC_CNTL, 0, ~UPLL_CTLREQ_MASK);
746462306a36Sopenharmony_ci
746562306a36Sopenharmony_ci	mdelay(10);
746662306a36Sopenharmony_ci
746762306a36Sopenharmony_ci	/* assert UPLL_CTLREQ */
746862306a36Sopenharmony_ci	WREG32_SMC_P(CG_VCEPLL_FUNC_CNTL, UPLL_CTLREQ_MASK, ~UPLL_CTLREQ_MASK);
746962306a36Sopenharmony_ci
747062306a36Sopenharmony_ci	/* wait for CTLACK and CTLACK2 to get asserted */
747162306a36Sopenharmony_ci	for (i = 0; i < 100; ++i) {
747262306a36Sopenharmony_ci		uint32_t mask = UPLL_CTLACK_MASK | UPLL_CTLACK2_MASK;
747362306a36Sopenharmony_ci		if ((RREG32_SMC(CG_VCEPLL_FUNC_CNTL) & mask) == mask)
747462306a36Sopenharmony_ci			break;
747562306a36Sopenharmony_ci		mdelay(10);
747662306a36Sopenharmony_ci	}
747762306a36Sopenharmony_ci
747862306a36Sopenharmony_ci	/* deassert UPLL_CTLREQ */
747962306a36Sopenharmony_ci	WREG32_SMC_P(CG_VCEPLL_FUNC_CNTL, 0, ~UPLL_CTLREQ_MASK);
748062306a36Sopenharmony_ci
748162306a36Sopenharmony_ci	if (i == 100) {
748262306a36Sopenharmony_ci		DRM_ERROR("Timeout setting UVD clocks!\n");
748362306a36Sopenharmony_ci		return -ETIMEDOUT;
748462306a36Sopenharmony_ci	}
748562306a36Sopenharmony_ci
748662306a36Sopenharmony_ci	return 0;
748762306a36Sopenharmony_ci}
748862306a36Sopenharmony_ci
748962306a36Sopenharmony_ciint si_set_vce_clocks(struct radeon_device *rdev, u32 evclk, u32 ecclk)
749062306a36Sopenharmony_ci{
749162306a36Sopenharmony_ci	unsigned fb_div = 0, evclk_div = 0, ecclk_div = 0;
749262306a36Sopenharmony_ci	int r;
749362306a36Sopenharmony_ci
749462306a36Sopenharmony_ci	/* bypass evclk and ecclk with bclk */
749562306a36Sopenharmony_ci	WREG32_SMC_P(CG_VCEPLL_FUNC_CNTL_2,
749662306a36Sopenharmony_ci		     EVCLK_SRC_SEL(1) | ECCLK_SRC_SEL(1),
749762306a36Sopenharmony_ci		     ~(EVCLK_SRC_SEL_MASK | ECCLK_SRC_SEL_MASK));
749862306a36Sopenharmony_ci
749962306a36Sopenharmony_ci	/* put PLL in bypass mode */
750062306a36Sopenharmony_ci	WREG32_SMC_P(CG_VCEPLL_FUNC_CNTL, VCEPLL_BYPASS_EN_MASK,
750162306a36Sopenharmony_ci		     ~VCEPLL_BYPASS_EN_MASK);
750262306a36Sopenharmony_ci
750362306a36Sopenharmony_ci	if (!evclk || !ecclk) {
750462306a36Sopenharmony_ci		/* keep the Bypass mode, put PLL to sleep */
750562306a36Sopenharmony_ci		WREG32_SMC_P(CG_VCEPLL_FUNC_CNTL, VCEPLL_SLEEP_MASK,
750662306a36Sopenharmony_ci			     ~VCEPLL_SLEEP_MASK);
750762306a36Sopenharmony_ci		return 0;
750862306a36Sopenharmony_ci	}
750962306a36Sopenharmony_ci
751062306a36Sopenharmony_ci	r = radeon_uvd_calc_upll_dividers(rdev, evclk, ecclk, 125000, 250000,
751162306a36Sopenharmony_ci					  16384, 0x03FFFFFF, 0, 128, 5,
751262306a36Sopenharmony_ci					  &fb_div, &evclk_div, &ecclk_div);
751362306a36Sopenharmony_ci	if (r)
751462306a36Sopenharmony_ci		return r;
751562306a36Sopenharmony_ci
751662306a36Sopenharmony_ci	/* set RESET_ANTI_MUX to 0 */
751762306a36Sopenharmony_ci	WREG32_SMC_P(CG_VCEPLL_FUNC_CNTL_5, 0, ~RESET_ANTI_MUX_MASK);
751862306a36Sopenharmony_ci
751962306a36Sopenharmony_ci	/* set VCO_MODE to 1 */
752062306a36Sopenharmony_ci	WREG32_SMC_P(CG_VCEPLL_FUNC_CNTL, VCEPLL_VCO_MODE_MASK,
752162306a36Sopenharmony_ci		     ~VCEPLL_VCO_MODE_MASK);
752262306a36Sopenharmony_ci
752362306a36Sopenharmony_ci	/* toggle VCEPLL_SLEEP to 1 then back to 0 */
752462306a36Sopenharmony_ci	WREG32_SMC_P(CG_VCEPLL_FUNC_CNTL, VCEPLL_SLEEP_MASK,
752562306a36Sopenharmony_ci		     ~VCEPLL_SLEEP_MASK);
752662306a36Sopenharmony_ci	WREG32_SMC_P(CG_VCEPLL_FUNC_CNTL, 0, ~VCEPLL_SLEEP_MASK);
752762306a36Sopenharmony_ci
752862306a36Sopenharmony_ci	/* deassert VCEPLL_RESET */
752962306a36Sopenharmony_ci	WREG32_SMC_P(CG_VCEPLL_FUNC_CNTL, 0, ~VCEPLL_RESET_MASK);
753062306a36Sopenharmony_ci
753162306a36Sopenharmony_ci	mdelay(1);
753262306a36Sopenharmony_ci
753362306a36Sopenharmony_ci	r = si_vce_send_vcepll_ctlreq(rdev);
753462306a36Sopenharmony_ci	if (r)
753562306a36Sopenharmony_ci		return r;
753662306a36Sopenharmony_ci
753762306a36Sopenharmony_ci	/* assert VCEPLL_RESET again */
753862306a36Sopenharmony_ci	WREG32_SMC_P(CG_VCEPLL_FUNC_CNTL, VCEPLL_RESET_MASK, ~VCEPLL_RESET_MASK);
753962306a36Sopenharmony_ci
754062306a36Sopenharmony_ci	/* disable spread spectrum. */
754162306a36Sopenharmony_ci	WREG32_SMC_P(CG_VCEPLL_SPREAD_SPECTRUM, 0, ~SSEN_MASK);
754262306a36Sopenharmony_ci
754362306a36Sopenharmony_ci	/* set feedback divider */
754462306a36Sopenharmony_ci	WREG32_SMC_P(CG_VCEPLL_FUNC_CNTL_3, VCEPLL_FB_DIV(fb_div), ~VCEPLL_FB_DIV_MASK);
754562306a36Sopenharmony_ci
754662306a36Sopenharmony_ci	/* set ref divider to 0 */
754762306a36Sopenharmony_ci	WREG32_SMC_P(CG_VCEPLL_FUNC_CNTL, 0, ~VCEPLL_REF_DIV_MASK);
754862306a36Sopenharmony_ci
754962306a36Sopenharmony_ci	/* set PDIV_A and PDIV_B */
755062306a36Sopenharmony_ci	WREG32_SMC_P(CG_VCEPLL_FUNC_CNTL_2,
755162306a36Sopenharmony_ci		     VCEPLL_PDIV_A(evclk_div) | VCEPLL_PDIV_B(ecclk_div),
755262306a36Sopenharmony_ci		     ~(VCEPLL_PDIV_A_MASK | VCEPLL_PDIV_B_MASK));
755362306a36Sopenharmony_ci
755462306a36Sopenharmony_ci	/* give the PLL some time to settle */
755562306a36Sopenharmony_ci	mdelay(15);
755662306a36Sopenharmony_ci
755762306a36Sopenharmony_ci	/* deassert PLL_RESET */
755862306a36Sopenharmony_ci	WREG32_SMC_P(CG_VCEPLL_FUNC_CNTL, 0, ~VCEPLL_RESET_MASK);
755962306a36Sopenharmony_ci
756062306a36Sopenharmony_ci	mdelay(15);
756162306a36Sopenharmony_ci
756262306a36Sopenharmony_ci	/* switch from bypass mode to normal mode */
756362306a36Sopenharmony_ci	WREG32_SMC_P(CG_VCEPLL_FUNC_CNTL, 0, ~VCEPLL_BYPASS_EN_MASK);
756462306a36Sopenharmony_ci
756562306a36Sopenharmony_ci	r = si_vce_send_vcepll_ctlreq(rdev);
756662306a36Sopenharmony_ci	if (r)
756762306a36Sopenharmony_ci		return r;
756862306a36Sopenharmony_ci
756962306a36Sopenharmony_ci	/* switch VCLK and DCLK selection */
757062306a36Sopenharmony_ci	WREG32_SMC_P(CG_VCEPLL_FUNC_CNTL_2,
757162306a36Sopenharmony_ci		     EVCLK_SRC_SEL(16) | ECCLK_SRC_SEL(16),
757262306a36Sopenharmony_ci		     ~(EVCLK_SRC_SEL_MASK | ECCLK_SRC_SEL_MASK));
757362306a36Sopenharmony_ci
757462306a36Sopenharmony_ci	mdelay(100);
757562306a36Sopenharmony_ci
757662306a36Sopenharmony_ci	return 0;
757762306a36Sopenharmony_ci}
7578