162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci * Copyright 2010 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/radeon_drm.h>
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci#include "atom.h"
3362306a36Sopenharmony_ci#include "cayman_blit_shaders.h"
3462306a36Sopenharmony_ci#include "clearstate_cayman.h"
3562306a36Sopenharmony_ci#include "evergreen.h"
3662306a36Sopenharmony_ci#include "ni.h"
3762306a36Sopenharmony_ci#include "ni_reg.h"
3862306a36Sopenharmony_ci#include "nid.h"
3962306a36Sopenharmony_ci#include "radeon.h"
4062306a36Sopenharmony_ci#include "radeon_asic.h"
4162306a36Sopenharmony_ci#include "radeon_audio.h"
4262306a36Sopenharmony_ci#include "radeon_ucode.h"
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci/*
4562306a36Sopenharmony_ci * Indirect registers accessor
4662306a36Sopenharmony_ci */
4762306a36Sopenharmony_ciu32 tn_smc_rreg(struct radeon_device *rdev, u32 reg)
4862306a36Sopenharmony_ci{
4962306a36Sopenharmony_ci	unsigned long flags;
5062306a36Sopenharmony_ci	u32 r;
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci	spin_lock_irqsave(&rdev->smc_idx_lock, flags);
5362306a36Sopenharmony_ci	WREG32(TN_SMC_IND_INDEX_0, (reg));
5462306a36Sopenharmony_ci	r = RREG32(TN_SMC_IND_DATA_0);
5562306a36Sopenharmony_ci	spin_unlock_irqrestore(&rdev->smc_idx_lock, flags);
5662306a36Sopenharmony_ci	return r;
5762306a36Sopenharmony_ci}
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_civoid tn_smc_wreg(struct radeon_device *rdev, u32 reg, u32 v)
6062306a36Sopenharmony_ci{
6162306a36Sopenharmony_ci	unsigned long flags;
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci	spin_lock_irqsave(&rdev->smc_idx_lock, flags);
6462306a36Sopenharmony_ci	WREG32(TN_SMC_IND_INDEX_0, (reg));
6562306a36Sopenharmony_ci	WREG32(TN_SMC_IND_DATA_0, (v));
6662306a36Sopenharmony_ci	spin_unlock_irqrestore(&rdev->smc_idx_lock, flags);
6762306a36Sopenharmony_ci}
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_cistatic const u32 tn_rlc_save_restore_register_list[] =
7062306a36Sopenharmony_ci{
7162306a36Sopenharmony_ci	0x98fc,
7262306a36Sopenharmony_ci	0x98f0,
7362306a36Sopenharmony_ci	0x9834,
7462306a36Sopenharmony_ci	0x9838,
7562306a36Sopenharmony_ci	0x9870,
7662306a36Sopenharmony_ci	0x9874,
7762306a36Sopenharmony_ci	0x8a14,
7862306a36Sopenharmony_ci	0x8b24,
7962306a36Sopenharmony_ci	0x8bcc,
8062306a36Sopenharmony_ci	0x8b10,
8162306a36Sopenharmony_ci	0x8c30,
8262306a36Sopenharmony_ci	0x8d00,
8362306a36Sopenharmony_ci	0x8d04,
8462306a36Sopenharmony_ci	0x8c00,
8562306a36Sopenharmony_ci	0x8c04,
8662306a36Sopenharmony_ci	0x8c10,
8762306a36Sopenharmony_ci	0x8c14,
8862306a36Sopenharmony_ci	0x8d8c,
8962306a36Sopenharmony_ci	0x8cf0,
9062306a36Sopenharmony_ci	0x8e38,
9162306a36Sopenharmony_ci	0x9508,
9262306a36Sopenharmony_ci	0x9688,
9362306a36Sopenharmony_ci	0x9608,
9462306a36Sopenharmony_ci	0x960c,
9562306a36Sopenharmony_ci	0x9610,
9662306a36Sopenharmony_ci	0x9614,
9762306a36Sopenharmony_ci	0x88c4,
9862306a36Sopenharmony_ci	0x8978,
9962306a36Sopenharmony_ci	0x88d4,
10062306a36Sopenharmony_ci	0x900c,
10162306a36Sopenharmony_ci	0x9100,
10262306a36Sopenharmony_ci	0x913c,
10362306a36Sopenharmony_ci	0x90e8,
10462306a36Sopenharmony_ci	0x9354,
10562306a36Sopenharmony_ci	0xa008,
10662306a36Sopenharmony_ci	0x98f8,
10762306a36Sopenharmony_ci	0x9148,
10862306a36Sopenharmony_ci	0x914c,
10962306a36Sopenharmony_ci	0x3f94,
11062306a36Sopenharmony_ci	0x98f4,
11162306a36Sopenharmony_ci	0x9b7c,
11262306a36Sopenharmony_ci	0x3f8c,
11362306a36Sopenharmony_ci	0x8950,
11462306a36Sopenharmony_ci	0x8954,
11562306a36Sopenharmony_ci	0x8a18,
11662306a36Sopenharmony_ci	0x8b28,
11762306a36Sopenharmony_ci	0x9144,
11862306a36Sopenharmony_ci	0x3f90,
11962306a36Sopenharmony_ci	0x915c,
12062306a36Sopenharmony_ci	0x9160,
12162306a36Sopenharmony_ci	0x9178,
12262306a36Sopenharmony_ci	0x917c,
12362306a36Sopenharmony_ci	0x9180,
12462306a36Sopenharmony_ci	0x918c,
12562306a36Sopenharmony_ci	0x9190,
12662306a36Sopenharmony_ci	0x9194,
12762306a36Sopenharmony_ci	0x9198,
12862306a36Sopenharmony_ci	0x919c,
12962306a36Sopenharmony_ci	0x91a8,
13062306a36Sopenharmony_ci	0x91ac,
13162306a36Sopenharmony_ci	0x91b0,
13262306a36Sopenharmony_ci	0x91b4,
13362306a36Sopenharmony_ci	0x91b8,
13462306a36Sopenharmony_ci	0x91c4,
13562306a36Sopenharmony_ci	0x91c8,
13662306a36Sopenharmony_ci	0x91cc,
13762306a36Sopenharmony_ci	0x91d0,
13862306a36Sopenharmony_ci	0x91d4,
13962306a36Sopenharmony_ci	0x91e0,
14062306a36Sopenharmony_ci	0x91e4,
14162306a36Sopenharmony_ci	0x91ec,
14262306a36Sopenharmony_ci	0x91f0,
14362306a36Sopenharmony_ci	0x91f4,
14462306a36Sopenharmony_ci	0x9200,
14562306a36Sopenharmony_ci	0x9204,
14662306a36Sopenharmony_ci	0x929c,
14762306a36Sopenharmony_ci	0x8030,
14862306a36Sopenharmony_ci	0x9150,
14962306a36Sopenharmony_ci	0x9a60,
15062306a36Sopenharmony_ci	0x920c,
15162306a36Sopenharmony_ci	0x9210,
15262306a36Sopenharmony_ci	0x9228,
15362306a36Sopenharmony_ci	0x922c,
15462306a36Sopenharmony_ci	0x9244,
15562306a36Sopenharmony_ci	0x9248,
15662306a36Sopenharmony_ci	0x91e8,
15762306a36Sopenharmony_ci	0x9294,
15862306a36Sopenharmony_ci	0x9208,
15962306a36Sopenharmony_ci	0x9224,
16062306a36Sopenharmony_ci	0x9240,
16162306a36Sopenharmony_ci	0x9220,
16262306a36Sopenharmony_ci	0x923c,
16362306a36Sopenharmony_ci	0x9258,
16462306a36Sopenharmony_ci	0x9744,
16562306a36Sopenharmony_ci	0xa200,
16662306a36Sopenharmony_ci	0xa204,
16762306a36Sopenharmony_ci	0xa208,
16862306a36Sopenharmony_ci	0xa20c,
16962306a36Sopenharmony_ci	0x8d58,
17062306a36Sopenharmony_ci	0x9030,
17162306a36Sopenharmony_ci	0x9034,
17262306a36Sopenharmony_ci	0x9038,
17362306a36Sopenharmony_ci	0x903c,
17462306a36Sopenharmony_ci	0x9040,
17562306a36Sopenharmony_ci	0x9654,
17662306a36Sopenharmony_ci	0x897c,
17762306a36Sopenharmony_ci	0xa210,
17862306a36Sopenharmony_ci	0xa214,
17962306a36Sopenharmony_ci	0x9868,
18062306a36Sopenharmony_ci	0xa02c,
18162306a36Sopenharmony_ci	0x9664,
18262306a36Sopenharmony_ci	0x9698,
18362306a36Sopenharmony_ci	0x949c,
18462306a36Sopenharmony_ci	0x8e10,
18562306a36Sopenharmony_ci	0x8e18,
18662306a36Sopenharmony_ci	0x8c50,
18762306a36Sopenharmony_ci	0x8c58,
18862306a36Sopenharmony_ci	0x8c60,
18962306a36Sopenharmony_ci	0x8c68,
19062306a36Sopenharmony_ci	0x89b4,
19162306a36Sopenharmony_ci	0x9830,
19262306a36Sopenharmony_ci	0x802c,
19362306a36Sopenharmony_ci};
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_ci/* Firmware Names */
19662306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/BARTS_pfp.bin");
19762306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/BARTS_me.bin");
19862306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/BARTS_mc.bin");
19962306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/BARTS_smc.bin");
20062306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/BTC_rlc.bin");
20162306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/TURKS_pfp.bin");
20262306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/TURKS_me.bin");
20362306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/TURKS_mc.bin");
20462306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/TURKS_smc.bin");
20562306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/CAICOS_pfp.bin");
20662306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/CAICOS_me.bin");
20762306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/CAICOS_mc.bin");
20862306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/CAICOS_smc.bin");
20962306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/CAYMAN_pfp.bin");
21062306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/CAYMAN_me.bin");
21162306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/CAYMAN_mc.bin");
21262306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/CAYMAN_rlc.bin");
21362306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/CAYMAN_smc.bin");
21462306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/ARUBA_pfp.bin");
21562306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/ARUBA_me.bin");
21662306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/ARUBA_rlc.bin");
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci
21962306a36Sopenharmony_cistatic const u32 cayman_golden_registers2[] =
22062306a36Sopenharmony_ci{
22162306a36Sopenharmony_ci	0x3e5c, 0xffffffff, 0x00000000,
22262306a36Sopenharmony_ci	0x3e48, 0xffffffff, 0x00000000,
22362306a36Sopenharmony_ci	0x3e4c, 0xffffffff, 0x00000000,
22462306a36Sopenharmony_ci	0x3e64, 0xffffffff, 0x00000000,
22562306a36Sopenharmony_ci	0x3e50, 0xffffffff, 0x00000000,
22662306a36Sopenharmony_ci	0x3e60, 0xffffffff, 0x00000000
22762306a36Sopenharmony_ci};
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_cistatic const u32 cayman_golden_registers[] =
23062306a36Sopenharmony_ci{
23162306a36Sopenharmony_ci	0x5eb4, 0xffffffff, 0x00000002,
23262306a36Sopenharmony_ci	0x5e78, 0x8f311ff1, 0x001000f0,
23362306a36Sopenharmony_ci	0x3f90, 0xffff0000, 0xff000000,
23462306a36Sopenharmony_ci	0x9148, 0xffff0000, 0xff000000,
23562306a36Sopenharmony_ci	0x3f94, 0xffff0000, 0xff000000,
23662306a36Sopenharmony_ci	0x914c, 0xffff0000, 0xff000000,
23762306a36Sopenharmony_ci	0xc78, 0x00000080, 0x00000080,
23862306a36Sopenharmony_ci	0xbd4, 0x70073777, 0x00011003,
23962306a36Sopenharmony_ci	0xd02c, 0xbfffff1f, 0x08421000,
24062306a36Sopenharmony_ci	0xd0b8, 0x73773777, 0x02011003,
24162306a36Sopenharmony_ci	0x5bc0, 0x00200000, 0x50100000,
24262306a36Sopenharmony_ci	0x98f8, 0x33773777, 0x02011003,
24362306a36Sopenharmony_ci	0x98fc, 0xffffffff, 0x76541032,
24462306a36Sopenharmony_ci	0x7030, 0x31000311, 0x00000011,
24562306a36Sopenharmony_ci	0x2f48, 0x33773777, 0x42010001,
24662306a36Sopenharmony_ci	0x6b28, 0x00000010, 0x00000012,
24762306a36Sopenharmony_ci	0x7728, 0x00000010, 0x00000012,
24862306a36Sopenharmony_ci	0x10328, 0x00000010, 0x00000012,
24962306a36Sopenharmony_ci	0x10f28, 0x00000010, 0x00000012,
25062306a36Sopenharmony_ci	0x11b28, 0x00000010, 0x00000012,
25162306a36Sopenharmony_ci	0x12728, 0x00000010, 0x00000012,
25262306a36Sopenharmony_ci	0x240c, 0x000007ff, 0x00000000,
25362306a36Sopenharmony_ci	0x8a14, 0xf000001f, 0x00000007,
25462306a36Sopenharmony_ci	0x8b24, 0x3fff3fff, 0x00ff0fff,
25562306a36Sopenharmony_ci	0x8b10, 0x0000ff0f, 0x00000000,
25662306a36Sopenharmony_ci	0x28a4c, 0x07ffffff, 0x06000000,
25762306a36Sopenharmony_ci	0x10c, 0x00000001, 0x00010003,
25862306a36Sopenharmony_ci	0xa02c, 0xffffffff, 0x0000009b,
25962306a36Sopenharmony_ci	0x913c, 0x0000010f, 0x01000100,
26062306a36Sopenharmony_ci	0x8c04, 0xf8ff00ff, 0x40600060,
26162306a36Sopenharmony_ci	0x28350, 0x00000f01, 0x00000000,
26262306a36Sopenharmony_ci	0x9508, 0x3700001f, 0x00000002,
26362306a36Sopenharmony_ci	0x960c, 0xffffffff, 0x54763210,
26462306a36Sopenharmony_ci	0x88c4, 0x001f3ae3, 0x00000082,
26562306a36Sopenharmony_ci	0x88d0, 0xffffffff, 0x0f40df40,
26662306a36Sopenharmony_ci	0x88d4, 0x0000001f, 0x00000010,
26762306a36Sopenharmony_ci	0x8974, 0xffffffff, 0x00000000
26862306a36Sopenharmony_ci};
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_cistatic const u32 dvst_golden_registers2[] =
27162306a36Sopenharmony_ci{
27262306a36Sopenharmony_ci	0x8f8, 0xffffffff, 0,
27362306a36Sopenharmony_ci	0x8fc, 0x00380000, 0,
27462306a36Sopenharmony_ci	0x8f8, 0xffffffff, 1,
27562306a36Sopenharmony_ci	0x8fc, 0x0e000000, 0
27662306a36Sopenharmony_ci};
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_cistatic const u32 dvst_golden_registers[] =
27962306a36Sopenharmony_ci{
28062306a36Sopenharmony_ci	0x690, 0x3fff3fff, 0x20c00033,
28162306a36Sopenharmony_ci	0x918c, 0x0fff0fff, 0x00010006,
28262306a36Sopenharmony_ci	0x91a8, 0x0fff0fff, 0x00010006,
28362306a36Sopenharmony_ci	0x9150, 0xffffdfff, 0x6e944040,
28462306a36Sopenharmony_ci	0x917c, 0x0fff0fff, 0x00030002,
28562306a36Sopenharmony_ci	0x9198, 0x0fff0fff, 0x00030002,
28662306a36Sopenharmony_ci	0x915c, 0x0fff0fff, 0x00010000,
28762306a36Sopenharmony_ci	0x3f90, 0xffff0001, 0xff000000,
28862306a36Sopenharmony_ci	0x9178, 0x0fff0fff, 0x00070000,
28962306a36Sopenharmony_ci	0x9194, 0x0fff0fff, 0x00070000,
29062306a36Sopenharmony_ci	0x9148, 0xffff0001, 0xff000000,
29162306a36Sopenharmony_ci	0x9190, 0x0fff0fff, 0x00090008,
29262306a36Sopenharmony_ci	0x91ac, 0x0fff0fff, 0x00090008,
29362306a36Sopenharmony_ci	0x3f94, 0xffff0000, 0xff000000,
29462306a36Sopenharmony_ci	0x914c, 0xffff0000, 0xff000000,
29562306a36Sopenharmony_ci	0x929c, 0x00000fff, 0x00000001,
29662306a36Sopenharmony_ci	0x55e4, 0xff607fff, 0xfc000100,
29762306a36Sopenharmony_ci	0x8a18, 0xff000fff, 0x00000100,
29862306a36Sopenharmony_ci	0x8b28, 0xff000fff, 0x00000100,
29962306a36Sopenharmony_ci	0x9144, 0xfffc0fff, 0x00000100,
30062306a36Sopenharmony_ci	0x6ed8, 0x00010101, 0x00010000,
30162306a36Sopenharmony_ci	0x9830, 0xffffffff, 0x00000000,
30262306a36Sopenharmony_ci	0x9834, 0xf00fffff, 0x00000400,
30362306a36Sopenharmony_ci	0x9838, 0xfffffffe, 0x00000000,
30462306a36Sopenharmony_ci	0xd0c0, 0xff000fff, 0x00000100,
30562306a36Sopenharmony_ci	0xd02c, 0xbfffff1f, 0x08421000,
30662306a36Sopenharmony_ci	0xd0b8, 0x73773777, 0x12010001,
30762306a36Sopenharmony_ci	0x5bb0, 0x000000f0, 0x00000070,
30862306a36Sopenharmony_ci	0x98f8, 0x73773777, 0x12010001,
30962306a36Sopenharmony_ci	0x98fc, 0xffffffff, 0x00000010,
31062306a36Sopenharmony_ci	0x9b7c, 0x00ff0000, 0x00fc0000,
31162306a36Sopenharmony_ci	0x8030, 0x00001f0f, 0x0000100a,
31262306a36Sopenharmony_ci	0x2f48, 0x73773777, 0x12010001,
31362306a36Sopenharmony_ci	0x2408, 0x00030000, 0x000c007f,
31462306a36Sopenharmony_ci	0x8a14, 0xf000003f, 0x00000007,
31562306a36Sopenharmony_ci	0x8b24, 0x3fff3fff, 0x00ff0fff,
31662306a36Sopenharmony_ci	0x8b10, 0x0000ff0f, 0x00000000,
31762306a36Sopenharmony_ci	0x28a4c, 0x07ffffff, 0x06000000,
31862306a36Sopenharmony_ci	0x4d8, 0x00000fff, 0x00000100,
31962306a36Sopenharmony_ci	0xa008, 0xffffffff, 0x00010000,
32062306a36Sopenharmony_ci	0x913c, 0xffff03ff, 0x01000100,
32162306a36Sopenharmony_ci	0x8c00, 0x000000ff, 0x00000003,
32262306a36Sopenharmony_ci	0x8c04, 0xf8ff00ff, 0x40600060,
32362306a36Sopenharmony_ci	0x8cf0, 0x1fff1fff, 0x08e00410,
32462306a36Sopenharmony_ci	0x28350, 0x00000f01, 0x00000000,
32562306a36Sopenharmony_ci	0x9508, 0xf700071f, 0x00000002,
32662306a36Sopenharmony_ci	0x960c, 0xffffffff, 0x54763210,
32762306a36Sopenharmony_ci	0x20ef8, 0x01ff01ff, 0x00000002,
32862306a36Sopenharmony_ci	0x20e98, 0xfffffbff, 0x00200000,
32962306a36Sopenharmony_ci	0x2015c, 0xffffffff, 0x00000f40,
33062306a36Sopenharmony_ci	0x88c4, 0x001f3ae3, 0x00000082,
33162306a36Sopenharmony_ci	0x8978, 0x3fffffff, 0x04050140,
33262306a36Sopenharmony_ci	0x88d4, 0x0000001f, 0x00000010,
33362306a36Sopenharmony_ci	0x8974, 0xffffffff, 0x00000000
33462306a36Sopenharmony_ci};
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_cistatic const u32 scrapper_golden_registers[] =
33762306a36Sopenharmony_ci{
33862306a36Sopenharmony_ci	0x690, 0x3fff3fff, 0x20c00033,
33962306a36Sopenharmony_ci	0x918c, 0x0fff0fff, 0x00010006,
34062306a36Sopenharmony_ci	0x918c, 0x0fff0fff, 0x00010006,
34162306a36Sopenharmony_ci	0x91a8, 0x0fff0fff, 0x00010006,
34262306a36Sopenharmony_ci	0x91a8, 0x0fff0fff, 0x00010006,
34362306a36Sopenharmony_ci	0x9150, 0xffffdfff, 0x6e944040,
34462306a36Sopenharmony_ci	0x9150, 0xffffdfff, 0x6e944040,
34562306a36Sopenharmony_ci	0x917c, 0x0fff0fff, 0x00030002,
34662306a36Sopenharmony_ci	0x917c, 0x0fff0fff, 0x00030002,
34762306a36Sopenharmony_ci	0x9198, 0x0fff0fff, 0x00030002,
34862306a36Sopenharmony_ci	0x9198, 0x0fff0fff, 0x00030002,
34962306a36Sopenharmony_ci	0x915c, 0x0fff0fff, 0x00010000,
35062306a36Sopenharmony_ci	0x915c, 0x0fff0fff, 0x00010000,
35162306a36Sopenharmony_ci	0x3f90, 0xffff0001, 0xff000000,
35262306a36Sopenharmony_ci	0x3f90, 0xffff0001, 0xff000000,
35362306a36Sopenharmony_ci	0x9178, 0x0fff0fff, 0x00070000,
35462306a36Sopenharmony_ci	0x9178, 0x0fff0fff, 0x00070000,
35562306a36Sopenharmony_ci	0x9194, 0x0fff0fff, 0x00070000,
35662306a36Sopenharmony_ci	0x9194, 0x0fff0fff, 0x00070000,
35762306a36Sopenharmony_ci	0x9148, 0xffff0001, 0xff000000,
35862306a36Sopenharmony_ci	0x9148, 0xffff0001, 0xff000000,
35962306a36Sopenharmony_ci	0x9190, 0x0fff0fff, 0x00090008,
36062306a36Sopenharmony_ci	0x9190, 0x0fff0fff, 0x00090008,
36162306a36Sopenharmony_ci	0x91ac, 0x0fff0fff, 0x00090008,
36262306a36Sopenharmony_ci	0x91ac, 0x0fff0fff, 0x00090008,
36362306a36Sopenharmony_ci	0x3f94, 0xffff0000, 0xff000000,
36462306a36Sopenharmony_ci	0x3f94, 0xffff0000, 0xff000000,
36562306a36Sopenharmony_ci	0x914c, 0xffff0000, 0xff000000,
36662306a36Sopenharmony_ci	0x914c, 0xffff0000, 0xff000000,
36762306a36Sopenharmony_ci	0x929c, 0x00000fff, 0x00000001,
36862306a36Sopenharmony_ci	0x929c, 0x00000fff, 0x00000001,
36962306a36Sopenharmony_ci	0x55e4, 0xff607fff, 0xfc000100,
37062306a36Sopenharmony_ci	0x8a18, 0xff000fff, 0x00000100,
37162306a36Sopenharmony_ci	0x8a18, 0xff000fff, 0x00000100,
37262306a36Sopenharmony_ci	0x8b28, 0xff000fff, 0x00000100,
37362306a36Sopenharmony_ci	0x8b28, 0xff000fff, 0x00000100,
37462306a36Sopenharmony_ci	0x9144, 0xfffc0fff, 0x00000100,
37562306a36Sopenharmony_ci	0x9144, 0xfffc0fff, 0x00000100,
37662306a36Sopenharmony_ci	0x6ed8, 0x00010101, 0x00010000,
37762306a36Sopenharmony_ci	0x9830, 0xffffffff, 0x00000000,
37862306a36Sopenharmony_ci	0x9830, 0xffffffff, 0x00000000,
37962306a36Sopenharmony_ci	0x9834, 0xf00fffff, 0x00000400,
38062306a36Sopenharmony_ci	0x9834, 0xf00fffff, 0x00000400,
38162306a36Sopenharmony_ci	0x9838, 0xfffffffe, 0x00000000,
38262306a36Sopenharmony_ci	0x9838, 0xfffffffe, 0x00000000,
38362306a36Sopenharmony_ci	0xd0c0, 0xff000fff, 0x00000100,
38462306a36Sopenharmony_ci	0xd02c, 0xbfffff1f, 0x08421000,
38562306a36Sopenharmony_ci	0xd02c, 0xbfffff1f, 0x08421000,
38662306a36Sopenharmony_ci	0xd0b8, 0x73773777, 0x12010001,
38762306a36Sopenharmony_ci	0xd0b8, 0x73773777, 0x12010001,
38862306a36Sopenharmony_ci	0x5bb0, 0x000000f0, 0x00000070,
38962306a36Sopenharmony_ci	0x98f8, 0x73773777, 0x12010001,
39062306a36Sopenharmony_ci	0x98f8, 0x73773777, 0x12010001,
39162306a36Sopenharmony_ci	0x98fc, 0xffffffff, 0x00000010,
39262306a36Sopenharmony_ci	0x98fc, 0xffffffff, 0x00000010,
39362306a36Sopenharmony_ci	0x9b7c, 0x00ff0000, 0x00fc0000,
39462306a36Sopenharmony_ci	0x9b7c, 0x00ff0000, 0x00fc0000,
39562306a36Sopenharmony_ci	0x8030, 0x00001f0f, 0x0000100a,
39662306a36Sopenharmony_ci	0x8030, 0x00001f0f, 0x0000100a,
39762306a36Sopenharmony_ci	0x2f48, 0x73773777, 0x12010001,
39862306a36Sopenharmony_ci	0x2f48, 0x73773777, 0x12010001,
39962306a36Sopenharmony_ci	0x2408, 0x00030000, 0x000c007f,
40062306a36Sopenharmony_ci	0x8a14, 0xf000003f, 0x00000007,
40162306a36Sopenharmony_ci	0x8a14, 0xf000003f, 0x00000007,
40262306a36Sopenharmony_ci	0x8b24, 0x3fff3fff, 0x00ff0fff,
40362306a36Sopenharmony_ci	0x8b24, 0x3fff3fff, 0x00ff0fff,
40462306a36Sopenharmony_ci	0x8b10, 0x0000ff0f, 0x00000000,
40562306a36Sopenharmony_ci	0x8b10, 0x0000ff0f, 0x00000000,
40662306a36Sopenharmony_ci	0x28a4c, 0x07ffffff, 0x06000000,
40762306a36Sopenharmony_ci	0x28a4c, 0x07ffffff, 0x06000000,
40862306a36Sopenharmony_ci	0x4d8, 0x00000fff, 0x00000100,
40962306a36Sopenharmony_ci	0x4d8, 0x00000fff, 0x00000100,
41062306a36Sopenharmony_ci	0xa008, 0xffffffff, 0x00010000,
41162306a36Sopenharmony_ci	0xa008, 0xffffffff, 0x00010000,
41262306a36Sopenharmony_ci	0x913c, 0xffff03ff, 0x01000100,
41362306a36Sopenharmony_ci	0x913c, 0xffff03ff, 0x01000100,
41462306a36Sopenharmony_ci	0x90e8, 0x001fffff, 0x010400c0,
41562306a36Sopenharmony_ci	0x8c00, 0x000000ff, 0x00000003,
41662306a36Sopenharmony_ci	0x8c00, 0x000000ff, 0x00000003,
41762306a36Sopenharmony_ci	0x8c04, 0xf8ff00ff, 0x40600060,
41862306a36Sopenharmony_ci	0x8c04, 0xf8ff00ff, 0x40600060,
41962306a36Sopenharmony_ci	0x8c30, 0x0000000f, 0x00040005,
42062306a36Sopenharmony_ci	0x8cf0, 0x1fff1fff, 0x08e00410,
42162306a36Sopenharmony_ci	0x8cf0, 0x1fff1fff, 0x08e00410,
42262306a36Sopenharmony_ci	0x900c, 0x00ffffff, 0x0017071f,
42362306a36Sopenharmony_ci	0x28350, 0x00000f01, 0x00000000,
42462306a36Sopenharmony_ci	0x28350, 0x00000f01, 0x00000000,
42562306a36Sopenharmony_ci	0x9508, 0xf700071f, 0x00000002,
42662306a36Sopenharmony_ci	0x9508, 0xf700071f, 0x00000002,
42762306a36Sopenharmony_ci	0x9688, 0x00300000, 0x0017000f,
42862306a36Sopenharmony_ci	0x960c, 0xffffffff, 0x54763210,
42962306a36Sopenharmony_ci	0x960c, 0xffffffff, 0x54763210,
43062306a36Sopenharmony_ci	0x20ef8, 0x01ff01ff, 0x00000002,
43162306a36Sopenharmony_ci	0x20e98, 0xfffffbff, 0x00200000,
43262306a36Sopenharmony_ci	0x2015c, 0xffffffff, 0x00000f40,
43362306a36Sopenharmony_ci	0x88c4, 0x001f3ae3, 0x00000082,
43462306a36Sopenharmony_ci	0x88c4, 0x001f3ae3, 0x00000082,
43562306a36Sopenharmony_ci	0x8978, 0x3fffffff, 0x04050140,
43662306a36Sopenharmony_ci	0x8978, 0x3fffffff, 0x04050140,
43762306a36Sopenharmony_ci	0x88d4, 0x0000001f, 0x00000010,
43862306a36Sopenharmony_ci	0x88d4, 0x0000001f, 0x00000010,
43962306a36Sopenharmony_ci	0x8974, 0xffffffff, 0x00000000,
44062306a36Sopenharmony_ci	0x8974, 0xffffffff, 0x00000000
44162306a36Sopenharmony_ci};
44262306a36Sopenharmony_ci
44362306a36Sopenharmony_cistatic void ni_init_golden_registers(struct radeon_device *rdev)
44462306a36Sopenharmony_ci{
44562306a36Sopenharmony_ci	switch (rdev->family) {
44662306a36Sopenharmony_ci	case CHIP_CAYMAN:
44762306a36Sopenharmony_ci		radeon_program_register_sequence(rdev,
44862306a36Sopenharmony_ci						 cayman_golden_registers,
44962306a36Sopenharmony_ci						 (const u32)ARRAY_SIZE(cayman_golden_registers));
45062306a36Sopenharmony_ci		radeon_program_register_sequence(rdev,
45162306a36Sopenharmony_ci						 cayman_golden_registers2,
45262306a36Sopenharmony_ci						 (const u32)ARRAY_SIZE(cayman_golden_registers2));
45362306a36Sopenharmony_ci		break;
45462306a36Sopenharmony_ci	case CHIP_ARUBA:
45562306a36Sopenharmony_ci		if ((rdev->pdev->device == 0x9900) ||
45662306a36Sopenharmony_ci		    (rdev->pdev->device == 0x9901) ||
45762306a36Sopenharmony_ci		    (rdev->pdev->device == 0x9903) ||
45862306a36Sopenharmony_ci		    (rdev->pdev->device == 0x9904) ||
45962306a36Sopenharmony_ci		    (rdev->pdev->device == 0x9905) ||
46062306a36Sopenharmony_ci		    (rdev->pdev->device == 0x9906) ||
46162306a36Sopenharmony_ci		    (rdev->pdev->device == 0x9907) ||
46262306a36Sopenharmony_ci		    (rdev->pdev->device == 0x9908) ||
46362306a36Sopenharmony_ci		    (rdev->pdev->device == 0x9909) ||
46462306a36Sopenharmony_ci		    (rdev->pdev->device == 0x990A) ||
46562306a36Sopenharmony_ci		    (rdev->pdev->device == 0x990B) ||
46662306a36Sopenharmony_ci		    (rdev->pdev->device == 0x990C) ||
46762306a36Sopenharmony_ci		    (rdev->pdev->device == 0x990D) ||
46862306a36Sopenharmony_ci		    (rdev->pdev->device == 0x990E) ||
46962306a36Sopenharmony_ci		    (rdev->pdev->device == 0x990F) ||
47062306a36Sopenharmony_ci		    (rdev->pdev->device == 0x9910) ||
47162306a36Sopenharmony_ci		    (rdev->pdev->device == 0x9913) ||
47262306a36Sopenharmony_ci		    (rdev->pdev->device == 0x9917) ||
47362306a36Sopenharmony_ci		    (rdev->pdev->device == 0x9918)) {
47462306a36Sopenharmony_ci			radeon_program_register_sequence(rdev,
47562306a36Sopenharmony_ci							 dvst_golden_registers,
47662306a36Sopenharmony_ci							 (const u32)ARRAY_SIZE(dvst_golden_registers));
47762306a36Sopenharmony_ci			radeon_program_register_sequence(rdev,
47862306a36Sopenharmony_ci							 dvst_golden_registers2,
47962306a36Sopenharmony_ci							 (const u32)ARRAY_SIZE(dvst_golden_registers2));
48062306a36Sopenharmony_ci		} else {
48162306a36Sopenharmony_ci			radeon_program_register_sequence(rdev,
48262306a36Sopenharmony_ci							 scrapper_golden_registers,
48362306a36Sopenharmony_ci							 (const u32)ARRAY_SIZE(scrapper_golden_registers));
48462306a36Sopenharmony_ci			radeon_program_register_sequence(rdev,
48562306a36Sopenharmony_ci							 dvst_golden_registers2,
48662306a36Sopenharmony_ci							 (const u32)ARRAY_SIZE(dvst_golden_registers2));
48762306a36Sopenharmony_ci		}
48862306a36Sopenharmony_ci		break;
48962306a36Sopenharmony_ci	default:
49062306a36Sopenharmony_ci		break;
49162306a36Sopenharmony_ci	}
49262306a36Sopenharmony_ci}
49362306a36Sopenharmony_ci
49462306a36Sopenharmony_ci#define BTC_IO_MC_REGS_SIZE 29
49562306a36Sopenharmony_ci
49662306a36Sopenharmony_cistatic const u32 barts_io_mc_regs[BTC_IO_MC_REGS_SIZE][2] = {
49762306a36Sopenharmony_ci	{0x00000077, 0xff010100},
49862306a36Sopenharmony_ci	{0x00000078, 0x00000000},
49962306a36Sopenharmony_ci	{0x00000079, 0x00001434},
50062306a36Sopenharmony_ci	{0x0000007a, 0xcc08ec08},
50162306a36Sopenharmony_ci	{0x0000007b, 0x00040000},
50262306a36Sopenharmony_ci	{0x0000007c, 0x000080c0},
50362306a36Sopenharmony_ci	{0x0000007d, 0x09000000},
50462306a36Sopenharmony_ci	{0x0000007e, 0x00210404},
50562306a36Sopenharmony_ci	{0x00000081, 0x08a8e800},
50662306a36Sopenharmony_ci	{0x00000082, 0x00030444},
50762306a36Sopenharmony_ci	{0x00000083, 0x00000000},
50862306a36Sopenharmony_ci	{0x00000085, 0x00000001},
50962306a36Sopenharmony_ci	{0x00000086, 0x00000002},
51062306a36Sopenharmony_ci	{0x00000087, 0x48490000},
51162306a36Sopenharmony_ci	{0x00000088, 0x20244647},
51262306a36Sopenharmony_ci	{0x00000089, 0x00000005},
51362306a36Sopenharmony_ci	{0x0000008b, 0x66030000},
51462306a36Sopenharmony_ci	{0x0000008c, 0x00006603},
51562306a36Sopenharmony_ci	{0x0000008d, 0x00000100},
51662306a36Sopenharmony_ci	{0x0000008f, 0x00001c0a},
51762306a36Sopenharmony_ci	{0x00000090, 0xff000001},
51862306a36Sopenharmony_ci	{0x00000094, 0x00101101},
51962306a36Sopenharmony_ci	{0x00000095, 0x00000fff},
52062306a36Sopenharmony_ci	{0x00000096, 0x00116fff},
52162306a36Sopenharmony_ci	{0x00000097, 0x60010000},
52262306a36Sopenharmony_ci	{0x00000098, 0x10010000},
52362306a36Sopenharmony_ci	{0x00000099, 0x00006000},
52462306a36Sopenharmony_ci	{0x0000009a, 0x00001000},
52562306a36Sopenharmony_ci	{0x0000009f, 0x00946a00}
52662306a36Sopenharmony_ci};
52762306a36Sopenharmony_ci
52862306a36Sopenharmony_cistatic const u32 turks_io_mc_regs[BTC_IO_MC_REGS_SIZE][2] = {
52962306a36Sopenharmony_ci	{0x00000077, 0xff010100},
53062306a36Sopenharmony_ci	{0x00000078, 0x00000000},
53162306a36Sopenharmony_ci	{0x00000079, 0x00001434},
53262306a36Sopenharmony_ci	{0x0000007a, 0xcc08ec08},
53362306a36Sopenharmony_ci	{0x0000007b, 0x00040000},
53462306a36Sopenharmony_ci	{0x0000007c, 0x000080c0},
53562306a36Sopenharmony_ci	{0x0000007d, 0x09000000},
53662306a36Sopenharmony_ci	{0x0000007e, 0x00210404},
53762306a36Sopenharmony_ci	{0x00000081, 0x08a8e800},
53862306a36Sopenharmony_ci	{0x00000082, 0x00030444},
53962306a36Sopenharmony_ci	{0x00000083, 0x00000000},
54062306a36Sopenharmony_ci	{0x00000085, 0x00000001},
54162306a36Sopenharmony_ci	{0x00000086, 0x00000002},
54262306a36Sopenharmony_ci	{0x00000087, 0x48490000},
54362306a36Sopenharmony_ci	{0x00000088, 0x20244647},
54462306a36Sopenharmony_ci	{0x00000089, 0x00000005},
54562306a36Sopenharmony_ci	{0x0000008b, 0x66030000},
54662306a36Sopenharmony_ci	{0x0000008c, 0x00006603},
54762306a36Sopenharmony_ci	{0x0000008d, 0x00000100},
54862306a36Sopenharmony_ci	{0x0000008f, 0x00001c0a},
54962306a36Sopenharmony_ci	{0x00000090, 0xff000001},
55062306a36Sopenharmony_ci	{0x00000094, 0x00101101},
55162306a36Sopenharmony_ci	{0x00000095, 0x00000fff},
55262306a36Sopenharmony_ci	{0x00000096, 0x00116fff},
55362306a36Sopenharmony_ci	{0x00000097, 0x60010000},
55462306a36Sopenharmony_ci	{0x00000098, 0x10010000},
55562306a36Sopenharmony_ci	{0x00000099, 0x00006000},
55662306a36Sopenharmony_ci	{0x0000009a, 0x00001000},
55762306a36Sopenharmony_ci	{0x0000009f, 0x00936a00}
55862306a36Sopenharmony_ci};
55962306a36Sopenharmony_ci
56062306a36Sopenharmony_cistatic const u32 caicos_io_mc_regs[BTC_IO_MC_REGS_SIZE][2] = {
56162306a36Sopenharmony_ci	{0x00000077, 0xff010100},
56262306a36Sopenharmony_ci	{0x00000078, 0x00000000},
56362306a36Sopenharmony_ci	{0x00000079, 0x00001434},
56462306a36Sopenharmony_ci	{0x0000007a, 0xcc08ec08},
56562306a36Sopenharmony_ci	{0x0000007b, 0x00040000},
56662306a36Sopenharmony_ci	{0x0000007c, 0x000080c0},
56762306a36Sopenharmony_ci	{0x0000007d, 0x09000000},
56862306a36Sopenharmony_ci	{0x0000007e, 0x00210404},
56962306a36Sopenharmony_ci	{0x00000081, 0x08a8e800},
57062306a36Sopenharmony_ci	{0x00000082, 0x00030444},
57162306a36Sopenharmony_ci	{0x00000083, 0x00000000},
57262306a36Sopenharmony_ci	{0x00000085, 0x00000001},
57362306a36Sopenharmony_ci	{0x00000086, 0x00000002},
57462306a36Sopenharmony_ci	{0x00000087, 0x48490000},
57562306a36Sopenharmony_ci	{0x00000088, 0x20244647},
57662306a36Sopenharmony_ci	{0x00000089, 0x00000005},
57762306a36Sopenharmony_ci	{0x0000008b, 0x66030000},
57862306a36Sopenharmony_ci	{0x0000008c, 0x00006603},
57962306a36Sopenharmony_ci	{0x0000008d, 0x00000100},
58062306a36Sopenharmony_ci	{0x0000008f, 0x00001c0a},
58162306a36Sopenharmony_ci	{0x00000090, 0xff000001},
58262306a36Sopenharmony_ci	{0x00000094, 0x00101101},
58362306a36Sopenharmony_ci	{0x00000095, 0x00000fff},
58462306a36Sopenharmony_ci	{0x00000096, 0x00116fff},
58562306a36Sopenharmony_ci	{0x00000097, 0x60010000},
58662306a36Sopenharmony_ci	{0x00000098, 0x10010000},
58762306a36Sopenharmony_ci	{0x00000099, 0x00006000},
58862306a36Sopenharmony_ci	{0x0000009a, 0x00001000},
58962306a36Sopenharmony_ci	{0x0000009f, 0x00916a00}
59062306a36Sopenharmony_ci};
59162306a36Sopenharmony_ci
59262306a36Sopenharmony_cistatic const u32 cayman_io_mc_regs[BTC_IO_MC_REGS_SIZE][2] = {
59362306a36Sopenharmony_ci	{0x00000077, 0xff010100},
59462306a36Sopenharmony_ci	{0x00000078, 0x00000000},
59562306a36Sopenharmony_ci	{0x00000079, 0x00001434},
59662306a36Sopenharmony_ci	{0x0000007a, 0xcc08ec08},
59762306a36Sopenharmony_ci	{0x0000007b, 0x00040000},
59862306a36Sopenharmony_ci	{0x0000007c, 0x000080c0},
59962306a36Sopenharmony_ci	{0x0000007d, 0x09000000},
60062306a36Sopenharmony_ci	{0x0000007e, 0x00210404},
60162306a36Sopenharmony_ci	{0x00000081, 0x08a8e800},
60262306a36Sopenharmony_ci	{0x00000082, 0x00030444},
60362306a36Sopenharmony_ci	{0x00000083, 0x00000000},
60462306a36Sopenharmony_ci	{0x00000085, 0x00000001},
60562306a36Sopenharmony_ci	{0x00000086, 0x00000002},
60662306a36Sopenharmony_ci	{0x00000087, 0x48490000},
60762306a36Sopenharmony_ci	{0x00000088, 0x20244647},
60862306a36Sopenharmony_ci	{0x00000089, 0x00000005},
60962306a36Sopenharmony_ci	{0x0000008b, 0x66030000},
61062306a36Sopenharmony_ci	{0x0000008c, 0x00006603},
61162306a36Sopenharmony_ci	{0x0000008d, 0x00000100},
61262306a36Sopenharmony_ci	{0x0000008f, 0x00001c0a},
61362306a36Sopenharmony_ci	{0x00000090, 0xff000001},
61462306a36Sopenharmony_ci	{0x00000094, 0x00101101},
61562306a36Sopenharmony_ci	{0x00000095, 0x00000fff},
61662306a36Sopenharmony_ci	{0x00000096, 0x00116fff},
61762306a36Sopenharmony_ci	{0x00000097, 0x60010000},
61862306a36Sopenharmony_ci	{0x00000098, 0x10010000},
61962306a36Sopenharmony_ci	{0x00000099, 0x00006000},
62062306a36Sopenharmony_ci	{0x0000009a, 0x00001000},
62162306a36Sopenharmony_ci	{0x0000009f, 0x00976b00}
62262306a36Sopenharmony_ci};
62362306a36Sopenharmony_ci
62462306a36Sopenharmony_ciint ni_mc_load_microcode(struct radeon_device *rdev)
62562306a36Sopenharmony_ci{
62662306a36Sopenharmony_ci	const __be32 *fw_data;
62762306a36Sopenharmony_ci	u32 mem_type, running, blackout = 0;
62862306a36Sopenharmony_ci	u32 *io_mc_regs;
62962306a36Sopenharmony_ci	int i, ucode_size, regs_size;
63062306a36Sopenharmony_ci
63162306a36Sopenharmony_ci	if (!rdev->mc_fw)
63262306a36Sopenharmony_ci		return -EINVAL;
63362306a36Sopenharmony_ci
63462306a36Sopenharmony_ci	switch (rdev->family) {
63562306a36Sopenharmony_ci	case CHIP_BARTS:
63662306a36Sopenharmony_ci		io_mc_regs = (u32 *)&barts_io_mc_regs;
63762306a36Sopenharmony_ci		ucode_size = BTC_MC_UCODE_SIZE;
63862306a36Sopenharmony_ci		regs_size = BTC_IO_MC_REGS_SIZE;
63962306a36Sopenharmony_ci		break;
64062306a36Sopenharmony_ci	case CHIP_TURKS:
64162306a36Sopenharmony_ci		io_mc_regs = (u32 *)&turks_io_mc_regs;
64262306a36Sopenharmony_ci		ucode_size = BTC_MC_UCODE_SIZE;
64362306a36Sopenharmony_ci		regs_size = BTC_IO_MC_REGS_SIZE;
64462306a36Sopenharmony_ci		break;
64562306a36Sopenharmony_ci	case CHIP_CAICOS:
64662306a36Sopenharmony_ci	default:
64762306a36Sopenharmony_ci		io_mc_regs = (u32 *)&caicos_io_mc_regs;
64862306a36Sopenharmony_ci		ucode_size = BTC_MC_UCODE_SIZE;
64962306a36Sopenharmony_ci		regs_size = BTC_IO_MC_REGS_SIZE;
65062306a36Sopenharmony_ci		break;
65162306a36Sopenharmony_ci	case CHIP_CAYMAN:
65262306a36Sopenharmony_ci		io_mc_regs = (u32 *)&cayman_io_mc_regs;
65362306a36Sopenharmony_ci		ucode_size = CAYMAN_MC_UCODE_SIZE;
65462306a36Sopenharmony_ci		regs_size = BTC_IO_MC_REGS_SIZE;
65562306a36Sopenharmony_ci		break;
65662306a36Sopenharmony_ci	}
65762306a36Sopenharmony_ci
65862306a36Sopenharmony_ci	mem_type = (RREG32(MC_SEQ_MISC0) & MC_SEQ_MISC0_GDDR5_MASK) >> MC_SEQ_MISC0_GDDR5_SHIFT;
65962306a36Sopenharmony_ci	running = RREG32(MC_SEQ_SUP_CNTL) & RUN_MASK;
66062306a36Sopenharmony_ci
66162306a36Sopenharmony_ci	if ((mem_type == MC_SEQ_MISC0_GDDR5_VALUE) && (running == 0)) {
66262306a36Sopenharmony_ci		if (running) {
66362306a36Sopenharmony_ci			blackout = RREG32(MC_SHARED_BLACKOUT_CNTL);
66462306a36Sopenharmony_ci			WREG32(MC_SHARED_BLACKOUT_CNTL, 1);
66562306a36Sopenharmony_ci		}
66662306a36Sopenharmony_ci
66762306a36Sopenharmony_ci		/* reset the engine and set to writable */
66862306a36Sopenharmony_ci		WREG32(MC_SEQ_SUP_CNTL, 0x00000008);
66962306a36Sopenharmony_ci		WREG32(MC_SEQ_SUP_CNTL, 0x00000010);
67062306a36Sopenharmony_ci
67162306a36Sopenharmony_ci		/* load mc io regs */
67262306a36Sopenharmony_ci		for (i = 0; i < regs_size; i++) {
67362306a36Sopenharmony_ci			WREG32(MC_SEQ_IO_DEBUG_INDEX, io_mc_regs[(i << 1)]);
67462306a36Sopenharmony_ci			WREG32(MC_SEQ_IO_DEBUG_DATA, io_mc_regs[(i << 1) + 1]);
67562306a36Sopenharmony_ci		}
67662306a36Sopenharmony_ci		/* load the MC ucode */
67762306a36Sopenharmony_ci		fw_data = (const __be32 *)rdev->mc_fw->data;
67862306a36Sopenharmony_ci		for (i = 0; i < ucode_size; i++)
67962306a36Sopenharmony_ci			WREG32(MC_SEQ_SUP_PGM, be32_to_cpup(fw_data++));
68062306a36Sopenharmony_ci
68162306a36Sopenharmony_ci		/* put the engine back into the active state */
68262306a36Sopenharmony_ci		WREG32(MC_SEQ_SUP_CNTL, 0x00000008);
68362306a36Sopenharmony_ci		WREG32(MC_SEQ_SUP_CNTL, 0x00000004);
68462306a36Sopenharmony_ci		WREG32(MC_SEQ_SUP_CNTL, 0x00000001);
68562306a36Sopenharmony_ci
68662306a36Sopenharmony_ci		/* wait for training to complete */
68762306a36Sopenharmony_ci		for (i = 0; i < rdev->usec_timeout; i++) {
68862306a36Sopenharmony_ci			if (RREG32(MC_IO_PAD_CNTL_D0) & MEM_FALL_OUT_CMD)
68962306a36Sopenharmony_ci				break;
69062306a36Sopenharmony_ci			udelay(1);
69162306a36Sopenharmony_ci		}
69262306a36Sopenharmony_ci
69362306a36Sopenharmony_ci		if (running)
69462306a36Sopenharmony_ci			WREG32(MC_SHARED_BLACKOUT_CNTL, blackout);
69562306a36Sopenharmony_ci	}
69662306a36Sopenharmony_ci
69762306a36Sopenharmony_ci	return 0;
69862306a36Sopenharmony_ci}
69962306a36Sopenharmony_ci
70062306a36Sopenharmony_ciint ni_init_microcode(struct radeon_device *rdev)
70162306a36Sopenharmony_ci{
70262306a36Sopenharmony_ci	const char *chip_name;
70362306a36Sopenharmony_ci	const char *rlc_chip_name;
70462306a36Sopenharmony_ci	size_t pfp_req_size, me_req_size, rlc_req_size, mc_req_size;
70562306a36Sopenharmony_ci	size_t smc_req_size = 0;
70662306a36Sopenharmony_ci	char fw_name[30];
70762306a36Sopenharmony_ci	int err;
70862306a36Sopenharmony_ci
70962306a36Sopenharmony_ci	DRM_DEBUG("\n");
71062306a36Sopenharmony_ci
71162306a36Sopenharmony_ci	switch (rdev->family) {
71262306a36Sopenharmony_ci	case CHIP_BARTS:
71362306a36Sopenharmony_ci		chip_name = "BARTS";
71462306a36Sopenharmony_ci		rlc_chip_name = "BTC";
71562306a36Sopenharmony_ci		pfp_req_size = EVERGREEN_PFP_UCODE_SIZE * 4;
71662306a36Sopenharmony_ci		me_req_size = EVERGREEN_PM4_UCODE_SIZE * 4;
71762306a36Sopenharmony_ci		rlc_req_size = EVERGREEN_RLC_UCODE_SIZE * 4;
71862306a36Sopenharmony_ci		mc_req_size = BTC_MC_UCODE_SIZE * 4;
71962306a36Sopenharmony_ci		smc_req_size = ALIGN(BARTS_SMC_UCODE_SIZE, 4);
72062306a36Sopenharmony_ci		break;
72162306a36Sopenharmony_ci	case CHIP_TURKS:
72262306a36Sopenharmony_ci		chip_name = "TURKS";
72362306a36Sopenharmony_ci		rlc_chip_name = "BTC";
72462306a36Sopenharmony_ci		pfp_req_size = EVERGREEN_PFP_UCODE_SIZE * 4;
72562306a36Sopenharmony_ci		me_req_size = EVERGREEN_PM4_UCODE_SIZE * 4;
72662306a36Sopenharmony_ci		rlc_req_size = EVERGREEN_RLC_UCODE_SIZE * 4;
72762306a36Sopenharmony_ci		mc_req_size = BTC_MC_UCODE_SIZE * 4;
72862306a36Sopenharmony_ci		smc_req_size = ALIGN(TURKS_SMC_UCODE_SIZE, 4);
72962306a36Sopenharmony_ci		break;
73062306a36Sopenharmony_ci	case CHIP_CAICOS:
73162306a36Sopenharmony_ci		chip_name = "CAICOS";
73262306a36Sopenharmony_ci		rlc_chip_name = "BTC";
73362306a36Sopenharmony_ci		pfp_req_size = EVERGREEN_PFP_UCODE_SIZE * 4;
73462306a36Sopenharmony_ci		me_req_size = EVERGREEN_PM4_UCODE_SIZE * 4;
73562306a36Sopenharmony_ci		rlc_req_size = EVERGREEN_RLC_UCODE_SIZE * 4;
73662306a36Sopenharmony_ci		mc_req_size = BTC_MC_UCODE_SIZE * 4;
73762306a36Sopenharmony_ci		smc_req_size = ALIGN(CAICOS_SMC_UCODE_SIZE, 4);
73862306a36Sopenharmony_ci		break;
73962306a36Sopenharmony_ci	case CHIP_CAYMAN:
74062306a36Sopenharmony_ci		chip_name = "CAYMAN";
74162306a36Sopenharmony_ci		rlc_chip_name = "CAYMAN";
74262306a36Sopenharmony_ci		pfp_req_size = CAYMAN_PFP_UCODE_SIZE * 4;
74362306a36Sopenharmony_ci		me_req_size = CAYMAN_PM4_UCODE_SIZE * 4;
74462306a36Sopenharmony_ci		rlc_req_size = CAYMAN_RLC_UCODE_SIZE * 4;
74562306a36Sopenharmony_ci		mc_req_size = CAYMAN_MC_UCODE_SIZE * 4;
74662306a36Sopenharmony_ci		smc_req_size = ALIGN(CAYMAN_SMC_UCODE_SIZE, 4);
74762306a36Sopenharmony_ci		break;
74862306a36Sopenharmony_ci	case CHIP_ARUBA:
74962306a36Sopenharmony_ci		chip_name = "ARUBA";
75062306a36Sopenharmony_ci		rlc_chip_name = "ARUBA";
75162306a36Sopenharmony_ci		/* pfp/me same size as CAYMAN */
75262306a36Sopenharmony_ci		pfp_req_size = CAYMAN_PFP_UCODE_SIZE * 4;
75362306a36Sopenharmony_ci		me_req_size = CAYMAN_PM4_UCODE_SIZE * 4;
75462306a36Sopenharmony_ci		rlc_req_size = ARUBA_RLC_UCODE_SIZE * 4;
75562306a36Sopenharmony_ci		mc_req_size = 0;
75662306a36Sopenharmony_ci		break;
75762306a36Sopenharmony_ci	default: BUG();
75862306a36Sopenharmony_ci	}
75962306a36Sopenharmony_ci
76062306a36Sopenharmony_ci	DRM_INFO("Loading %s Microcode\n", chip_name);
76162306a36Sopenharmony_ci
76262306a36Sopenharmony_ci	snprintf(fw_name, sizeof(fw_name), "radeon/%s_pfp.bin", chip_name);
76362306a36Sopenharmony_ci	err = request_firmware(&rdev->pfp_fw, fw_name, rdev->dev);
76462306a36Sopenharmony_ci	if (err)
76562306a36Sopenharmony_ci		goto out;
76662306a36Sopenharmony_ci	if (rdev->pfp_fw->size != pfp_req_size) {
76762306a36Sopenharmony_ci		pr_err("ni_cp: Bogus length %zu in firmware \"%s\"\n",
76862306a36Sopenharmony_ci		       rdev->pfp_fw->size, fw_name);
76962306a36Sopenharmony_ci		err = -EINVAL;
77062306a36Sopenharmony_ci		goto out;
77162306a36Sopenharmony_ci	}
77262306a36Sopenharmony_ci
77362306a36Sopenharmony_ci	snprintf(fw_name, sizeof(fw_name), "radeon/%s_me.bin", chip_name);
77462306a36Sopenharmony_ci	err = request_firmware(&rdev->me_fw, fw_name, rdev->dev);
77562306a36Sopenharmony_ci	if (err)
77662306a36Sopenharmony_ci		goto out;
77762306a36Sopenharmony_ci	if (rdev->me_fw->size != me_req_size) {
77862306a36Sopenharmony_ci		pr_err("ni_cp: Bogus length %zu in firmware \"%s\"\n",
77962306a36Sopenharmony_ci		       rdev->me_fw->size, fw_name);
78062306a36Sopenharmony_ci		err = -EINVAL;
78162306a36Sopenharmony_ci	}
78262306a36Sopenharmony_ci
78362306a36Sopenharmony_ci	snprintf(fw_name, sizeof(fw_name), "radeon/%s_rlc.bin", rlc_chip_name);
78462306a36Sopenharmony_ci	err = request_firmware(&rdev->rlc_fw, fw_name, rdev->dev);
78562306a36Sopenharmony_ci	if (err)
78662306a36Sopenharmony_ci		goto out;
78762306a36Sopenharmony_ci	if (rdev->rlc_fw->size != rlc_req_size) {
78862306a36Sopenharmony_ci		pr_err("ni_rlc: Bogus length %zu in firmware \"%s\"\n",
78962306a36Sopenharmony_ci		       rdev->rlc_fw->size, fw_name);
79062306a36Sopenharmony_ci		err = -EINVAL;
79162306a36Sopenharmony_ci	}
79262306a36Sopenharmony_ci
79362306a36Sopenharmony_ci	/* no MC ucode on TN */
79462306a36Sopenharmony_ci	if (!(rdev->flags & RADEON_IS_IGP)) {
79562306a36Sopenharmony_ci		snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin", chip_name);
79662306a36Sopenharmony_ci		err = request_firmware(&rdev->mc_fw, fw_name, rdev->dev);
79762306a36Sopenharmony_ci		if (err)
79862306a36Sopenharmony_ci			goto out;
79962306a36Sopenharmony_ci		if (rdev->mc_fw->size != mc_req_size) {
80062306a36Sopenharmony_ci			pr_err("ni_mc: Bogus length %zu in firmware \"%s\"\n",
80162306a36Sopenharmony_ci			       rdev->mc_fw->size, fw_name);
80262306a36Sopenharmony_ci			err = -EINVAL;
80362306a36Sopenharmony_ci		}
80462306a36Sopenharmony_ci	}
80562306a36Sopenharmony_ci
80662306a36Sopenharmony_ci	if ((rdev->family >= CHIP_BARTS) && (rdev->family <= CHIP_CAYMAN)) {
80762306a36Sopenharmony_ci		snprintf(fw_name, sizeof(fw_name), "radeon/%s_smc.bin", chip_name);
80862306a36Sopenharmony_ci		err = request_firmware(&rdev->smc_fw, fw_name, rdev->dev);
80962306a36Sopenharmony_ci		if (err) {
81062306a36Sopenharmony_ci			pr_err("smc: error loading firmware \"%s\"\n", fw_name);
81162306a36Sopenharmony_ci			release_firmware(rdev->smc_fw);
81262306a36Sopenharmony_ci			rdev->smc_fw = NULL;
81362306a36Sopenharmony_ci			err = 0;
81462306a36Sopenharmony_ci		} else if (rdev->smc_fw->size != smc_req_size) {
81562306a36Sopenharmony_ci			pr_err("ni_mc: Bogus length %zu in firmware \"%s\"\n",
81662306a36Sopenharmony_ci			       rdev->smc_fw->size, fw_name);
81762306a36Sopenharmony_ci			err = -EINVAL;
81862306a36Sopenharmony_ci		}
81962306a36Sopenharmony_ci	}
82062306a36Sopenharmony_ci
82162306a36Sopenharmony_ciout:
82262306a36Sopenharmony_ci	if (err) {
82362306a36Sopenharmony_ci		if (err != -EINVAL)
82462306a36Sopenharmony_ci			pr_err("ni_cp: Failed to load firmware \"%s\"\n",
82562306a36Sopenharmony_ci			       fw_name);
82662306a36Sopenharmony_ci		release_firmware(rdev->pfp_fw);
82762306a36Sopenharmony_ci		rdev->pfp_fw = NULL;
82862306a36Sopenharmony_ci		release_firmware(rdev->me_fw);
82962306a36Sopenharmony_ci		rdev->me_fw = NULL;
83062306a36Sopenharmony_ci		release_firmware(rdev->rlc_fw);
83162306a36Sopenharmony_ci		rdev->rlc_fw = NULL;
83262306a36Sopenharmony_ci		release_firmware(rdev->mc_fw);
83362306a36Sopenharmony_ci		rdev->mc_fw = NULL;
83462306a36Sopenharmony_ci	}
83562306a36Sopenharmony_ci	return err;
83662306a36Sopenharmony_ci}
83762306a36Sopenharmony_ci
83862306a36Sopenharmony_ci/**
83962306a36Sopenharmony_ci * cayman_get_allowed_info_register - fetch the register for the info ioctl
84062306a36Sopenharmony_ci *
84162306a36Sopenharmony_ci * @rdev: radeon_device pointer
84262306a36Sopenharmony_ci * @reg: register offset in bytes
84362306a36Sopenharmony_ci * @val: register value
84462306a36Sopenharmony_ci *
84562306a36Sopenharmony_ci * Returns 0 for success or -EINVAL for an invalid register
84662306a36Sopenharmony_ci *
84762306a36Sopenharmony_ci */
84862306a36Sopenharmony_ciint cayman_get_allowed_info_register(struct radeon_device *rdev,
84962306a36Sopenharmony_ci				     u32 reg, u32 *val)
85062306a36Sopenharmony_ci{
85162306a36Sopenharmony_ci	switch (reg) {
85262306a36Sopenharmony_ci	case GRBM_STATUS:
85362306a36Sopenharmony_ci	case GRBM_STATUS_SE0:
85462306a36Sopenharmony_ci	case GRBM_STATUS_SE1:
85562306a36Sopenharmony_ci	case SRBM_STATUS:
85662306a36Sopenharmony_ci	case SRBM_STATUS2:
85762306a36Sopenharmony_ci	case (DMA_STATUS_REG + DMA0_REGISTER_OFFSET):
85862306a36Sopenharmony_ci	case (DMA_STATUS_REG + DMA1_REGISTER_OFFSET):
85962306a36Sopenharmony_ci	case UVD_STATUS:
86062306a36Sopenharmony_ci		*val = RREG32(reg);
86162306a36Sopenharmony_ci		return 0;
86262306a36Sopenharmony_ci	default:
86362306a36Sopenharmony_ci		return -EINVAL;
86462306a36Sopenharmony_ci	}
86562306a36Sopenharmony_ci}
86662306a36Sopenharmony_ci
86762306a36Sopenharmony_ciint tn_get_temp(struct radeon_device *rdev)
86862306a36Sopenharmony_ci{
86962306a36Sopenharmony_ci	u32 temp = RREG32_SMC(TN_CURRENT_GNB_TEMP) & 0x7ff;
87062306a36Sopenharmony_ci	int actual_temp = (temp / 8) - 49;
87162306a36Sopenharmony_ci
87262306a36Sopenharmony_ci	return actual_temp * 1000;
87362306a36Sopenharmony_ci}
87462306a36Sopenharmony_ci
87562306a36Sopenharmony_ci/*
87662306a36Sopenharmony_ci * Core functions
87762306a36Sopenharmony_ci */
87862306a36Sopenharmony_cistatic void cayman_gpu_init(struct radeon_device *rdev)
87962306a36Sopenharmony_ci{
88062306a36Sopenharmony_ci	u32 gb_addr_config = 0;
88162306a36Sopenharmony_ci	u32 mc_arb_ramcfg;
88262306a36Sopenharmony_ci	u32 cgts_tcc_disable;
88362306a36Sopenharmony_ci	u32 sx_debug_1;
88462306a36Sopenharmony_ci	u32 smx_dc_ctl0;
88562306a36Sopenharmony_ci	u32 cgts_sm_ctrl_reg;
88662306a36Sopenharmony_ci	u32 hdp_host_path_cntl;
88762306a36Sopenharmony_ci	u32 tmp;
88862306a36Sopenharmony_ci	u32 disabled_rb_mask;
88962306a36Sopenharmony_ci	int i, j;
89062306a36Sopenharmony_ci
89162306a36Sopenharmony_ci	switch (rdev->family) {
89262306a36Sopenharmony_ci	case CHIP_CAYMAN:
89362306a36Sopenharmony_ci		rdev->config.cayman.max_shader_engines = 2;
89462306a36Sopenharmony_ci		rdev->config.cayman.max_pipes_per_simd = 4;
89562306a36Sopenharmony_ci		rdev->config.cayman.max_tile_pipes = 8;
89662306a36Sopenharmony_ci		rdev->config.cayman.max_simds_per_se = 12;
89762306a36Sopenharmony_ci		rdev->config.cayman.max_backends_per_se = 4;
89862306a36Sopenharmony_ci		rdev->config.cayman.max_texture_channel_caches = 8;
89962306a36Sopenharmony_ci		rdev->config.cayman.max_gprs = 256;
90062306a36Sopenharmony_ci		rdev->config.cayman.max_threads = 256;
90162306a36Sopenharmony_ci		rdev->config.cayman.max_gs_threads = 32;
90262306a36Sopenharmony_ci		rdev->config.cayman.max_stack_entries = 512;
90362306a36Sopenharmony_ci		rdev->config.cayman.sx_num_of_sets = 8;
90462306a36Sopenharmony_ci		rdev->config.cayman.sx_max_export_size = 256;
90562306a36Sopenharmony_ci		rdev->config.cayman.sx_max_export_pos_size = 64;
90662306a36Sopenharmony_ci		rdev->config.cayman.sx_max_export_smx_size = 192;
90762306a36Sopenharmony_ci		rdev->config.cayman.max_hw_contexts = 8;
90862306a36Sopenharmony_ci		rdev->config.cayman.sq_num_cf_insts = 2;
90962306a36Sopenharmony_ci
91062306a36Sopenharmony_ci		rdev->config.cayman.sc_prim_fifo_size = 0x100;
91162306a36Sopenharmony_ci		rdev->config.cayman.sc_hiz_tile_fifo_size = 0x30;
91262306a36Sopenharmony_ci		rdev->config.cayman.sc_earlyz_tile_fifo_size = 0x130;
91362306a36Sopenharmony_ci		gb_addr_config = CAYMAN_GB_ADDR_CONFIG_GOLDEN;
91462306a36Sopenharmony_ci		break;
91562306a36Sopenharmony_ci	case CHIP_ARUBA:
91662306a36Sopenharmony_ci	default:
91762306a36Sopenharmony_ci		rdev->config.cayman.max_shader_engines = 1;
91862306a36Sopenharmony_ci		rdev->config.cayman.max_pipes_per_simd = 4;
91962306a36Sopenharmony_ci		rdev->config.cayman.max_tile_pipes = 2;
92062306a36Sopenharmony_ci		if ((rdev->pdev->device == 0x9900) ||
92162306a36Sopenharmony_ci		    (rdev->pdev->device == 0x9901) ||
92262306a36Sopenharmony_ci		    (rdev->pdev->device == 0x9905) ||
92362306a36Sopenharmony_ci		    (rdev->pdev->device == 0x9906) ||
92462306a36Sopenharmony_ci		    (rdev->pdev->device == 0x9907) ||
92562306a36Sopenharmony_ci		    (rdev->pdev->device == 0x9908) ||
92662306a36Sopenharmony_ci		    (rdev->pdev->device == 0x9909) ||
92762306a36Sopenharmony_ci		    (rdev->pdev->device == 0x990B) ||
92862306a36Sopenharmony_ci		    (rdev->pdev->device == 0x990C) ||
92962306a36Sopenharmony_ci		    (rdev->pdev->device == 0x990F) ||
93062306a36Sopenharmony_ci		    (rdev->pdev->device == 0x9910) ||
93162306a36Sopenharmony_ci		    (rdev->pdev->device == 0x9917) ||
93262306a36Sopenharmony_ci		    (rdev->pdev->device == 0x9999) ||
93362306a36Sopenharmony_ci		    (rdev->pdev->device == 0x999C)) {
93462306a36Sopenharmony_ci			rdev->config.cayman.max_simds_per_se = 6;
93562306a36Sopenharmony_ci			rdev->config.cayman.max_backends_per_se = 2;
93662306a36Sopenharmony_ci			rdev->config.cayman.max_hw_contexts = 8;
93762306a36Sopenharmony_ci			rdev->config.cayman.sx_max_export_size = 256;
93862306a36Sopenharmony_ci			rdev->config.cayman.sx_max_export_pos_size = 64;
93962306a36Sopenharmony_ci			rdev->config.cayman.sx_max_export_smx_size = 192;
94062306a36Sopenharmony_ci		} else if ((rdev->pdev->device == 0x9903) ||
94162306a36Sopenharmony_ci			   (rdev->pdev->device == 0x9904) ||
94262306a36Sopenharmony_ci			   (rdev->pdev->device == 0x990A) ||
94362306a36Sopenharmony_ci			   (rdev->pdev->device == 0x990D) ||
94462306a36Sopenharmony_ci			   (rdev->pdev->device == 0x990E) ||
94562306a36Sopenharmony_ci			   (rdev->pdev->device == 0x9913) ||
94662306a36Sopenharmony_ci			   (rdev->pdev->device == 0x9918) ||
94762306a36Sopenharmony_ci			   (rdev->pdev->device == 0x999D)) {
94862306a36Sopenharmony_ci			rdev->config.cayman.max_simds_per_se = 4;
94962306a36Sopenharmony_ci			rdev->config.cayman.max_backends_per_se = 2;
95062306a36Sopenharmony_ci			rdev->config.cayman.max_hw_contexts = 8;
95162306a36Sopenharmony_ci			rdev->config.cayman.sx_max_export_size = 256;
95262306a36Sopenharmony_ci			rdev->config.cayman.sx_max_export_pos_size = 64;
95362306a36Sopenharmony_ci			rdev->config.cayman.sx_max_export_smx_size = 192;
95462306a36Sopenharmony_ci		} else if ((rdev->pdev->device == 0x9919) ||
95562306a36Sopenharmony_ci			   (rdev->pdev->device == 0x9990) ||
95662306a36Sopenharmony_ci			   (rdev->pdev->device == 0x9991) ||
95762306a36Sopenharmony_ci			   (rdev->pdev->device == 0x9994) ||
95862306a36Sopenharmony_ci			   (rdev->pdev->device == 0x9995) ||
95962306a36Sopenharmony_ci			   (rdev->pdev->device == 0x9996) ||
96062306a36Sopenharmony_ci			   (rdev->pdev->device == 0x999A) ||
96162306a36Sopenharmony_ci			   (rdev->pdev->device == 0x99A0)) {
96262306a36Sopenharmony_ci			rdev->config.cayman.max_simds_per_se = 3;
96362306a36Sopenharmony_ci			rdev->config.cayman.max_backends_per_se = 1;
96462306a36Sopenharmony_ci			rdev->config.cayman.max_hw_contexts = 4;
96562306a36Sopenharmony_ci			rdev->config.cayman.sx_max_export_size = 128;
96662306a36Sopenharmony_ci			rdev->config.cayman.sx_max_export_pos_size = 32;
96762306a36Sopenharmony_ci			rdev->config.cayman.sx_max_export_smx_size = 96;
96862306a36Sopenharmony_ci		} else {
96962306a36Sopenharmony_ci			rdev->config.cayman.max_simds_per_se = 2;
97062306a36Sopenharmony_ci			rdev->config.cayman.max_backends_per_se = 1;
97162306a36Sopenharmony_ci			rdev->config.cayman.max_hw_contexts = 4;
97262306a36Sopenharmony_ci			rdev->config.cayman.sx_max_export_size = 128;
97362306a36Sopenharmony_ci			rdev->config.cayman.sx_max_export_pos_size = 32;
97462306a36Sopenharmony_ci			rdev->config.cayman.sx_max_export_smx_size = 96;
97562306a36Sopenharmony_ci		}
97662306a36Sopenharmony_ci		rdev->config.cayman.max_texture_channel_caches = 2;
97762306a36Sopenharmony_ci		rdev->config.cayman.max_gprs = 256;
97862306a36Sopenharmony_ci		rdev->config.cayman.max_threads = 256;
97962306a36Sopenharmony_ci		rdev->config.cayman.max_gs_threads = 32;
98062306a36Sopenharmony_ci		rdev->config.cayman.max_stack_entries = 512;
98162306a36Sopenharmony_ci		rdev->config.cayman.sx_num_of_sets = 8;
98262306a36Sopenharmony_ci		rdev->config.cayman.sq_num_cf_insts = 2;
98362306a36Sopenharmony_ci
98462306a36Sopenharmony_ci		rdev->config.cayman.sc_prim_fifo_size = 0x40;
98562306a36Sopenharmony_ci		rdev->config.cayman.sc_hiz_tile_fifo_size = 0x30;
98662306a36Sopenharmony_ci		rdev->config.cayman.sc_earlyz_tile_fifo_size = 0x130;
98762306a36Sopenharmony_ci		gb_addr_config = ARUBA_GB_ADDR_CONFIG_GOLDEN;
98862306a36Sopenharmony_ci		break;
98962306a36Sopenharmony_ci	}
99062306a36Sopenharmony_ci
99162306a36Sopenharmony_ci	/* Initialize HDP */
99262306a36Sopenharmony_ci	for (i = 0, j = 0; i < 32; i++, j += 0x18) {
99362306a36Sopenharmony_ci		WREG32((0x2c14 + j), 0x00000000);
99462306a36Sopenharmony_ci		WREG32((0x2c18 + j), 0x00000000);
99562306a36Sopenharmony_ci		WREG32((0x2c1c + j), 0x00000000);
99662306a36Sopenharmony_ci		WREG32((0x2c20 + j), 0x00000000);
99762306a36Sopenharmony_ci		WREG32((0x2c24 + j), 0x00000000);
99862306a36Sopenharmony_ci	}
99962306a36Sopenharmony_ci
100062306a36Sopenharmony_ci	WREG32(GRBM_CNTL, GRBM_READ_TIMEOUT(0xff));
100162306a36Sopenharmony_ci	WREG32(SRBM_INT_CNTL, 0x1);
100262306a36Sopenharmony_ci	WREG32(SRBM_INT_ACK, 0x1);
100362306a36Sopenharmony_ci
100462306a36Sopenharmony_ci	evergreen_fix_pci_max_read_req_size(rdev);
100562306a36Sopenharmony_ci
100662306a36Sopenharmony_ci	RREG32(MC_SHARED_CHMAP);
100762306a36Sopenharmony_ci	mc_arb_ramcfg = RREG32(MC_ARB_RAMCFG);
100862306a36Sopenharmony_ci
100962306a36Sopenharmony_ci	tmp = (mc_arb_ramcfg & NOOFCOLS_MASK) >> NOOFCOLS_SHIFT;
101062306a36Sopenharmony_ci	rdev->config.cayman.mem_row_size_in_kb = (4 * (1 << (8 + tmp))) / 1024;
101162306a36Sopenharmony_ci	if (rdev->config.cayman.mem_row_size_in_kb > 4)
101262306a36Sopenharmony_ci		rdev->config.cayman.mem_row_size_in_kb = 4;
101362306a36Sopenharmony_ci	/* XXX use MC settings? */
101462306a36Sopenharmony_ci	rdev->config.cayman.shader_engine_tile_size = 32;
101562306a36Sopenharmony_ci	rdev->config.cayman.num_gpus = 1;
101662306a36Sopenharmony_ci	rdev->config.cayman.multi_gpu_tile_size = 64;
101762306a36Sopenharmony_ci
101862306a36Sopenharmony_ci	tmp = (gb_addr_config & NUM_PIPES_MASK) >> NUM_PIPES_SHIFT;
101962306a36Sopenharmony_ci	rdev->config.cayman.num_tile_pipes = (1 << tmp);
102062306a36Sopenharmony_ci	tmp = (gb_addr_config & PIPE_INTERLEAVE_SIZE_MASK) >> PIPE_INTERLEAVE_SIZE_SHIFT;
102162306a36Sopenharmony_ci	rdev->config.cayman.mem_max_burst_length_bytes = (tmp + 1) * 256;
102262306a36Sopenharmony_ci	tmp = (gb_addr_config & NUM_SHADER_ENGINES_MASK) >> NUM_SHADER_ENGINES_SHIFT;
102362306a36Sopenharmony_ci	rdev->config.cayman.num_shader_engines = tmp + 1;
102462306a36Sopenharmony_ci	tmp = (gb_addr_config & NUM_GPUS_MASK) >> NUM_GPUS_SHIFT;
102562306a36Sopenharmony_ci	rdev->config.cayman.num_gpus = tmp + 1;
102662306a36Sopenharmony_ci	tmp = (gb_addr_config & MULTI_GPU_TILE_SIZE_MASK) >> MULTI_GPU_TILE_SIZE_SHIFT;
102762306a36Sopenharmony_ci	rdev->config.cayman.multi_gpu_tile_size = 1 << tmp;
102862306a36Sopenharmony_ci	tmp = (gb_addr_config & ROW_SIZE_MASK) >> ROW_SIZE_SHIFT;
102962306a36Sopenharmony_ci	rdev->config.cayman.mem_row_size_in_kb = 1 << tmp;
103062306a36Sopenharmony_ci
103162306a36Sopenharmony_ci
103262306a36Sopenharmony_ci	/* setup tiling info dword.  gb_addr_config is not adequate since it does
103362306a36Sopenharmony_ci	 * not have bank info, so create a custom tiling dword.
103462306a36Sopenharmony_ci	 * bits 3:0   num_pipes
103562306a36Sopenharmony_ci	 * bits 7:4   num_banks
103662306a36Sopenharmony_ci	 * bits 11:8  group_size
103762306a36Sopenharmony_ci	 * bits 15:12 row_size
103862306a36Sopenharmony_ci	 */
103962306a36Sopenharmony_ci	rdev->config.cayman.tile_config = 0;
104062306a36Sopenharmony_ci	switch (rdev->config.cayman.num_tile_pipes) {
104162306a36Sopenharmony_ci	case 1:
104262306a36Sopenharmony_ci	default:
104362306a36Sopenharmony_ci		rdev->config.cayman.tile_config |= (0 << 0);
104462306a36Sopenharmony_ci		break;
104562306a36Sopenharmony_ci	case 2:
104662306a36Sopenharmony_ci		rdev->config.cayman.tile_config |= (1 << 0);
104762306a36Sopenharmony_ci		break;
104862306a36Sopenharmony_ci	case 4:
104962306a36Sopenharmony_ci		rdev->config.cayman.tile_config |= (2 << 0);
105062306a36Sopenharmony_ci		break;
105162306a36Sopenharmony_ci	case 8:
105262306a36Sopenharmony_ci		rdev->config.cayman.tile_config |= (3 << 0);
105362306a36Sopenharmony_ci		break;
105462306a36Sopenharmony_ci	}
105562306a36Sopenharmony_ci
105662306a36Sopenharmony_ci	/* num banks is 8 on all fusion asics. 0 = 4, 1 = 8, 2 = 16 */
105762306a36Sopenharmony_ci	if (rdev->flags & RADEON_IS_IGP)
105862306a36Sopenharmony_ci		rdev->config.cayman.tile_config |= 1 << 4;
105962306a36Sopenharmony_ci	else {
106062306a36Sopenharmony_ci		switch ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) {
106162306a36Sopenharmony_ci		case 0: /* four banks */
106262306a36Sopenharmony_ci			rdev->config.cayman.tile_config |= 0 << 4;
106362306a36Sopenharmony_ci			break;
106462306a36Sopenharmony_ci		case 1: /* eight banks */
106562306a36Sopenharmony_ci			rdev->config.cayman.tile_config |= 1 << 4;
106662306a36Sopenharmony_ci			break;
106762306a36Sopenharmony_ci		case 2: /* sixteen banks */
106862306a36Sopenharmony_ci		default:
106962306a36Sopenharmony_ci			rdev->config.cayman.tile_config |= 2 << 4;
107062306a36Sopenharmony_ci			break;
107162306a36Sopenharmony_ci		}
107262306a36Sopenharmony_ci	}
107362306a36Sopenharmony_ci	rdev->config.cayman.tile_config |=
107462306a36Sopenharmony_ci		((gb_addr_config & PIPE_INTERLEAVE_SIZE_MASK) >> PIPE_INTERLEAVE_SIZE_SHIFT) << 8;
107562306a36Sopenharmony_ci	rdev->config.cayman.tile_config |=
107662306a36Sopenharmony_ci		((gb_addr_config & ROW_SIZE_MASK) >> ROW_SIZE_SHIFT) << 12;
107762306a36Sopenharmony_ci
107862306a36Sopenharmony_ci	tmp = 0;
107962306a36Sopenharmony_ci	for (i = (rdev->config.cayman.max_shader_engines - 1); i >= 0; i--) {
108062306a36Sopenharmony_ci		u32 rb_disable_bitmap;
108162306a36Sopenharmony_ci
108262306a36Sopenharmony_ci		WREG32(GRBM_GFX_INDEX, INSTANCE_BROADCAST_WRITES | SE_INDEX(i));
108362306a36Sopenharmony_ci		WREG32(RLC_GFX_INDEX, INSTANCE_BROADCAST_WRITES | SE_INDEX(i));
108462306a36Sopenharmony_ci		rb_disable_bitmap = (RREG32(CC_RB_BACKEND_DISABLE) & 0x00ff0000) >> 16;
108562306a36Sopenharmony_ci		tmp <<= 4;
108662306a36Sopenharmony_ci		tmp |= rb_disable_bitmap;
108762306a36Sopenharmony_ci	}
108862306a36Sopenharmony_ci	/* enabled rb are just the one not disabled :) */
108962306a36Sopenharmony_ci	disabled_rb_mask = tmp;
109062306a36Sopenharmony_ci	tmp = 0;
109162306a36Sopenharmony_ci	for (i = 0; i < (rdev->config.cayman.max_backends_per_se * rdev->config.cayman.max_shader_engines); i++)
109262306a36Sopenharmony_ci		tmp |= (1 << i);
109362306a36Sopenharmony_ci	/* if all the backends are disabled, fix it up here */
109462306a36Sopenharmony_ci	if ((disabled_rb_mask & tmp) == tmp) {
109562306a36Sopenharmony_ci		for (i = 0; i < (rdev->config.cayman.max_backends_per_se * rdev->config.cayman.max_shader_engines); i++)
109662306a36Sopenharmony_ci			disabled_rb_mask &= ~(1 << i);
109762306a36Sopenharmony_ci	}
109862306a36Sopenharmony_ci
109962306a36Sopenharmony_ci	for (i = 0; i < rdev->config.cayman.max_shader_engines; i++) {
110062306a36Sopenharmony_ci		u32 simd_disable_bitmap;
110162306a36Sopenharmony_ci
110262306a36Sopenharmony_ci		WREG32(GRBM_GFX_INDEX, INSTANCE_BROADCAST_WRITES | SE_INDEX(i));
110362306a36Sopenharmony_ci		WREG32(RLC_GFX_INDEX, INSTANCE_BROADCAST_WRITES | SE_INDEX(i));
110462306a36Sopenharmony_ci		simd_disable_bitmap = (RREG32(CC_GC_SHADER_PIPE_CONFIG) & 0xffff0000) >> 16;
110562306a36Sopenharmony_ci		simd_disable_bitmap |= 0xffffffff << rdev->config.cayman.max_simds_per_se;
110662306a36Sopenharmony_ci		tmp <<= 16;
110762306a36Sopenharmony_ci		tmp |= simd_disable_bitmap;
110862306a36Sopenharmony_ci	}
110962306a36Sopenharmony_ci	rdev->config.cayman.active_simds = hweight32(~tmp);
111062306a36Sopenharmony_ci
111162306a36Sopenharmony_ci	WREG32(GRBM_GFX_INDEX, INSTANCE_BROADCAST_WRITES | SE_BROADCAST_WRITES);
111262306a36Sopenharmony_ci	WREG32(RLC_GFX_INDEX, INSTANCE_BROADCAST_WRITES | SE_BROADCAST_WRITES);
111362306a36Sopenharmony_ci
111462306a36Sopenharmony_ci	WREG32(GB_ADDR_CONFIG, gb_addr_config);
111562306a36Sopenharmony_ci	WREG32(DMIF_ADDR_CONFIG, gb_addr_config);
111662306a36Sopenharmony_ci	if (ASIC_IS_DCE6(rdev))
111762306a36Sopenharmony_ci		WREG32(DMIF_ADDR_CALC, gb_addr_config);
111862306a36Sopenharmony_ci	WREG32(HDP_ADDR_CONFIG, gb_addr_config);
111962306a36Sopenharmony_ci	WREG32(DMA_TILING_CONFIG + DMA0_REGISTER_OFFSET, gb_addr_config);
112062306a36Sopenharmony_ci	WREG32(DMA_TILING_CONFIG + DMA1_REGISTER_OFFSET, gb_addr_config);
112162306a36Sopenharmony_ci	WREG32(UVD_UDEC_ADDR_CONFIG, gb_addr_config);
112262306a36Sopenharmony_ci	WREG32(UVD_UDEC_DB_ADDR_CONFIG, gb_addr_config);
112362306a36Sopenharmony_ci	WREG32(UVD_UDEC_DBW_ADDR_CONFIG, gb_addr_config);
112462306a36Sopenharmony_ci
112562306a36Sopenharmony_ci	if ((rdev->config.cayman.max_backends_per_se == 1) &&
112662306a36Sopenharmony_ci	    (rdev->flags & RADEON_IS_IGP)) {
112762306a36Sopenharmony_ci		if ((disabled_rb_mask & 3) == 2) {
112862306a36Sopenharmony_ci			/* RB1 disabled, RB0 enabled */
112962306a36Sopenharmony_ci			tmp = 0x00000000;
113062306a36Sopenharmony_ci		} else {
113162306a36Sopenharmony_ci			/* RB0 disabled, RB1 enabled */
113262306a36Sopenharmony_ci			tmp = 0x11111111;
113362306a36Sopenharmony_ci		}
113462306a36Sopenharmony_ci	} else {
113562306a36Sopenharmony_ci		tmp = gb_addr_config & NUM_PIPES_MASK;
113662306a36Sopenharmony_ci		tmp = r6xx_remap_render_backend(rdev, tmp,
113762306a36Sopenharmony_ci						rdev->config.cayman.max_backends_per_se *
113862306a36Sopenharmony_ci						rdev->config.cayman.max_shader_engines,
113962306a36Sopenharmony_ci						CAYMAN_MAX_BACKENDS, disabled_rb_mask);
114062306a36Sopenharmony_ci	}
114162306a36Sopenharmony_ci	rdev->config.cayman.backend_map = tmp;
114262306a36Sopenharmony_ci	WREG32(GB_BACKEND_MAP, tmp);
114362306a36Sopenharmony_ci
114462306a36Sopenharmony_ci	cgts_tcc_disable = 0xffff0000;
114562306a36Sopenharmony_ci	for (i = 0; i < rdev->config.cayman.max_texture_channel_caches; i++)
114662306a36Sopenharmony_ci		cgts_tcc_disable &= ~(1 << (16 + i));
114762306a36Sopenharmony_ci	WREG32(CGTS_TCC_DISABLE, cgts_tcc_disable);
114862306a36Sopenharmony_ci	WREG32(CGTS_SYS_TCC_DISABLE, cgts_tcc_disable);
114962306a36Sopenharmony_ci	WREG32(CGTS_USER_SYS_TCC_DISABLE, cgts_tcc_disable);
115062306a36Sopenharmony_ci	WREG32(CGTS_USER_TCC_DISABLE, cgts_tcc_disable);
115162306a36Sopenharmony_ci
115262306a36Sopenharmony_ci	/* reprogram the shader complex */
115362306a36Sopenharmony_ci	cgts_sm_ctrl_reg = RREG32(CGTS_SM_CTRL_REG);
115462306a36Sopenharmony_ci	for (i = 0; i < 16; i++)
115562306a36Sopenharmony_ci		WREG32(CGTS_SM_CTRL_REG, OVERRIDE);
115662306a36Sopenharmony_ci	WREG32(CGTS_SM_CTRL_REG, cgts_sm_ctrl_reg);
115762306a36Sopenharmony_ci
115862306a36Sopenharmony_ci	/* set HW defaults for 3D engine */
115962306a36Sopenharmony_ci	WREG32(CP_MEQ_THRESHOLDS, MEQ1_START(0x30) | MEQ2_START(0x60));
116062306a36Sopenharmony_ci
116162306a36Sopenharmony_ci	sx_debug_1 = RREG32(SX_DEBUG_1);
116262306a36Sopenharmony_ci	sx_debug_1 |= ENABLE_NEW_SMX_ADDRESS;
116362306a36Sopenharmony_ci	WREG32(SX_DEBUG_1, sx_debug_1);
116462306a36Sopenharmony_ci
116562306a36Sopenharmony_ci	smx_dc_ctl0 = RREG32(SMX_DC_CTL0);
116662306a36Sopenharmony_ci	smx_dc_ctl0 &= ~NUMBER_OF_SETS(0x1ff);
116762306a36Sopenharmony_ci	smx_dc_ctl0 |= NUMBER_OF_SETS(rdev->config.cayman.sx_num_of_sets);
116862306a36Sopenharmony_ci	WREG32(SMX_DC_CTL0, smx_dc_ctl0);
116962306a36Sopenharmony_ci
117062306a36Sopenharmony_ci	WREG32(SPI_CONFIG_CNTL_1, VTX_DONE_DELAY(4) | CRC_SIMD_ID_WADDR_DISABLE);
117162306a36Sopenharmony_ci
117262306a36Sopenharmony_ci	/* need to be explicitly zero-ed */
117362306a36Sopenharmony_ci	WREG32(VGT_OFFCHIP_LDS_BASE, 0);
117462306a36Sopenharmony_ci	WREG32(SQ_LSTMP_RING_BASE, 0);
117562306a36Sopenharmony_ci	WREG32(SQ_HSTMP_RING_BASE, 0);
117662306a36Sopenharmony_ci	WREG32(SQ_ESTMP_RING_BASE, 0);
117762306a36Sopenharmony_ci	WREG32(SQ_GSTMP_RING_BASE, 0);
117862306a36Sopenharmony_ci	WREG32(SQ_VSTMP_RING_BASE, 0);
117962306a36Sopenharmony_ci	WREG32(SQ_PSTMP_RING_BASE, 0);
118062306a36Sopenharmony_ci
118162306a36Sopenharmony_ci	WREG32(TA_CNTL_AUX, DISABLE_CUBE_ANISO);
118262306a36Sopenharmony_ci
118362306a36Sopenharmony_ci	WREG32(SX_EXPORT_BUFFER_SIZES, (COLOR_BUFFER_SIZE((rdev->config.cayman.sx_max_export_size / 4) - 1) |
118462306a36Sopenharmony_ci					POSITION_BUFFER_SIZE((rdev->config.cayman.sx_max_export_pos_size / 4) - 1) |
118562306a36Sopenharmony_ci					SMX_BUFFER_SIZE((rdev->config.cayman.sx_max_export_smx_size / 4) - 1)));
118662306a36Sopenharmony_ci
118762306a36Sopenharmony_ci	WREG32(PA_SC_FIFO_SIZE, (SC_PRIM_FIFO_SIZE(rdev->config.cayman.sc_prim_fifo_size) |
118862306a36Sopenharmony_ci				 SC_HIZ_TILE_FIFO_SIZE(rdev->config.cayman.sc_hiz_tile_fifo_size) |
118962306a36Sopenharmony_ci				 SC_EARLYZ_TILE_FIFO_SIZE(rdev->config.cayman.sc_earlyz_tile_fifo_size)));
119062306a36Sopenharmony_ci
119162306a36Sopenharmony_ci
119262306a36Sopenharmony_ci	WREG32(VGT_NUM_INSTANCES, 1);
119362306a36Sopenharmony_ci
119462306a36Sopenharmony_ci	WREG32(CP_PERFMON_CNTL, 0);
119562306a36Sopenharmony_ci
119662306a36Sopenharmony_ci	WREG32(SQ_MS_FIFO_SIZES, (CACHE_FIFO_SIZE(16 * rdev->config.cayman.sq_num_cf_insts) |
119762306a36Sopenharmony_ci				  FETCH_FIFO_HIWATER(0x4) |
119862306a36Sopenharmony_ci				  DONE_FIFO_HIWATER(0xe0) |
119962306a36Sopenharmony_ci				  ALU_UPDATE_FIFO_HIWATER(0x8)));
120062306a36Sopenharmony_ci
120162306a36Sopenharmony_ci	WREG32(SQ_GPR_RESOURCE_MGMT_1, NUM_CLAUSE_TEMP_GPRS(4));
120262306a36Sopenharmony_ci	WREG32(SQ_CONFIG, (VC_ENABLE |
120362306a36Sopenharmony_ci			   EXPORT_SRC_C |
120462306a36Sopenharmony_ci			   GFX_PRIO(0) |
120562306a36Sopenharmony_ci			   CS1_PRIO(0) |
120662306a36Sopenharmony_ci			   CS2_PRIO(1)));
120762306a36Sopenharmony_ci	WREG32(SQ_DYN_GPR_CNTL_PS_FLUSH_REQ, DYN_GPR_ENABLE);
120862306a36Sopenharmony_ci
120962306a36Sopenharmony_ci	WREG32(PA_SC_FORCE_EOV_MAX_CNTS, (FORCE_EOV_MAX_CLK_CNT(4095) |
121062306a36Sopenharmony_ci					  FORCE_EOV_MAX_REZ_CNT(255)));
121162306a36Sopenharmony_ci
121262306a36Sopenharmony_ci	WREG32(VGT_CACHE_INVALIDATION, CACHE_INVALIDATION(VC_AND_TC) |
121362306a36Sopenharmony_ci	       AUTO_INVLD_EN(ES_AND_GS_AUTO));
121462306a36Sopenharmony_ci
121562306a36Sopenharmony_ci	WREG32(VGT_GS_VERTEX_REUSE, 16);
121662306a36Sopenharmony_ci	WREG32(PA_SC_LINE_STIPPLE_STATE, 0);
121762306a36Sopenharmony_ci
121862306a36Sopenharmony_ci	WREG32(CB_PERF_CTR0_SEL_0, 0);
121962306a36Sopenharmony_ci	WREG32(CB_PERF_CTR0_SEL_1, 0);
122062306a36Sopenharmony_ci	WREG32(CB_PERF_CTR1_SEL_0, 0);
122162306a36Sopenharmony_ci	WREG32(CB_PERF_CTR1_SEL_1, 0);
122262306a36Sopenharmony_ci	WREG32(CB_PERF_CTR2_SEL_0, 0);
122362306a36Sopenharmony_ci	WREG32(CB_PERF_CTR2_SEL_1, 0);
122462306a36Sopenharmony_ci	WREG32(CB_PERF_CTR3_SEL_0, 0);
122562306a36Sopenharmony_ci	WREG32(CB_PERF_CTR3_SEL_1, 0);
122662306a36Sopenharmony_ci
122762306a36Sopenharmony_ci	tmp = RREG32(HDP_MISC_CNTL);
122862306a36Sopenharmony_ci	tmp |= HDP_FLUSH_INVALIDATE_CACHE;
122962306a36Sopenharmony_ci	WREG32(HDP_MISC_CNTL, tmp);
123062306a36Sopenharmony_ci
123162306a36Sopenharmony_ci	hdp_host_path_cntl = RREG32(HDP_HOST_PATH_CNTL);
123262306a36Sopenharmony_ci	WREG32(HDP_HOST_PATH_CNTL, hdp_host_path_cntl);
123362306a36Sopenharmony_ci
123462306a36Sopenharmony_ci	WREG32(PA_CL_ENHANCE, CLIP_VTX_REORDER_ENA | NUM_CLIP_SEQ(3));
123562306a36Sopenharmony_ci
123662306a36Sopenharmony_ci	udelay(50);
123762306a36Sopenharmony_ci
123862306a36Sopenharmony_ci	/* set clockgating golden values on TN */
123962306a36Sopenharmony_ci	if (rdev->family == CHIP_ARUBA) {
124062306a36Sopenharmony_ci		tmp = RREG32_CG(CG_CGTT_LOCAL_0);
124162306a36Sopenharmony_ci		tmp &= ~0x00380000;
124262306a36Sopenharmony_ci		WREG32_CG(CG_CGTT_LOCAL_0, tmp);
124362306a36Sopenharmony_ci		tmp = RREG32_CG(CG_CGTT_LOCAL_1);
124462306a36Sopenharmony_ci		tmp &= ~0x0e000000;
124562306a36Sopenharmony_ci		WREG32_CG(CG_CGTT_LOCAL_1, tmp);
124662306a36Sopenharmony_ci	}
124762306a36Sopenharmony_ci}
124862306a36Sopenharmony_ci
124962306a36Sopenharmony_ci/*
125062306a36Sopenharmony_ci * GART
125162306a36Sopenharmony_ci */
125262306a36Sopenharmony_civoid cayman_pcie_gart_tlb_flush(struct radeon_device *rdev)
125362306a36Sopenharmony_ci{
125462306a36Sopenharmony_ci	/* flush hdp cache */
125562306a36Sopenharmony_ci	WREG32(HDP_MEM_COHERENCY_FLUSH_CNTL, 0x1);
125662306a36Sopenharmony_ci
125762306a36Sopenharmony_ci	/* bits 0-7 are the VM contexts0-7 */
125862306a36Sopenharmony_ci	WREG32(VM_INVALIDATE_REQUEST, 1);
125962306a36Sopenharmony_ci}
126062306a36Sopenharmony_ci
126162306a36Sopenharmony_cistatic int cayman_pcie_gart_enable(struct radeon_device *rdev)
126262306a36Sopenharmony_ci{
126362306a36Sopenharmony_ci	int i, r;
126462306a36Sopenharmony_ci
126562306a36Sopenharmony_ci	if (rdev->gart.robj == NULL) {
126662306a36Sopenharmony_ci		dev_err(rdev->dev, "No VRAM object for PCIE GART.\n");
126762306a36Sopenharmony_ci		return -EINVAL;
126862306a36Sopenharmony_ci	}
126962306a36Sopenharmony_ci	r = radeon_gart_table_vram_pin(rdev);
127062306a36Sopenharmony_ci	if (r)
127162306a36Sopenharmony_ci		return r;
127262306a36Sopenharmony_ci	/* Setup TLB control */
127362306a36Sopenharmony_ci	WREG32(MC_VM_MX_L1_TLB_CNTL,
127462306a36Sopenharmony_ci	       (0xA << 7) |
127562306a36Sopenharmony_ci	       ENABLE_L1_TLB |
127662306a36Sopenharmony_ci	       ENABLE_L1_FRAGMENT_PROCESSING |
127762306a36Sopenharmony_ci	       SYSTEM_ACCESS_MODE_NOT_IN_SYS |
127862306a36Sopenharmony_ci	       ENABLE_ADVANCED_DRIVER_MODEL |
127962306a36Sopenharmony_ci	       SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU);
128062306a36Sopenharmony_ci	/* Setup L2 cache */
128162306a36Sopenharmony_ci	WREG32(VM_L2_CNTL, ENABLE_L2_CACHE |
128262306a36Sopenharmony_ci	       ENABLE_L2_FRAGMENT_PROCESSING |
128362306a36Sopenharmony_ci	       ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE |
128462306a36Sopenharmony_ci	       ENABLE_L2_PDE0_CACHE_LRU_UPDATE_BY_WRITE |
128562306a36Sopenharmony_ci	       EFFECTIVE_L2_QUEUE_SIZE(7) |
128662306a36Sopenharmony_ci	       CONTEXT1_IDENTITY_ACCESS_MODE(1));
128762306a36Sopenharmony_ci	WREG32(VM_L2_CNTL2, INVALIDATE_ALL_L1_TLBS | INVALIDATE_L2_CACHE);
128862306a36Sopenharmony_ci	WREG32(VM_L2_CNTL3, L2_CACHE_BIGK_ASSOCIATIVITY |
128962306a36Sopenharmony_ci	       BANK_SELECT(6) |
129062306a36Sopenharmony_ci	       L2_CACHE_BIGK_FRAGMENT_SIZE(6));
129162306a36Sopenharmony_ci	/* setup context0 */
129262306a36Sopenharmony_ci	WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR, rdev->mc.gtt_start >> 12);
129362306a36Sopenharmony_ci	WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR, rdev->mc.gtt_end >> 12);
129462306a36Sopenharmony_ci	WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR, rdev->gart.table_addr >> 12);
129562306a36Sopenharmony_ci	WREG32(VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR,
129662306a36Sopenharmony_ci			(u32)(rdev->dummy_page.addr >> 12));
129762306a36Sopenharmony_ci	WREG32(VM_CONTEXT0_CNTL2, 0);
129862306a36Sopenharmony_ci	WREG32(VM_CONTEXT0_CNTL, ENABLE_CONTEXT | PAGE_TABLE_DEPTH(0) |
129962306a36Sopenharmony_ci				RANGE_PROTECTION_FAULT_ENABLE_DEFAULT);
130062306a36Sopenharmony_ci
130162306a36Sopenharmony_ci	WREG32(0x15D4, 0);
130262306a36Sopenharmony_ci	WREG32(0x15D8, 0);
130362306a36Sopenharmony_ci	WREG32(0x15DC, 0);
130462306a36Sopenharmony_ci
130562306a36Sopenharmony_ci	/* empty context1-7 */
130662306a36Sopenharmony_ci	/* Assign the pt base to something valid for now; the pts used for
130762306a36Sopenharmony_ci	 * the VMs are determined by the application and setup and assigned
130862306a36Sopenharmony_ci	 * on the fly in the vm part of radeon_gart.c
130962306a36Sopenharmony_ci	 */
131062306a36Sopenharmony_ci	for (i = 1; i < 8; i++) {
131162306a36Sopenharmony_ci		WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR + (i << 2), 0);
131262306a36Sopenharmony_ci		WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR + (i << 2),
131362306a36Sopenharmony_ci			rdev->vm_manager.max_pfn - 1);
131462306a36Sopenharmony_ci		WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (i << 2),
131562306a36Sopenharmony_ci		       rdev->vm_manager.saved_table_addr[i]);
131662306a36Sopenharmony_ci	}
131762306a36Sopenharmony_ci
131862306a36Sopenharmony_ci	/* enable context1-7 */
131962306a36Sopenharmony_ci	WREG32(VM_CONTEXT1_PROTECTION_FAULT_DEFAULT_ADDR,
132062306a36Sopenharmony_ci	       (u32)(rdev->dummy_page.addr >> 12));
132162306a36Sopenharmony_ci	WREG32(VM_CONTEXT1_CNTL2, 4);
132262306a36Sopenharmony_ci	WREG32(VM_CONTEXT1_CNTL, ENABLE_CONTEXT | PAGE_TABLE_DEPTH(1) |
132362306a36Sopenharmony_ci				PAGE_TABLE_BLOCK_SIZE(radeon_vm_block_size - 9) |
132462306a36Sopenharmony_ci				RANGE_PROTECTION_FAULT_ENABLE_INTERRUPT |
132562306a36Sopenharmony_ci				RANGE_PROTECTION_FAULT_ENABLE_DEFAULT |
132662306a36Sopenharmony_ci				DUMMY_PAGE_PROTECTION_FAULT_ENABLE_INTERRUPT |
132762306a36Sopenharmony_ci				DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT |
132862306a36Sopenharmony_ci				PDE0_PROTECTION_FAULT_ENABLE_INTERRUPT |
132962306a36Sopenharmony_ci				PDE0_PROTECTION_FAULT_ENABLE_DEFAULT |
133062306a36Sopenharmony_ci				VALID_PROTECTION_FAULT_ENABLE_INTERRUPT |
133162306a36Sopenharmony_ci				VALID_PROTECTION_FAULT_ENABLE_DEFAULT |
133262306a36Sopenharmony_ci				READ_PROTECTION_FAULT_ENABLE_INTERRUPT |
133362306a36Sopenharmony_ci				READ_PROTECTION_FAULT_ENABLE_DEFAULT |
133462306a36Sopenharmony_ci				WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT |
133562306a36Sopenharmony_ci				WRITE_PROTECTION_FAULT_ENABLE_DEFAULT);
133662306a36Sopenharmony_ci
133762306a36Sopenharmony_ci	cayman_pcie_gart_tlb_flush(rdev);
133862306a36Sopenharmony_ci	DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n",
133962306a36Sopenharmony_ci		 (unsigned)(rdev->mc.gtt_size >> 20),
134062306a36Sopenharmony_ci		 (unsigned long long)rdev->gart.table_addr);
134162306a36Sopenharmony_ci	rdev->gart.ready = true;
134262306a36Sopenharmony_ci	return 0;
134362306a36Sopenharmony_ci}
134462306a36Sopenharmony_ci
134562306a36Sopenharmony_cistatic void cayman_pcie_gart_disable(struct radeon_device *rdev)
134662306a36Sopenharmony_ci{
134762306a36Sopenharmony_ci	unsigned i;
134862306a36Sopenharmony_ci
134962306a36Sopenharmony_ci	for (i = 1; i < 8; ++i) {
135062306a36Sopenharmony_ci		rdev->vm_manager.saved_table_addr[i] = RREG32(
135162306a36Sopenharmony_ci			VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (i << 2));
135262306a36Sopenharmony_ci	}
135362306a36Sopenharmony_ci
135462306a36Sopenharmony_ci	/* Disable all tables */
135562306a36Sopenharmony_ci	WREG32(VM_CONTEXT0_CNTL, 0);
135662306a36Sopenharmony_ci	WREG32(VM_CONTEXT1_CNTL, 0);
135762306a36Sopenharmony_ci	/* Setup TLB control */
135862306a36Sopenharmony_ci	WREG32(MC_VM_MX_L1_TLB_CNTL, ENABLE_L1_FRAGMENT_PROCESSING |
135962306a36Sopenharmony_ci	       SYSTEM_ACCESS_MODE_NOT_IN_SYS |
136062306a36Sopenharmony_ci	       SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU);
136162306a36Sopenharmony_ci	/* Setup L2 cache */
136262306a36Sopenharmony_ci	WREG32(VM_L2_CNTL, ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE |
136362306a36Sopenharmony_ci	       ENABLE_L2_PDE0_CACHE_LRU_UPDATE_BY_WRITE |
136462306a36Sopenharmony_ci	       EFFECTIVE_L2_QUEUE_SIZE(7) |
136562306a36Sopenharmony_ci	       CONTEXT1_IDENTITY_ACCESS_MODE(1));
136662306a36Sopenharmony_ci	WREG32(VM_L2_CNTL2, 0);
136762306a36Sopenharmony_ci	WREG32(VM_L2_CNTL3, L2_CACHE_BIGK_ASSOCIATIVITY |
136862306a36Sopenharmony_ci	       L2_CACHE_BIGK_FRAGMENT_SIZE(6));
136962306a36Sopenharmony_ci	radeon_gart_table_vram_unpin(rdev);
137062306a36Sopenharmony_ci}
137162306a36Sopenharmony_ci
137262306a36Sopenharmony_cistatic void cayman_pcie_gart_fini(struct radeon_device *rdev)
137362306a36Sopenharmony_ci{
137462306a36Sopenharmony_ci	cayman_pcie_gart_disable(rdev);
137562306a36Sopenharmony_ci	radeon_gart_table_vram_free(rdev);
137662306a36Sopenharmony_ci	radeon_gart_fini(rdev);
137762306a36Sopenharmony_ci}
137862306a36Sopenharmony_ci
137962306a36Sopenharmony_civoid cayman_cp_int_cntl_setup(struct radeon_device *rdev,
138062306a36Sopenharmony_ci			      int ring, u32 cp_int_cntl)
138162306a36Sopenharmony_ci{
138262306a36Sopenharmony_ci	WREG32(SRBM_GFX_CNTL, RINGID(ring));
138362306a36Sopenharmony_ci	WREG32(CP_INT_CNTL, cp_int_cntl);
138462306a36Sopenharmony_ci}
138562306a36Sopenharmony_ci
138662306a36Sopenharmony_ci/*
138762306a36Sopenharmony_ci * CP.
138862306a36Sopenharmony_ci */
138962306a36Sopenharmony_civoid cayman_fence_ring_emit(struct radeon_device *rdev,
139062306a36Sopenharmony_ci			    struct radeon_fence *fence)
139162306a36Sopenharmony_ci{
139262306a36Sopenharmony_ci	struct radeon_ring *ring = &rdev->ring[fence->ring];
139362306a36Sopenharmony_ci	u64 addr = rdev->fence_drv[fence->ring].gpu_addr;
139462306a36Sopenharmony_ci	u32 cp_coher_cntl = PACKET3_FULL_CACHE_ENA | PACKET3_TC_ACTION_ENA |
139562306a36Sopenharmony_ci		PACKET3_SH_ACTION_ENA;
139662306a36Sopenharmony_ci
139762306a36Sopenharmony_ci	/* flush read cache over gart for this vmid */
139862306a36Sopenharmony_ci	radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3));
139962306a36Sopenharmony_ci	radeon_ring_write(ring, PACKET3_ENGINE_ME | cp_coher_cntl);
140062306a36Sopenharmony_ci	radeon_ring_write(ring, 0xFFFFFFFF);
140162306a36Sopenharmony_ci	radeon_ring_write(ring, 0);
140262306a36Sopenharmony_ci	radeon_ring_write(ring, 10); /* poll interval */
140362306a36Sopenharmony_ci	/* EVENT_WRITE_EOP - flush caches, send int */
140462306a36Sopenharmony_ci	radeon_ring_write(ring, PACKET3(PACKET3_EVENT_WRITE_EOP, 4));
140562306a36Sopenharmony_ci	radeon_ring_write(ring, EVENT_TYPE(CACHE_FLUSH_AND_INV_EVENT_TS) | EVENT_INDEX(5));
140662306a36Sopenharmony_ci	radeon_ring_write(ring, lower_32_bits(addr));
140762306a36Sopenharmony_ci	radeon_ring_write(ring, (upper_32_bits(addr) & 0xff) | DATA_SEL(1) | INT_SEL(2));
140862306a36Sopenharmony_ci	radeon_ring_write(ring, fence->seq);
140962306a36Sopenharmony_ci	radeon_ring_write(ring, 0);
141062306a36Sopenharmony_ci}
141162306a36Sopenharmony_ci
141262306a36Sopenharmony_civoid cayman_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib)
141362306a36Sopenharmony_ci{
141462306a36Sopenharmony_ci	struct radeon_ring *ring = &rdev->ring[ib->ring];
141562306a36Sopenharmony_ci	unsigned vm_id = ib->vm ? ib->vm->ids[ib->ring].id : 0;
141662306a36Sopenharmony_ci	u32 cp_coher_cntl = PACKET3_FULL_CACHE_ENA | PACKET3_TC_ACTION_ENA |
141762306a36Sopenharmony_ci		PACKET3_SH_ACTION_ENA;
141862306a36Sopenharmony_ci
141962306a36Sopenharmony_ci	/* set to DX10/11 mode */
142062306a36Sopenharmony_ci	radeon_ring_write(ring, PACKET3(PACKET3_MODE_CONTROL, 0));
142162306a36Sopenharmony_ci	radeon_ring_write(ring, 1);
142262306a36Sopenharmony_ci
142362306a36Sopenharmony_ci	if (ring->rptr_save_reg) {
142462306a36Sopenharmony_ci		uint32_t next_rptr = ring->wptr + 3 + 4 + 8;
142562306a36Sopenharmony_ci		radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1));
142662306a36Sopenharmony_ci		radeon_ring_write(ring, ((ring->rptr_save_reg -
142762306a36Sopenharmony_ci					  PACKET3_SET_CONFIG_REG_START) >> 2));
142862306a36Sopenharmony_ci		radeon_ring_write(ring, next_rptr);
142962306a36Sopenharmony_ci	}
143062306a36Sopenharmony_ci
143162306a36Sopenharmony_ci	radeon_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2));
143262306a36Sopenharmony_ci	radeon_ring_write(ring,
143362306a36Sopenharmony_ci#ifdef __BIG_ENDIAN
143462306a36Sopenharmony_ci			  (2 << 0) |
143562306a36Sopenharmony_ci#endif
143662306a36Sopenharmony_ci			  (ib->gpu_addr & 0xFFFFFFFC));
143762306a36Sopenharmony_ci	radeon_ring_write(ring, upper_32_bits(ib->gpu_addr) & 0xFF);
143862306a36Sopenharmony_ci	radeon_ring_write(ring, ib->length_dw | (vm_id << 24));
143962306a36Sopenharmony_ci
144062306a36Sopenharmony_ci	/* flush read cache over gart for this vmid */
144162306a36Sopenharmony_ci	radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3));
144262306a36Sopenharmony_ci	radeon_ring_write(ring, PACKET3_ENGINE_ME | cp_coher_cntl);
144362306a36Sopenharmony_ci	radeon_ring_write(ring, 0xFFFFFFFF);
144462306a36Sopenharmony_ci	radeon_ring_write(ring, 0);
144562306a36Sopenharmony_ci	radeon_ring_write(ring, (vm_id << 24) | 10); /* poll interval */
144662306a36Sopenharmony_ci}
144762306a36Sopenharmony_ci
144862306a36Sopenharmony_cistatic void cayman_cp_enable(struct radeon_device *rdev, bool enable)
144962306a36Sopenharmony_ci{
145062306a36Sopenharmony_ci	if (enable)
145162306a36Sopenharmony_ci		WREG32(CP_ME_CNTL, 0);
145262306a36Sopenharmony_ci	else {
145362306a36Sopenharmony_ci		if (rdev->asic->copy.copy_ring_index == RADEON_RING_TYPE_GFX_INDEX)
145462306a36Sopenharmony_ci			radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size);
145562306a36Sopenharmony_ci		WREG32(CP_ME_CNTL, (CP_ME_HALT | CP_PFP_HALT));
145662306a36Sopenharmony_ci		WREG32(SCRATCH_UMSK, 0);
145762306a36Sopenharmony_ci		rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false;
145862306a36Sopenharmony_ci	}
145962306a36Sopenharmony_ci}
146062306a36Sopenharmony_ci
146162306a36Sopenharmony_ciu32 cayman_gfx_get_rptr(struct radeon_device *rdev,
146262306a36Sopenharmony_ci			struct radeon_ring *ring)
146362306a36Sopenharmony_ci{
146462306a36Sopenharmony_ci	u32 rptr;
146562306a36Sopenharmony_ci
146662306a36Sopenharmony_ci	if (rdev->wb.enabled)
146762306a36Sopenharmony_ci		rptr = rdev->wb.wb[ring->rptr_offs/4];
146862306a36Sopenharmony_ci	else {
146962306a36Sopenharmony_ci		if (ring->idx == RADEON_RING_TYPE_GFX_INDEX)
147062306a36Sopenharmony_ci			rptr = RREG32(CP_RB0_RPTR);
147162306a36Sopenharmony_ci		else if (ring->idx == CAYMAN_RING_TYPE_CP1_INDEX)
147262306a36Sopenharmony_ci			rptr = RREG32(CP_RB1_RPTR);
147362306a36Sopenharmony_ci		else
147462306a36Sopenharmony_ci			rptr = RREG32(CP_RB2_RPTR);
147562306a36Sopenharmony_ci	}
147662306a36Sopenharmony_ci
147762306a36Sopenharmony_ci	return rptr;
147862306a36Sopenharmony_ci}
147962306a36Sopenharmony_ci
148062306a36Sopenharmony_ciu32 cayman_gfx_get_wptr(struct radeon_device *rdev,
148162306a36Sopenharmony_ci			struct radeon_ring *ring)
148262306a36Sopenharmony_ci{
148362306a36Sopenharmony_ci	u32 wptr;
148462306a36Sopenharmony_ci
148562306a36Sopenharmony_ci	if (ring->idx == RADEON_RING_TYPE_GFX_INDEX)
148662306a36Sopenharmony_ci		wptr = RREG32(CP_RB0_WPTR);
148762306a36Sopenharmony_ci	else if (ring->idx == CAYMAN_RING_TYPE_CP1_INDEX)
148862306a36Sopenharmony_ci		wptr = RREG32(CP_RB1_WPTR);
148962306a36Sopenharmony_ci	else
149062306a36Sopenharmony_ci		wptr = RREG32(CP_RB2_WPTR);
149162306a36Sopenharmony_ci
149262306a36Sopenharmony_ci	return wptr;
149362306a36Sopenharmony_ci}
149462306a36Sopenharmony_ci
149562306a36Sopenharmony_civoid cayman_gfx_set_wptr(struct radeon_device *rdev,
149662306a36Sopenharmony_ci			 struct radeon_ring *ring)
149762306a36Sopenharmony_ci{
149862306a36Sopenharmony_ci	if (ring->idx == RADEON_RING_TYPE_GFX_INDEX) {
149962306a36Sopenharmony_ci		WREG32(CP_RB0_WPTR, ring->wptr);
150062306a36Sopenharmony_ci		(void)RREG32(CP_RB0_WPTR);
150162306a36Sopenharmony_ci	} else if (ring->idx == CAYMAN_RING_TYPE_CP1_INDEX) {
150262306a36Sopenharmony_ci		WREG32(CP_RB1_WPTR, ring->wptr);
150362306a36Sopenharmony_ci		(void)RREG32(CP_RB1_WPTR);
150462306a36Sopenharmony_ci	} else {
150562306a36Sopenharmony_ci		WREG32(CP_RB2_WPTR, ring->wptr);
150662306a36Sopenharmony_ci		(void)RREG32(CP_RB2_WPTR);
150762306a36Sopenharmony_ci	}
150862306a36Sopenharmony_ci}
150962306a36Sopenharmony_ci
151062306a36Sopenharmony_cistatic int cayman_cp_load_microcode(struct radeon_device *rdev)
151162306a36Sopenharmony_ci{
151262306a36Sopenharmony_ci	const __be32 *fw_data;
151362306a36Sopenharmony_ci	int i;
151462306a36Sopenharmony_ci
151562306a36Sopenharmony_ci	if (!rdev->me_fw || !rdev->pfp_fw)
151662306a36Sopenharmony_ci		return -EINVAL;
151762306a36Sopenharmony_ci
151862306a36Sopenharmony_ci	cayman_cp_enable(rdev, false);
151962306a36Sopenharmony_ci
152062306a36Sopenharmony_ci	fw_data = (const __be32 *)rdev->pfp_fw->data;
152162306a36Sopenharmony_ci	WREG32(CP_PFP_UCODE_ADDR, 0);
152262306a36Sopenharmony_ci	for (i = 0; i < CAYMAN_PFP_UCODE_SIZE; i++)
152362306a36Sopenharmony_ci		WREG32(CP_PFP_UCODE_DATA, be32_to_cpup(fw_data++));
152462306a36Sopenharmony_ci	WREG32(CP_PFP_UCODE_ADDR, 0);
152562306a36Sopenharmony_ci
152662306a36Sopenharmony_ci	fw_data = (const __be32 *)rdev->me_fw->data;
152762306a36Sopenharmony_ci	WREG32(CP_ME_RAM_WADDR, 0);
152862306a36Sopenharmony_ci	for (i = 0; i < CAYMAN_PM4_UCODE_SIZE; i++)
152962306a36Sopenharmony_ci		WREG32(CP_ME_RAM_DATA, be32_to_cpup(fw_data++));
153062306a36Sopenharmony_ci
153162306a36Sopenharmony_ci	WREG32(CP_PFP_UCODE_ADDR, 0);
153262306a36Sopenharmony_ci	WREG32(CP_ME_RAM_WADDR, 0);
153362306a36Sopenharmony_ci	WREG32(CP_ME_RAM_RADDR, 0);
153462306a36Sopenharmony_ci	return 0;
153562306a36Sopenharmony_ci}
153662306a36Sopenharmony_ci
153762306a36Sopenharmony_cistatic int cayman_cp_start(struct radeon_device *rdev)
153862306a36Sopenharmony_ci{
153962306a36Sopenharmony_ci	struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
154062306a36Sopenharmony_ci	int r, i;
154162306a36Sopenharmony_ci
154262306a36Sopenharmony_ci	r = radeon_ring_lock(rdev, ring, 7);
154362306a36Sopenharmony_ci	if (r) {
154462306a36Sopenharmony_ci		DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r);
154562306a36Sopenharmony_ci		return r;
154662306a36Sopenharmony_ci	}
154762306a36Sopenharmony_ci	radeon_ring_write(ring, PACKET3(PACKET3_ME_INITIALIZE, 5));
154862306a36Sopenharmony_ci	radeon_ring_write(ring, 0x1);
154962306a36Sopenharmony_ci	radeon_ring_write(ring, 0x0);
155062306a36Sopenharmony_ci	radeon_ring_write(ring, rdev->config.cayman.max_hw_contexts - 1);
155162306a36Sopenharmony_ci	radeon_ring_write(ring, PACKET3_ME_INITIALIZE_DEVICE_ID(1));
155262306a36Sopenharmony_ci	radeon_ring_write(ring, 0);
155362306a36Sopenharmony_ci	radeon_ring_write(ring, 0);
155462306a36Sopenharmony_ci	radeon_ring_unlock_commit(rdev, ring, false);
155562306a36Sopenharmony_ci
155662306a36Sopenharmony_ci	cayman_cp_enable(rdev, true);
155762306a36Sopenharmony_ci
155862306a36Sopenharmony_ci	r = radeon_ring_lock(rdev, ring, cayman_default_size + 19);
155962306a36Sopenharmony_ci	if (r) {
156062306a36Sopenharmony_ci		DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r);
156162306a36Sopenharmony_ci		return r;
156262306a36Sopenharmony_ci	}
156362306a36Sopenharmony_ci
156462306a36Sopenharmony_ci	/* setup clear context state */
156562306a36Sopenharmony_ci	radeon_ring_write(ring, PACKET3(PACKET3_PREAMBLE_CNTL, 0));
156662306a36Sopenharmony_ci	radeon_ring_write(ring, PACKET3_PREAMBLE_BEGIN_CLEAR_STATE);
156762306a36Sopenharmony_ci
156862306a36Sopenharmony_ci	for (i = 0; i < cayman_default_size; i++)
156962306a36Sopenharmony_ci		radeon_ring_write(ring, cayman_default_state[i]);
157062306a36Sopenharmony_ci
157162306a36Sopenharmony_ci	radeon_ring_write(ring, PACKET3(PACKET3_PREAMBLE_CNTL, 0));
157262306a36Sopenharmony_ci	radeon_ring_write(ring, PACKET3_PREAMBLE_END_CLEAR_STATE);
157362306a36Sopenharmony_ci
157462306a36Sopenharmony_ci	/* set clear context state */
157562306a36Sopenharmony_ci	radeon_ring_write(ring, PACKET3(PACKET3_CLEAR_STATE, 0));
157662306a36Sopenharmony_ci	radeon_ring_write(ring, 0);
157762306a36Sopenharmony_ci
157862306a36Sopenharmony_ci	/* SQ_VTX_BASE_VTX_LOC */
157962306a36Sopenharmony_ci	radeon_ring_write(ring, 0xc0026f00);
158062306a36Sopenharmony_ci	radeon_ring_write(ring, 0x00000000);
158162306a36Sopenharmony_ci	radeon_ring_write(ring, 0x00000000);
158262306a36Sopenharmony_ci	radeon_ring_write(ring, 0x00000000);
158362306a36Sopenharmony_ci
158462306a36Sopenharmony_ci	/* Clear consts */
158562306a36Sopenharmony_ci	radeon_ring_write(ring, 0xc0036f00);
158662306a36Sopenharmony_ci	radeon_ring_write(ring, 0x00000bc4);
158762306a36Sopenharmony_ci	radeon_ring_write(ring, 0xffffffff);
158862306a36Sopenharmony_ci	radeon_ring_write(ring, 0xffffffff);
158962306a36Sopenharmony_ci	radeon_ring_write(ring, 0xffffffff);
159062306a36Sopenharmony_ci
159162306a36Sopenharmony_ci	radeon_ring_write(ring, 0xc0026900);
159262306a36Sopenharmony_ci	radeon_ring_write(ring, 0x00000316);
159362306a36Sopenharmony_ci	radeon_ring_write(ring, 0x0000000e); /* VGT_VERTEX_REUSE_BLOCK_CNTL */
159462306a36Sopenharmony_ci	radeon_ring_write(ring, 0x00000010); /*  */
159562306a36Sopenharmony_ci
159662306a36Sopenharmony_ci	radeon_ring_unlock_commit(rdev, ring, false);
159762306a36Sopenharmony_ci
159862306a36Sopenharmony_ci	/* XXX init other rings */
159962306a36Sopenharmony_ci
160062306a36Sopenharmony_ci	return 0;
160162306a36Sopenharmony_ci}
160262306a36Sopenharmony_ci
160362306a36Sopenharmony_cistatic void cayman_cp_fini(struct radeon_device *rdev)
160462306a36Sopenharmony_ci{
160562306a36Sopenharmony_ci	struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
160662306a36Sopenharmony_ci	cayman_cp_enable(rdev, false);
160762306a36Sopenharmony_ci	radeon_ring_fini(rdev, ring);
160862306a36Sopenharmony_ci	radeon_scratch_free(rdev, ring->rptr_save_reg);
160962306a36Sopenharmony_ci}
161062306a36Sopenharmony_ci
161162306a36Sopenharmony_cistatic int cayman_cp_resume(struct radeon_device *rdev)
161262306a36Sopenharmony_ci{
161362306a36Sopenharmony_ci	static const int ridx[] = {
161462306a36Sopenharmony_ci		RADEON_RING_TYPE_GFX_INDEX,
161562306a36Sopenharmony_ci		CAYMAN_RING_TYPE_CP1_INDEX,
161662306a36Sopenharmony_ci		CAYMAN_RING_TYPE_CP2_INDEX
161762306a36Sopenharmony_ci	};
161862306a36Sopenharmony_ci	static const unsigned cp_rb_cntl[] = {
161962306a36Sopenharmony_ci		CP_RB0_CNTL,
162062306a36Sopenharmony_ci		CP_RB1_CNTL,
162162306a36Sopenharmony_ci		CP_RB2_CNTL,
162262306a36Sopenharmony_ci	};
162362306a36Sopenharmony_ci	static const unsigned cp_rb_rptr_addr[] = {
162462306a36Sopenharmony_ci		CP_RB0_RPTR_ADDR,
162562306a36Sopenharmony_ci		CP_RB1_RPTR_ADDR,
162662306a36Sopenharmony_ci		CP_RB2_RPTR_ADDR
162762306a36Sopenharmony_ci	};
162862306a36Sopenharmony_ci	static const unsigned cp_rb_rptr_addr_hi[] = {
162962306a36Sopenharmony_ci		CP_RB0_RPTR_ADDR_HI,
163062306a36Sopenharmony_ci		CP_RB1_RPTR_ADDR_HI,
163162306a36Sopenharmony_ci		CP_RB2_RPTR_ADDR_HI
163262306a36Sopenharmony_ci	};
163362306a36Sopenharmony_ci	static const unsigned cp_rb_base[] = {
163462306a36Sopenharmony_ci		CP_RB0_BASE,
163562306a36Sopenharmony_ci		CP_RB1_BASE,
163662306a36Sopenharmony_ci		CP_RB2_BASE
163762306a36Sopenharmony_ci	};
163862306a36Sopenharmony_ci	static const unsigned cp_rb_rptr[] = {
163962306a36Sopenharmony_ci		CP_RB0_RPTR,
164062306a36Sopenharmony_ci		CP_RB1_RPTR,
164162306a36Sopenharmony_ci		CP_RB2_RPTR
164262306a36Sopenharmony_ci	};
164362306a36Sopenharmony_ci	static const unsigned cp_rb_wptr[] = {
164462306a36Sopenharmony_ci		CP_RB0_WPTR,
164562306a36Sopenharmony_ci		CP_RB1_WPTR,
164662306a36Sopenharmony_ci		CP_RB2_WPTR
164762306a36Sopenharmony_ci	};
164862306a36Sopenharmony_ci	struct radeon_ring *ring;
164962306a36Sopenharmony_ci	int i, r;
165062306a36Sopenharmony_ci
165162306a36Sopenharmony_ci	/* Reset cp; if cp is reset, then PA, SH, VGT also need to be reset */
165262306a36Sopenharmony_ci	WREG32(GRBM_SOFT_RESET, (SOFT_RESET_CP |
165362306a36Sopenharmony_ci				 SOFT_RESET_PA |
165462306a36Sopenharmony_ci				 SOFT_RESET_SH |
165562306a36Sopenharmony_ci				 SOFT_RESET_VGT |
165662306a36Sopenharmony_ci				 SOFT_RESET_SPI |
165762306a36Sopenharmony_ci				 SOFT_RESET_SX));
165862306a36Sopenharmony_ci	RREG32(GRBM_SOFT_RESET);
165962306a36Sopenharmony_ci	mdelay(15);
166062306a36Sopenharmony_ci	WREG32(GRBM_SOFT_RESET, 0);
166162306a36Sopenharmony_ci	RREG32(GRBM_SOFT_RESET);
166262306a36Sopenharmony_ci
166362306a36Sopenharmony_ci	WREG32(CP_SEM_WAIT_TIMER, 0x0);
166462306a36Sopenharmony_ci	WREG32(CP_SEM_INCOMPLETE_TIMER_CNTL, 0x0);
166562306a36Sopenharmony_ci
166662306a36Sopenharmony_ci	/* Set the write pointer delay */
166762306a36Sopenharmony_ci	WREG32(CP_RB_WPTR_DELAY, 0);
166862306a36Sopenharmony_ci
166962306a36Sopenharmony_ci	WREG32(CP_DEBUG, (1 << 27));
167062306a36Sopenharmony_ci
167162306a36Sopenharmony_ci	/* set the wb address whether it's enabled or not */
167262306a36Sopenharmony_ci	WREG32(SCRATCH_ADDR, ((rdev->wb.gpu_addr + RADEON_WB_SCRATCH_OFFSET) >> 8) & 0xFFFFFFFF);
167362306a36Sopenharmony_ci	WREG32(SCRATCH_UMSK, 0xff);
167462306a36Sopenharmony_ci
167562306a36Sopenharmony_ci	for (i = 0; i < 3; ++i) {
167662306a36Sopenharmony_ci		uint32_t rb_cntl;
167762306a36Sopenharmony_ci		uint64_t addr;
167862306a36Sopenharmony_ci
167962306a36Sopenharmony_ci		/* Set ring buffer size */
168062306a36Sopenharmony_ci		ring = &rdev->ring[ridx[i]];
168162306a36Sopenharmony_ci		rb_cntl = order_base_2(ring->ring_size / 8);
168262306a36Sopenharmony_ci		rb_cntl |= order_base_2(RADEON_GPU_PAGE_SIZE/8) << 8;
168362306a36Sopenharmony_ci#ifdef __BIG_ENDIAN
168462306a36Sopenharmony_ci		rb_cntl |= BUF_SWAP_32BIT;
168562306a36Sopenharmony_ci#endif
168662306a36Sopenharmony_ci		WREG32(cp_rb_cntl[i], rb_cntl);
168762306a36Sopenharmony_ci
168862306a36Sopenharmony_ci		/* set the wb address whether it's enabled or not */
168962306a36Sopenharmony_ci		addr = rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET;
169062306a36Sopenharmony_ci		WREG32(cp_rb_rptr_addr[i], addr & 0xFFFFFFFC);
169162306a36Sopenharmony_ci		WREG32(cp_rb_rptr_addr_hi[i], upper_32_bits(addr) & 0xFF);
169262306a36Sopenharmony_ci	}
169362306a36Sopenharmony_ci
169462306a36Sopenharmony_ci	/* set the rb base addr, this causes an internal reset of ALL rings */
169562306a36Sopenharmony_ci	for (i = 0; i < 3; ++i) {
169662306a36Sopenharmony_ci		ring = &rdev->ring[ridx[i]];
169762306a36Sopenharmony_ci		WREG32(cp_rb_base[i], ring->gpu_addr >> 8);
169862306a36Sopenharmony_ci	}
169962306a36Sopenharmony_ci
170062306a36Sopenharmony_ci	for (i = 0; i < 3; ++i) {
170162306a36Sopenharmony_ci		/* Initialize the ring buffer's read and write pointers */
170262306a36Sopenharmony_ci		ring = &rdev->ring[ridx[i]];
170362306a36Sopenharmony_ci		WREG32_P(cp_rb_cntl[i], RB_RPTR_WR_ENA, ~RB_RPTR_WR_ENA);
170462306a36Sopenharmony_ci
170562306a36Sopenharmony_ci		ring->wptr = 0;
170662306a36Sopenharmony_ci		WREG32(cp_rb_rptr[i], 0);
170762306a36Sopenharmony_ci		WREG32(cp_rb_wptr[i], ring->wptr);
170862306a36Sopenharmony_ci
170962306a36Sopenharmony_ci		mdelay(1);
171062306a36Sopenharmony_ci		WREG32_P(cp_rb_cntl[i], 0, ~RB_RPTR_WR_ENA);
171162306a36Sopenharmony_ci	}
171262306a36Sopenharmony_ci
171362306a36Sopenharmony_ci	/* start the rings */
171462306a36Sopenharmony_ci	cayman_cp_start(rdev);
171562306a36Sopenharmony_ci	rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = true;
171662306a36Sopenharmony_ci	rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX].ready = false;
171762306a36Sopenharmony_ci	rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX].ready = false;
171862306a36Sopenharmony_ci	/* this only test cp0 */
171962306a36Sopenharmony_ci	r = radeon_ring_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]);
172062306a36Sopenharmony_ci	if (r) {
172162306a36Sopenharmony_ci		rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false;
172262306a36Sopenharmony_ci		rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX].ready = false;
172362306a36Sopenharmony_ci		rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX].ready = false;
172462306a36Sopenharmony_ci		return r;
172562306a36Sopenharmony_ci	}
172662306a36Sopenharmony_ci
172762306a36Sopenharmony_ci	if (rdev->asic->copy.copy_ring_index == RADEON_RING_TYPE_GFX_INDEX)
172862306a36Sopenharmony_ci		radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size);
172962306a36Sopenharmony_ci
173062306a36Sopenharmony_ci	return 0;
173162306a36Sopenharmony_ci}
173262306a36Sopenharmony_ci
173362306a36Sopenharmony_ciu32 cayman_gpu_check_soft_reset(struct radeon_device *rdev)
173462306a36Sopenharmony_ci{
173562306a36Sopenharmony_ci	u32 reset_mask = 0;
173662306a36Sopenharmony_ci	u32 tmp;
173762306a36Sopenharmony_ci
173862306a36Sopenharmony_ci	/* GRBM_STATUS */
173962306a36Sopenharmony_ci	tmp = RREG32(GRBM_STATUS);
174062306a36Sopenharmony_ci	if (tmp & (PA_BUSY | SC_BUSY |
174162306a36Sopenharmony_ci		   SH_BUSY | SX_BUSY |
174262306a36Sopenharmony_ci		   TA_BUSY | VGT_BUSY |
174362306a36Sopenharmony_ci		   DB_BUSY | CB_BUSY |
174462306a36Sopenharmony_ci		   GDS_BUSY | SPI_BUSY |
174562306a36Sopenharmony_ci		   IA_BUSY | IA_BUSY_NO_DMA))
174662306a36Sopenharmony_ci		reset_mask |= RADEON_RESET_GFX;
174762306a36Sopenharmony_ci
174862306a36Sopenharmony_ci	if (tmp & (CF_RQ_PENDING | PF_RQ_PENDING |
174962306a36Sopenharmony_ci		   CP_BUSY | CP_COHERENCY_BUSY))
175062306a36Sopenharmony_ci		reset_mask |= RADEON_RESET_CP;
175162306a36Sopenharmony_ci
175262306a36Sopenharmony_ci	if (tmp & GRBM_EE_BUSY)
175362306a36Sopenharmony_ci		reset_mask |= RADEON_RESET_GRBM | RADEON_RESET_GFX | RADEON_RESET_CP;
175462306a36Sopenharmony_ci
175562306a36Sopenharmony_ci	/* DMA_STATUS_REG 0 */
175662306a36Sopenharmony_ci	tmp = RREG32(DMA_STATUS_REG + DMA0_REGISTER_OFFSET);
175762306a36Sopenharmony_ci	if (!(tmp & DMA_IDLE))
175862306a36Sopenharmony_ci		reset_mask |= RADEON_RESET_DMA;
175962306a36Sopenharmony_ci
176062306a36Sopenharmony_ci	/* DMA_STATUS_REG 1 */
176162306a36Sopenharmony_ci	tmp = RREG32(DMA_STATUS_REG + DMA1_REGISTER_OFFSET);
176262306a36Sopenharmony_ci	if (!(tmp & DMA_IDLE))
176362306a36Sopenharmony_ci		reset_mask |= RADEON_RESET_DMA1;
176462306a36Sopenharmony_ci
176562306a36Sopenharmony_ci	/* SRBM_STATUS2 */
176662306a36Sopenharmony_ci	tmp = RREG32(SRBM_STATUS2);
176762306a36Sopenharmony_ci	if (tmp & DMA_BUSY)
176862306a36Sopenharmony_ci		reset_mask |= RADEON_RESET_DMA;
176962306a36Sopenharmony_ci
177062306a36Sopenharmony_ci	if (tmp & DMA1_BUSY)
177162306a36Sopenharmony_ci		reset_mask |= RADEON_RESET_DMA1;
177262306a36Sopenharmony_ci
177362306a36Sopenharmony_ci	/* SRBM_STATUS */
177462306a36Sopenharmony_ci	tmp = RREG32(SRBM_STATUS);
177562306a36Sopenharmony_ci	if (tmp & (RLC_RQ_PENDING | RLC_BUSY))
177662306a36Sopenharmony_ci		reset_mask |= RADEON_RESET_RLC;
177762306a36Sopenharmony_ci
177862306a36Sopenharmony_ci	if (tmp & IH_BUSY)
177962306a36Sopenharmony_ci		reset_mask |= RADEON_RESET_IH;
178062306a36Sopenharmony_ci
178162306a36Sopenharmony_ci	if (tmp & SEM_BUSY)
178262306a36Sopenharmony_ci		reset_mask |= RADEON_RESET_SEM;
178362306a36Sopenharmony_ci
178462306a36Sopenharmony_ci	if (tmp & GRBM_RQ_PENDING)
178562306a36Sopenharmony_ci		reset_mask |= RADEON_RESET_GRBM;
178662306a36Sopenharmony_ci
178762306a36Sopenharmony_ci	if (tmp & VMC_BUSY)
178862306a36Sopenharmony_ci		reset_mask |= RADEON_RESET_VMC;
178962306a36Sopenharmony_ci
179062306a36Sopenharmony_ci	if (tmp & (MCB_BUSY | MCB_NON_DISPLAY_BUSY |
179162306a36Sopenharmony_ci		   MCC_BUSY | MCD_BUSY))
179262306a36Sopenharmony_ci		reset_mask |= RADEON_RESET_MC;
179362306a36Sopenharmony_ci
179462306a36Sopenharmony_ci	if (evergreen_is_display_hung(rdev))
179562306a36Sopenharmony_ci		reset_mask |= RADEON_RESET_DISPLAY;
179662306a36Sopenharmony_ci
179762306a36Sopenharmony_ci	/* VM_L2_STATUS */
179862306a36Sopenharmony_ci	tmp = RREG32(VM_L2_STATUS);
179962306a36Sopenharmony_ci	if (tmp & L2_BUSY)
180062306a36Sopenharmony_ci		reset_mask |= RADEON_RESET_VMC;
180162306a36Sopenharmony_ci
180262306a36Sopenharmony_ci	/* Skip MC reset as it's mostly likely not hung, just busy */
180362306a36Sopenharmony_ci	if (reset_mask & RADEON_RESET_MC) {
180462306a36Sopenharmony_ci		DRM_DEBUG("MC busy: 0x%08X, clearing.\n", reset_mask);
180562306a36Sopenharmony_ci		reset_mask &= ~RADEON_RESET_MC;
180662306a36Sopenharmony_ci	}
180762306a36Sopenharmony_ci
180862306a36Sopenharmony_ci	return reset_mask;
180962306a36Sopenharmony_ci}
181062306a36Sopenharmony_ci
181162306a36Sopenharmony_cistatic void cayman_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask)
181262306a36Sopenharmony_ci{
181362306a36Sopenharmony_ci	struct evergreen_mc_save save;
181462306a36Sopenharmony_ci	u32 grbm_soft_reset = 0, srbm_soft_reset = 0;
181562306a36Sopenharmony_ci	u32 tmp;
181662306a36Sopenharmony_ci
181762306a36Sopenharmony_ci	if (reset_mask == 0)
181862306a36Sopenharmony_ci		return;
181962306a36Sopenharmony_ci
182062306a36Sopenharmony_ci	dev_info(rdev->dev, "GPU softreset: 0x%08X\n", reset_mask);
182162306a36Sopenharmony_ci
182262306a36Sopenharmony_ci	evergreen_print_gpu_status_regs(rdev);
182362306a36Sopenharmony_ci	dev_info(rdev->dev, "  VM_CONTEXT0_PROTECTION_FAULT_ADDR   0x%08X\n",
182462306a36Sopenharmony_ci		 RREG32(0x14F8));
182562306a36Sopenharmony_ci	dev_info(rdev->dev, "  VM_CONTEXT0_PROTECTION_FAULT_STATUS 0x%08X\n",
182662306a36Sopenharmony_ci		 RREG32(0x14D8));
182762306a36Sopenharmony_ci	dev_info(rdev->dev, "  VM_CONTEXT1_PROTECTION_FAULT_ADDR   0x%08X\n",
182862306a36Sopenharmony_ci		 RREG32(0x14FC));
182962306a36Sopenharmony_ci	dev_info(rdev->dev, "  VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x%08X\n",
183062306a36Sopenharmony_ci		 RREG32(0x14DC));
183162306a36Sopenharmony_ci
183262306a36Sopenharmony_ci	/* Disable CP parsing/prefetching */
183362306a36Sopenharmony_ci	WREG32(CP_ME_CNTL, CP_ME_HALT | CP_PFP_HALT);
183462306a36Sopenharmony_ci
183562306a36Sopenharmony_ci	if (reset_mask & RADEON_RESET_DMA) {
183662306a36Sopenharmony_ci		/* dma0 */
183762306a36Sopenharmony_ci		tmp = RREG32(DMA_RB_CNTL + DMA0_REGISTER_OFFSET);
183862306a36Sopenharmony_ci		tmp &= ~DMA_RB_ENABLE;
183962306a36Sopenharmony_ci		WREG32(DMA_RB_CNTL + DMA0_REGISTER_OFFSET, tmp);
184062306a36Sopenharmony_ci	}
184162306a36Sopenharmony_ci
184262306a36Sopenharmony_ci	if (reset_mask & RADEON_RESET_DMA1) {
184362306a36Sopenharmony_ci		/* dma1 */
184462306a36Sopenharmony_ci		tmp = RREG32(DMA_RB_CNTL + DMA1_REGISTER_OFFSET);
184562306a36Sopenharmony_ci		tmp &= ~DMA_RB_ENABLE;
184662306a36Sopenharmony_ci		WREG32(DMA_RB_CNTL + DMA1_REGISTER_OFFSET, tmp);
184762306a36Sopenharmony_ci	}
184862306a36Sopenharmony_ci
184962306a36Sopenharmony_ci	udelay(50);
185062306a36Sopenharmony_ci
185162306a36Sopenharmony_ci	evergreen_mc_stop(rdev, &save);
185262306a36Sopenharmony_ci	if (evergreen_mc_wait_for_idle(rdev)) {
185362306a36Sopenharmony_ci		dev_warn(rdev->dev, "Wait for MC idle timedout !\n");
185462306a36Sopenharmony_ci	}
185562306a36Sopenharmony_ci
185662306a36Sopenharmony_ci	if (reset_mask & (RADEON_RESET_GFX | RADEON_RESET_COMPUTE)) {
185762306a36Sopenharmony_ci		grbm_soft_reset = SOFT_RESET_CB |
185862306a36Sopenharmony_ci			SOFT_RESET_DB |
185962306a36Sopenharmony_ci			SOFT_RESET_GDS |
186062306a36Sopenharmony_ci			SOFT_RESET_PA |
186162306a36Sopenharmony_ci			SOFT_RESET_SC |
186262306a36Sopenharmony_ci			SOFT_RESET_SPI |
186362306a36Sopenharmony_ci			SOFT_RESET_SH |
186462306a36Sopenharmony_ci			SOFT_RESET_SX |
186562306a36Sopenharmony_ci			SOFT_RESET_TC |
186662306a36Sopenharmony_ci			SOFT_RESET_TA |
186762306a36Sopenharmony_ci			SOFT_RESET_VGT |
186862306a36Sopenharmony_ci			SOFT_RESET_IA;
186962306a36Sopenharmony_ci	}
187062306a36Sopenharmony_ci
187162306a36Sopenharmony_ci	if (reset_mask & RADEON_RESET_CP) {
187262306a36Sopenharmony_ci		grbm_soft_reset |= SOFT_RESET_CP | SOFT_RESET_VGT;
187362306a36Sopenharmony_ci
187462306a36Sopenharmony_ci		srbm_soft_reset |= SOFT_RESET_GRBM;
187562306a36Sopenharmony_ci	}
187662306a36Sopenharmony_ci
187762306a36Sopenharmony_ci	if (reset_mask & RADEON_RESET_DMA)
187862306a36Sopenharmony_ci		srbm_soft_reset |= SOFT_RESET_DMA;
187962306a36Sopenharmony_ci
188062306a36Sopenharmony_ci	if (reset_mask & RADEON_RESET_DMA1)
188162306a36Sopenharmony_ci		srbm_soft_reset |= SOFT_RESET_DMA1;
188262306a36Sopenharmony_ci
188362306a36Sopenharmony_ci	if (reset_mask & RADEON_RESET_DISPLAY)
188462306a36Sopenharmony_ci		srbm_soft_reset |= SOFT_RESET_DC;
188562306a36Sopenharmony_ci
188662306a36Sopenharmony_ci	if (reset_mask & RADEON_RESET_RLC)
188762306a36Sopenharmony_ci		srbm_soft_reset |= SOFT_RESET_RLC;
188862306a36Sopenharmony_ci
188962306a36Sopenharmony_ci	if (reset_mask & RADEON_RESET_SEM)
189062306a36Sopenharmony_ci		srbm_soft_reset |= SOFT_RESET_SEM;
189162306a36Sopenharmony_ci
189262306a36Sopenharmony_ci	if (reset_mask & RADEON_RESET_IH)
189362306a36Sopenharmony_ci		srbm_soft_reset |= SOFT_RESET_IH;
189462306a36Sopenharmony_ci
189562306a36Sopenharmony_ci	if (reset_mask & RADEON_RESET_GRBM)
189662306a36Sopenharmony_ci		srbm_soft_reset |= SOFT_RESET_GRBM;
189762306a36Sopenharmony_ci
189862306a36Sopenharmony_ci	if (reset_mask & RADEON_RESET_VMC)
189962306a36Sopenharmony_ci		srbm_soft_reset |= SOFT_RESET_VMC;
190062306a36Sopenharmony_ci
190162306a36Sopenharmony_ci	if (!(rdev->flags & RADEON_IS_IGP)) {
190262306a36Sopenharmony_ci		if (reset_mask & RADEON_RESET_MC)
190362306a36Sopenharmony_ci			srbm_soft_reset |= SOFT_RESET_MC;
190462306a36Sopenharmony_ci	}
190562306a36Sopenharmony_ci
190662306a36Sopenharmony_ci	if (grbm_soft_reset) {
190762306a36Sopenharmony_ci		tmp = RREG32(GRBM_SOFT_RESET);
190862306a36Sopenharmony_ci		tmp |= grbm_soft_reset;
190962306a36Sopenharmony_ci		dev_info(rdev->dev, "GRBM_SOFT_RESET=0x%08X\n", tmp);
191062306a36Sopenharmony_ci		WREG32(GRBM_SOFT_RESET, tmp);
191162306a36Sopenharmony_ci		tmp = RREG32(GRBM_SOFT_RESET);
191262306a36Sopenharmony_ci
191362306a36Sopenharmony_ci		udelay(50);
191462306a36Sopenharmony_ci
191562306a36Sopenharmony_ci		tmp &= ~grbm_soft_reset;
191662306a36Sopenharmony_ci		WREG32(GRBM_SOFT_RESET, tmp);
191762306a36Sopenharmony_ci		tmp = RREG32(GRBM_SOFT_RESET);
191862306a36Sopenharmony_ci	}
191962306a36Sopenharmony_ci
192062306a36Sopenharmony_ci	if (srbm_soft_reset) {
192162306a36Sopenharmony_ci		tmp = RREG32(SRBM_SOFT_RESET);
192262306a36Sopenharmony_ci		tmp |= srbm_soft_reset;
192362306a36Sopenharmony_ci		dev_info(rdev->dev, "SRBM_SOFT_RESET=0x%08X\n", tmp);
192462306a36Sopenharmony_ci		WREG32(SRBM_SOFT_RESET, tmp);
192562306a36Sopenharmony_ci		tmp = RREG32(SRBM_SOFT_RESET);
192662306a36Sopenharmony_ci
192762306a36Sopenharmony_ci		udelay(50);
192862306a36Sopenharmony_ci
192962306a36Sopenharmony_ci		tmp &= ~srbm_soft_reset;
193062306a36Sopenharmony_ci		WREG32(SRBM_SOFT_RESET, tmp);
193162306a36Sopenharmony_ci		tmp = RREG32(SRBM_SOFT_RESET);
193262306a36Sopenharmony_ci	}
193362306a36Sopenharmony_ci
193462306a36Sopenharmony_ci	/* Wait a little for things to settle down */
193562306a36Sopenharmony_ci	udelay(50);
193662306a36Sopenharmony_ci
193762306a36Sopenharmony_ci	evergreen_mc_resume(rdev, &save);
193862306a36Sopenharmony_ci	udelay(50);
193962306a36Sopenharmony_ci
194062306a36Sopenharmony_ci	evergreen_print_gpu_status_regs(rdev);
194162306a36Sopenharmony_ci}
194262306a36Sopenharmony_ci
194362306a36Sopenharmony_ciint cayman_asic_reset(struct radeon_device *rdev, bool hard)
194462306a36Sopenharmony_ci{
194562306a36Sopenharmony_ci	u32 reset_mask;
194662306a36Sopenharmony_ci
194762306a36Sopenharmony_ci	if (hard) {
194862306a36Sopenharmony_ci		evergreen_gpu_pci_config_reset(rdev);
194962306a36Sopenharmony_ci		return 0;
195062306a36Sopenharmony_ci	}
195162306a36Sopenharmony_ci
195262306a36Sopenharmony_ci	reset_mask = cayman_gpu_check_soft_reset(rdev);
195362306a36Sopenharmony_ci
195462306a36Sopenharmony_ci	if (reset_mask)
195562306a36Sopenharmony_ci		r600_set_bios_scratch_engine_hung(rdev, true);
195662306a36Sopenharmony_ci
195762306a36Sopenharmony_ci	cayman_gpu_soft_reset(rdev, reset_mask);
195862306a36Sopenharmony_ci
195962306a36Sopenharmony_ci	reset_mask = cayman_gpu_check_soft_reset(rdev);
196062306a36Sopenharmony_ci
196162306a36Sopenharmony_ci	if (reset_mask)
196262306a36Sopenharmony_ci		evergreen_gpu_pci_config_reset(rdev);
196362306a36Sopenharmony_ci
196462306a36Sopenharmony_ci	r600_set_bios_scratch_engine_hung(rdev, false);
196562306a36Sopenharmony_ci
196662306a36Sopenharmony_ci	return 0;
196762306a36Sopenharmony_ci}
196862306a36Sopenharmony_ci
196962306a36Sopenharmony_ci/**
197062306a36Sopenharmony_ci * cayman_gfx_is_lockup - Check if the GFX engine is locked up
197162306a36Sopenharmony_ci *
197262306a36Sopenharmony_ci * @rdev: radeon_device pointer
197362306a36Sopenharmony_ci * @ring: radeon_ring structure holding ring information
197462306a36Sopenharmony_ci *
197562306a36Sopenharmony_ci * Check if the GFX engine is locked up.
197662306a36Sopenharmony_ci * Returns true if the engine appears to be locked up, false if not.
197762306a36Sopenharmony_ci */
197862306a36Sopenharmony_cibool cayman_gfx_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring)
197962306a36Sopenharmony_ci{
198062306a36Sopenharmony_ci	u32 reset_mask = cayman_gpu_check_soft_reset(rdev);
198162306a36Sopenharmony_ci
198262306a36Sopenharmony_ci	if (!(reset_mask & (RADEON_RESET_GFX |
198362306a36Sopenharmony_ci			    RADEON_RESET_COMPUTE |
198462306a36Sopenharmony_ci			    RADEON_RESET_CP))) {
198562306a36Sopenharmony_ci		radeon_ring_lockup_update(rdev, ring);
198662306a36Sopenharmony_ci		return false;
198762306a36Sopenharmony_ci	}
198862306a36Sopenharmony_ci	return radeon_ring_test_lockup(rdev, ring);
198962306a36Sopenharmony_ci}
199062306a36Sopenharmony_ci
199162306a36Sopenharmony_cistatic void cayman_uvd_init(struct radeon_device *rdev)
199262306a36Sopenharmony_ci{
199362306a36Sopenharmony_ci	int r;
199462306a36Sopenharmony_ci
199562306a36Sopenharmony_ci	if (!rdev->has_uvd)
199662306a36Sopenharmony_ci		return;
199762306a36Sopenharmony_ci
199862306a36Sopenharmony_ci	r = radeon_uvd_init(rdev);
199962306a36Sopenharmony_ci	if (r) {
200062306a36Sopenharmony_ci		dev_err(rdev->dev, "failed UVD (%d) init.\n", r);
200162306a36Sopenharmony_ci		/*
200262306a36Sopenharmony_ci		 * At this point rdev->uvd.vcpu_bo is NULL which trickles down
200362306a36Sopenharmony_ci		 * to early fails uvd_v2_2_resume() and thus nothing happens
200462306a36Sopenharmony_ci		 * there. So it is pointless to try to go through that code
200562306a36Sopenharmony_ci		 * hence why we disable uvd here.
200662306a36Sopenharmony_ci		 */
200762306a36Sopenharmony_ci		rdev->has_uvd = false;
200862306a36Sopenharmony_ci		return;
200962306a36Sopenharmony_ci	}
201062306a36Sopenharmony_ci	rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_obj = NULL;
201162306a36Sopenharmony_ci	r600_ring_init(rdev, &rdev->ring[R600_RING_TYPE_UVD_INDEX], 4096);
201262306a36Sopenharmony_ci}
201362306a36Sopenharmony_ci
201462306a36Sopenharmony_cistatic void cayman_uvd_start(struct radeon_device *rdev)
201562306a36Sopenharmony_ci{
201662306a36Sopenharmony_ci	int r;
201762306a36Sopenharmony_ci
201862306a36Sopenharmony_ci	if (!rdev->has_uvd)
201962306a36Sopenharmony_ci		return;
202062306a36Sopenharmony_ci
202162306a36Sopenharmony_ci	r = uvd_v2_2_resume(rdev);
202262306a36Sopenharmony_ci	if (r) {
202362306a36Sopenharmony_ci		dev_err(rdev->dev, "failed UVD resume (%d).\n", r);
202462306a36Sopenharmony_ci		goto error;
202562306a36Sopenharmony_ci	}
202662306a36Sopenharmony_ci	r = radeon_fence_driver_start_ring(rdev, R600_RING_TYPE_UVD_INDEX);
202762306a36Sopenharmony_ci	if (r) {
202862306a36Sopenharmony_ci		dev_err(rdev->dev, "failed initializing UVD fences (%d).\n", r);
202962306a36Sopenharmony_ci		goto error;
203062306a36Sopenharmony_ci	}
203162306a36Sopenharmony_ci	return;
203262306a36Sopenharmony_ci
203362306a36Sopenharmony_cierror:
203462306a36Sopenharmony_ci	rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;
203562306a36Sopenharmony_ci}
203662306a36Sopenharmony_ci
203762306a36Sopenharmony_cistatic void cayman_uvd_resume(struct radeon_device *rdev)
203862306a36Sopenharmony_ci{
203962306a36Sopenharmony_ci	struct radeon_ring *ring;
204062306a36Sopenharmony_ci	int r;
204162306a36Sopenharmony_ci
204262306a36Sopenharmony_ci	if (!rdev->has_uvd || !rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size)
204362306a36Sopenharmony_ci		return;
204462306a36Sopenharmony_ci
204562306a36Sopenharmony_ci	ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
204662306a36Sopenharmony_ci	r = radeon_ring_init(rdev, ring, ring->ring_size, 0, PACKET0(UVD_NO_OP, 0));
204762306a36Sopenharmony_ci	if (r) {
204862306a36Sopenharmony_ci		dev_err(rdev->dev, "failed initializing UVD ring (%d).\n", r);
204962306a36Sopenharmony_ci		return;
205062306a36Sopenharmony_ci	}
205162306a36Sopenharmony_ci	r = uvd_v1_0_init(rdev);
205262306a36Sopenharmony_ci	if (r) {
205362306a36Sopenharmony_ci		dev_err(rdev->dev, "failed initializing UVD (%d).\n", r);
205462306a36Sopenharmony_ci		return;
205562306a36Sopenharmony_ci	}
205662306a36Sopenharmony_ci}
205762306a36Sopenharmony_ci
205862306a36Sopenharmony_cistatic void cayman_vce_init(struct radeon_device *rdev)
205962306a36Sopenharmony_ci{
206062306a36Sopenharmony_ci	int r;
206162306a36Sopenharmony_ci
206262306a36Sopenharmony_ci	/* Only set for CHIP_ARUBA */
206362306a36Sopenharmony_ci	if (!rdev->has_vce)
206462306a36Sopenharmony_ci		return;
206562306a36Sopenharmony_ci
206662306a36Sopenharmony_ci	r = radeon_vce_init(rdev);
206762306a36Sopenharmony_ci	if (r) {
206862306a36Sopenharmony_ci		dev_err(rdev->dev, "failed VCE (%d) init.\n", r);
206962306a36Sopenharmony_ci		/*
207062306a36Sopenharmony_ci		 * At this point rdev->vce.vcpu_bo is NULL which trickles down
207162306a36Sopenharmony_ci		 * to early fails cayman_vce_start() and thus nothing happens
207262306a36Sopenharmony_ci		 * there. So it is pointless to try to go through that code
207362306a36Sopenharmony_ci		 * hence why we disable vce here.
207462306a36Sopenharmony_ci		 */
207562306a36Sopenharmony_ci		rdev->has_vce = false;
207662306a36Sopenharmony_ci		return;
207762306a36Sopenharmony_ci	}
207862306a36Sopenharmony_ci	rdev->ring[TN_RING_TYPE_VCE1_INDEX].ring_obj = NULL;
207962306a36Sopenharmony_ci	r600_ring_init(rdev, &rdev->ring[TN_RING_TYPE_VCE1_INDEX], 4096);
208062306a36Sopenharmony_ci	rdev->ring[TN_RING_TYPE_VCE2_INDEX].ring_obj = NULL;
208162306a36Sopenharmony_ci	r600_ring_init(rdev, &rdev->ring[TN_RING_TYPE_VCE2_INDEX], 4096);
208262306a36Sopenharmony_ci}
208362306a36Sopenharmony_ci
208462306a36Sopenharmony_cistatic void cayman_vce_start(struct radeon_device *rdev)
208562306a36Sopenharmony_ci{
208662306a36Sopenharmony_ci	int r;
208762306a36Sopenharmony_ci
208862306a36Sopenharmony_ci	if (!rdev->has_vce)
208962306a36Sopenharmony_ci		return;
209062306a36Sopenharmony_ci
209162306a36Sopenharmony_ci	r = radeon_vce_resume(rdev);
209262306a36Sopenharmony_ci	if (r) {
209362306a36Sopenharmony_ci		dev_err(rdev->dev, "failed VCE resume (%d).\n", r);
209462306a36Sopenharmony_ci		goto error;
209562306a36Sopenharmony_ci	}
209662306a36Sopenharmony_ci	r = vce_v1_0_resume(rdev);
209762306a36Sopenharmony_ci	if (r) {
209862306a36Sopenharmony_ci		dev_err(rdev->dev, "failed VCE resume (%d).\n", r);
209962306a36Sopenharmony_ci		goto error;
210062306a36Sopenharmony_ci	}
210162306a36Sopenharmony_ci	r = radeon_fence_driver_start_ring(rdev, TN_RING_TYPE_VCE1_INDEX);
210262306a36Sopenharmony_ci	if (r) {
210362306a36Sopenharmony_ci		dev_err(rdev->dev, "failed initializing VCE1 fences (%d).\n", r);
210462306a36Sopenharmony_ci		goto error;
210562306a36Sopenharmony_ci	}
210662306a36Sopenharmony_ci	r = radeon_fence_driver_start_ring(rdev, TN_RING_TYPE_VCE2_INDEX);
210762306a36Sopenharmony_ci	if (r) {
210862306a36Sopenharmony_ci		dev_err(rdev->dev, "failed initializing VCE2 fences (%d).\n", r);
210962306a36Sopenharmony_ci		goto error;
211062306a36Sopenharmony_ci	}
211162306a36Sopenharmony_ci	return;
211262306a36Sopenharmony_ci
211362306a36Sopenharmony_cierror:
211462306a36Sopenharmony_ci	rdev->ring[TN_RING_TYPE_VCE1_INDEX].ring_size = 0;
211562306a36Sopenharmony_ci	rdev->ring[TN_RING_TYPE_VCE2_INDEX].ring_size = 0;
211662306a36Sopenharmony_ci}
211762306a36Sopenharmony_ci
211862306a36Sopenharmony_cistatic void cayman_vce_resume(struct radeon_device *rdev)
211962306a36Sopenharmony_ci{
212062306a36Sopenharmony_ci	struct radeon_ring *ring;
212162306a36Sopenharmony_ci	int r;
212262306a36Sopenharmony_ci
212362306a36Sopenharmony_ci	if (!rdev->has_vce || !rdev->ring[TN_RING_TYPE_VCE1_INDEX].ring_size)
212462306a36Sopenharmony_ci		return;
212562306a36Sopenharmony_ci
212662306a36Sopenharmony_ci	ring = &rdev->ring[TN_RING_TYPE_VCE1_INDEX];
212762306a36Sopenharmony_ci	r = radeon_ring_init(rdev, ring, ring->ring_size, 0, 0x0);
212862306a36Sopenharmony_ci	if (r) {
212962306a36Sopenharmony_ci		dev_err(rdev->dev, "failed initializing VCE1 ring (%d).\n", r);
213062306a36Sopenharmony_ci		return;
213162306a36Sopenharmony_ci	}
213262306a36Sopenharmony_ci	ring = &rdev->ring[TN_RING_TYPE_VCE2_INDEX];
213362306a36Sopenharmony_ci	r = radeon_ring_init(rdev, ring, ring->ring_size, 0, 0x0);
213462306a36Sopenharmony_ci	if (r) {
213562306a36Sopenharmony_ci		dev_err(rdev->dev, "failed initializing VCE1 ring (%d).\n", r);
213662306a36Sopenharmony_ci		return;
213762306a36Sopenharmony_ci	}
213862306a36Sopenharmony_ci	r = vce_v1_0_init(rdev);
213962306a36Sopenharmony_ci	if (r) {
214062306a36Sopenharmony_ci		dev_err(rdev->dev, "failed initializing VCE (%d).\n", r);
214162306a36Sopenharmony_ci		return;
214262306a36Sopenharmony_ci	}
214362306a36Sopenharmony_ci}
214462306a36Sopenharmony_ci
214562306a36Sopenharmony_cistatic int cayman_startup(struct radeon_device *rdev)
214662306a36Sopenharmony_ci{
214762306a36Sopenharmony_ci	struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
214862306a36Sopenharmony_ci	int r;
214962306a36Sopenharmony_ci
215062306a36Sopenharmony_ci	/* enable pcie gen2 link */
215162306a36Sopenharmony_ci	evergreen_pcie_gen2_enable(rdev);
215262306a36Sopenharmony_ci	/* enable aspm */
215362306a36Sopenharmony_ci	evergreen_program_aspm(rdev);
215462306a36Sopenharmony_ci
215562306a36Sopenharmony_ci	/* scratch needs to be initialized before MC */
215662306a36Sopenharmony_ci	r = r600_vram_scratch_init(rdev);
215762306a36Sopenharmony_ci	if (r)
215862306a36Sopenharmony_ci		return r;
215962306a36Sopenharmony_ci
216062306a36Sopenharmony_ci	evergreen_mc_program(rdev);
216162306a36Sopenharmony_ci
216262306a36Sopenharmony_ci	if (!(rdev->flags & RADEON_IS_IGP) && !rdev->pm.dpm_enabled) {
216362306a36Sopenharmony_ci		r = ni_mc_load_microcode(rdev);
216462306a36Sopenharmony_ci		if (r) {
216562306a36Sopenharmony_ci			DRM_ERROR("Failed to load MC firmware!\n");
216662306a36Sopenharmony_ci			return r;
216762306a36Sopenharmony_ci		}
216862306a36Sopenharmony_ci	}
216962306a36Sopenharmony_ci
217062306a36Sopenharmony_ci	r = cayman_pcie_gart_enable(rdev);
217162306a36Sopenharmony_ci	if (r)
217262306a36Sopenharmony_ci		return r;
217362306a36Sopenharmony_ci	cayman_gpu_init(rdev);
217462306a36Sopenharmony_ci
217562306a36Sopenharmony_ci	/* allocate rlc buffers */
217662306a36Sopenharmony_ci	if (rdev->flags & RADEON_IS_IGP) {
217762306a36Sopenharmony_ci		rdev->rlc.reg_list = tn_rlc_save_restore_register_list;
217862306a36Sopenharmony_ci		rdev->rlc.reg_list_size =
217962306a36Sopenharmony_ci			(u32)ARRAY_SIZE(tn_rlc_save_restore_register_list);
218062306a36Sopenharmony_ci		rdev->rlc.cs_data = cayman_cs_data;
218162306a36Sopenharmony_ci		r = sumo_rlc_init(rdev);
218262306a36Sopenharmony_ci		if (r) {
218362306a36Sopenharmony_ci			DRM_ERROR("Failed to init rlc BOs!\n");
218462306a36Sopenharmony_ci			return r;
218562306a36Sopenharmony_ci		}
218662306a36Sopenharmony_ci	}
218762306a36Sopenharmony_ci
218862306a36Sopenharmony_ci	/* allocate wb buffer */
218962306a36Sopenharmony_ci	r = radeon_wb_init(rdev);
219062306a36Sopenharmony_ci	if (r)
219162306a36Sopenharmony_ci		return r;
219262306a36Sopenharmony_ci
219362306a36Sopenharmony_ci	r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX);
219462306a36Sopenharmony_ci	if (r) {
219562306a36Sopenharmony_ci		dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r);
219662306a36Sopenharmony_ci		return r;
219762306a36Sopenharmony_ci	}
219862306a36Sopenharmony_ci
219962306a36Sopenharmony_ci	cayman_uvd_start(rdev);
220062306a36Sopenharmony_ci	cayman_vce_start(rdev);
220162306a36Sopenharmony_ci
220262306a36Sopenharmony_ci	r = radeon_fence_driver_start_ring(rdev, CAYMAN_RING_TYPE_CP1_INDEX);
220362306a36Sopenharmony_ci	if (r) {
220462306a36Sopenharmony_ci		dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r);
220562306a36Sopenharmony_ci		return r;
220662306a36Sopenharmony_ci	}
220762306a36Sopenharmony_ci
220862306a36Sopenharmony_ci	r = radeon_fence_driver_start_ring(rdev, CAYMAN_RING_TYPE_CP2_INDEX);
220962306a36Sopenharmony_ci	if (r) {
221062306a36Sopenharmony_ci		dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r);
221162306a36Sopenharmony_ci		return r;
221262306a36Sopenharmony_ci	}
221362306a36Sopenharmony_ci
221462306a36Sopenharmony_ci	r = radeon_fence_driver_start_ring(rdev, R600_RING_TYPE_DMA_INDEX);
221562306a36Sopenharmony_ci	if (r) {
221662306a36Sopenharmony_ci		dev_err(rdev->dev, "failed initializing DMA fences (%d).\n", r);
221762306a36Sopenharmony_ci		return r;
221862306a36Sopenharmony_ci	}
221962306a36Sopenharmony_ci
222062306a36Sopenharmony_ci	r = radeon_fence_driver_start_ring(rdev, CAYMAN_RING_TYPE_DMA1_INDEX);
222162306a36Sopenharmony_ci	if (r) {
222262306a36Sopenharmony_ci		dev_err(rdev->dev, "failed initializing DMA fences (%d).\n", r);
222362306a36Sopenharmony_ci		return r;
222462306a36Sopenharmony_ci	}
222562306a36Sopenharmony_ci
222662306a36Sopenharmony_ci	/* Enable IRQ */
222762306a36Sopenharmony_ci	if (!rdev->irq.installed) {
222862306a36Sopenharmony_ci		r = radeon_irq_kms_init(rdev);
222962306a36Sopenharmony_ci		if (r)
223062306a36Sopenharmony_ci			return r;
223162306a36Sopenharmony_ci	}
223262306a36Sopenharmony_ci
223362306a36Sopenharmony_ci	r = r600_irq_init(rdev);
223462306a36Sopenharmony_ci	if (r) {
223562306a36Sopenharmony_ci		DRM_ERROR("radeon: IH init failed (%d).\n", r);
223662306a36Sopenharmony_ci		radeon_irq_kms_fini(rdev);
223762306a36Sopenharmony_ci		return r;
223862306a36Sopenharmony_ci	}
223962306a36Sopenharmony_ci	evergreen_irq_set(rdev);
224062306a36Sopenharmony_ci
224162306a36Sopenharmony_ci	r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET,
224262306a36Sopenharmony_ci			     RADEON_CP_PACKET2);
224362306a36Sopenharmony_ci	if (r)
224462306a36Sopenharmony_ci		return r;
224562306a36Sopenharmony_ci
224662306a36Sopenharmony_ci	ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX];
224762306a36Sopenharmony_ci	r = radeon_ring_init(rdev, ring, ring->ring_size, R600_WB_DMA_RPTR_OFFSET,
224862306a36Sopenharmony_ci			     DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0));
224962306a36Sopenharmony_ci	if (r)
225062306a36Sopenharmony_ci		return r;
225162306a36Sopenharmony_ci
225262306a36Sopenharmony_ci	ring = &rdev->ring[CAYMAN_RING_TYPE_DMA1_INDEX];
225362306a36Sopenharmony_ci	r = radeon_ring_init(rdev, ring, ring->ring_size, CAYMAN_WB_DMA1_RPTR_OFFSET,
225462306a36Sopenharmony_ci			     DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0));
225562306a36Sopenharmony_ci	if (r)
225662306a36Sopenharmony_ci		return r;
225762306a36Sopenharmony_ci
225862306a36Sopenharmony_ci	r = cayman_cp_load_microcode(rdev);
225962306a36Sopenharmony_ci	if (r)
226062306a36Sopenharmony_ci		return r;
226162306a36Sopenharmony_ci	r = cayman_cp_resume(rdev);
226262306a36Sopenharmony_ci	if (r)
226362306a36Sopenharmony_ci		return r;
226462306a36Sopenharmony_ci
226562306a36Sopenharmony_ci	r = cayman_dma_resume(rdev);
226662306a36Sopenharmony_ci	if (r)
226762306a36Sopenharmony_ci		return r;
226862306a36Sopenharmony_ci
226962306a36Sopenharmony_ci	cayman_uvd_resume(rdev);
227062306a36Sopenharmony_ci	cayman_vce_resume(rdev);
227162306a36Sopenharmony_ci
227262306a36Sopenharmony_ci	r = radeon_ib_pool_init(rdev);
227362306a36Sopenharmony_ci	if (r) {
227462306a36Sopenharmony_ci		dev_err(rdev->dev, "IB initialization failed (%d).\n", r);
227562306a36Sopenharmony_ci		return r;
227662306a36Sopenharmony_ci	}
227762306a36Sopenharmony_ci
227862306a36Sopenharmony_ci	r = radeon_vm_manager_init(rdev);
227962306a36Sopenharmony_ci	if (r) {
228062306a36Sopenharmony_ci		dev_err(rdev->dev, "vm manager initialization failed (%d).\n", r);
228162306a36Sopenharmony_ci		return r;
228262306a36Sopenharmony_ci	}
228362306a36Sopenharmony_ci
228462306a36Sopenharmony_ci	r = radeon_audio_init(rdev);
228562306a36Sopenharmony_ci	if (r)
228662306a36Sopenharmony_ci		return r;
228762306a36Sopenharmony_ci
228862306a36Sopenharmony_ci	return 0;
228962306a36Sopenharmony_ci}
229062306a36Sopenharmony_ci
229162306a36Sopenharmony_ciint cayman_resume(struct radeon_device *rdev)
229262306a36Sopenharmony_ci{
229362306a36Sopenharmony_ci	int r;
229462306a36Sopenharmony_ci
229562306a36Sopenharmony_ci	/* Do not reset GPU before posting, on rv770 hw unlike on r500 hw,
229662306a36Sopenharmony_ci	 * posting will perform necessary task to bring back GPU into good
229762306a36Sopenharmony_ci	 * shape.
229862306a36Sopenharmony_ci	 */
229962306a36Sopenharmony_ci	/* post card */
230062306a36Sopenharmony_ci	atom_asic_init(rdev->mode_info.atom_context);
230162306a36Sopenharmony_ci
230262306a36Sopenharmony_ci	/* init golden registers */
230362306a36Sopenharmony_ci	ni_init_golden_registers(rdev);
230462306a36Sopenharmony_ci
230562306a36Sopenharmony_ci	if (rdev->pm.pm_method == PM_METHOD_DPM)
230662306a36Sopenharmony_ci		radeon_pm_resume(rdev);
230762306a36Sopenharmony_ci
230862306a36Sopenharmony_ci	rdev->accel_working = true;
230962306a36Sopenharmony_ci	r = cayman_startup(rdev);
231062306a36Sopenharmony_ci	if (r) {
231162306a36Sopenharmony_ci		DRM_ERROR("cayman startup failed on resume\n");
231262306a36Sopenharmony_ci		rdev->accel_working = false;
231362306a36Sopenharmony_ci		return r;
231462306a36Sopenharmony_ci	}
231562306a36Sopenharmony_ci	return r;
231662306a36Sopenharmony_ci}
231762306a36Sopenharmony_ci
231862306a36Sopenharmony_ciint cayman_suspend(struct radeon_device *rdev)
231962306a36Sopenharmony_ci{
232062306a36Sopenharmony_ci	radeon_pm_suspend(rdev);
232162306a36Sopenharmony_ci	radeon_audio_fini(rdev);
232262306a36Sopenharmony_ci	radeon_vm_manager_fini(rdev);
232362306a36Sopenharmony_ci	cayman_cp_enable(rdev, false);
232462306a36Sopenharmony_ci	cayman_dma_stop(rdev);
232562306a36Sopenharmony_ci	if (rdev->has_uvd) {
232662306a36Sopenharmony_ci		radeon_uvd_suspend(rdev);
232762306a36Sopenharmony_ci		uvd_v1_0_fini(rdev);
232862306a36Sopenharmony_ci	}
232962306a36Sopenharmony_ci	evergreen_irq_suspend(rdev);
233062306a36Sopenharmony_ci	radeon_wb_disable(rdev);
233162306a36Sopenharmony_ci	cayman_pcie_gart_disable(rdev);
233262306a36Sopenharmony_ci	return 0;
233362306a36Sopenharmony_ci}
233462306a36Sopenharmony_ci
233562306a36Sopenharmony_ci/* Plan is to move initialization in that function and use
233662306a36Sopenharmony_ci * helper function so that radeon_device_init pretty much
233762306a36Sopenharmony_ci * do nothing more than calling asic specific function. This
233862306a36Sopenharmony_ci * should also allow to remove a bunch of callback function
233962306a36Sopenharmony_ci * like vram_info.
234062306a36Sopenharmony_ci */
234162306a36Sopenharmony_ciint cayman_init(struct radeon_device *rdev)
234262306a36Sopenharmony_ci{
234362306a36Sopenharmony_ci	struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
234462306a36Sopenharmony_ci	int r;
234562306a36Sopenharmony_ci
234662306a36Sopenharmony_ci	/* Read BIOS */
234762306a36Sopenharmony_ci	if (!radeon_get_bios(rdev)) {
234862306a36Sopenharmony_ci		if (ASIC_IS_AVIVO(rdev))
234962306a36Sopenharmony_ci			return -EINVAL;
235062306a36Sopenharmony_ci	}
235162306a36Sopenharmony_ci	/* Must be an ATOMBIOS */
235262306a36Sopenharmony_ci	if (!rdev->is_atom_bios) {
235362306a36Sopenharmony_ci		dev_err(rdev->dev, "Expecting atombios for cayman GPU\n");
235462306a36Sopenharmony_ci		return -EINVAL;
235562306a36Sopenharmony_ci	}
235662306a36Sopenharmony_ci	r = radeon_atombios_init(rdev);
235762306a36Sopenharmony_ci	if (r)
235862306a36Sopenharmony_ci		return r;
235962306a36Sopenharmony_ci
236062306a36Sopenharmony_ci	/* Post card if necessary */
236162306a36Sopenharmony_ci	if (!radeon_card_posted(rdev)) {
236262306a36Sopenharmony_ci		if (!rdev->bios) {
236362306a36Sopenharmony_ci			dev_err(rdev->dev, "Card not posted and no BIOS - ignoring\n");
236462306a36Sopenharmony_ci			return -EINVAL;
236562306a36Sopenharmony_ci		}
236662306a36Sopenharmony_ci		DRM_INFO("GPU not posted. posting now...\n");
236762306a36Sopenharmony_ci		atom_asic_init(rdev->mode_info.atom_context);
236862306a36Sopenharmony_ci	}
236962306a36Sopenharmony_ci	/* init golden registers */
237062306a36Sopenharmony_ci	ni_init_golden_registers(rdev);
237162306a36Sopenharmony_ci	/* Initialize scratch registers */
237262306a36Sopenharmony_ci	r600_scratch_init(rdev);
237362306a36Sopenharmony_ci	/* Initialize surface registers */
237462306a36Sopenharmony_ci	radeon_surface_init(rdev);
237562306a36Sopenharmony_ci	/* Initialize clocks */
237662306a36Sopenharmony_ci	radeon_get_clock_info(rdev->ddev);
237762306a36Sopenharmony_ci	/* Fence driver */
237862306a36Sopenharmony_ci	radeon_fence_driver_init(rdev);
237962306a36Sopenharmony_ci	/* initialize memory controller */
238062306a36Sopenharmony_ci	r = evergreen_mc_init(rdev);
238162306a36Sopenharmony_ci	if (r)
238262306a36Sopenharmony_ci		return r;
238362306a36Sopenharmony_ci	/* Memory manager */
238462306a36Sopenharmony_ci	r = radeon_bo_init(rdev);
238562306a36Sopenharmony_ci	if (r)
238662306a36Sopenharmony_ci		return r;
238762306a36Sopenharmony_ci
238862306a36Sopenharmony_ci	if (rdev->flags & RADEON_IS_IGP) {
238962306a36Sopenharmony_ci		if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) {
239062306a36Sopenharmony_ci			r = ni_init_microcode(rdev);
239162306a36Sopenharmony_ci			if (r) {
239262306a36Sopenharmony_ci				DRM_ERROR("Failed to load firmware!\n");
239362306a36Sopenharmony_ci				return r;
239462306a36Sopenharmony_ci			}
239562306a36Sopenharmony_ci		}
239662306a36Sopenharmony_ci	} else {
239762306a36Sopenharmony_ci		if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw || !rdev->mc_fw) {
239862306a36Sopenharmony_ci			r = ni_init_microcode(rdev);
239962306a36Sopenharmony_ci			if (r) {
240062306a36Sopenharmony_ci				DRM_ERROR("Failed to load firmware!\n");
240162306a36Sopenharmony_ci				return r;
240262306a36Sopenharmony_ci			}
240362306a36Sopenharmony_ci		}
240462306a36Sopenharmony_ci	}
240562306a36Sopenharmony_ci
240662306a36Sopenharmony_ci	/* Initialize power management */
240762306a36Sopenharmony_ci	radeon_pm_init(rdev);
240862306a36Sopenharmony_ci
240962306a36Sopenharmony_ci	ring->ring_obj = NULL;
241062306a36Sopenharmony_ci	r600_ring_init(rdev, ring, 1024 * 1024);
241162306a36Sopenharmony_ci
241262306a36Sopenharmony_ci	ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX];
241362306a36Sopenharmony_ci	ring->ring_obj = NULL;
241462306a36Sopenharmony_ci	r600_ring_init(rdev, ring, 64 * 1024);
241562306a36Sopenharmony_ci
241662306a36Sopenharmony_ci	ring = &rdev->ring[CAYMAN_RING_TYPE_DMA1_INDEX];
241762306a36Sopenharmony_ci	ring->ring_obj = NULL;
241862306a36Sopenharmony_ci	r600_ring_init(rdev, ring, 64 * 1024);
241962306a36Sopenharmony_ci
242062306a36Sopenharmony_ci	cayman_uvd_init(rdev);
242162306a36Sopenharmony_ci	cayman_vce_init(rdev);
242262306a36Sopenharmony_ci
242362306a36Sopenharmony_ci	rdev->ih.ring_obj = NULL;
242462306a36Sopenharmony_ci	r600_ih_ring_init(rdev, 64 * 1024);
242562306a36Sopenharmony_ci
242662306a36Sopenharmony_ci	r = r600_pcie_gart_init(rdev);
242762306a36Sopenharmony_ci	if (r)
242862306a36Sopenharmony_ci		return r;
242962306a36Sopenharmony_ci
243062306a36Sopenharmony_ci	rdev->accel_working = true;
243162306a36Sopenharmony_ci	r = cayman_startup(rdev);
243262306a36Sopenharmony_ci	if (r) {
243362306a36Sopenharmony_ci		dev_err(rdev->dev, "disabling GPU acceleration\n");
243462306a36Sopenharmony_ci		cayman_cp_fini(rdev);
243562306a36Sopenharmony_ci		cayman_dma_fini(rdev);
243662306a36Sopenharmony_ci		r600_irq_fini(rdev);
243762306a36Sopenharmony_ci		if (rdev->flags & RADEON_IS_IGP)
243862306a36Sopenharmony_ci			sumo_rlc_fini(rdev);
243962306a36Sopenharmony_ci		radeon_wb_fini(rdev);
244062306a36Sopenharmony_ci		radeon_ib_pool_fini(rdev);
244162306a36Sopenharmony_ci		radeon_vm_manager_fini(rdev);
244262306a36Sopenharmony_ci		radeon_irq_kms_fini(rdev);
244362306a36Sopenharmony_ci		cayman_pcie_gart_fini(rdev);
244462306a36Sopenharmony_ci		rdev->accel_working = false;
244562306a36Sopenharmony_ci	}
244662306a36Sopenharmony_ci
244762306a36Sopenharmony_ci	/* Don't start up if the MC ucode is missing.
244862306a36Sopenharmony_ci	 * The default clocks and voltages before the MC ucode
244962306a36Sopenharmony_ci	 * is loaded are not suffient for advanced operations.
245062306a36Sopenharmony_ci	 *
245162306a36Sopenharmony_ci	 * We can skip this check for TN, because there is no MC
245262306a36Sopenharmony_ci	 * ucode.
245362306a36Sopenharmony_ci	 */
245462306a36Sopenharmony_ci	if (!rdev->mc_fw && !(rdev->flags & RADEON_IS_IGP)) {
245562306a36Sopenharmony_ci		DRM_ERROR("radeon: MC ucode required for NI+.\n");
245662306a36Sopenharmony_ci		return -EINVAL;
245762306a36Sopenharmony_ci	}
245862306a36Sopenharmony_ci
245962306a36Sopenharmony_ci	return 0;
246062306a36Sopenharmony_ci}
246162306a36Sopenharmony_ci
246262306a36Sopenharmony_civoid cayman_fini(struct radeon_device *rdev)
246362306a36Sopenharmony_ci{
246462306a36Sopenharmony_ci	radeon_pm_fini(rdev);
246562306a36Sopenharmony_ci	cayman_cp_fini(rdev);
246662306a36Sopenharmony_ci	cayman_dma_fini(rdev);
246762306a36Sopenharmony_ci	r600_irq_fini(rdev);
246862306a36Sopenharmony_ci	if (rdev->flags & RADEON_IS_IGP)
246962306a36Sopenharmony_ci		sumo_rlc_fini(rdev);
247062306a36Sopenharmony_ci	radeon_wb_fini(rdev);
247162306a36Sopenharmony_ci	radeon_vm_manager_fini(rdev);
247262306a36Sopenharmony_ci	radeon_ib_pool_fini(rdev);
247362306a36Sopenharmony_ci	radeon_irq_kms_fini(rdev);
247462306a36Sopenharmony_ci	uvd_v1_0_fini(rdev);
247562306a36Sopenharmony_ci	radeon_uvd_fini(rdev);
247662306a36Sopenharmony_ci	if (rdev->has_vce)
247762306a36Sopenharmony_ci		radeon_vce_fini(rdev);
247862306a36Sopenharmony_ci	cayman_pcie_gart_fini(rdev);
247962306a36Sopenharmony_ci	r600_vram_scratch_fini(rdev);
248062306a36Sopenharmony_ci	radeon_gem_fini(rdev);
248162306a36Sopenharmony_ci	radeon_fence_driver_fini(rdev);
248262306a36Sopenharmony_ci	radeon_bo_fini(rdev);
248362306a36Sopenharmony_ci	radeon_atombios_fini(rdev);
248462306a36Sopenharmony_ci	kfree(rdev->bios);
248562306a36Sopenharmony_ci	rdev->bios = NULL;
248662306a36Sopenharmony_ci}
248762306a36Sopenharmony_ci
248862306a36Sopenharmony_ci/*
248962306a36Sopenharmony_ci * vm
249062306a36Sopenharmony_ci */
249162306a36Sopenharmony_ciint cayman_vm_init(struct radeon_device *rdev)
249262306a36Sopenharmony_ci{
249362306a36Sopenharmony_ci	/* number of VMs */
249462306a36Sopenharmony_ci	rdev->vm_manager.nvm = 8;
249562306a36Sopenharmony_ci	/* base offset of vram pages */
249662306a36Sopenharmony_ci	if (rdev->flags & RADEON_IS_IGP) {
249762306a36Sopenharmony_ci		u64 tmp = RREG32(FUS_MC_VM_FB_OFFSET);
249862306a36Sopenharmony_ci		tmp <<= 22;
249962306a36Sopenharmony_ci		rdev->vm_manager.vram_base_offset = tmp;
250062306a36Sopenharmony_ci	} else
250162306a36Sopenharmony_ci		rdev->vm_manager.vram_base_offset = 0;
250262306a36Sopenharmony_ci	return 0;
250362306a36Sopenharmony_ci}
250462306a36Sopenharmony_ci
250562306a36Sopenharmony_civoid cayman_vm_fini(struct radeon_device *rdev)
250662306a36Sopenharmony_ci{
250762306a36Sopenharmony_ci}
250862306a36Sopenharmony_ci
250962306a36Sopenharmony_ci/**
251062306a36Sopenharmony_ci * cayman_vm_decode_fault - print human readable fault info
251162306a36Sopenharmony_ci *
251262306a36Sopenharmony_ci * @rdev: radeon_device pointer
251362306a36Sopenharmony_ci * @status: VM_CONTEXT1_PROTECTION_FAULT_STATUS register value
251462306a36Sopenharmony_ci * @addr: VM_CONTEXT1_PROTECTION_FAULT_ADDR register value
251562306a36Sopenharmony_ci *
251662306a36Sopenharmony_ci * Print human readable fault information (cayman/TN).
251762306a36Sopenharmony_ci */
251862306a36Sopenharmony_civoid cayman_vm_decode_fault(struct radeon_device *rdev,
251962306a36Sopenharmony_ci			    u32 status, u32 addr)
252062306a36Sopenharmony_ci{
252162306a36Sopenharmony_ci	u32 mc_id = (status & MEMORY_CLIENT_ID_MASK) >> MEMORY_CLIENT_ID_SHIFT;
252262306a36Sopenharmony_ci	u32 vmid = (status & FAULT_VMID_MASK) >> FAULT_VMID_SHIFT;
252362306a36Sopenharmony_ci	u32 protections = (status & PROTECTIONS_MASK) >> PROTECTIONS_SHIFT;
252462306a36Sopenharmony_ci	char *block;
252562306a36Sopenharmony_ci
252662306a36Sopenharmony_ci	switch (mc_id) {
252762306a36Sopenharmony_ci	case 32:
252862306a36Sopenharmony_ci	case 16:
252962306a36Sopenharmony_ci	case 96:
253062306a36Sopenharmony_ci	case 80:
253162306a36Sopenharmony_ci	case 160:
253262306a36Sopenharmony_ci	case 144:
253362306a36Sopenharmony_ci	case 224:
253462306a36Sopenharmony_ci	case 208:
253562306a36Sopenharmony_ci		block = "CB";
253662306a36Sopenharmony_ci		break;
253762306a36Sopenharmony_ci	case 33:
253862306a36Sopenharmony_ci	case 17:
253962306a36Sopenharmony_ci	case 97:
254062306a36Sopenharmony_ci	case 81:
254162306a36Sopenharmony_ci	case 161:
254262306a36Sopenharmony_ci	case 145:
254362306a36Sopenharmony_ci	case 225:
254462306a36Sopenharmony_ci	case 209:
254562306a36Sopenharmony_ci		block = "CB_FMASK";
254662306a36Sopenharmony_ci		break;
254762306a36Sopenharmony_ci	case 34:
254862306a36Sopenharmony_ci	case 18:
254962306a36Sopenharmony_ci	case 98:
255062306a36Sopenharmony_ci	case 82:
255162306a36Sopenharmony_ci	case 162:
255262306a36Sopenharmony_ci	case 146:
255362306a36Sopenharmony_ci	case 226:
255462306a36Sopenharmony_ci	case 210:
255562306a36Sopenharmony_ci		block = "CB_CMASK";
255662306a36Sopenharmony_ci		break;
255762306a36Sopenharmony_ci	case 35:
255862306a36Sopenharmony_ci	case 19:
255962306a36Sopenharmony_ci	case 99:
256062306a36Sopenharmony_ci	case 83:
256162306a36Sopenharmony_ci	case 163:
256262306a36Sopenharmony_ci	case 147:
256362306a36Sopenharmony_ci	case 227:
256462306a36Sopenharmony_ci	case 211:
256562306a36Sopenharmony_ci		block = "CB_IMMED";
256662306a36Sopenharmony_ci		break;
256762306a36Sopenharmony_ci	case 36:
256862306a36Sopenharmony_ci	case 20:
256962306a36Sopenharmony_ci	case 100:
257062306a36Sopenharmony_ci	case 84:
257162306a36Sopenharmony_ci	case 164:
257262306a36Sopenharmony_ci	case 148:
257362306a36Sopenharmony_ci	case 228:
257462306a36Sopenharmony_ci	case 212:
257562306a36Sopenharmony_ci		block = "DB";
257662306a36Sopenharmony_ci		break;
257762306a36Sopenharmony_ci	case 37:
257862306a36Sopenharmony_ci	case 21:
257962306a36Sopenharmony_ci	case 101:
258062306a36Sopenharmony_ci	case 85:
258162306a36Sopenharmony_ci	case 165:
258262306a36Sopenharmony_ci	case 149:
258362306a36Sopenharmony_ci	case 229:
258462306a36Sopenharmony_ci	case 213:
258562306a36Sopenharmony_ci		block = "DB_HTILE";
258662306a36Sopenharmony_ci		break;
258762306a36Sopenharmony_ci	case 38:
258862306a36Sopenharmony_ci	case 22:
258962306a36Sopenharmony_ci	case 102:
259062306a36Sopenharmony_ci	case 86:
259162306a36Sopenharmony_ci	case 166:
259262306a36Sopenharmony_ci	case 150:
259362306a36Sopenharmony_ci	case 230:
259462306a36Sopenharmony_ci	case 214:
259562306a36Sopenharmony_ci		block = "SX";
259662306a36Sopenharmony_ci		break;
259762306a36Sopenharmony_ci	case 39:
259862306a36Sopenharmony_ci	case 23:
259962306a36Sopenharmony_ci	case 103:
260062306a36Sopenharmony_ci	case 87:
260162306a36Sopenharmony_ci	case 167:
260262306a36Sopenharmony_ci	case 151:
260362306a36Sopenharmony_ci	case 231:
260462306a36Sopenharmony_ci	case 215:
260562306a36Sopenharmony_ci		block = "DB_STEN";
260662306a36Sopenharmony_ci		break;
260762306a36Sopenharmony_ci	case 40:
260862306a36Sopenharmony_ci	case 24:
260962306a36Sopenharmony_ci	case 104:
261062306a36Sopenharmony_ci	case 88:
261162306a36Sopenharmony_ci	case 232:
261262306a36Sopenharmony_ci	case 216:
261362306a36Sopenharmony_ci	case 168:
261462306a36Sopenharmony_ci	case 152:
261562306a36Sopenharmony_ci		block = "TC_TFETCH";
261662306a36Sopenharmony_ci		break;
261762306a36Sopenharmony_ci	case 41:
261862306a36Sopenharmony_ci	case 25:
261962306a36Sopenharmony_ci	case 105:
262062306a36Sopenharmony_ci	case 89:
262162306a36Sopenharmony_ci	case 233:
262262306a36Sopenharmony_ci	case 217:
262362306a36Sopenharmony_ci	case 169:
262462306a36Sopenharmony_ci	case 153:
262562306a36Sopenharmony_ci		block = "TC_VFETCH";
262662306a36Sopenharmony_ci		break;
262762306a36Sopenharmony_ci	case 42:
262862306a36Sopenharmony_ci	case 26:
262962306a36Sopenharmony_ci	case 106:
263062306a36Sopenharmony_ci	case 90:
263162306a36Sopenharmony_ci	case 234:
263262306a36Sopenharmony_ci	case 218:
263362306a36Sopenharmony_ci	case 170:
263462306a36Sopenharmony_ci	case 154:
263562306a36Sopenharmony_ci		block = "VC";
263662306a36Sopenharmony_ci		break;
263762306a36Sopenharmony_ci	case 112:
263862306a36Sopenharmony_ci		block = "CP";
263962306a36Sopenharmony_ci		break;
264062306a36Sopenharmony_ci	case 113:
264162306a36Sopenharmony_ci	case 114:
264262306a36Sopenharmony_ci		block = "SH";
264362306a36Sopenharmony_ci		break;
264462306a36Sopenharmony_ci	case 115:
264562306a36Sopenharmony_ci		block = "VGT";
264662306a36Sopenharmony_ci		break;
264762306a36Sopenharmony_ci	case 178:
264862306a36Sopenharmony_ci		block = "IH";
264962306a36Sopenharmony_ci		break;
265062306a36Sopenharmony_ci	case 51:
265162306a36Sopenharmony_ci		block = "RLC";
265262306a36Sopenharmony_ci		break;
265362306a36Sopenharmony_ci	case 55:
265462306a36Sopenharmony_ci		block = "DMA";
265562306a36Sopenharmony_ci		break;
265662306a36Sopenharmony_ci	case 56:
265762306a36Sopenharmony_ci		block = "HDP";
265862306a36Sopenharmony_ci		break;
265962306a36Sopenharmony_ci	default:
266062306a36Sopenharmony_ci		block = "unknown";
266162306a36Sopenharmony_ci		break;
266262306a36Sopenharmony_ci	}
266362306a36Sopenharmony_ci
266462306a36Sopenharmony_ci	printk("VM fault (0x%02x, vmid %d) at page %u, %s from %s (%d)\n",
266562306a36Sopenharmony_ci	       protections, vmid, addr,
266662306a36Sopenharmony_ci	       (status & MEMORY_CLIENT_RW_MASK) ? "write" : "read",
266762306a36Sopenharmony_ci	       block, mc_id);
266862306a36Sopenharmony_ci}
266962306a36Sopenharmony_ci
267062306a36Sopenharmony_ci/*
267162306a36Sopenharmony_ci * cayman_vm_flush - vm flush using the CP
267262306a36Sopenharmony_ci *
267362306a36Sopenharmony_ci * Update the page table base and flush the VM TLB
267462306a36Sopenharmony_ci * using the CP (cayman-si).
267562306a36Sopenharmony_ci */
267662306a36Sopenharmony_civoid cayman_vm_flush(struct radeon_device *rdev, struct radeon_ring *ring,
267762306a36Sopenharmony_ci		     unsigned vm_id, uint64_t pd_addr)
267862306a36Sopenharmony_ci{
267962306a36Sopenharmony_ci	radeon_ring_write(ring, PACKET0(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (vm_id << 2), 0));
268062306a36Sopenharmony_ci	radeon_ring_write(ring, pd_addr >> 12);
268162306a36Sopenharmony_ci
268262306a36Sopenharmony_ci	/* flush hdp cache */
268362306a36Sopenharmony_ci	radeon_ring_write(ring, PACKET0(HDP_MEM_COHERENCY_FLUSH_CNTL, 0));
268462306a36Sopenharmony_ci	radeon_ring_write(ring, 0x1);
268562306a36Sopenharmony_ci
268662306a36Sopenharmony_ci	/* bits 0-7 are the VM contexts0-7 */
268762306a36Sopenharmony_ci	radeon_ring_write(ring, PACKET0(VM_INVALIDATE_REQUEST, 0));
268862306a36Sopenharmony_ci	radeon_ring_write(ring, 1 << vm_id);
268962306a36Sopenharmony_ci
269062306a36Sopenharmony_ci	/* wait for the invalidate to complete */
269162306a36Sopenharmony_ci	radeon_ring_write(ring, PACKET3(PACKET3_WAIT_REG_MEM, 5));
269262306a36Sopenharmony_ci	radeon_ring_write(ring, (WAIT_REG_MEM_FUNCTION(0) |  /* always */
269362306a36Sopenharmony_ci				 WAIT_REG_MEM_ENGINE(0))); /* me */
269462306a36Sopenharmony_ci	radeon_ring_write(ring, VM_INVALIDATE_REQUEST >> 2);
269562306a36Sopenharmony_ci	radeon_ring_write(ring, 0);
269662306a36Sopenharmony_ci	radeon_ring_write(ring, 0); /* ref */
269762306a36Sopenharmony_ci	radeon_ring_write(ring, 0); /* mask */
269862306a36Sopenharmony_ci	radeon_ring_write(ring, 0x20); /* poll interval */
269962306a36Sopenharmony_ci
270062306a36Sopenharmony_ci	/* sync PFP to ME, otherwise we might get invalid PFP reads */
270162306a36Sopenharmony_ci	radeon_ring_write(ring, PACKET3(PACKET3_PFP_SYNC_ME, 0));
270262306a36Sopenharmony_ci	radeon_ring_write(ring, 0x0);
270362306a36Sopenharmony_ci}
270462306a36Sopenharmony_ci
270562306a36Sopenharmony_ciint tn_set_vce_clocks(struct radeon_device *rdev, u32 evclk, u32 ecclk)
270662306a36Sopenharmony_ci{
270762306a36Sopenharmony_ci	struct atom_clock_dividers dividers;
270862306a36Sopenharmony_ci	int r, i;
270962306a36Sopenharmony_ci
271062306a36Sopenharmony_ci	r = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM,
271162306a36Sopenharmony_ci					   ecclk, false, &dividers);
271262306a36Sopenharmony_ci	if (r)
271362306a36Sopenharmony_ci		return r;
271462306a36Sopenharmony_ci
271562306a36Sopenharmony_ci	for (i = 0; i < 100; i++) {
271662306a36Sopenharmony_ci		if (RREG32(CG_ECLK_STATUS) & ECLK_STATUS)
271762306a36Sopenharmony_ci			break;
271862306a36Sopenharmony_ci		mdelay(10);
271962306a36Sopenharmony_ci	}
272062306a36Sopenharmony_ci	if (i == 100)
272162306a36Sopenharmony_ci		return -ETIMEDOUT;
272262306a36Sopenharmony_ci
272362306a36Sopenharmony_ci	WREG32_P(CG_ECLK_CNTL, dividers.post_div, ~(ECLK_DIR_CNTL_EN|ECLK_DIVIDER_MASK));
272462306a36Sopenharmony_ci
272562306a36Sopenharmony_ci	for (i = 0; i < 100; i++) {
272662306a36Sopenharmony_ci		if (RREG32(CG_ECLK_STATUS) & ECLK_STATUS)
272762306a36Sopenharmony_ci			break;
272862306a36Sopenharmony_ci		mdelay(10);
272962306a36Sopenharmony_ci	}
273062306a36Sopenharmony_ci	if (i == 100)
273162306a36Sopenharmony_ci		return -ETIMEDOUT;
273262306a36Sopenharmony_ci
273362306a36Sopenharmony_ci	return 0;
273462306a36Sopenharmony_ci}
2735