xref: /dflybsd-src/sys/dev/drm/radeon/ni.c (revision fcd4983f104ccbc67b86e44d3eb379aa01d53b86)
1926deccbSFrançois Tigeot /*
2926deccbSFrançois Tigeot  * Copyright 2010 Advanced Micro Devices, Inc.
3926deccbSFrançois Tigeot  *
4926deccbSFrançois Tigeot  * Permission is hereby granted, free of charge, to any person obtaining a
5926deccbSFrançois Tigeot  * copy of this software and associated documentation files (the "Software"),
6926deccbSFrançois Tigeot  * to deal in the Software without restriction, including without limitation
7926deccbSFrançois Tigeot  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8926deccbSFrançois Tigeot  * and/or sell copies of the Software, and to permit persons to whom the
9926deccbSFrançois Tigeot  * Software is furnished to do so, subject to the following conditions:
10926deccbSFrançois Tigeot  *
11926deccbSFrançois Tigeot  * The above copyright notice and this permission notice shall be included in
12926deccbSFrançois Tigeot  * all copies or substantial portions of the Software.
13926deccbSFrançois Tigeot  *
14926deccbSFrançois Tigeot  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15926deccbSFrançois Tigeot  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16926deccbSFrançois Tigeot  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17926deccbSFrançois Tigeot  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18926deccbSFrançois Tigeot  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19926deccbSFrançois Tigeot  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20926deccbSFrançois Tigeot  * OTHER DEALINGS IN THE SOFTWARE.
21926deccbSFrançois Tigeot  *
22926deccbSFrançois Tigeot  * Authors: Alex Deucher
23926deccbSFrançois Tigeot  * $FreeBSD: head/sys/dev/drm2/radeon/ni.c 254885 2013-08-25 19:37:15Z dumbbell $
24926deccbSFrançois Tigeot  */
2557e252bfSMichael Neumann #include <linux/firmware.h>
26*fcd4983fSzrj #include <linux/module.h>
27*fcd4983fSzrj #include <drm/drmP.h>
28926deccbSFrançois Tigeot #include "radeon.h"
29926deccbSFrançois Tigeot #include "radeon_asic.h"
30926deccbSFrançois Tigeot #include <uapi_drm/radeon_drm.h>
31926deccbSFrançois Tigeot #include "nid.h"
32926deccbSFrançois Tigeot #include "atom.h"
33926deccbSFrançois Tigeot #include "ni_reg.h"
34926deccbSFrançois Tigeot #include "cayman_blit_shaders.h"
3557e252bfSMichael Neumann #include "radeon_ucode.h"
3657e252bfSMichael Neumann #include "clearstate_cayman.h"
37926deccbSFrançois Tigeot 
3857e252bfSMichael Neumann static u32 tn_rlc_save_restore_register_list[] =
3957e252bfSMichael Neumann {
4057e252bfSMichael Neumann 	0x98fc,
4157e252bfSMichael Neumann 	0x98f0,
4257e252bfSMichael Neumann 	0x9834,
4357e252bfSMichael Neumann 	0x9838,
4457e252bfSMichael Neumann 	0x9870,
4557e252bfSMichael Neumann 	0x9874,
4657e252bfSMichael Neumann 	0x8a14,
4757e252bfSMichael Neumann 	0x8b24,
4857e252bfSMichael Neumann 	0x8bcc,
4957e252bfSMichael Neumann 	0x8b10,
5057e252bfSMichael Neumann 	0x8c30,
5157e252bfSMichael Neumann 	0x8d00,
5257e252bfSMichael Neumann 	0x8d04,
5357e252bfSMichael Neumann 	0x8c00,
5457e252bfSMichael Neumann 	0x8c04,
5557e252bfSMichael Neumann 	0x8c10,
5657e252bfSMichael Neumann 	0x8c14,
5757e252bfSMichael Neumann 	0x8d8c,
5857e252bfSMichael Neumann 	0x8cf0,
5957e252bfSMichael Neumann 	0x8e38,
6057e252bfSMichael Neumann 	0x9508,
6157e252bfSMichael Neumann 	0x9688,
6257e252bfSMichael Neumann 	0x9608,
6357e252bfSMichael Neumann 	0x960c,
6457e252bfSMichael Neumann 	0x9610,
6557e252bfSMichael Neumann 	0x9614,
6657e252bfSMichael Neumann 	0x88c4,
6757e252bfSMichael Neumann 	0x8978,
6857e252bfSMichael Neumann 	0x88d4,
6957e252bfSMichael Neumann 	0x900c,
7057e252bfSMichael Neumann 	0x9100,
7157e252bfSMichael Neumann 	0x913c,
7257e252bfSMichael Neumann 	0x90e8,
7357e252bfSMichael Neumann 	0x9354,
7457e252bfSMichael Neumann 	0xa008,
7557e252bfSMichael Neumann 	0x98f8,
7657e252bfSMichael Neumann 	0x9148,
7757e252bfSMichael Neumann 	0x914c,
7857e252bfSMichael Neumann 	0x3f94,
7957e252bfSMichael Neumann 	0x98f4,
8057e252bfSMichael Neumann 	0x9b7c,
8157e252bfSMichael Neumann 	0x3f8c,
8257e252bfSMichael Neumann 	0x8950,
8357e252bfSMichael Neumann 	0x8954,
8457e252bfSMichael Neumann 	0x8a18,
8557e252bfSMichael Neumann 	0x8b28,
8657e252bfSMichael Neumann 	0x9144,
8757e252bfSMichael Neumann 	0x3f90,
8857e252bfSMichael Neumann 	0x915c,
8957e252bfSMichael Neumann 	0x9160,
9057e252bfSMichael Neumann 	0x9178,
9157e252bfSMichael Neumann 	0x917c,
9257e252bfSMichael Neumann 	0x9180,
9357e252bfSMichael Neumann 	0x918c,
9457e252bfSMichael Neumann 	0x9190,
9557e252bfSMichael Neumann 	0x9194,
9657e252bfSMichael Neumann 	0x9198,
9757e252bfSMichael Neumann 	0x919c,
9857e252bfSMichael Neumann 	0x91a8,
9957e252bfSMichael Neumann 	0x91ac,
10057e252bfSMichael Neumann 	0x91b0,
10157e252bfSMichael Neumann 	0x91b4,
10257e252bfSMichael Neumann 	0x91b8,
10357e252bfSMichael Neumann 	0x91c4,
10457e252bfSMichael Neumann 	0x91c8,
10557e252bfSMichael Neumann 	0x91cc,
10657e252bfSMichael Neumann 	0x91d0,
10757e252bfSMichael Neumann 	0x91d4,
10857e252bfSMichael Neumann 	0x91e0,
10957e252bfSMichael Neumann 	0x91e4,
11057e252bfSMichael Neumann 	0x91ec,
11157e252bfSMichael Neumann 	0x91f0,
11257e252bfSMichael Neumann 	0x91f4,
11357e252bfSMichael Neumann 	0x9200,
11457e252bfSMichael Neumann 	0x9204,
11557e252bfSMichael Neumann 	0x929c,
11657e252bfSMichael Neumann 	0x8030,
11757e252bfSMichael Neumann 	0x9150,
11857e252bfSMichael Neumann 	0x9a60,
11957e252bfSMichael Neumann 	0x920c,
12057e252bfSMichael Neumann 	0x9210,
12157e252bfSMichael Neumann 	0x9228,
12257e252bfSMichael Neumann 	0x922c,
12357e252bfSMichael Neumann 	0x9244,
12457e252bfSMichael Neumann 	0x9248,
12557e252bfSMichael Neumann 	0x91e8,
12657e252bfSMichael Neumann 	0x9294,
12757e252bfSMichael Neumann 	0x9208,
12857e252bfSMichael Neumann 	0x9224,
12957e252bfSMichael Neumann 	0x9240,
13057e252bfSMichael Neumann 	0x9220,
13157e252bfSMichael Neumann 	0x923c,
13257e252bfSMichael Neumann 	0x9258,
13357e252bfSMichael Neumann 	0x9744,
13457e252bfSMichael Neumann 	0xa200,
13557e252bfSMichael Neumann 	0xa204,
13657e252bfSMichael Neumann 	0xa208,
13757e252bfSMichael Neumann 	0xa20c,
13857e252bfSMichael Neumann 	0x8d58,
13957e252bfSMichael Neumann 	0x9030,
14057e252bfSMichael Neumann 	0x9034,
14157e252bfSMichael Neumann 	0x9038,
14257e252bfSMichael Neumann 	0x903c,
14357e252bfSMichael Neumann 	0x9040,
14457e252bfSMichael Neumann 	0x9654,
14557e252bfSMichael Neumann 	0x897c,
14657e252bfSMichael Neumann 	0xa210,
14757e252bfSMichael Neumann 	0xa214,
14857e252bfSMichael Neumann 	0x9868,
14957e252bfSMichael Neumann 	0xa02c,
15057e252bfSMichael Neumann 	0x9664,
15157e252bfSMichael Neumann 	0x9698,
15257e252bfSMichael Neumann 	0x949c,
15357e252bfSMichael Neumann 	0x8e10,
15457e252bfSMichael Neumann 	0x8e18,
15557e252bfSMichael Neumann 	0x8c50,
15657e252bfSMichael Neumann 	0x8c58,
15757e252bfSMichael Neumann 	0x8c60,
15857e252bfSMichael Neumann 	0x8c68,
15957e252bfSMichael Neumann 	0x89b4,
16057e252bfSMichael Neumann 	0x9830,
16157e252bfSMichael Neumann 	0x802c,
16257e252bfSMichael Neumann };
16357e252bfSMichael Neumann static u32 tn_rlc_save_restore_register_list_size = ARRAY_SIZE(tn_rlc_save_restore_register_list);
16457e252bfSMichael Neumann 
165b403bed8SMichael Neumann extern void evergreen_print_gpu_status_regs(struct radeon_device *rdev);
166926deccbSFrançois Tigeot extern void evergreen_pcie_gen2_enable(struct radeon_device *rdev);
16757e252bfSMichael Neumann extern void evergreen_program_aspm(struct radeon_device *rdev);
168926deccbSFrançois Tigeot 
16957e252bfSMichael Neumann /* Firmware Names */
17057e252bfSMichael Neumann MODULE_FIRMWARE("radeon/BARTS_pfp.bin");
17157e252bfSMichael Neumann MODULE_FIRMWARE("radeon/BARTS_me.bin");
17257e252bfSMichael Neumann MODULE_FIRMWARE("radeon/BARTS_mc.bin");
17357e252bfSMichael Neumann MODULE_FIRMWARE("radeon/BARTS_smc.bin");
17457e252bfSMichael Neumann MODULE_FIRMWARE("radeon/BTC_rlc.bin");
17557e252bfSMichael Neumann MODULE_FIRMWARE("radeon/TURKS_pfp.bin");
17657e252bfSMichael Neumann MODULE_FIRMWARE("radeon/TURKS_me.bin");
17757e252bfSMichael Neumann MODULE_FIRMWARE("radeon/TURKS_mc.bin");
17857e252bfSMichael Neumann MODULE_FIRMWARE("radeon/TURKS_smc.bin");
17957e252bfSMichael Neumann MODULE_FIRMWARE("radeon/CAICOS_pfp.bin");
18057e252bfSMichael Neumann MODULE_FIRMWARE("radeon/CAICOS_me.bin");
18157e252bfSMichael Neumann MODULE_FIRMWARE("radeon/CAICOS_mc.bin");
18257e252bfSMichael Neumann MODULE_FIRMWARE("radeon/CAICOS_smc.bin");
18357e252bfSMichael Neumann MODULE_FIRMWARE("radeon/CAYMAN_pfp.bin");
18457e252bfSMichael Neumann MODULE_FIRMWARE("radeon/CAYMAN_me.bin");
18557e252bfSMichael Neumann MODULE_FIRMWARE("radeon/CAYMAN_mc.bin");
18657e252bfSMichael Neumann MODULE_FIRMWARE("radeon/CAYMAN_rlc.bin");
18757e252bfSMichael Neumann MODULE_FIRMWARE("radeon/CAYMAN_smc.bin");
18857e252bfSMichael Neumann MODULE_FIRMWARE("radeon/ARUBA_pfp.bin");
18957e252bfSMichael Neumann MODULE_FIRMWARE("radeon/ARUBA_me.bin");
19057e252bfSMichael Neumann MODULE_FIRMWARE("radeon/ARUBA_rlc.bin");
191f43cf1b1SMichael Neumann 
192f43cf1b1SMichael Neumann static const u32 cayman_golden_registers2[] =
193f43cf1b1SMichael Neumann {
194f43cf1b1SMichael Neumann 	0x3e5c, 0xffffffff, 0x00000000,
195f43cf1b1SMichael Neumann 	0x3e48, 0xffffffff, 0x00000000,
196f43cf1b1SMichael Neumann 	0x3e4c, 0xffffffff, 0x00000000,
197f43cf1b1SMichael Neumann 	0x3e64, 0xffffffff, 0x00000000,
198f43cf1b1SMichael Neumann 	0x3e50, 0xffffffff, 0x00000000,
199f43cf1b1SMichael Neumann 	0x3e60, 0xffffffff, 0x00000000
200f43cf1b1SMichael Neumann };
201f43cf1b1SMichael Neumann 
202f43cf1b1SMichael Neumann static const u32 cayman_golden_registers[] =
203f43cf1b1SMichael Neumann {
204f43cf1b1SMichael Neumann 	0x5eb4, 0xffffffff, 0x00000002,
205f43cf1b1SMichael Neumann 	0x5e78, 0x8f311ff1, 0x001000f0,
206f43cf1b1SMichael Neumann 	0x3f90, 0xffff0000, 0xff000000,
207f43cf1b1SMichael Neumann 	0x9148, 0xffff0000, 0xff000000,
208f43cf1b1SMichael Neumann 	0x3f94, 0xffff0000, 0xff000000,
209f43cf1b1SMichael Neumann 	0x914c, 0xffff0000, 0xff000000,
210f43cf1b1SMichael Neumann 	0xc78, 0x00000080, 0x00000080,
211f43cf1b1SMichael Neumann 	0xbd4, 0x70073777, 0x00011003,
212f43cf1b1SMichael Neumann 	0xd02c, 0xbfffff1f, 0x08421000,
213f43cf1b1SMichael Neumann 	0xd0b8, 0x73773777, 0x02011003,
214f43cf1b1SMichael Neumann 	0x5bc0, 0x00200000, 0x50100000,
215f43cf1b1SMichael Neumann 	0x98f8, 0x33773777, 0x02011003,
216f43cf1b1SMichael Neumann 	0x98fc, 0xffffffff, 0x76541032,
217f43cf1b1SMichael Neumann 	0x7030, 0x31000311, 0x00000011,
218f43cf1b1SMichael Neumann 	0x2f48, 0x33773777, 0x42010001,
219f43cf1b1SMichael Neumann 	0x6b28, 0x00000010, 0x00000012,
220f43cf1b1SMichael Neumann 	0x7728, 0x00000010, 0x00000012,
221f43cf1b1SMichael Neumann 	0x10328, 0x00000010, 0x00000012,
222f43cf1b1SMichael Neumann 	0x10f28, 0x00000010, 0x00000012,
223f43cf1b1SMichael Neumann 	0x11b28, 0x00000010, 0x00000012,
224f43cf1b1SMichael Neumann 	0x12728, 0x00000010, 0x00000012,
225f43cf1b1SMichael Neumann 	0x240c, 0x000007ff, 0x00000000,
226f43cf1b1SMichael Neumann 	0x8a14, 0xf000001f, 0x00000007,
227f43cf1b1SMichael Neumann 	0x8b24, 0x3fff3fff, 0x00ff0fff,
228f43cf1b1SMichael Neumann 	0x8b10, 0x0000ff0f, 0x00000000,
229f43cf1b1SMichael Neumann 	0x28a4c, 0x07ffffff, 0x06000000,
230f43cf1b1SMichael Neumann 	0x10c, 0x00000001, 0x00010003,
231f43cf1b1SMichael Neumann 	0xa02c, 0xffffffff, 0x0000009b,
232f43cf1b1SMichael Neumann 	0x913c, 0x0000010f, 0x01000100,
233f43cf1b1SMichael Neumann 	0x8c04, 0xf8ff00ff, 0x40600060,
234f43cf1b1SMichael Neumann 	0x28350, 0x00000f01, 0x00000000,
235f43cf1b1SMichael Neumann 	0x9508, 0x3700001f, 0x00000002,
236f43cf1b1SMichael Neumann 	0x960c, 0xffffffff, 0x54763210,
237f43cf1b1SMichael Neumann 	0x88c4, 0x001f3ae3, 0x00000082,
238f43cf1b1SMichael Neumann 	0x88d0, 0xffffffff, 0x0f40df40,
239f43cf1b1SMichael Neumann 	0x88d4, 0x0000001f, 0x00000010,
240f43cf1b1SMichael Neumann 	0x8974, 0xffffffff, 0x00000000
241f43cf1b1SMichael Neumann };
242f43cf1b1SMichael Neumann 
243f43cf1b1SMichael Neumann static const u32 dvst_golden_registers2[] =
244f43cf1b1SMichael Neumann {
245f43cf1b1SMichael Neumann 	0x8f8, 0xffffffff, 0,
246f43cf1b1SMichael Neumann 	0x8fc, 0x00380000, 0,
247f43cf1b1SMichael Neumann 	0x8f8, 0xffffffff, 1,
248f43cf1b1SMichael Neumann 	0x8fc, 0x0e000000, 0
249f43cf1b1SMichael Neumann };
250f43cf1b1SMichael Neumann 
251f43cf1b1SMichael Neumann static const u32 dvst_golden_registers[] =
252f43cf1b1SMichael Neumann {
253f43cf1b1SMichael Neumann 	0x690, 0x3fff3fff, 0x20c00033,
254f43cf1b1SMichael Neumann 	0x918c, 0x0fff0fff, 0x00010006,
255f43cf1b1SMichael Neumann 	0x91a8, 0x0fff0fff, 0x00010006,
256f43cf1b1SMichael Neumann 	0x9150, 0xffffdfff, 0x6e944040,
257f43cf1b1SMichael Neumann 	0x917c, 0x0fff0fff, 0x00030002,
258f43cf1b1SMichael Neumann 	0x9198, 0x0fff0fff, 0x00030002,
259f43cf1b1SMichael Neumann 	0x915c, 0x0fff0fff, 0x00010000,
260f43cf1b1SMichael Neumann 	0x3f90, 0xffff0001, 0xff000000,
261f43cf1b1SMichael Neumann 	0x9178, 0x0fff0fff, 0x00070000,
262f43cf1b1SMichael Neumann 	0x9194, 0x0fff0fff, 0x00070000,
263f43cf1b1SMichael Neumann 	0x9148, 0xffff0001, 0xff000000,
264f43cf1b1SMichael Neumann 	0x9190, 0x0fff0fff, 0x00090008,
265f43cf1b1SMichael Neumann 	0x91ac, 0x0fff0fff, 0x00090008,
266f43cf1b1SMichael Neumann 	0x3f94, 0xffff0000, 0xff000000,
267f43cf1b1SMichael Neumann 	0x914c, 0xffff0000, 0xff000000,
268f43cf1b1SMichael Neumann 	0x929c, 0x00000fff, 0x00000001,
269f43cf1b1SMichael Neumann 	0x55e4, 0xff607fff, 0xfc000100,
270f43cf1b1SMichael Neumann 	0x8a18, 0xff000fff, 0x00000100,
271f43cf1b1SMichael Neumann 	0x8b28, 0xff000fff, 0x00000100,
272f43cf1b1SMichael Neumann 	0x9144, 0xfffc0fff, 0x00000100,
273f43cf1b1SMichael Neumann 	0x6ed8, 0x00010101, 0x00010000,
274f43cf1b1SMichael Neumann 	0x9830, 0xffffffff, 0x00000000,
275f43cf1b1SMichael Neumann 	0x9834, 0xf00fffff, 0x00000400,
276f43cf1b1SMichael Neumann 	0x9838, 0xfffffffe, 0x00000000,
277f43cf1b1SMichael Neumann 	0xd0c0, 0xff000fff, 0x00000100,
278f43cf1b1SMichael Neumann 	0xd02c, 0xbfffff1f, 0x08421000,
279f43cf1b1SMichael Neumann 	0xd0b8, 0x73773777, 0x12010001,
280f43cf1b1SMichael Neumann 	0x5bb0, 0x000000f0, 0x00000070,
281f43cf1b1SMichael Neumann 	0x98f8, 0x73773777, 0x12010001,
282f43cf1b1SMichael Neumann 	0x98fc, 0xffffffff, 0x00000010,
283f43cf1b1SMichael Neumann 	0x9b7c, 0x00ff0000, 0x00fc0000,
284f43cf1b1SMichael Neumann 	0x8030, 0x00001f0f, 0x0000100a,
285f43cf1b1SMichael Neumann 	0x2f48, 0x73773777, 0x12010001,
286f43cf1b1SMichael Neumann 	0x2408, 0x00030000, 0x000c007f,
287f43cf1b1SMichael Neumann 	0x8a14, 0xf000003f, 0x00000007,
288f43cf1b1SMichael Neumann 	0x8b24, 0x3fff3fff, 0x00ff0fff,
289f43cf1b1SMichael Neumann 	0x8b10, 0x0000ff0f, 0x00000000,
290f43cf1b1SMichael Neumann 	0x28a4c, 0x07ffffff, 0x06000000,
291f43cf1b1SMichael Neumann 	0x4d8, 0x00000fff, 0x00000100,
292f43cf1b1SMichael Neumann 	0xa008, 0xffffffff, 0x00010000,
293f43cf1b1SMichael Neumann 	0x913c, 0xffff03ff, 0x01000100,
294f43cf1b1SMichael Neumann 	0x8c00, 0x000000ff, 0x00000003,
295f43cf1b1SMichael Neumann 	0x8c04, 0xf8ff00ff, 0x40600060,
296f43cf1b1SMichael Neumann 	0x8cf0, 0x1fff1fff, 0x08e00410,
297f43cf1b1SMichael Neumann 	0x28350, 0x00000f01, 0x00000000,
298f43cf1b1SMichael Neumann 	0x9508, 0xf700071f, 0x00000002,
299f43cf1b1SMichael Neumann 	0x960c, 0xffffffff, 0x54763210,
300f43cf1b1SMichael Neumann 	0x20ef8, 0x01ff01ff, 0x00000002,
301f43cf1b1SMichael Neumann 	0x20e98, 0xfffffbff, 0x00200000,
302f43cf1b1SMichael Neumann 	0x2015c, 0xffffffff, 0x00000f40,
303f43cf1b1SMichael Neumann 	0x88c4, 0x001f3ae3, 0x00000082,
304f43cf1b1SMichael Neumann 	0x8978, 0x3fffffff, 0x04050140,
305f43cf1b1SMichael Neumann 	0x88d4, 0x0000001f, 0x00000010,
306f43cf1b1SMichael Neumann 	0x8974, 0xffffffff, 0x00000000
307f43cf1b1SMichael Neumann };
308f43cf1b1SMichael Neumann 
309f43cf1b1SMichael Neumann static const u32 scrapper_golden_registers[] =
310f43cf1b1SMichael Neumann {
311f43cf1b1SMichael Neumann 	0x690, 0x3fff3fff, 0x20c00033,
312f43cf1b1SMichael Neumann 	0x918c, 0x0fff0fff, 0x00010006,
313f43cf1b1SMichael Neumann 	0x918c, 0x0fff0fff, 0x00010006,
314f43cf1b1SMichael Neumann 	0x91a8, 0x0fff0fff, 0x00010006,
315f43cf1b1SMichael Neumann 	0x91a8, 0x0fff0fff, 0x00010006,
316f43cf1b1SMichael Neumann 	0x9150, 0xffffdfff, 0x6e944040,
317f43cf1b1SMichael Neumann 	0x9150, 0xffffdfff, 0x6e944040,
318f43cf1b1SMichael Neumann 	0x917c, 0x0fff0fff, 0x00030002,
319f43cf1b1SMichael Neumann 	0x917c, 0x0fff0fff, 0x00030002,
320f43cf1b1SMichael Neumann 	0x9198, 0x0fff0fff, 0x00030002,
321f43cf1b1SMichael Neumann 	0x9198, 0x0fff0fff, 0x00030002,
322f43cf1b1SMichael Neumann 	0x915c, 0x0fff0fff, 0x00010000,
323f43cf1b1SMichael Neumann 	0x915c, 0x0fff0fff, 0x00010000,
324f43cf1b1SMichael Neumann 	0x3f90, 0xffff0001, 0xff000000,
325f43cf1b1SMichael Neumann 	0x3f90, 0xffff0001, 0xff000000,
326f43cf1b1SMichael Neumann 	0x9178, 0x0fff0fff, 0x00070000,
327f43cf1b1SMichael Neumann 	0x9178, 0x0fff0fff, 0x00070000,
328f43cf1b1SMichael Neumann 	0x9194, 0x0fff0fff, 0x00070000,
329f43cf1b1SMichael Neumann 	0x9194, 0x0fff0fff, 0x00070000,
330f43cf1b1SMichael Neumann 	0x9148, 0xffff0001, 0xff000000,
331f43cf1b1SMichael Neumann 	0x9148, 0xffff0001, 0xff000000,
332f43cf1b1SMichael Neumann 	0x9190, 0x0fff0fff, 0x00090008,
333f43cf1b1SMichael Neumann 	0x9190, 0x0fff0fff, 0x00090008,
334f43cf1b1SMichael Neumann 	0x91ac, 0x0fff0fff, 0x00090008,
335f43cf1b1SMichael Neumann 	0x91ac, 0x0fff0fff, 0x00090008,
336f43cf1b1SMichael Neumann 	0x3f94, 0xffff0000, 0xff000000,
337f43cf1b1SMichael Neumann 	0x3f94, 0xffff0000, 0xff000000,
338f43cf1b1SMichael Neumann 	0x914c, 0xffff0000, 0xff000000,
339f43cf1b1SMichael Neumann 	0x914c, 0xffff0000, 0xff000000,
340f43cf1b1SMichael Neumann 	0x929c, 0x00000fff, 0x00000001,
341f43cf1b1SMichael Neumann 	0x929c, 0x00000fff, 0x00000001,
342f43cf1b1SMichael Neumann 	0x55e4, 0xff607fff, 0xfc000100,
343f43cf1b1SMichael Neumann 	0x8a18, 0xff000fff, 0x00000100,
344f43cf1b1SMichael Neumann 	0x8a18, 0xff000fff, 0x00000100,
345f43cf1b1SMichael Neumann 	0x8b28, 0xff000fff, 0x00000100,
346f43cf1b1SMichael Neumann 	0x8b28, 0xff000fff, 0x00000100,
347f43cf1b1SMichael Neumann 	0x9144, 0xfffc0fff, 0x00000100,
348f43cf1b1SMichael Neumann 	0x9144, 0xfffc0fff, 0x00000100,
349f43cf1b1SMichael Neumann 	0x6ed8, 0x00010101, 0x00010000,
350f43cf1b1SMichael Neumann 	0x9830, 0xffffffff, 0x00000000,
351f43cf1b1SMichael Neumann 	0x9830, 0xffffffff, 0x00000000,
352f43cf1b1SMichael Neumann 	0x9834, 0xf00fffff, 0x00000400,
353f43cf1b1SMichael Neumann 	0x9834, 0xf00fffff, 0x00000400,
354f43cf1b1SMichael Neumann 	0x9838, 0xfffffffe, 0x00000000,
355f43cf1b1SMichael Neumann 	0x9838, 0xfffffffe, 0x00000000,
356f43cf1b1SMichael Neumann 	0xd0c0, 0xff000fff, 0x00000100,
357f43cf1b1SMichael Neumann 	0xd02c, 0xbfffff1f, 0x08421000,
358f43cf1b1SMichael Neumann 	0xd02c, 0xbfffff1f, 0x08421000,
359f43cf1b1SMichael Neumann 	0xd0b8, 0x73773777, 0x12010001,
360f43cf1b1SMichael Neumann 	0xd0b8, 0x73773777, 0x12010001,
361f43cf1b1SMichael Neumann 	0x5bb0, 0x000000f0, 0x00000070,
362f43cf1b1SMichael Neumann 	0x98f8, 0x73773777, 0x12010001,
363f43cf1b1SMichael Neumann 	0x98f8, 0x73773777, 0x12010001,
364f43cf1b1SMichael Neumann 	0x98fc, 0xffffffff, 0x00000010,
365f43cf1b1SMichael Neumann 	0x98fc, 0xffffffff, 0x00000010,
366f43cf1b1SMichael Neumann 	0x9b7c, 0x00ff0000, 0x00fc0000,
367f43cf1b1SMichael Neumann 	0x9b7c, 0x00ff0000, 0x00fc0000,
368f43cf1b1SMichael Neumann 	0x8030, 0x00001f0f, 0x0000100a,
369f43cf1b1SMichael Neumann 	0x8030, 0x00001f0f, 0x0000100a,
370f43cf1b1SMichael Neumann 	0x2f48, 0x73773777, 0x12010001,
371f43cf1b1SMichael Neumann 	0x2f48, 0x73773777, 0x12010001,
372f43cf1b1SMichael Neumann 	0x2408, 0x00030000, 0x000c007f,
373f43cf1b1SMichael Neumann 	0x8a14, 0xf000003f, 0x00000007,
374f43cf1b1SMichael Neumann 	0x8a14, 0xf000003f, 0x00000007,
375f43cf1b1SMichael Neumann 	0x8b24, 0x3fff3fff, 0x00ff0fff,
376f43cf1b1SMichael Neumann 	0x8b24, 0x3fff3fff, 0x00ff0fff,
377f43cf1b1SMichael Neumann 	0x8b10, 0x0000ff0f, 0x00000000,
378f43cf1b1SMichael Neumann 	0x8b10, 0x0000ff0f, 0x00000000,
379f43cf1b1SMichael Neumann 	0x28a4c, 0x07ffffff, 0x06000000,
380f43cf1b1SMichael Neumann 	0x28a4c, 0x07ffffff, 0x06000000,
381f43cf1b1SMichael Neumann 	0x4d8, 0x00000fff, 0x00000100,
382f43cf1b1SMichael Neumann 	0x4d8, 0x00000fff, 0x00000100,
383f43cf1b1SMichael Neumann 	0xa008, 0xffffffff, 0x00010000,
384f43cf1b1SMichael Neumann 	0xa008, 0xffffffff, 0x00010000,
385f43cf1b1SMichael Neumann 	0x913c, 0xffff03ff, 0x01000100,
386f43cf1b1SMichael Neumann 	0x913c, 0xffff03ff, 0x01000100,
387f43cf1b1SMichael Neumann 	0x90e8, 0x001fffff, 0x010400c0,
388f43cf1b1SMichael Neumann 	0x8c00, 0x000000ff, 0x00000003,
389f43cf1b1SMichael Neumann 	0x8c00, 0x000000ff, 0x00000003,
390f43cf1b1SMichael Neumann 	0x8c04, 0xf8ff00ff, 0x40600060,
391f43cf1b1SMichael Neumann 	0x8c04, 0xf8ff00ff, 0x40600060,
392f43cf1b1SMichael Neumann 	0x8c30, 0x0000000f, 0x00040005,
393f43cf1b1SMichael Neumann 	0x8cf0, 0x1fff1fff, 0x08e00410,
394f43cf1b1SMichael Neumann 	0x8cf0, 0x1fff1fff, 0x08e00410,
395f43cf1b1SMichael Neumann 	0x900c, 0x00ffffff, 0x0017071f,
396f43cf1b1SMichael Neumann 	0x28350, 0x00000f01, 0x00000000,
397f43cf1b1SMichael Neumann 	0x28350, 0x00000f01, 0x00000000,
398f43cf1b1SMichael Neumann 	0x9508, 0xf700071f, 0x00000002,
399f43cf1b1SMichael Neumann 	0x9508, 0xf700071f, 0x00000002,
400f43cf1b1SMichael Neumann 	0x9688, 0x00300000, 0x0017000f,
401f43cf1b1SMichael Neumann 	0x960c, 0xffffffff, 0x54763210,
402f43cf1b1SMichael Neumann 	0x960c, 0xffffffff, 0x54763210,
403f43cf1b1SMichael Neumann 	0x20ef8, 0x01ff01ff, 0x00000002,
404f43cf1b1SMichael Neumann 	0x20e98, 0xfffffbff, 0x00200000,
405f43cf1b1SMichael Neumann 	0x2015c, 0xffffffff, 0x00000f40,
406f43cf1b1SMichael Neumann 	0x88c4, 0x001f3ae3, 0x00000082,
407f43cf1b1SMichael Neumann 	0x88c4, 0x001f3ae3, 0x00000082,
408f43cf1b1SMichael Neumann 	0x8978, 0x3fffffff, 0x04050140,
409f43cf1b1SMichael Neumann 	0x8978, 0x3fffffff, 0x04050140,
410f43cf1b1SMichael Neumann 	0x88d4, 0x0000001f, 0x00000010,
411f43cf1b1SMichael Neumann 	0x88d4, 0x0000001f, 0x00000010,
412f43cf1b1SMichael Neumann 	0x8974, 0xffffffff, 0x00000000,
413f43cf1b1SMichael Neumann 	0x8974, 0xffffffff, 0x00000000
414f43cf1b1SMichael Neumann };
415f43cf1b1SMichael Neumann 
416f43cf1b1SMichael Neumann static void ni_init_golden_registers(struct radeon_device *rdev)
417f43cf1b1SMichael Neumann {
418f43cf1b1SMichael Neumann 	switch (rdev->family) {
419f43cf1b1SMichael Neumann 	case CHIP_CAYMAN:
420f43cf1b1SMichael Neumann 		radeon_program_register_sequence(rdev,
421f43cf1b1SMichael Neumann 						 cayman_golden_registers,
422f43cf1b1SMichael Neumann 						 (const u32)ARRAY_SIZE(cayman_golden_registers));
423f43cf1b1SMichael Neumann 		radeon_program_register_sequence(rdev,
424f43cf1b1SMichael Neumann 						 cayman_golden_registers2,
425f43cf1b1SMichael Neumann 						 (const u32)ARRAY_SIZE(cayman_golden_registers2));
426f43cf1b1SMichael Neumann 		break;
427f43cf1b1SMichael Neumann 	case CHIP_ARUBA:
428f43cf1b1SMichael Neumann 		if ((rdev->ddev->pci_device == 0x9900) ||
429f43cf1b1SMichael Neumann 		    (rdev->ddev->pci_device == 0x9901) ||
430f43cf1b1SMichael Neumann 		    (rdev->ddev->pci_device == 0x9903) ||
431f43cf1b1SMichael Neumann 		    (rdev->ddev->pci_device == 0x9904) ||
432f43cf1b1SMichael Neumann 		    (rdev->ddev->pci_device == 0x9905) ||
433f43cf1b1SMichael Neumann 		    (rdev->ddev->pci_device == 0x9906) ||
434f43cf1b1SMichael Neumann 		    (rdev->ddev->pci_device == 0x9907) ||
435f43cf1b1SMichael Neumann 		    (rdev->ddev->pci_device == 0x9908) ||
436f43cf1b1SMichael Neumann 		    (rdev->ddev->pci_device == 0x9909) ||
437f43cf1b1SMichael Neumann 		    (rdev->ddev->pci_device == 0x990A) ||
438f43cf1b1SMichael Neumann 		    (rdev->ddev->pci_device == 0x990B) ||
439f43cf1b1SMichael Neumann 		    (rdev->ddev->pci_device == 0x990C) ||
440f43cf1b1SMichael Neumann 		    (rdev->ddev->pci_device == 0x990D) ||
441f43cf1b1SMichael Neumann 		    (rdev->ddev->pci_device == 0x990E) ||
442f43cf1b1SMichael Neumann 		    (rdev->ddev->pci_device == 0x990F) ||
443f43cf1b1SMichael Neumann 		    (rdev->ddev->pci_device == 0x9910) ||
444f43cf1b1SMichael Neumann 		    (rdev->ddev->pci_device == 0x9913) ||
445f43cf1b1SMichael Neumann 		    (rdev->ddev->pci_device == 0x9917) ||
446f43cf1b1SMichael Neumann 		    (rdev->ddev->pci_device == 0x9918)) {
447f43cf1b1SMichael Neumann 			radeon_program_register_sequence(rdev,
448f43cf1b1SMichael Neumann 							 dvst_golden_registers,
449f43cf1b1SMichael Neumann 							 (const u32)ARRAY_SIZE(dvst_golden_registers));
450f43cf1b1SMichael Neumann 			radeon_program_register_sequence(rdev,
451f43cf1b1SMichael Neumann 							 dvst_golden_registers2,
452f43cf1b1SMichael Neumann 							 (const u32)ARRAY_SIZE(dvst_golden_registers2));
453f43cf1b1SMichael Neumann 		} else {
454f43cf1b1SMichael Neumann 			radeon_program_register_sequence(rdev,
455f43cf1b1SMichael Neumann 							 scrapper_golden_registers,
456f43cf1b1SMichael Neumann 							 (const u32)ARRAY_SIZE(scrapper_golden_registers));
457f43cf1b1SMichael Neumann 			radeon_program_register_sequence(rdev,
458f43cf1b1SMichael Neumann 							 dvst_golden_registers2,
459f43cf1b1SMichael Neumann 							 (const u32)ARRAY_SIZE(dvst_golden_registers2));
460f43cf1b1SMichael Neumann 		}
461f43cf1b1SMichael Neumann 		break;
462f43cf1b1SMichael Neumann 	default:
463f43cf1b1SMichael Neumann 		break;
464f43cf1b1SMichael Neumann 	}
465f43cf1b1SMichael Neumann }
466f43cf1b1SMichael Neumann 
467926deccbSFrançois Tigeot #define BTC_IO_MC_REGS_SIZE 29
468926deccbSFrançois Tigeot 
469926deccbSFrançois Tigeot static const u32 barts_io_mc_regs[BTC_IO_MC_REGS_SIZE][2] = {
470926deccbSFrançois Tigeot 	{0x00000077, 0xff010100},
471926deccbSFrançois Tigeot 	{0x00000078, 0x00000000},
472926deccbSFrançois Tigeot 	{0x00000079, 0x00001434},
473926deccbSFrançois Tigeot 	{0x0000007a, 0xcc08ec08},
474926deccbSFrançois Tigeot 	{0x0000007b, 0x00040000},
475926deccbSFrançois Tigeot 	{0x0000007c, 0x000080c0},
476926deccbSFrançois Tigeot 	{0x0000007d, 0x09000000},
477926deccbSFrançois Tigeot 	{0x0000007e, 0x00210404},
478926deccbSFrançois Tigeot 	{0x00000081, 0x08a8e800},
479926deccbSFrançois Tigeot 	{0x00000082, 0x00030444},
480926deccbSFrançois Tigeot 	{0x00000083, 0x00000000},
481926deccbSFrançois Tigeot 	{0x00000085, 0x00000001},
482926deccbSFrançois Tigeot 	{0x00000086, 0x00000002},
483926deccbSFrançois Tigeot 	{0x00000087, 0x48490000},
484926deccbSFrançois Tigeot 	{0x00000088, 0x20244647},
485926deccbSFrançois Tigeot 	{0x00000089, 0x00000005},
486926deccbSFrançois Tigeot 	{0x0000008b, 0x66030000},
487926deccbSFrançois Tigeot 	{0x0000008c, 0x00006603},
488926deccbSFrançois Tigeot 	{0x0000008d, 0x00000100},
489926deccbSFrançois Tigeot 	{0x0000008f, 0x00001c0a},
490926deccbSFrançois Tigeot 	{0x00000090, 0xff000001},
491926deccbSFrançois Tigeot 	{0x00000094, 0x00101101},
492926deccbSFrançois Tigeot 	{0x00000095, 0x00000fff},
493926deccbSFrançois Tigeot 	{0x00000096, 0x00116fff},
494926deccbSFrançois Tigeot 	{0x00000097, 0x60010000},
495926deccbSFrançois Tigeot 	{0x00000098, 0x10010000},
496926deccbSFrançois Tigeot 	{0x00000099, 0x00006000},
497926deccbSFrançois Tigeot 	{0x0000009a, 0x00001000},
498926deccbSFrançois Tigeot 	{0x0000009f, 0x00946a00}
499926deccbSFrançois Tigeot };
500926deccbSFrançois Tigeot 
501926deccbSFrançois Tigeot static const u32 turks_io_mc_regs[BTC_IO_MC_REGS_SIZE][2] = {
502926deccbSFrançois Tigeot 	{0x00000077, 0xff010100},
503926deccbSFrançois Tigeot 	{0x00000078, 0x00000000},
504926deccbSFrançois Tigeot 	{0x00000079, 0x00001434},
505926deccbSFrançois Tigeot 	{0x0000007a, 0xcc08ec08},
506926deccbSFrançois Tigeot 	{0x0000007b, 0x00040000},
507926deccbSFrançois Tigeot 	{0x0000007c, 0x000080c0},
508926deccbSFrançois Tigeot 	{0x0000007d, 0x09000000},
509926deccbSFrançois Tigeot 	{0x0000007e, 0x00210404},
510926deccbSFrançois Tigeot 	{0x00000081, 0x08a8e800},
511926deccbSFrançois Tigeot 	{0x00000082, 0x00030444},
512926deccbSFrançois Tigeot 	{0x00000083, 0x00000000},
513926deccbSFrançois Tigeot 	{0x00000085, 0x00000001},
514926deccbSFrançois Tigeot 	{0x00000086, 0x00000002},
515926deccbSFrançois Tigeot 	{0x00000087, 0x48490000},
516926deccbSFrançois Tigeot 	{0x00000088, 0x20244647},
517926deccbSFrançois Tigeot 	{0x00000089, 0x00000005},
518926deccbSFrançois Tigeot 	{0x0000008b, 0x66030000},
519926deccbSFrançois Tigeot 	{0x0000008c, 0x00006603},
520926deccbSFrançois Tigeot 	{0x0000008d, 0x00000100},
521926deccbSFrançois Tigeot 	{0x0000008f, 0x00001c0a},
522926deccbSFrançois Tigeot 	{0x00000090, 0xff000001},
523926deccbSFrançois Tigeot 	{0x00000094, 0x00101101},
524926deccbSFrançois Tigeot 	{0x00000095, 0x00000fff},
525926deccbSFrançois Tigeot 	{0x00000096, 0x00116fff},
526926deccbSFrançois Tigeot 	{0x00000097, 0x60010000},
527926deccbSFrançois Tigeot 	{0x00000098, 0x10010000},
528926deccbSFrançois Tigeot 	{0x00000099, 0x00006000},
529926deccbSFrançois Tigeot 	{0x0000009a, 0x00001000},
530926deccbSFrançois Tigeot 	{0x0000009f, 0x00936a00}
531926deccbSFrançois Tigeot };
532926deccbSFrançois Tigeot 
533926deccbSFrançois Tigeot static const u32 caicos_io_mc_regs[BTC_IO_MC_REGS_SIZE][2] = {
534926deccbSFrançois Tigeot 	{0x00000077, 0xff010100},
535926deccbSFrançois Tigeot 	{0x00000078, 0x00000000},
536926deccbSFrançois Tigeot 	{0x00000079, 0x00001434},
537926deccbSFrançois Tigeot 	{0x0000007a, 0xcc08ec08},
538926deccbSFrançois Tigeot 	{0x0000007b, 0x00040000},
539926deccbSFrançois Tigeot 	{0x0000007c, 0x000080c0},
540926deccbSFrançois Tigeot 	{0x0000007d, 0x09000000},
541926deccbSFrançois Tigeot 	{0x0000007e, 0x00210404},
542926deccbSFrançois Tigeot 	{0x00000081, 0x08a8e800},
543926deccbSFrançois Tigeot 	{0x00000082, 0x00030444},
544926deccbSFrançois Tigeot 	{0x00000083, 0x00000000},
545926deccbSFrançois Tigeot 	{0x00000085, 0x00000001},
546926deccbSFrançois Tigeot 	{0x00000086, 0x00000002},
547926deccbSFrançois Tigeot 	{0x00000087, 0x48490000},
548926deccbSFrançois Tigeot 	{0x00000088, 0x20244647},
549926deccbSFrançois Tigeot 	{0x00000089, 0x00000005},
550926deccbSFrançois Tigeot 	{0x0000008b, 0x66030000},
551926deccbSFrançois Tigeot 	{0x0000008c, 0x00006603},
552926deccbSFrançois Tigeot 	{0x0000008d, 0x00000100},
553926deccbSFrançois Tigeot 	{0x0000008f, 0x00001c0a},
554926deccbSFrançois Tigeot 	{0x00000090, 0xff000001},
555926deccbSFrançois Tigeot 	{0x00000094, 0x00101101},
556926deccbSFrançois Tigeot 	{0x00000095, 0x00000fff},
557926deccbSFrançois Tigeot 	{0x00000096, 0x00116fff},
558926deccbSFrançois Tigeot 	{0x00000097, 0x60010000},
559926deccbSFrançois Tigeot 	{0x00000098, 0x10010000},
560926deccbSFrançois Tigeot 	{0x00000099, 0x00006000},
561926deccbSFrançois Tigeot 	{0x0000009a, 0x00001000},
562926deccbSFrançois Tigeot 	{0x0000009f, 0x00916a00}
563926deccbSFrançois Tigeot };
564926deccbSFrançois Tigeot 
565926deccbSFrançois Tigeot static const u32 cayman_io_mc_regs[BTC_IO_MC_REGS_SIZE][2] = {
566926deccbSFrançois Tigeot 	{0x00000077, 0xff010100},
567926deccbSFrançois Tigeot 	{0x00000078, 0x00000000},
568926deccbSFrançois Tigeot 	{0x00000079, 0x00001434},
569926deccbSFrançois Tigeot 	{0x0000007a, 0xcc08ec08},
570926deccbSFrançois Tigeot 	{0x0000007b, 0x00040000},
571926deccbSFrançois Tigeot 	{0x0000007c, 0x000080c0},
572926deccbSFrançois Tigeot 	{0x0000007d, 0x09000000},
573926deccbSFrançois Tigeot 	{0x0000007e, 0x00210404},
574926deccbSFrançois Tigeot 	{0x00000081, 0x08a8e800},
575926deccbSFrançois Tigeot 	{0x00000082, 0x00030444},
576926deccbSFrançois Tigeot 	{0x00000083, 0x00000000},
577926deccbSFrançois Tigeot 	{0x00000085, 0x00000001},
578926deccbSFrançois Tigeot 	{0x00000086, 0x00000002},
579926deccbSFrançois Tigeot 	{0x00000087, 0x48490000},
580926deccbSFrançois Tigeot 	{0x00000088, 0x20244647},
581926deccbSFrançois Tigeot 	{0x00000089, 0x00000005},
582926deccbSFrançois Tigeot 	{0x0000008b, 0x66030000},
583926deccbSFrançois Tigeot 	{0x0000008c, 0x00006603},
584926deccbSFrançois Tigeot 	{0x0000008d, 0x00000100},
585926deccbSFrançois Tigeot 	{0x0000008f, 0x00001c0a},
586926deccbSFrançois Tigeot 	{0x00000090, 0xff000001},
587926deccbSFrançois Tigeot 	{0x00000094, 0x00101101},
588926deccbSFrançois Tigeot 	{0x00000095, 0x00000fff},
589926deccbSFrançois Tigeot 	{0x00000096, 0x00116fff},
590926deccbSFrançois Tigeot 	{0x00000097, 0x60010000},
591926deccbSFrançois Tigeot 	{0x00000098, 0x10010000},
592926deccbSFrançois Tigeot 	{0x00000099, 0x00006000},
593926deccbSFrançois Tigeot 	{0x0000009a, 0x00001000},
594926deccbSFrançois Tigeot 	{0x0000009f, 0x00976b00}
595926deccbSFrançois Tigeot };
596926deccbSFrançois Tigeot 
597926deccbSFrançois Tigeot int ni_mc_load_microcode(struct radeon_device *rdev)
598926deccbSFrançois Tigeot {
599926deccbSFrançois Tigeot 	const __be32 *fw_data;
600926deccbSFrançois Tigeot 	u32 mem_type, running, blackout = 0;
601926deccbSFrançois Tigeot 	u32 *io_mc_regs;
602926deccbSFrançois Tigeot 	int i, ucode_size, regs_size;
603926deccbSFrançois Tigeot 
604926deccbSFrançois Tigeot 	if (!rdev->mc_fw)
605926deccbSFrançois Tigeot 		return -EINVAL;
606926deccbSFrançois Tigeot 
607926deccbSFrançois Tigeot 	switch (rdev->family) {
608926deccbSFrançois Tigeot 	case CHIP_BARTS:
609926deccbSFrançois Tigeot 		io_mc_regs = (u32 *)&barts_io_mc_regs;
610926deccbSFrançois Tigeot 		ucode_size = BTC_MC_UCODE_SIZE;
611926deccbSFrançois Tigeot 		regs_size = BTC_IO_MC_REGS_SIZE;
612926deccbSFrançois Tigeot 		break;
613926deccbSFrançois Tigeot 	case CHIP_TURKS:
614926deccbSFrançois Tigeot 		io_mc_regs = (u32 *)&turks_io_mc_regs;
615926deccbSFrançois Tigeot 		ucode_size = BTC_MC_UCODE_SIZE;
616926deccbSFrançois Tigeot 		regs_size = BTC_IO_MC_REGS_SIZE;
617926deccbSFrançois Tigeot 		break;
618926deccbSFrançois Tigeot 	case CHIP_CAICOS:
619926deccbSFrançois Tigeot 	default:
620926deccbSFrançois Tigeot 		io_mc_regs = (u32 *)&caicos_io_mc_regs;
621926deccbSFrançois Tigeot 		ucode_size = BTC_MC_UCODE_SIZE;
622926deccbSFrançois Tigeot 		regs_size = BTC_IO_MC_REGS_SIZE;
623926deccbSFrançois Tigeot 		break;
624926deccbSFrançois Tigeot 	case CHIP_CAYMAN:
625926deccbSFrançois Tigeot 		io_mc_regs = (u32 *)&cayman_io_mc_regs;
626926deccbSFrançois Tigeot 		ucode_size = CAYMAN_MC_UCODE_SIZE;
627926deccbSFrançois Tigeot 		regs_size = BTC_IO_MC_REGS_SIZE;
628926deccbSFrançois Tigeot 		break;
629926deccbSFrançois Tigeot 	}
630926deccbSFrançois Tigeot 
631926deccbSFrançois Tigeot 	mem_type = (RREG32(MC_SEQ_MISC0) & MC_SEQ_MISC0_GDDR5_MASK) >> MC_SEQ_MISC0_GDDR5_SHIFT;
632926deccbSFrançois Tigeot 	running = RREG32(MC_SEQ_SUP_CNTL) & RUN_MASK;
633926deccbSFrançois Tigeot 
634926deccbSFrançois Tigeot 	if ((mem_type == MC_SEQ_MISC0_GDDR5_VALUE) && (running == 0)) {
635926deccbSFrançois Tigeot 		if (running) {
636926deccbSFrançois Tigeot 			blackout = RREG32(MC_SHARED_BLACKOUT_CNTL);
637926deccbSFrançois Tigeot 			WREG32(MC_SHARED_BLACKOUT_CNTL, 1);
638926deccbSFrançois Tigeot 		}
639926deccbSFrançois Tigeot 
640926deccbSFrançois Tigeot 		/* reset the engine and set to writable */
641926deccbSFrançois Tigeot 		WREG32(MC_SEQ_SUP_CNTL, 0x00000008);
642926deccbSFrançois Tigeot 		WREG32(MC_SEQ_SUP_CNTL, 0x00000010);
643926deccbSFrançois Tigeot 
644926deccbSFrançois Tigeot 		/* load mc io regs */
645926deccbSFrançois Tigeot 		for (i = 0; i < regs_size; i++) {
646926deccbSFrançois Tigeot 			WREG32(MC_SEQ_IO_DEBUG_INDEX, io_mc_regs[(i << 1)]);
647926deccbSFrançois Tigeot 			WREG32(MC_SEQ_IO_DEBUG_DATA, io_mc_regs[(i << 1) + 1]);
648926deccbSFrançois Tigeot 		}
649926deccbSFrançois Tigeot 		/* load the MC ucode */
650926deccbSFrançois Tigeot 		fw_data = (const __be32 *)rdev->mc_fw->data;
651926deccbSFrançois Tigeot 		for (i = 0; i < ucode_size; i++)
652926deccbSFrançois Tigeot 			WREG32(MC_SEQ_SUP_PGM, be32_to_cpup(fw_data++));
653926deccbSFrançois Tigeot 
654926deccbSFrançois Tigeot 		/* put the engine back into the active state */
655926deccbSFrançois Tigeot 		WREG32(MC_SEQ_SUP_CNTL, 0x00000008);
656926deccbSFrançois Tigeot 		WREG32(MC_SEQ_SUP_CNTL, 0x00000004);
657926deccbSFrançois Tigeot 		WREG32(MC_SEQ_SUP_CNTL, 0x00000001);
658926deccbSFrançois Tigeot 
659926deccbSFrançois Tigeot 		/* wait for training to complete */
660926deccbSFrançois Tigeot 		for (i = 0; i < rdev->usec_timeout; i++) {
661926deccbSFrançois Tigeot 			if (RREG32(MC_IO_PAD_CNTL_D0) & MEM_FALL_OUT_CMD)
662926deccbSFrançois Tigeot 				break;
663926deccbSFrançois Tigeot 			DRM_UDELAY(1);
664926deccbSFrançois Tigeot 		}
665926deccbSFrançois Tigeot 
666926deccbSFrançois Tigeot 		if (running)
667926deccbSFrançois Tigeot 			WREG32(MC_SHARED_BLACKOUT_CNTL, blackout);
668926deccbSFrançois Tigeot 	}
669926deccbSFrançois Tigeot 
670926deccbSFrançois Tigeot 	return 0;
671926deccbSFrançois Tigeot }
672926deccbSFrançois Tigeot 
673926deccbSFrançois Tigeot int ni_init_microcode(struct radeon_device *rdev)
674926deccbSFrançois Tigeot {
675926deccbSFrançois Tigeot 	const char *chip_name;
676926deccbSFrançois Tigeot 	const char *rlc_chip_name;
677926deccbSFrançois Tigeot 	size_t pfp_req_size, me_req_size, rlc_req_size, mc_req_size;
67857e252bfSMichael Neumann 	size_t smc_req_size = 0;
679926deccbSFrançois Tigeot 	char fw_name[30];
680926deccbSFrançois Tigeot 	int err;
681926deccbSFrançois Tigeot 
682926deccbSFrançois Tigeot 	DRM_DEBUG("\n");
683926deccbSFrançois Tigeot 
684926deccbSFrançois Tigeot 	switch (rdev->family) {
685926deccbSFrançois Tigeot 	case CHIP_BARTS:
686926deccbSFrançois Tigeot 		chip_name = "BARTS";
687926deccbSFrançois Tigeot 		rlc_chip_name = "BTC";
688926deccbSFrançois Tigeot 		pfp_req_size = EVERGREEN_PFP_UCODE_SIZE * 4;
689926deccbSFrançois Tigeot 		me_req_size = EVERGREEN_PM4_UCODE_SIZE * 4;
690926deccbSFrançois Tigeot 		rlc_req_size = EVERGREEN_RLC_UCODE_SIZE * 4;
691926deccbSFrançois Tigeot 		mc_req_size = BTC_MC_UCODE_SIZE * 4;
69257e252bfSMichael Neumann 		smc_req_size = ALIGN(BARTS_SMC_UCODE_SIZE, 4);
693926deccbSFrançois Tigeot 		break;
694926deccbSFrançois Tigeot 	case CHIP_TURKS:
695926deccbSFrançois Tigeot 		chip_name = "TURKS";
696926deccbSFrançois Tigeot 		rlc_chip_name = "BTC";
697926deccbSFrançois Tigeot 		pfp_req_size = EVERGREEN_PFP_UCODE_SIZE * 4;
698926deccbSFrançois Tigeot 		me_req_size = EVERGREEN_PM4_UCODE_SIZE * 4;
699926deccbSFrançois Tigeot 		rlc_req_size = EVERGREEN_RLC_UCODE_SIZE * 4;
700926deccbSFrançois Tigeot 		mc_req_size = BTC_MC_UCODE_SIZE * 4;
70157e252bfSMichael Neumann 		smc_req_size = ALIGN(TURKS_SMC_UCODE_SIZE, 4);
702926deccbSFrançois Tigeot 		break;
703926deccbSFrançois Tigeot 	case CHIP_CAICOS:
704926deccbSFrançois Tigeot 		chip_name = "CAICOS";
705926deccbSFrançois Tigeot 		rlc_chip_name = "BTC";
706926deccbSFrançois Tigeot 		pfp_req_size = EVERGREEN_PFP_UCODE_SIZE * 4;
707926deccbSFrançois Tigeot 		me_req_size = EVERGREEN_PM4_UCODE_SIZE * 4;
708926deccbSFrançois Tigeot 		rlc_req_size = EVERGREEN_RLC_UCODE_SIZE * 4;
709926deccbSFrançois Tigeot 		mc_req_size = BTC_MC_UCODE_SIZE * 4;
71057e252bfSMichael Neumann 		smc_req_size = ALIGN(CAICOS_SMC_UCODE_SIZE, 4);
711926deccbSFrançois Tigeot 		break;
712926deccbSFrançois Tigeot 	case CHIP_CAYMAN:
713926deccbSFrançois Tigeot 		chip_name = "CAYMAN";
714926deccbSFrançois Tigeot 		rlc_chip_name = "CAYMAN";
715926deccbSFrançois Tigeot 		pfp_req_size = CAYMAN_PFP_UCODE_SIZE * 4;
716926deccbSFrançois Tigeot 		me_req_size = CAYMAN_PM4_UCODE_SIZE * 4;
717926deccbSFrançois Tigeot 		rlc_req_size = CAYMAN_RLC_UCODE_SIZE * 4;
718926deccbSFrançois Tigeot 		mc_req_size = CAYMAN_MC_UCODE_SIZE * 4;
71957e252bfSMichael Neumann 		smc_req_size = ALIGN(CAYMAN_SMC_UCODE_SIZE, 4);
720926deccbSFrançois Tigeot 		break;
721926deccbSFrançois Tigeot 	case CHIP_ARUBA:
722926deccbSFrançois Tigeot 		chip_name = "ARUBA";
723926deccbSFrançois Tigeot 		rlc_chip_name = "ARUBA";
724926deccbSFrançois Tigeot 		/* pfp/me same size as CAYMAN */
725926deccbSFrançois Tigeot 		pfp_req_size = CAYMAN_PFP_UCODE_SIZE * 4;
726926deccbSFrançois Tigeot 		me_req_size = CAYMAN_PM4_UCODE_SIZE * 4;
727926deccbSFrançois Tigeot 		rlc_req_size = ARUBA_RLC_UCODE_SIZE * 4;
728926deccbSFrançois Tigeot 		mc_req_size = 0;
729926deccbSFrançois Tigeot 		break;
730926deccbSFrançois Tigeot 	default: panic("%s: Unsupported family %d", __func__, rdev->family);
731926deccbSFrançois Tigeot 	}
732926deccbSFrançois Tigeot 
733926deccbSFrançois Tigeot 	DRM_INFO("Loading %s Microcode\n", chip_name);
734926deccbSFrançois Tigeot 
735926deccbSFrançois Tigeot 	ksnprintf(fw_name, sizeof(fw_name), "radeonkmsfw_%s_pfp", chip_name);
736*fcd4983fSzrj 	err = request_firmware(&rdev->pfp_fw, fw_name, rdev->dev);
737*fcd4983fSzrj 	if (err)
738926deccbSFrançois Tigeot 		goto out;
739926deccbSFrançois Tigeot 	if (rdev->pfp_fw->datasize != pfp_req_size) {
740926deccbSFrançois Tigeot 		DRM_ERROR(
74157e252bfSMichael Neumann 		       "ni_pfp: Bogus length %zu in firmware \"%s\"\n",
742926deccbSFrançois Tigeot 		       rdev->pfp_fw->datasize, fw_name);
743926deccbSFrançois Tigeot 		err = -EINVAL;
744926deccbSFrançois Tigeot 		goto out;
745926deccbSFrançois Tigeot 	}
746926deccbSFrançois Tigeot 
747926deccbSFrançois Tigeot 	ksnprintf(fw_name, sizeof(fw_name), "radeonkmsfw_%s_me", chip_name);
748*fcd4983fSzrj 	err = request_firmware(&rdev->me_fw, fw_name, rdev->dev);
749*fcd4983fSzrj 	if (err)
750926deccbSFrançois Tigeot 		goto out;
751926deccbSFrançois Tigeot 	if (rdev->me_fw->datasize != me_req_size) {
752926deccbSFrançois Tigeot 		DRM_ERROR(
75357e252bfSMichael Neumann 		       "ni_me: Bogus length %zu in firmware \"%s\"\n",
754926deccbSFrançois Tigeot 		       rdev->me_fw->datasize, fw_name);
755926deccbSFrançois Tigeot 		err = -EINVAL;
756926deccbSFrançois Tigeot 	}
757926deccbSFrançois Tigeot 
758926deccbSFrançois Tigeot 	ksnprintf(fw_name, sizeof(fw_name), "radeonkmsfw_%s_rlc",
759926deccbSFrançois Tigeot 		  rlc_chip_name);
760*fcd4983fSzrj 	err = request_firmware(&rdev->rlc_fw, fw_name, rdev->dev);
761*fcd4983fSzrj 	if (err)
762926deccbSFrançois Tigeot 		goto out;
763926deccbSFrançois Tigeot 	if (rdev->rlc_fw->datasize != rlc_req_size) {
764926deccbSFrançois Tigeot 		DRM_ERROR(
765926deccbSFrançois Tigeot 		       "ni_rlc: Bogus length %zu in firmware \"%s\"\n",
766926deccbSFrançois Tigeot 		       rdev->rlc_fw->datasize, fw_name);
767926deccbSFrançois Tigeot 		err = -EINVAL;
768926deccbSFrançois Tigeot 	}
769926deccbSFrançois Tigeot 
770926deccbSFrançois Tigeot 	/* no MC ucode on TN */
771926deccbSFrançois Tigeot 	if (!(rdev->flags & RADEON_IS_IGP)) {
772*fcd4983fSzrj 		ksnprintf(fw_name, sizeof(fw_name), "radeonkmsfw_%s_mc", chip_name);
773*fcd4983fSzrj 		err = request_firmware(&rdev->mc_fw, fw_name, rdev->dev);
774*fcd4983fSzrj 		if (err)
775926deccbSFrançois Tigeot 			goto out;
776926deccbSFrançois Tigeot 		if (rdev->mc_fw->datasize != mc_req_size) {
777926deccbSFrançois Tigeot 			DRM_ERROR(
778926deccbSFrançois Tigeot 			       "ni_mc: Bogus length %zu in firmware \"%s\"\n",
779926deccbSFrançois Tigeot 			       rdev->mc_fw->datasize, fw_name);
780926deccbSFrançois Tigeot 			err = -EINVAL;
781926deccbSFrançois Tigeot 		}
782926deccbSFrançois Tigeot 	}
78357e252bfSMichael Neumann 
78457e252bfSMichael Neumann 	if ((rdev->family >= CHIP_BARTS) && (rdev->family <= CHIP_CAYMAN)) {
78557e252bfSMichael Neumann 		ksnprintf(fw_name, sizeof(fw_name), "radeonkmsfw_%s_smc", chip_name);
78657e252bfSMichael Neumann 		err = request_firmware(&rdev->smc_fw, fw_name, rdev->dev);
78757e252bfSMichael Neumann 		if (err) {
78857e252bfSMichael Neumann 			printk(KERN_ERR
78957e252bfSMichael Neumann 			       "smc: error loading firmware \"%s\"\n",
79057e252bfSMichael Neumann 			       fw_name);
79157e252bfSMichael Neumann 			release_firmware(rdev->smc_fw);
79257e252bfSMichael Neumann 			rdev->smc_fw = NULL;
79357e252bfSMichael Neumann 		} else if (rdev->smc_fw->datasize != smc_req_size) {
79457e252bfSMichael Neumann 			printk(KERN_ERR
79557e252bfSMichael Neumann 			       "ni_smc: Bogus length %zu in firmware \"%s\"\n",
79657e252bfSMichael Neumann 			       rdev->smc_fw->datasize, fw_name);
79757e252bfSMichael Neumann 			err = -EINVAL;
79857e252bfSMichael Neumann 		}
79957e252bfSMichael Neumann 	}
80057e252bfSMichael Neumann 
801926deccbSFrançois Tigeot out:
802926deccbSFrançois Tigeot 	if (err) {
803926deccbSFrançois Tigeot 		if (err != -EINVAL)
804926deccbSFrançois Tigeot 			DRM_ERROR(
805926deccbSFrançois Tigeot 			       "ni_cp: Failed to load firmware \"%s\"\n",
806926deccbSFrançois Tigeot 			       fw_name);
807*fcd4983fSzrj 		release_firmware(rdev->pfp_fw);
808926deccbSFrançois Tigeot 		rdev->pfp_fw = NULL;
809*fcd4983fSzrj 		release_firmware(rdev->me_fw);
810926deccbSFrançois Tigeot 		rdev->me_fw = NULL;
811*fcd4983fSzrj 		release_firmware(rdev->rlc_fw);
812926deccbSFrançois Tigeot 		rdev->rlc_fw = NULL;
813*fcd4983fSzrj 		release_firmware(rdev->mc_fw);
814926deccbSFrançois Tigeot 		rdev->mc_fw = NULL;
815*fcd4983fSzrj 		release_firmware(rdev->smc_fw);
81657e252bfSMichael Neumann 		rdev->smc_fw = NULL;
81757e252bfSMichael Neumann 	}
818926deccbSFrançois Tigeot 	return err;
819926deccbSFrançois Tigeot }
820926deccbSFrançois Tigeot 
821926deccbSFrançois Tigeot /**
822926deccbSFrançois Tigeot  * ni_fini_microcode - drop the firmwares image references
823926deccbSFrançois Tigeot  *
824926deccbSFrançois Tigeot  * @rdev: radeon_device pointer
825926deccbSFrançois Tigeot  *
826926deccbSFrançois Tigeot  * Drop the pfp, me, mc and rlc firmwares image references.
827926deccbSFrançois Tigeot  * Called at driver shutdown.
828926deccbSFrançois Tigeot  */
829926deccbSFrançois Tigeot void ni_fini_microcode(struct radeon_device *rdev)
830926deccbSFrançois Tigeot {
831*fcd4983fSzrj 	release_firmware(rdev->pfp_fw);
832926deccbSFrançois Tigeot 	rdev->pfp_fw = NULL;
833*fcd4983fSzrj 	release_firmware(rdev->me_fw);
834926deccbSFrançois Tigeot 	rdev->me_fw = NULL;
835*fcd4983fSzrj 	release_firmware(rdev->rlc_fw);
836926deccbSFrançois Tigeot 	rdev->rlc_fw = NULL;
837*fcd4983fSzrj 	release_firmware(rdev->mc_fw);
838926deccbSFrançois Tigeot 	rdev->mc_fw = NULL;
839926deccbSFrançois Tigeot }
840926deccbSFrançois Tigeot 
84157e252bfSMichael Neumann int tn_get_temp(struct radeon_device *rdev)
84257e252bfSMichael Neumann {
84357e252bfSMichael Neumann 	u32 temp = RREG32_SMC(TN_CURRENT_GNB_TEMP) & 0x7ff;
84457e252bfSMichael Neumann 	int actual_temp = (temp / 8) - 49;
84557e252bfSMichael Neumann 
84657e252bfSMichael Neumann 	return actual_temp * 1000;
84757e252bfSMichael Neumann }
84857e252bfSMichael Neumann 
849926deccbSFrançois Tigeot /*
850926deccbSFrançois Tigeot  * Core functions
851926deccbSFrançois Tigeot  */
852926deccbSFrançois Tigeot static void cayman_gpu_init(struct radeon_device *rdev)
853926deccbSFrançois Tigeot {
854926deccbSFrançois Tigeot 	u32 gb_addr_config = 0;
855926deccbSFrançois Tigeot 	u32 mc_shared_chmap, mc_arb_ramcfg;
856926deccbSFrançois Tigeot 	u32 cgts_tcc_disable;
857926deccbSFrançois Tigeot 	u32 sx_debug_1;
858926deccbSFrançois Tigeot 	u32 smx_dc_ctl0;
859926deccbSFrançois Tigeot 	u32 cgts_sm_ctrl_reg;
860926deccbSFrançois Tigeot 	u32 hdp_host_path_cntl;
861926deccbSFrançois Tigeot 	u32 tmp;
862926deccbSFrançois Tigeot 	u32 disabled_rb_mask;
863926deccbSFrançois Tigeot 	int i, j;
864926deccbSFrançois Tigeot 
865926deccbSFrançois Tigeot 	switch (rdev->family) {
866926deccbSFrançois Tigeot 	case CHIP_CAYMAN:
867926deccbSFrançois Tigeot 		rdev->config.cayman.max_shader_engines = 2;
868926deccbSFrançois Tigeot 		rdev->config.cayman.max_pipes_per_simd = 4;
869926deccbSFrançois Tigeot 		rdev->config.cayman.max_tile_pipes = 8;
870926deccbSFrançois Tigeot 		rdev->config.cayman.max_simds_per_se = 12;
871926deccbSFrançois Tigeot 		rdev->config.cayman.max_backends_per_se = 4;
872926deccbSFrançois Tigeot 		rdev->config.cayman.max_texture_channel_caches = 8;
873926deccbSFrançois Tigeot 		rdev->config.cayman.max_gprs = 256;
874926deccbSFrançois Tigeot 		rdev->config.cayman.max_threads = 256;
875926deccbSFrançois Tigeot 		rdev->config.cayman.max_gs_threads = 32;
876926deccbSFrançois Tigeot 		rdev->config.cayman.max_stack_entries = 512;
877926deccbSFrançois Tigeot 		rdev->config.cayman.sx_num_of_sets = 8;
878926deccbSFrançois Tigeot 		rdev->config.cayman.sx_max_export_size = 256;
879926deccbSFrançois Tigeot 		rdev->config.cayman.sx_max_export_pos_size = 64;
880926deccbSFrançois Tigeot 		rdev->config.cayman.sx_max_export_smx_size = 192;
881926deccbSFrançois Tigeot 		rdev->config.cayman.max_hw_contexts = 8;
882926deccbSFrançois Tigeot 		rdev->config.cayman.sq_num_cf_insts = 2;
883926deccbSFrançois Tigeot 
884926deccbSFrançois Tigeot 		rdev->config.cayman.sc_prim_fifo_size = 0x100;
885926deccbSFrançois Tigeot 		rdev->config.cayman.sc_hiz_tile_fifo_size = 0x30;
886926deccbSFrançois Tigeot 		rdev->config.cayman.sc_earlyz_tile_fifo_size = 0x130;
887926deccbSFrançois Tigeot 		gb_addr_config = CAYMAN_GB_ADDR_CONFIG_GOLDEN;
888926deccbSFrançois Tigeot 		break;
889926deccbSFrançois Tigeot 	case CHIP_ARUBA:
890926deccbSFrançois Tigeot 	default:
891926deccbSFrançois Tigeot 		rdev->config.cayman.max_shader_engines = 1;
892926deccbSFrançois Tigeot 		rdev->config.cayman.max_pipes_per_simd = 4;
893926deccbSFrançois Tigeot 		rdev->config.cayman.max_tile_pipes = 2;
894926deccbSFrançois Tigeot 		if ((rdev->ddev->pci_device == 0x9900) ||
895926deccbSFrançois Tigeot 		    (rdev->ddev->pci_device == 0x9901) ||
896926deccbSFrançois Tigeot 		    (rdev->ddev->pci_device == 0x9905) ||
897926deccbSFrançois Tigeot 		    (rdev->ddev->pci_device == 0x9906) ||
898926deccbSFrançois Tigeot 		    (rdev->ddev->pci_device == 0x9907) ||
899926deccbSFrançois Tigeot 		    (rdev->ddev->pci_device == 0x9908) ||
900926deccbSFrançois Tigeot 		    (rdev->ddev->pci_device == 0x9909) ||
901b403bed8SMichael Neumann 		    (rdev->ddev->pci_device == 0x990B) ||
902b403bed8SMichael Neumann 		    (rdev->ddev->pci_device == 0x990C) ||
903b403bed8SMichael Neumann 		    (rdev->ddev->pci_device == 0x990F) ||
904926deccbSFrançois Tigeot 		    (rdev->ddev->pci_device == 0x9910) ||
905b403bed8SMichael Neumann 		    (rdev->ddev->pci_device == 0x9917) ||
906f43cf1b1SMichael Neumann 		    (rdev->ddev->pci_device == 0x9999) ||
907f43cf1b1SMichael Neumann 		    (rdev->ddev->pci_device == 0x999C)) {
908926deccbSFrançois Tigeot 			rdev->config.cayman.max_simds_per_se = 6;
909926deccbSFrançois Tigeot 			rdev->config.cayman.max_backends_per_se = 2;
910926deccbSFrançois Tigeot 		} else if ((rdev->ddev->pci_device == 0x9903) ||
911926deccbSFrançois Tigeot 			   (rdev->ddev->pci_device == 0x9904) ||
912926deccbSFrançois Tigeot 			   (rdev->ddev->pci_device == 0x990A) ||
913b403bed8SMichael Neumann 			   (rdev->ddev->pci_device == 0x990D) ||
914b403bed8SMichael Neumann 			   (rdev->ddev->pci_device == 0x990E) ||
915926deccbSFrançois Tigeot 			   (rdev->ddev->pci_device == 0x9913) ||
916f43cf1b1SMichael Neumann 			   (rdev->ddev->pci_device == 0x9918) ||
917f43cf1b1SMichael Neumann 			   (rdev->ddev->pci_device == 0x999D)) {
918926deccbSFrançois Tigeot 			rdev->config.cayman.max_simds_per_se = 4;
919926deccbSFrançois Tigeot 			rdev->config.cayman.max_backends_per_se = 2;
920926deccbSFrançois Tigeot 		} else if ((rdev->ddev->pci_device == 0x9919) ||
921926deccbSFrançois Tigeot 			   (rdev->ddev->pci_device == 0x9990) ||
922926deccbSFrançois Tigeot 			   (rdev->ddev->pci_device == 0x9991) ||
923926deccbSFrançois Tigeot 			   (rdev->ddev->pci_device == 0x9994) ||
924b403bed8SMichael Neumann 			   (rdev->ddev->pci_device == 0x9995) ||
925b403bed8SMichael Neumann 			   (rdev->ddev->pci_device == 0x9996) ||
926b403bed8SMichael Neumann 			   (rdev->ddev->pci_device == 0x999A) ||
927926deccbSFrançois Tigeot 			   (rdev->ddev->pci_device == 0x99A0)) {
928926deccbSFrançois Tigeot 			rdev->config.cayman.max_simds_per_se = 3;
929926deccbSFrançois Tigeot 			rdev->config.cayman.max_backends_per_se = 1;
930926deccbSFrançois Tigeot 		} else {
931926deccbSFrançois Tigeot 			rdev->config.cayman.max_simds_per_se = 2;
932926deccbSFrançois Tigeot 			rdev->config.cayman.max_backends_per_se = 1;
933926deccbSFrançois Tigeot 		}
934926deccbSFrançois Tigeot 		rdev->config.cayman.max_texture_channel_caches = 2;
935926deccbSFrançois Tigeot 		rdev->config.cayman.max_gprs = 256;
936926deccbSFrançois Tigeot 		rdev->config.cayman.max_threads = 256;
937926deccbSFrançois Tigeot 		rdev->config.cayman.max_gs_threads = 32;
938926deccbSFrançois Tigeot 		rdev->config.cayman.max_stack_entries = 512;
939926deccbSFrançois Tigeot 		rdev->config.cayman.sx_num_of_sets = 8;
940926deccbSFrançois Tigeot 		rdev->config.cayman.sx_max_export_size = 256;
941926deccbSFrançois Tigeot 		rdev->config.cayman.sx_max_export_pos_size = 64;
942926deccbSFrançois Tigeot 		rdev->config.cayman.sx_max_export_smx_size = 192;
943926deccbSFrançois Tigeot 		rdev->config.cayman.max_hw_contexts = 8;
944926deccbSFrançois Tigeot 		rdev->config.cayman.sq_num_cf_insts = 2;
945926deccbSFrançois Tigeot 
946926deccbSFrançois Tigeot 		rdev->config.cayman.sc_prim_fifo_size = 0x40;
947926deccbSFrançois Tigeot 		rdev->config.cayman.sc_hiz_tile_fifo_size = 0x30;
948926deccbSFrançois Tigeot 		rdev->config.cayman.sc_earlyz_tile_fifo_size = 0x130;
949926deccbSFrançois Tigeot 		gb_addr_config = ARUBA_GB_ADDR_CONFIG_GOLDEN;
950926deccbSFrançois Tigeot 		break;
951926deccbSFrançois Tigeot 	}
952926deccbSFrançois Tigeot 
953926deccbSFrançois Tigeot 	/* Initialize HDP */
954926deccbSFrançois Tigeot 	for (i = 0, j = 0; i < 32; i++, j += 0x18) {
955926deccbSFrançois Tigeot 		WREG32((0x2c14 + j), 0x00000000);
956926deccbSFrançois Tigeot 		WREG32((0x2c18 + j), 0x00000000);
957926deccbSFrançois Tigeot 		WREG32((0x2c1c + j), 0x00000000);
958926deccbSFrançois Tigeot 		WREG32((0x2c20 + j), 0x00000000);
959926deccbSFrançois Tigeot 		WREG32((0x2c24 + j), 0x00000000);
960926deccbSFrançois Tigeot 	}
961926deccbSFrançois Tigeot 
962926deccbSFrançois Tigeot 	WREG32(GRBM_CNTL, GRBM_READ_TIMEOUT(0xff));
963926deccbSFrançois Tigeot 
964926deccbSFrançois Tigeot 	evergreen_fix_pci_max_read_req_size(rdev);
965926deccbSFrançois Tigeot 
966926deccbSFrançois Tigeot 	mc_shared_chmap = RREG32(MC_SHARED_CHMAP);
967926deccbSFrançois Tigeot 	mc_arb_ramcfg = RREG32(MC_ARB_RAMCFG);
968926deccbSFrançois Tigeot 
969926deccbSFrançois Tigeot 	tmp = (mc_arb_ramcfg & NOOFCOLS_MASK) >> NOOFCOLS_SHIFT;
970926deccbSFrançois Tigeot 	rdev->config.cayman.mem_row_size_in_kb = (4 * (1 << (8 + tmp))) / 1024;
971926deccbSFrançois Tigeot 	if (rdev->config.cayman.mem_row_size_in_kb > 4)
972926deccbSFrançois Tigeot 		rdev->config.cayman.mem_row_size_in_kb = 4;
973926deccbSFrançois Tigeot 	/* XXX use MC settings? */
974926deccbSFrançois Tigeot 	rdev->config.cayman.shader_engine_tile_size = 32;
975926deccbSFrançois Tigeot 	rdev->config.cayman.num_gpus = 1;
976926deccbSFrançois Tigeot 	rdev->config.cayman.multi_gpu_tile_size = 64;
977926deccbSFrançois Tigeot 
978926deccbSFrançois Tigeot 	tmp = (gb_addr_config & NUM_PIPES_MASK) >> NUM_PIPES_SHIFT;
979926deccbSFrançois Tigeot 	rdev->config.cayman.num_tile_pipes = (1 << tmp);
980926deccbSFrançois Tigeot 	tmp = (gb_addr_config & PIPE_INTERLEAVE_SIZE_MASK) >> PIPE_INTERLEAVE_SIZE_SHIFT;
981926deccbSFrançois Tigeot 	rdev->config.cayman.mem_max_burst_length_bytes = (tmp + 1) * 256;
982926deccbSFrançois Tigeot 	tmp = (gb_addr_config & NUM_SHADER_ENGINES_MASK) >> NUM_SHADER_ENGINES_SHIFT;
983926deccbSFrançois Tigeot 	rdev->config.cayman.num_shader_engines = tmp + 1;
984926deccbSFrançois Tigeot 	tmp = (gb_addr_config & NUM_GPUS_MASK) >> NUM_GPUS_SHIFT;
985926deccbSFrançois Tigeot 	rdev->config.cayman.num_gpus = tmp + 1;
986926deccbSFrançois Tigeot 	tmp = (gb_addr_config & MULTI_GPU_TILE_SIZE_MASK) >> MULTI_GPU_TILE_SIZE_SHIFT;
987926deccbSFrançois Tigeot 	rdev->config.cayman.multi_gpu_tile_size = 1 << tmp;
988926deccbSFrançois Tigeot 	tmp = (gb_addr_config & ROW_SIZE_MASK) >> ROW_SIZE_SHIFT;
989926deccbSFrançois Tigeot 	rdev->config.cayman.mem_row_size_in_kb = 1 << tmp;
990926deccbSFrançois Tigeot 
991926deccbSFrançois Tigeot 
992926deccbSFrançois Tigeot 	/* setup tiling info dword.  gb_addr_config is not adequate since it does
993926deccbSFrançois Tigeot 	 * not have bank info, so create a custom tiling dword.
994926deccbSFrançois Tigeot 	 * bits 3:0   num_pipes
995926deccbSFrançois Tigeot 	 * bits 7:4   num_banks
996926deccbSFrançois Tigeot 	 * bits 11:8  group_size
997926deccbSFrançois Tigeot 	 * bits 15:12 row_size
998926deccbSFrançois Tigeot 	 */
999926deccbSFrançois Tigeot 	rdev->config.cayman.tile_config = 0;
1000926deccbSFrançois Tigeot 	switch (rdev->config.cayman.num_tile_pipes) {
1001926deccbSFrançois Tigeot 	case 1:
1002926deccbSFrançois Tigeot 	default:
1003926deccbSFrançois Tigeot 		rdev->config.cayman.tile_config |= (0 << 0);
1004926deccbSFrançois Tigeot 		break;
1005926deccbSFrançois Tigeot 	case 2:
1006926deccbSFrançois Tigeot 		rdev->config.cayman.tile_config |= (1 << 0);
1007926deccbSFrançois Tigeot 		break;
1008926deccbSFrançois Tigeot 	case 4:
1009926deccbSFrançois Tigeot 		rdev->config.cayman.tile_config |= (2 << 0);
1010926deccbSFrançois Tigeot 		break;
1011926deccbSFrançois Tigeot 	case 8:
1012926deccbSFrançois Tigeot 		rdev->config.cayman.tile_config |= (3 << 0);
1013926deccbSFrançois Tigeot 		break;
1014926deccbSFrançois Tigeot 	}
1015926deccbSFrançois Tigeot 
1016926deccbSFrançois Tigeot 	/* num banks is 8 on all fusion asics. 0 = 4, 1 = 8, 2 = 16 */
1017926deccbSFrançois Tigeot 	if (rdev->flags & RADEON_IS_IGP)
1018926deccbSFrançois Tigeot 		rdev->config.cayman.tile_config |= 1 << 4;
1019926deccbSFrançois Tigeot 	else {
1020926deccbSFrançois Tigeot 		switch ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) {
1021926deccbSFrançois Tigeot 		case 0: /* four banks */
1022926deccbSFrançois Tigeot 			rdev->config.cayman.tile_config |= 0 << 4;
1023926deccbSFrançois Tigeot 			break;
1024926deccbSFrançois Tigeot 		case 1: /* eight banks */
1025926deccbSFrançois Tigeot 			rdev->config.cayman.tile_config |= 1 << 4;
1026926deccbSFrançois Tigeot 			break;
1027926deccbSFrançois Tigeot 		case 2: /* sixteen banks */
1028926deccbSFrançois Tigeot 		default:
1029926deccbSFrançois Tigeot 			rdev->config.cayman.tile_config |= 2 << 4;
1030926deccbSFrançois Tigeot 			break;
1031926deccbSFrançois Tigeot 		}
1032926deccbSFrançois Tigeot 	}
1033926deccbSFrançois Tigeot 	rdev->config.cayman.tile_config |=
1034926deccbSFrançois Tigeot 		((gb_addr_config & PIPE_INTERLEAVE_SIZE_MASK) >> PIPE_INTERLEAVE_SIZE_SHIFT) << 8;
1035926deccbSFrançois Tigeot 	rdev->config.cayman.tile_config |=
1036926deccbSFrançois Tigeot 		((gb_addr_config & ROW_SIZE_MASK) >> ROW_SIZE_SHIFT) << 12;
1037926deccbSFrançois Tigeot 
1038926deccbSFrançois Tigeot 	tmp = 0;
1039926deccbSFrançois Tigeot 	for (i = (rdev->config.cayman.max_shader_engines - 1); i >= 0; i--) {
1040926deccbSFrançois Tigeot 		u32 rb_disable_bitmap;
1041926deccbSFrançois Tigeot 
1042926deccbSFrançois Tigeot 		WREG32(GRBM_GFX_INDEX, INSTANCE_BROADCAST_WRITES | SE_INDEX(i));
1043926deccbSFrançois Tigeot 		WREG32(RLC_GFX_INDEX, INSTANCE_BROADCAST_WRITES | SE_INDEX(i));
1044926deccbSFrançois Tigeot 		rb_disable_bitmap = (RREG32(CC_RB_BACKEND_DISABLE) & 0x00ff0000) >> 16;
1045926deccbSFrançois Tigeot 		tmp <<= 4;
1046926deccbSFrançois Tigeot 		tmp |= rb_disable_bitmap;
1047926deccbSFrançois Tigeot 	}
1048926deccbSFrançois Tigeot 	/* enabled rb are just the one not disabled :) */
1049926deccbSFrançois Tigeot 	disabled_rb_mask = tmp;
1050f43cf1b1SMichael Neumann 	tmp = 0;
1051f43cf1b1SMichael Neumann 	for (i = 0; i < (rdev->config.cayman.max_backends_per_se * rdev->config.cayman.max_shader_engines); i++)
1052f43cf1b1SMichael Neumann 		tmp |= (1 << i);
1053f43cf1b1SMichael Neumann 	/* if all the backends are disabled, fix it up here */
1054f43cf1b1SMichael Neumann 	if ((disabled_rb_mask & tmp) == tmp) {
1055f43cf1b1SMichael Neumann 		for (i = 0; i < (rdev->config.cayman.max_backends_per_se * rdev->config.cayman.max_shader_engines); i++)
1056f43cf1b1SMichael Neumann 			disabled_rb_mask &= ~(1 << i);
1057f43cf1b1SMichael Neumann 	}
1058926deccbSFrançois Tigeot 
1059926deccbSFrançois Tigeot 	WREG32(GRBM_GFX_INDEX, INSTANCE_BROADCAST_WRITES | SE_BROADCAST_WRITES);
1060926deccbSFrançois Tigeot 	WREG32(RLC_GFX_INDEX, INSTANCE_BROADCAST_WRITES | SE_BROADCAST_WRITES);
1061926deccbSFrançois Tigeot 
1062926deccbSFrançois Tigeot 	WREG32(GB_ADDR_CONFIG, gb_addr_config);
1063926deccbSFrançois Tigeot 	WREG32(DMIF_ADDR_CONFIG, gb_addr_config);
1064f43cf1b1SMichael Neumann 	if (ASIC_IS_DCE6(rdev))
1065f43cf1b1SMichael Neumann 		WREG32(DMIF_ADDR_CALC, gb_addr_config);
1066926deccbSFrançois Tigeot 	WREG32(HDP_ADDR_CONFIG, gb_addr_config);
1067926deccbSFrançois Tigeot 	WREG32(DMA_TILING_CONFIG + DMA0_REGISTER_OFFSET, gb_addr_config);
1068926deccbSFrançois Tigeot 	WREG32(DMA_TILING_CONFIG + DMA1_REGISTER_OFFSET, gb_addr_config);
1069f43cf1b1SMichael Neumann 	WREG32(UVD_UDEC_ADDR_CONFIG, gb_addr_config);
1070f43cf1b1SMichael Neumann 	WREG32(UVD_UDEC_DB_ADDR_CONFIG, gb_addr_config);
1071f43cf1b1SMichael Neumann 	WREG32(UVD_UDEC_DBW_ADDR_CONFIG, gb_addr_config);
1072926deccbSFrançois Tigeot 
1073b403bed8SMichael Neumann 	if ((rdev->config.cayman.max_backends_per_se == 1) &&
1074b403bed8SMichael Neumann 	    (rdev->flags & RADEON_IS_IGP)) {
1075b403bed8SMichael Neumann 		if ((disabled_rb_mask & 3) == 1) {
1076b403bed8SMichael Neumann 			/* RB0 disabled, RB1 enabled */
1077b403bed8SMichael Neumann 			tmp = 0x11111111;
1078b403bed8SMichael Neumann 		} else {
1079b403bed8SMichael Neumann 			/* RB1 disabled, RB0 enabled */
1080b403bed8SMichael Neumann 			tmp = 0x00000000;
1081b403bed8SMichael Neumann 		}
1082b403bed8SMichael Neumann 	} else {
1083926deccbSFrançois Tigeot 		tmp = gb_addr_config & NUM_PIPES_MASK;
1084926deccbSFrançois Tigeot 		tmp = r6xx_remap_render_backend(rdev, tmp,
1085926deccbSFrançois Tigeot 						rdev->config.cayman.max_backends_per_se *
1086926deccbSFrançois Tigeot 						rdev->config.cayman.max_shader_engines,
1087926deccbSFrançois Tigeot 						CAYMAN_MAX_BACKENDS, disabled_rb_mask);
1088b403bed8SMichael Neumann 	}
1089926deccbSFrançois Tigeot 	WREG32(GB_BACKEND_MAP, tmp);
1090926deccbSFrançois Tigeot 
1091926deccbSFrançois Tigeot 	cgts_tcc_disable = 0xffff0000;
1092926deccbSFrançois Tigeot 	for (i = 0; i < rdev->config.cayman.max_texture_channel_caches; i++)
1093926deccbSFrançois Tigeot 		cgts_tcc_disable &= ~(1 << (16 + i));
1094926deccbSFrançois Tigeot 	WREG32(CGTS_TCC_DISABLE, cgts_tcc_disable);
1095926deccbSFrançois Tigeot 	WREG32(CGTS_SYS_TCC_DISABLE, cgts_tcc_disable);
1096926deccbSFrançois Tigeot 	WREG32(CGTS_USER_SYS_TCC_DISABLE, cgts_tcc_disable);
1097926deccbSFrançois Tigeot 	WREG32(CGTS_USER_TCC_DISABLE, cgts_tcc_disable);
1098926deccbSFrançois Tigeot 
1099926deccbSFrançois Tigeot 	/* reprogram the shader complex */
1100926deccbSFrançois Tigeot 	cgts_sm_ctrl_reg = RREG32(CGTS_SM_CTRL_REG);
1101926deccbSFrançois Tigeot 	for (i = 0; i < 16; i++)
1102926deccbSFrançois Tigeot 		WREG32(CGTS_SM_CTRL_REG, OVERRIDE);
1103926deccbSFrançois Tigeot 	WREG32(CGTS_SM_CTRL_REG, cgts_sm_ctrl_reg);
1104926deccbSFrançois Tigeot 
1105926deccbSFrançois Tigeot 	/* set HW defaults for 3D engine */
1106926deccbSFrançois Tigeot 	WREG32(CP_MEQ_THRESHOLDS, MEQ1_START(0x30) | MEQ2_START(0x60));
1107926deccbSFrançois Tigeot 
1108926deccbSFrançois Tigeot 	sx_debug_1 = RREG32(SX_DEBUG_1);
1109926deccbSFrançois Tigeot 	sx_debug_1 |= ENABLE_NEW_SMX_ADDRESS;
1110926deccbSFrançois Tigeot 	WREG32(SX_DEBUG_1, sx_debug_1);
1111926deccbSFrançois Tigeot 
1112926deccbSFrançois Tigeot 	smx_dc_ctl0 = RREG32(SMX_DC_CTL0);
1113926deccbSFrançois Tigeot 	smx_dc_ctl0 &= ~NUMBER_OF_SETS(0x1ff);
1114926deccbSFrançois Tigeot 	smx_dc_ctl0 |= NUMBER_OF_SETS(rdev->config.cayman.sx_num_of_sets);
1115926deccbSFrançois Tigeot 	WREG32(SMX_DC_CTL0, smx_dc_ctl0);
1116926deccbSFrançois Tigeot 
1117926deccbSFrançois Tigeot 	WREG32(SPI_CONFIG_CNTL_1, VTX_DONE_DELAY(4) | CRC_SIMD_ID_WADDR_DISABLE);
1118926deccbSFrançois Tigeot 
1119926deccbSFrançois Tigeot 	/* need to be explicitly zero-ed */
1120926deccbSFrançois Tigeot 	WREG32(VGT_OFFCHIP_LDS_BASE, 0);
1121926deccbSFrançois Tigeot 	WREG32(SQ_LSTMP_RING_BASE, 0);
1122926deccbSFrançois Tigeot 	WREG32(SQ_HSTMP_RING_BASE, 0);
1123926deccbSFrançois Tigeot 	WREG32(SQ_ESTMP_RING_BASE, 0);
1124926deccbSFrançois Tigeot 	WREG32(SQ_GSTMP_RING_BASE, 0);
1125926deccbSFrançois Tigeot 	WREG32(SQ_VSTMP_RING_BASE, 0);
1126926deccbSFrançois Tigeot 	WREG32(SQ_PSTMP_RING_BASE, 0);
1127926deccbSFrançois Tigeot 
1128926deccbSFrançois Tigeot 	WREG32(TA_CNTL_AUX, DISABLE_CUBE_ANISO);
1129926deccbSFrançois Tigeot 
1130926deccbSFrançois Tigeot 	WREG32(SX_EXPORT_BUFFER_SIZES, (COLOR_BUFFER_SIZE((rdev->config.cayman.sx_max_export_size / 4) - 1) |
1131926deccbSFrançois Tigeot 					POSITION_BUFFER_SIZE((rdev->config.cayman.sx_max_export_pos_size / 4) - 1) |
1132926deccbSFrançois Tigeot 					SMX_BUFFER_SIZE((rdev->config.cayman.sx_max_export_smx_size / 4) - 1)));
1133926deccbSFrançois Tigeot 
1134926deccbSFrançois Tigeot 	WREG32(PA_SC_FIFO_SIZE, (SC_PRIM_FIFO_SIZE(rdev->config.cayman.sc_prim_fifo_size) |
1135926deccbSFrançois Tigeot 				 SC_HIZ_TILE_FIFO_SIZE(rdev->config.cayman.sc_hiz_tile_fifo_size) |
1136926deccbSFrançois Tigeot 				 SC_EARLYZ_TILE_FIFO_SIZE(rdev->config.cayman.sc_earlyz_tile_fifo_size)));
1137926deccbSFrançois Tigeot 
1138926deccbSFrançois Tigeot 
1139926deccbSFrançois Tigeot 	WREG32(VGT_NUM_INSTANCES, 1);
1140926deccbSFrançois Tigeot 
1141926deccbSFrançois Tigeot 	WREG32(CP_PERFMON_CNTL, 0);
1142926deccbSFrançois Tigeot 
1143926deccbSFrançois Tigeot 	WREG32(SQ_MS_FIFO_SIZES, (CACHE_FIFO_SIZE(16 * rdev->config.cayman.sq_num_cf_insts) |
1144926deccbSFrançois Tigeot 				  FETCH_FIFO_HIWATER(0x4) |
1145926deccbSFrançois Tigeot 				  DONE_FIFO_HIWATER(0xe0) |
1146926deccbSFrançois Tigeot 				  ALU_UPDATE_FIFO_HIWATER(0x8)));
1147926deccbSFrançois Tigeot 
1148926deccbSFrançois Tigeot 	WREG32(SQ_GPR_RESOURCE_MGMT_1, NUM_CLAUSE_TEMP_GPRS(4));
1149926deccbSFrançois Tigeot 	WREG32(SQ_CONFIG, (VC_ENABLE |
1150926deccbSFrançois Tigeot 			   EXPORT_SRC_C |
1151926deccbSFrançois Tigeot 			   GFX_PRIO(0) |
1152926deccbSFrançois Tigeot 			   CS1_PRIO(0) |
1153926deccbSFrançois Tigeot 			   CS2_PRIO(1)));
1154926deccbSFrançois Tigeot 	WREG32(SQ_DYN_GPR_CNTL_PS_FLUSH_REQ, DYN_GPR_ENABLE);
1155926deccbSFrançois Tigeot 
1156926deccbSFrançois Tigeot 	WREG32(PA_SC_FORCE_EOV_MAX_CNTS, (FORCE_EOV_MAX_CLK_CNT(4095) |
1157926deccbSFrançois Tigeot 					  FORCE_EOV_MAX_REZ_CNT(255)));
1158926deccbSFrançois Tigeot 
1159926deccbSFrançois Tigeot 	WREG32(VGT_CACHE_INVALIDATION, CACHE_INVALIDATION(VC_AND_TC) |
1160926deccbSFrançois Tigeot 	       AUTO_INVLD_EN(ES_AND_GS_AUTO));
1161926deccbSFrançois Tigeot 
1162926deccbSFrançois Tigeot 	WREG32(VGT_GS_VERTEX_REUSE, 16);
1163926deccbSFrançois Tigeot 	WREG32(PA_SC_LINE_STIPPLE_STATE, 0);
1164926deccbSFrançois Tigeot 
1165926deccbSFrançois Tigeot 	WREG32(CB_PERF_CTR0_SEL_0, 0);
1166926deccbSFrançois Tigeot 	WREG32(CB_PERF_CTR0_SEL_1, 0);
1167926deccbSFrançois Tigeot 	WREG32(CB_PERF_CTR1_SEL_0, 0);
1168926deccbSFrançois Tigeot 	WREG32(CB_PERF_CTR1_SEL_1, 0);
1169926deccbSFrançois Tigeot 	WREG32(CB_PERF_CTR2_SEL_0, 0);
1170926deccbSFrançois Tigeot 	WREG32(CB_PERF_CTR2_SEL_1, 0);
1171926deccbSFrançois Tigeot 	WREG32(CB_PERF_CTR3_SEL_0, 0);
1172926deccbSFrançois Tigeot 	WREG32(CB_PERF_CTR3_SEL_1, 0);
1173926deccbSFrançois Tigeot 
1174926deccbSFrançois Tigeot 	tmp = RREG32(HDP_MISC_CNTL);
1175926deccbSFrançois Tigeot 	tmp |= HDP_FLUSH_INVALIDATE_CACHE;
1176926deccbSFrançois Tigeot 	WREG32(HDP_MISC_CNTL, tmp);
1177926deccbSFrançois Tigeot 
1178926deccbSFrançois Tigeot 	hdp_host_path_cntl = RREG32(HDP_HOST_PATH_CNTL);
1179926deccbSFrançois Tigeot 	WREG32(HDP_HOST_PATH_CNTL, hdp_host_path_cntl);
1180926deccbSFrançois Tigeot 
1181926deccbSFrançois Tigeot 	WREG32(PA_CL_ENHANCE, CLIP_VTX_REORDER_ENA | NUM_CLIP_SEQ(3));
1182926deccbSFrançois Tigeot 
1183926deccbSFrançois Tigeot 	DRM_UDELAY(50);
118457e252bfSMichael Neumann 
118557e252bfSMichael Neumann 	/* set clockgating golden values on TN */
118657e252bfSMichael Neumann 	if (rdev->family == CHIP_ARUBA) {
118757e252bfSMichael Neumann 		tmp = RREG32_CG(CG_CGTT_LOCAL_0);
118857e252bfSMichael Neumann 		tmp &= ~0x00380000;
118957e252bfSMichael Neumann 		WREG32_CG(CG_CGTT_LOCAL_0, tmp);
119057e252bfSMichael Neumann                 tmp = RREG32_CG(CG_CGTT_LOCAL_1);
119157e252bfSMichael Neumann 		tmp &= ~0x0e000000;
119257e252bfSMichael Neumann 		WREG32_CG(CG_CGTT_LOCAL_1, tmp);
119357e252bfSMichael Neumann 	}
1194926deccbSFrançois Tigeot }
1195926deccbSFrançois Tigeot 
1196926deccbSFrançois Tigeot /*
1197926deccbSFrançois Tigeot  * GART
1198926deccbSFrançois Tigeot  */
1199926deccbSFrançois Tigeot void cayman_pcie_gart_tlb_flush(struct radeon_device *rdev)
1200926deccbSFrançois Tigeot {
1201926deccbSFrançois Tigeot 	/* flush hdp cache */
1202926deccbSFrançois Tigeot 	WREG32(HDP_MEM_COHERENCY_FLUSH_CNTL, 0x1);
1203926deccbSFrançois Tigeot 
1204926deccbSFrançois Tigeot 	/* bits 0-7 are the VM contexts0-7 */
1205926deccbSFrançois Tigeot 	WREG32(VM_INVALIDATE_REQUEST, 1);
1206926deccbSFrançois Tigeot }
1207926deccbSFrançois Tigeot 
1208926deccbSFrançois Tigeot static int cayman_pcie_gart_enable(struct radeon_device *rdev)
1209926deccbSFrançois Tigeot {
1210926deccbSFrançois Tigeot 	int i, r;
1211926deccbSFrançois Tigeot 
1212926deccbSFrançois Tigeot 	if (rdev->gart.robj == NULL) {
1213926deccbSFrançois Tigeot 		dev_err(rdev->dev, "No VRAM object for PCIE GART.\n");
1214926deccbSFrançois Tigeot 		return -EINVAL;
1215926deccbSFrançois Tigeot 	}
1216926deccbSFrançois Tigeot 	r = radeon_gart_table_vram_pin(rdev);
1217926deccbSFrançois Tigeot 	if (r)
1218926deccbSFrançois Tigeot 		return r;
1219926deccbSFrançois Tigeot 	radeon_gart_restore(rdev);
1220926deccbSFrançois Tigeot 	/* Setup TLB control */
1221926deccbSFrançois Tigeot 	WREG32(MC_VM_MX_L1_TLB_CNTL,
1222926deccbSFrançois Tigeot 	       (0xA << 7) |
1223926deccbSFrançois Tigeot 	       ENABLE_L1_TLB |
1224926deccbSFrançois Tigeot 	       ENABLE_L1_FRAGMENT_PROCESSING |
1225926deccbSFrançois Tigeot 	       SYSTEM_ACCESS_MODE_NOT_IN_SYS |
1226926deccbSFrançois Tigeot 	       ENABLE_ADVANCED_DRIVER_MODEL |
1227926deccbSFrançois Tigeot 	       SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU);
1228926deccbSFrançois Tigeot 	/* Setup L2 cache */
1229926deccbSFrançois Tigeot 	WREG32(VM_L2_CNTL, ENABLE_L2_CACHE |
1230926deccbSFrançois Tigeot 	       ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE |
1231926deccbSFrançois Tigeot 	       ENABLE_L2_PDE0_CACHE_LRU_UPDATE_BY_WRITE |
1232926deccbSFrançois Tigeot 	       EFFECTIVE_L2_QUEUE_SIZE(7) |
1233926deccbSFrançois Tigeot 	       CONTEXT1_IDENTITY_ACCESS_MODE(1));
1234926deccbSFrançois Tigeot 	WREG32(VM_L2_CNTL2, INVALIDATE_ALL_L1_TLBS | INVALIDATE_L2_CACHE);
1235926deccbSFrançois Tigeot 	WREG32(VM_L2_CNTL3, L2_CACHE_BIGK_ASSOCIATIVITY |
1236926deccbSFrançois Tigeot 	       L2_CACHE_BIGK_FRAGMENT_SIZE(6));
1237926deccbSFrançois Tigeot 	/* setup context0 */
1238926deccbSFrançois Tigeot 	WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR, rdev->mc.gtt_start >> 12);
1239926deccbSFrançois Tigeot 	WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR, rdev->mc.gtt_end >> 12);
1240926deccbSFrançois Tigeot 	WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR, rdev->gart.table_addr >> 12);
1241926deccbSFrançois Tigeot 	WREG32(VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR,
1242926deccbSFrançois Tigeot 			(u32)(rdev->dummy_page.addr >> 12));
1243926deccbSFrançois Tigeot 	WREG32(VM_CONTEXT0_CNTL2, 0);
1244926deccbSFrançois Tigeot 	WREG32(VM_CONTEXT0_CNTL, ENABLE_CONTEXT | PAGE_TABLE_DEPTH(0) |
1245926deccbSFrançois Tigeot 				RANGE_PROTECTION_FAULT_ENABLE_DEFAULT);
1246926deccbSFrançois Tigeot 
1247926deccbSFrançois Tigeot 	WREG32(0x15D4, 0);
1248926deccbSFrançois Tigeot 	WREG32(0x15D8, 0);
1249926deccbSFrançois Tigeot 	WREG32(0x15DC, 0);
1250926deccbSFrançois Tigeot 
1251926deccbSFrançois Tigeot 	/* empty context1-7 */
1252926deccbSFrançois Tigeot 	/* Assign the pt base to something valid for now; the pts used for
1253926deccbSFrançois Tigeot 	 * the VMs are determined by the application and setup and assigned
1254926deccbSFrançois Tigeot 	 * on the fly in the vm part of radeon_gart.c
1255926deccbSFrançois Tigeot 	 */
1256926deccbSFrançois Tigeot 	for (i = 1; i < 8; i++) {
1257926deccbSFrançois Tigeot 		WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR + (i << 2), 0);
1258926deccbSFrançois Tigeot 		WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR + (i << 2), rdev->vm_manager.max_pfn);
1259926deccbSFrançois Tigeot 		WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (i << 2),
1260926deccbSFrançois Tigeot 			rdev->gart.table_addr >> 12);
1261926deccbSFrançois Tigeot 	}
1262926deccbSFrançois Tigeot 
1263926deccbSFrançois Tigeot 	/* enable context1-7 */
1264926deccbSFrançois Tigeot 	WREG32(VM_CONTEXT1_PROTECTION_FAULT_DEFAULT_ADDR,
1265926deccbSFrançois Tigeot 	       (u32)(rdev->dummy_page.addr >> 12));
1266926deccbSFrançois Tigeot 	WREG32(VM_CONTEXT1_CNTL2, 4);
1267926deccbSFrançois Tigeot 	WREG32(VM_CONTEXT1_CNTL, ENABLE_CONTEXT | PAGE_TABLE_DEPTH(1) |
1268926deccbSFrançois Tigeot 				RANGE_PROTECTION_FAULT_ENABLE_INTERRUPT |
1269926deccbSFrançois Tigeot 				RANGE_PROTECTION_FAULT_ENABLE_DEFAULT |
1270926deccbSFrançois Tigeot 				DUMMY_PAGE_PROTECTION_FAULT_ENABLE_INTERRUPT |
1271926deccbSFrançois Tigeot 				DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT |
1272926deccbSFrançois Tigeot 				PDE0_PROTECTION_FAULT_ENABLE_INTERRUPT |
1273926deccbSFrançois Tigeot 				PDE0_PROTECTION_FAULT_ENABLE_DEFAULT |
1274926deccbSFrançois Tigeot 				VALID_PROTECTION_FAULT_ENABLE_INTERRUPT |
1275926deccbSFrançois Tigeot 				VALID_PROTECTION_FAULT_ENABLE_DEFAULT |
1276926deccbSFrançois Tigeot 				READ_PROTECTION_FAULT_ENABLE_INTERRUPT |
1277926deccbSFrançois Tigeot 				READ_PROTECTION_FAULT_ENABLE_DEFAULT |
1278926deccbSFrançois Tigeot 				WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT |
1279926deccbSFrançois Tigeot 				WRITE_PROTECTION_FAULT_ENABLE_DEFAULT);
1280926deccbSFrançois Tigeot 
1281926deccbSFrançois Tigeot 	cayman_pcie_gart_tlb_flush(rdev);
1282926deccbSFrançois Tigeot 	DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n",
1283926deccbSFrançois Tigeot 		 (unsigned)(rdev->mc.gtt_size >> 20),
1284926deccbSFrançois Tigeot 		 (unsigned long long)rdev->gart.table_addr);
1285926deccbSFrançois Tigeot 	rdev->gart.ready = true;
1286926deccbSFrançois Tigeot 	return 0;
1287926deccbSFrançois Tigeot }
1288926deccbSFrançois Tigeot 
1289926deccbSFrançois Tigeot static void cayman_pcie_gart_disable(struct radeon_device *rdev)
1290926deccbSFrançois Tigeot {
1291926deccbSFrançois Tigeot 	/* Disable all tables */
1292926deccbSFrançois Tigeot 	WREG32(VM_CONTEXT0_CNTL, 0);
1293926deccbSFrançois Tigeot 	WREG32(VM_CONTEXT1_CNTL, 0);
1294926deccbSFrançois Tigeot 	/* Setup TLB control */
1295926deccbSFrançois Tigeot 	WREG32(MC_VM_MX_L1_TLB_CNTL, ENABLE_L1_FRAGMENT_PROCESSING |
1296926deccbSFrançois Tigeot 	       SYSTEM_ACCESS_MODE_NOT_IN_SYS |
1297926deccbSFrançois Tigeot 	       SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU);
1298926deccbSFrançois Tigeot 	/* Setup L2 cache */
1299926deccbSFrançois Tigeot 	WREG32(VM_L2_CNTL, ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE |
1300926deccbSFrançois Tigeot 	       ENABLE_L2_PDE0_CACHE_LRU_UPDATE_BY_WRITE |
1301926deccbSFrançois Tigeot 	       EFFECTIVE_L2_QUEUE_SIZE(7) |
1302926deccbSFrançois Tigeot 	       CONTEXT1_IDENTITY_ACCESS_MODE(1));
1303926deccbSFrançois Tigeot 	WREG32(VM_L2_CNTL2, 0);
1304926deccbSFrançois Tigeot 	WREG32(VM_L2_CNTL3, L2_CACHE_BIGK_ASSOCIATIVITY |
1305926deccbSFrançois Tigeot 	       L2_CACHE_BIGK_FRAGMENT_SIZE(6));
1306926deccbSFrançois Tigeot 	radeon_gart_table_vram_unpin(rdev);
1307926deccbSFrançois Tigeot }
1308926deccbSFrançois Tigeot 
1309926deccbSFrançois Tigeot static void cayman_pcie_gart_fini(struct radeon_device *rdev)
1310926deccbSFrançois Tigeot {
1311926deccbSFrançois Tigeot 	cayman_pcie_gart_disable(rdev);
1312926deccbSFrançois Tigeot 	radeon_gart_table_vram_free(rdev);
1313926deccbSFrançois Tigeot 	radeon_gart_fini(rdev);
1314926deccbSFrançois Tigeot }
1315926deccbSFrançois Tigeot 
1316926deccbSFrançois Tigeot void cayman_cp_int_cntl_setup(struct radeon_device *rdev,
1317926deccbSFrançois Tigeot 			      int ring, u32 cp_int_cntl)
1318926deccbSFrançois Tigeot {
1319926deccbSFrançois Tigeot 	u32 srbm_gfx_cntl = RREG32(SRBM_GFX_CNTL) & ~3;
1320926deccbSFrançois Tigeot 
1321926deccbSFrançois Tigeot 	WREG32(SRBM_GFX_CNTL, srbm_gfx_cntl | (ring & 3));
1322926deccbSFrançois Tigeot 	WREG32(CP_INT_CNTL, cp_int_cntl);
1323926deccbSFrançois Tigeot }
1324926deccbSFrançois Tigeot 
1325926deccbSFrançois Tigeot /*
1326926deccbSFrançois Tigeot  * CP.
1327926deccbSFrançois Tigeot  */
1328926deccbSFrançois Tigeot void cayman_fence_ring_emit(struct radeon_device *rdev,
1329926deccbSFrançois Tigeot 			    struct radeon_fence *fence)
1330926deccbSFrançois Tigeot {
1331926deccbSFrançois Tigeot 	struct radeon_ring *ring = &rdev->ring[fence->ring];
1332926deccbSFrançois Tigeot 	u64 addr = rdev->fence_drv[fence->ring].gpu_addr;
1333926deccbSFrançois Tigeot 
1334926deccbSFrançois Tigeot 	/* flush read cache over gart for this vmid */
1335926deccbSFrançois Tigeot 	radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1));
1336926deccbSFrançois Tigeot 	radeon_ring_write(ring, (CP_COHER_CNTL2 - PACKET3_SET_CONFIG_REG_START) >> 2);
1337926deccbSFrançois Tigeot 	radeon_ring_write(ring, 0);
1338926deccbSFrançois Tigeot 	radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3));
1339926deccbSFrançois Tigeot 	radeon_ring_write(ring, PACKET3_TC_ACTION_ENA | PACKET3_SH_ACTION_ENA);
1340926deccbSFrançois Tigeot 	radeon_ring_write(ring, 0xFFFFFFFF);
1341926deccbSFrançois Tigeot 	radeon_ring_write(ring, 0);
1342926deccbSFrançois Tigeot 	radeon_ring_write(ring, 10); /* poll interval */
1343926deccbSFrançois Tigeot 	/* EVENT_WRITE_EOP - flush caches, send int */
1344926deccbSFrançois Tigeot 	radeon_ring_write(ring, PACKET3(PACKET3_EVENT_WRITE_EOP, 4));
1345926deccbSFrançois Tigeot 	radeon_ring_write(ring, EVENT_TYPE(CACHE_FLUSH_AND_INV_EVENT_TS) | EVENT_INDEX(5));
1346926deccbSFrançois Tigeot 	radeon_ring_write(ring, addr & 0xffffffff);
1347926deccbSFrançois Tigeot 	radeon_ring_write(ring, (upper_32_bits(addr) & 0xff) | DATA_SEL(1) | INT_SEL(2));
1348926deccbSFrançois Tigeot 	radeon_ring_write(ring, fence->seq);
1349926deccbSFrançois Tigeot 	radeon_ring_write(ring, 0);
1350926deccbSFrançois Tigeot }
1351926deccbSFrançois Tigeot 
1352926deccbSFrançois Tigeot void cayman_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib)
1353926deccbSFrançois Tigeot {
1354926deccbSFrançois Tigeot 	struct radeon_ring *ring = &rdev->ring[ib->ring];
1355926deccbSFrançois Tigeot 
1356926deccbSFrançois Tigeot 	/* set to DX10/11 mode */
1357926deccbSFrançois Tigeot 	radeon_ring_write(ring, PACKET3(PACKET3_MODE_CONTROL, 0));
1358926deccbSFrançois Tigeot 	radeon_ring_write(ring, 1);
1359926deccbSFrançois Tigeot 
1360926deccbSFrançois Tigeot 	if (ring->rptr_save_reg) {
1361926deccbSFrançois Tigeot 		uint32_t next_rptr = ring->wptr + 3 + 4 + 8;
1362926deccbSFrançois Tigeot 		radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1));
1363926deccbSFrançois Tigeot 		radeon_ring_write(ring, ((ring->rptr_save_reg -
1364926deccbSFrançois Tigeot 					  PACKET3_SET_CONFIG_REG_START) >> 2));
1365926deccbSFrançois Tigeot 		radeon_ring_write(ring, next_rptr);
1366926deccbSFrançois Tigeot 	}
1367926deccbSFrançois Tigeot 
1368926deccbSFrançois Tigeot 	radeon_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2));
1369926deccbSFrançois Tigeot 	radeon_ring_write(ring,
1370926deccbSFrançois Tigeot #ifdef __BIG_ENDIAN
1371926deccbSFrançois Tigeot 			  (2 << 0) |
1372926deccbSFrançois Tigeot #endif
1373926deccbSFrançois Tigeot 			  (ib->gpu_addr & 0xFFFFFFFC));
1374926deccbSFrançois Tigeot 	radeon_ring_write(ring, upper_32_bits(ib->gpu_addr) & 0xFF);
1375926deccbSFrançois Tigeot 	radeon_ring_write(ring, ib->length_dw |
1376926deccbSFrançois Tigeot 			  (ib->vm ? (ib->vm->id << 24) : 0));
1377926deccbSFrançois Tigeot 
1378926deccbSFrançois Tigeot 	/* flush read cache over gart for this vmid */
1379926deccbSFrançois Tigeot 	radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1));
1380926deccbSFrançois Tigeot 	radeon_ring_write(ring, (CP_COHER_CNTL2 - PACKET3_SET_CONFIG_REG_START) >> 2);
1381926deccbSFrançois Tigeot 	radeon_ring_write(ring, ib->vm ? ib->vm->id : 0);
1382926deccbSFrançois Tigeot 	radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3));
1383926deccbSFrançois Tigeot 	radeon_ring_write(ring, PACKET3_TC_ACTION_ENA | PACKET3_SH_ACTION_ENA);
1384926deccbSFrançois Tigeot 	radeon_ring_write(ring, 0xFFFFFFFF);
1385926deccbSFrançois Tigeot 	radeon_ring_write(ring, 0);
1386926deccbSFrançois Tigeot 	radeon_ring_write(ring, 10); /* poll interval */
1387926deccbSFrançois Tigeot }
1388926deccbSFrançois Tigeot 
1389f43cf1b1SMichael Neumann void cayman_uvd_semaphore_emit(struct radeon_device *rdev,
1390f43cf1b1SMichael Neumann 			       struct radeon_ring *ring,
1391f43cf1b1SMichael Neumann 			       struct radeon_semaphore *semaphore,
1392f43cf1b1SMichael Neumann 			       bool emit_wait)
1393f43cf1b1SMichael Neumann {
1394f43cf1b1SMichael Neumann 	uint64_t addr = semaphore->gpu_addr;
1395f43cf1b1SMichael Neumann 
1396f43cf1b1SMichael Neumann 	radeon_ring_write(ring, PACKET0(UVD_SEMA_ADDR_LOW, 0));
1397f43cf1b1SMichael Neumann 	radeon_ring_write(ring, (addr >> 3) & 0x000FFFFF);
1398f43cf1b1SMichael Neumann 
1399f43cf1b1SMichael Neumann 	radeon_ring_write(ring, PACKET0(UVD_SEMA_ADDR_HIGH, 0));
1400f43cf1b1SMichael Neumann 	radeon_ring_write(ring, (addr >> 23) & 0x000FFFFF);
1401f43cf1b1SMichael Neumann 
1402f43cf1b1SMichael Neumann 	radeon_ring_write(ring, PACKET0(UVD_SEMA_CMD, 0));
1403f43cf1b1SMichael Neumann 	radeon_ring_write(ring, 0x80 | (emit_wait ? 1 : 0));
1404f43cf1b1SMichael Neumann }
1405f43cf1b1SMichael Neumann 
1406926deccbSFrançois Tigeot static void cayman_cp_enable(struct radeon_device *rdev, bool enable)
1407926deccbSFrançois Tigeot {
1408926deccbSFrançois Tigeot 	if (enable)
1409926deccbSFrançois Tigeot 		WREG32(CP_ME_CNTL, 0);
1410926deccbSFrançois Tigeot 	else {
1411926deccbSFrançois Tigeot 		radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size);
1412926deccbSFrançois Tigeot 		WREG32(CP_ME_CNTL, (CP_ME_HALT | CP_PFP_HALT));
1413926deccbSFrançois Tigeot 		WREG32(SCRATCH_UMSK, 0);
1414926deccbSFrançois Tigeot 		rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false;
1415926deccbSFrançois Tigeot 	}
1416926deccbSFrançois Tigeot }
1417926deccbSFrançois Tigeot 
1418926deccbSFrançois Tigeot static int cayman_cp_load_microcode(struct radeon_device *rdev)
1419926deccbSFrançois Tigeot {
1420926deccbSFrançois Tigeot 	const __be32 *fw_data;
1421926deccbSFrançois Tigeot 	int i;
1422926deccbSFrançois Tigeot 
1423926deccbSFrançois Tigeot 	if (!rdev->me_fw || !rdev->pfp_fw)
1424926deccbSFrançois Tigeot 		return -EINVAL;
1425926deccbSFrançois Tigeot 
1426926deccbSFrançois Tigeot 	cayman_cp_enable(rdev, false);
1427926deccbSFrançois Tigeot 
1428926deccbSFrançois Tigeot 	fw_data = (const __be32 *)rdev->pfp_fw->data;
1429926deccbSFrançois Tigeot 	WREG32(CP_PFP_UCODE_ADDR, 0);
1430926deccbSFrançois Tigeot 	for (i = 0; i < CAYMAN_PFP_UCODE_SIZE; i++)
1431926deccbSFrançois Tigeot 		WREG32(CP_PFP_UCODE_DATA, be32_to_cpup(fw_data++));
1432926deccbSFrançois Tigeot 	WREG32(CP_PFP_UCODE_ADDR, 0);
1433926deccbSFrançois Tigeot 
1434926deccbSFrançois Tigeot 	fw_data = (const __be32 *)rdev->me_fw->data;
1435926deccbSFrançois Tigeot 	WREG32(CP_ME_RAM_WADDR, 0);
1436926deccbSFrançois Tigeot 	for (i = 0; i < CAYMAN_PM4_UCODE_SIZE; i++)
1437926deccbSFrançois Tigeot 		WREG32(CP_ME_RAM_DATA, be32_to_cpup(fw_data++));
1438926deccbSFrançois Tigeot 
1439926deccbSFrançois Tigeot 	WREG32(CP_PFP_UCODE_ADDR, 0);
1440926deccbSFrançois Tigeot 	WREG32(CP_ME_RAM_WADDR, 0);
1441926deccbSFrançois Tigeot 	WREG32(CP_ME_RAM_RADDR, 0);
1442926deccbSFrançois Tigeot 	return 0;
1443926deccbSFrançois Tigeot }
1444926deccbSFrançois Tigeot 
1445926deccbSFrançois Tigeot static int cayman_cp_start(struct radeon_device *rdev)
1446926deccbSFrançois Tigeot {
1447926deccbSFrançois Tigeot 	struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
1448926deccbSFrançois Tigeot 	int r, i;
1449926deccbSFrançois Tigeot 
1450926deccbSFrançois Tigeot 	r = radeon_ring_lock(rdev, ring, 7);
1451926deccbSFrançois Tigeot 	if (r) {
1452926deccbSFrançois Tigeot 		DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r);
1453926deccbSFrançois Tigeot 		return r;
1454926deccbSFrançois Tigeot 	}
1455926deccbSFrançois Tigeot 	radeon_ring_write(ring, PACKET3(PACKET3_ME_INITIALIZE, 5));
1456926deccbSFrançois Tigeot 	radeon_ring_write(ring, 0x1);
1457926deccbSFrançois Tigeot 	radeon_ring_write(ring, 0x0);
1458926deccbSFrançois Tigeot 	radeon_ring_write(ring, rdev->config.cayman.max_hw_contexts - 1);
1459926deccbSFrançois Tigeot 	radeon_ring_write(ring, PACKET3_ME_INITIALIZE_DEVICE_ID(1));
1460926deccbSFrançois Tigeot 	radeon_ring_write(ring, 0);
1461926deccbSFrançois Tigeot 	radeon_ring_write(ring, 0);
1462926deccbSFrançois Tigeot 	radeon_ring_unlock_commit(rdev, ring);
1463926deccbSFrançois Tigeot 
1464926deccbSFrançois Tigeot 	cayman_cp_enable(rdev, true);
1465926deccbSFrançois Tigeot 
1466926deccbSFrançois Tigeot 	r = radeon_ring_lock(rdev, ring, cayman_default_size + 19);
1467926deccbSFrançois Tigeot 	if (r) {
1468926deccbSFrançois Tigeot 		DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r);
1469926deccbSFrançois Tigeot 		return r;
1470926deccbSFrançois Tigeot 	}
1471926deccbSFrançois Tigeot 
1472926deccbSFrançois Tigeot 	/* setup clear context state */
1473926deccbSFrançois Tigeot 	radeon_ring_write(ring, PACKET3(PACKET3_PREAMBLE_CNTL, 0));
1474926deccbSFrançois Tigeot 	radeon_ring_write(ring, PACKET3_PREAMBLE_BEGIN_CLEAR_STATE);
1475926deccbSFrançois Tigeot 
1476926deccbSFrançois Tigeot 	for (i = 0; i < cayman_default_size; i++)
1477926deccbSFrançois Tigeot 		radeon_ring_write(ring, cayman_default_state[i]);
1478926deccbSFrançois Tigeot 
1479926deccbSFrançois Tigeot 	radeon_ring_write(ring, PACKET3(PACKET3_PREAMBLE_CNTL, 0));
1480926deccbSFrançois Tigeot 	radeon_ring_write(ring, PACKET3_PREAMBLE_END_CLEAR_STATE);
1481926deccbSFrançois Tigeot 
1482926deccbSFrançois Tigeot 	/* set clear context state */
1483926deccbSFrançois Tigeot 	radeon_ring_write(ring, PACKET3(PACKET3_CLEAR_STATE, 0));
1484926deccbSFrançois Tigeot 	radeon_ring_write(ring, 0);
1485926deccbSFrançois Tigeot 
1486926deccbSFrançois Tigeot 	/* SQ_VTX_BASE_VTX_LOC */
1487926deccbSFrançois Tigeot 	radeon_ring_write(ring, 0xc0026f00);
1488926deccbSFrançois Tigeot 	radeon_ring_write(ring, 0x00000000);
1489926deccbSFrançois Tigeot 	radeon_ring_write(ring, 0x00000000);
1490926deccbSFrançois Tigeot 	radeon_ring_write(ring, 0x00000000);
1491926deccbSFrançois Tigeot 
1492926deccbSFrançois Tigeot 	/* Clear consts */
1493926deccbSFrançois Tigeot 	radeon_ring_write(ring, 0xc0036f00);
1494926deccbSFrançois Tigeot 	radeon_ring_write(ring, 0x00000bc4);
1495926deccbSFrançois Tigeot 	radeon_ring_write(ring, 0xffffffff);
1496926deccbSFrançois Tigeot 	radeon_ring_write(ring, 0xffffffff);
1497926deccbSFrançois Tigeot 	radeon_ring_write(ring, 0xffffffff);
1498926deccbSFrançois Tigeot 
1499926deccbSFrançois Tigeot 	radeon_ring_write(ring, 0xc0026900);
1500926deccbSFrançois Tigeot 	radeon_ring_write(ring, 0x00000316);
1501926deccbSFrançois Tigeot 	radeon_ring_write(ring, 0x0000000e); /* VGT_VERTEX_REUSE_BLOCK_CNTL */
1502926deccbSFrançois Tigeot 	radeon_ring_write(ring, 0x00000010); /*  */
1503926deccbSFrançois Tigeot 
1504926deccbSFrançois Tigeot 	radeon_ring_unlock_commit(rdev, ring);
1505926deccbSFrançois Tigeot 
1506926deccbSFrançois Tigeot 	/* XXX init other rings */
1507926deccbSFrançois Tigeot 
1508926deccbSFrançois Tigeot 	return 0;
1509926deccbSFrançois Tigeot }
1510926deccbSFrançois Tigeot 
1511926deccbSFrançois Tigeot static void cayman_cp_fini(struct radeon_device *rdev)
1512926deccbSFrançois Tigeot {
1513926deccbSFrançois Tigeot 	struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
1514926deccbSFrançois Tigeot 	cayman_cp_enable(rdev, false);
1515926deccbSFrançois Tigeot 	radeon_ring_fini(rdev, ring);
1516926deccbSFrançois Tigeot 	radeon_scratch_free(rdev, ring->rptr_save_reg);
1517926deccbSFrançois Tigeot }
1518926deccbSFrançois Tigeot 
1519926deccbSFrançois Tigeot static int cayman_cp_resume(struct radeon_device *rdev)
1520926deccbSFrançois Tigeot {
1521926deccbSFrançois Tigeot 	static const int ridx[] = {
1522926deccbSFrançois Tigeot 		RADEON_RING_TYPE_GFX_INDEX,
1523926deccbSFrançois Tigeot 		CAYMAN_RING_TYPE_CP1_INDEX,
1524926deccbSFrançois Tigeot 		CAYMAN_RING_TYPE_CP2_INDEX
1525926deccbSFrançois Tigeot 	};
1526926deccbSFrançois Tigeot 	static const unsigned cp_rb_cntl[] = {
1527926deccbSFrançois Tigeot 		CP_RB0_CNTL,
1528926deccbSFrançois Tigeot 		CP_RB1_CNTL,
1529926deccbSFrançois Tigeot 		CP_RB2_CNTL,
1530926deccbSFrançois Tigeot 	};
1531926deccbSFrançois Tigeot 	static const unsigned cp_rb_rptr_addr[] = {
1532926deccbSFrançois Tigeot 		CP_RB0_RPTR_ADDR,
1533926deccbSFrançois Tigeot 		CP_RB1_RPTR_ADDR,
1534926deccbSFrançois Tigeot 		CP_RB2_RPTR_ADDR
1535926deccbSFrançois Tigeot 	};
1536926deccbSFrançois Tigeot 	static const unsigned cp_rb_rptr_addr_hi[] = {
1537926deccbSFrançois Tigeot 		CP_RB0_RPTR_ADDR_HI,
1538926deccbSFrançois Tigeot 		CP_RB1_RPTR_ADDR_HI,
1539926deccbSFrançois Tigeot 		CP_RB2_RPTR_ADDR_HI
1540926deccbSFrançois Tigeot 	};
1541926deccbSFrançois Tigeot 	static const unsigned cp_rb_base[] = {
1542926deccbSFrançois Tigeot 		CP_RB0_BASE,
1543926deccbSFrançois Tigeot 		CP_RB1_BASE,
1544926deccbSFrançois Tigeot 		CP_RB2_BASE
1545926deccbSFrançois Tigeot 	};
1546926deccbSFrançois Tigeot 	struct radeon_ring *ring;
1547926deccbSFrançois Tigeot 	int i, r;
1548926deccbSFrançois Tigeot 
1549926deccbSFrançois Tigeot 	/* Reset cp; if cp is reset, then PA, SH, VGT also need to be reset */
1550926deccbSFrançois Tigeot 	WREG32(GRBM_SOFT_RESET, (SOFT_RESET_CP |
1551926deccbSFrançois Tigeot 				 SOFT_RESET_PA |
1552926deccbSFrançois Tigeot 				 SOFT_RESET_SH |
1553926deccbSFrançois Tigeot 				 SOFT_RESET_VGT |
1554926deccbSFrançois Tigeot 				 SOFT_RESET_SPI |
1555926deccbSFrançois Tigeot 				 SOFT_RESET_SX));
1556926deccbSFrançois Tigeot 	RREG32(GRBM_SOFT_RESET);
1557926deccbSFrançois Tigeot 	DRM_MDELAY(15);
1558926deccbSFrançois Tigeot 	WREG32(GRBM_SOFT_RESET, 0);
1559926deccbSFrançois Tigeot 	RREG32(GRBM_SOFT_RESET);
1560926deccbSFrançois Tigeot 
1561926deccbSFrançois Tigeot 	WREG32(CP_SEM_WAIT_TIMER, 0x0);
1562926deccbSFrançois Tigeot 	WREG32(CP_SEM_INCOMPLETE_TIMER_CNTL, 0x0);
1563926deccbSFrançois Tigeot 
1564926deccbSFrançois Tigeot 	/* Set the write pointer delay */
1565926deccbSFrançois Tigeot 	WREG32(CP_RB_WPTR_DELAY, 0);
1566926deccbSFrançois Tigeot 
1567926deccbSFrançois Tigeot 	WREG32(CP_DEBUG, (1 << 27));
1568926deccbSFrançois Tigeot 
1569926deccbSFrançois Tigeot 	/* set the wb address whether it's enabled or not */
1570926deccbSFrançois Tigeot 	WREG32(SCRATCH_ADDR, ((rdev->wb.gpu_addr + RADEON_WB_SCRATCH_OFFSET) >> 8) & 0xFFFFFFFF);
1571926deccbSFrançois Tigeot 	WREG32(SCRATCH_UMSK, 0xff);
1572926deccbSFrançois Tigeot 
1573926deccbSFrançois Tigeot 	for (i = 0; i < 3; ++i) {
1574926deccbSFrançois Tigeot 		uint32_t rb_cntl;
1575926deccbSFrançois Tigeot 		uint64_t addr;
1576926deccbSFrançois Tigeot 
1577926deccbSFrançois Tigeot 		/* Set ring buffer size */
1578926deccbSFrançois Tigeot 		ring = &rdev->ring[ridx[i]];
1579926deccbSFrançois Tigeot 		rb_cntl = drm_order(ring->ring_size / 8);
1580926deccbSFrançois Tigeot 		rb_cntl |= drm_order(RADEON_GPU_PAGE_SIZE/8) << 8;
1581926deccbSFrançois Tigeot #ifdef __BIG_ENDIAN
1582926deccbSFrançois Tigeot 		rb_cntl |= BUF_SWAP_32BIT;
1583926deccbSFrançois Tigeot #endif
1584926deccbSFrançois Tigeot 		WREG32(cp_rb_cntl[i], rb_cntl);
1585926deccbSFrançois Tigeot 
1586926deccbSFrançois Tigeot 		/* set the wb address whether it's enabled or not */
1587926deccbSFrançois Tigeot 		addr = rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET;
1588926deccbSFrançois Tigeot 		WREG32(cp_rb_rptr_addr[i], addr & 0xFFFFFFFC);
1589926deccbSFrançois Tigeot 		WREG32(cp_rb_rptr_addr_hi[i], upper_32_bits(addr) & 0xFF);
1590926deccbSFrançois Tigeot 	}
1591926deccbSFrançois Tigeot 
1592926deccbSFrançois Tigeot 	/* set the rb base addr, this causes an internal reset of ALL rings */
1593926deccbSFrançois Tigeot 	for (i = 0; i < 3; ++i) {
1594926deccbSFrançois Tigeot 		ring = &rdev->ring[ridx[i]];
1595926deccbSFrançois Tigeot 		WREG32(cp_rb_base[i], ring->gpu_addr >> 8);
1596926deccbSFrançois Tigeot 	}
1597926deccbSFrançois Tigeot 
1598926deccbSFrançois Tigeot 	for (i = 0; i < 3; ++i) {
1599926deccbSFrançois Tigeot 		/* Initialize the ring buffer's read and write pointers */
1600926deccbSFrançois Tigeot 		ring = &rdev->ring[ridx[i]];
1601926deccbSFrançois Tigeot 		WREG32_P(cp_rb_cntl[i], RB_RPTR_WR_ENA, ~RB_RPTR_WR_ENA);
1602926deccbSFrançois Tigeot 
1603926deccbSFrançois Tigeot 		ring->rptr = ring->wptr = 0;
1604926deccbSFrançois Tigeot 		WREG32(ring->rptr_reg, ring->rptr);
1605926deccbSFrançois Tigeot 		WREG32(ring->wptr_reg, ring->wptr);
1606926deccbSFrançois Tigeot 
1607926deccbSFrançois Tigeot 		DRM_MDELAY(1);
1608926deccbSFrançois Tigeot 		WREG32_P(cp_rb_cntl[i], 0, ~RB_RPTR_WR_ENA);
1609926deccbSFrançois Tigeot 	}
1610926deccbSFrançois Tigeot 
1611926deccbSFrançois Tigeot 	/* start the rings */
1612926deccbSFrançois Tigeot 	cayman_cp_start(rdev);
1613926deccbSFrançois Tigeot 	rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = true;
1614926deccbSFrançois Tigeot 	rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX].ready = false;
1615926deccbSFrançois Tigeot 	rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX].ready = false;
1616926deccbSFrançois Tigeot 	/* this only test cp0 */
1617926deccbSFrançois Tigeot 	r = radeon_ring_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]);
1618926deccbSFrançois Tigeot 	if (r) {
1619926deccbSFrançois Tigeot 		rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false;
1620926deccbSFrançois Tigeot 		rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX].ready = false;
1621926deccbSFrançois Tigeot 		rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX].ready = false;
1622926deccbSFrançois Tigeot 		return r;
1623926deccbSFrançois Tigeot 	}
1624926deccbSFrançois Tigeot 
1625926deccbSFrançois Tigeot 	return 0;
1626926deccbSFrançois Tigeot }
1627926deccbSFrançois Tigeot 
1628926deccbSFrançois Tigeot /*
1629926deccbSFrançois Tigeot  * DMA
1630926deccbSFrançois Tigeot  * Starting with R600, the GPU has an asynchronous
1631926deccbSFrançois Tigeot  * DMA engine.  The programming model is very similar
1632926deccbSFrançois Tigeot  * to the 3D engine (ring buffer, IBs, etc.), but the
1633926deccbSFrançois Tigeot  * DMA controller has it's own packet format that is
1634926deccbSFrançois Tigeot  * different form the PM4 format used by the 3D engine.
1635926deccbSFrançois Tigeot  * It supports copying data, writing embedded data,
1636926deccbSFrançois Tigeot  * solid fills, and a number of other things.  It also
1637926deccbSFrançois Tigeot  * has support for tiling/detiling of buffers.
1638926deccbSFrançois Tigeot  * Cayman and newer support two asynchronous DMA engines.
1639926deccbSFrançois Tigeot  */
1640926deccbSFrançois Tigeot /**
1641926deccbSFrançois Tigeot  * cayman_dma_ring_ib_execute - Schedule an IB on the DMA engine
1642926deccbSFrançois Tigeot  *
1643926deccbSFrançois Tigeot  * @rdev: radeon_device pointer
1644926deccbSFrançois Tigeot  * @ib: IB object to schedule
1645926deccbSFrançois Tigeot  *
1646926deccbSFrançois Tigeot  * Schedule an IB in the DMA ring (cayman-SI).
1647926deccbSFrançois Tigeot  */
1648926deccbSFrançois Tigeot void cayman_dma_ring_ib_execute(struct radeon_device *rdev,
1649926deccbSFrançois Tigeot 				struct radeon_ib *ib)
1650926deccbSFrançois Tigeot {
1651926deccbSFrançois Tigeot 	struct radeon_ring *ring = &rdev->ring[ib->ring];
1652926deccbSFrançois Tigeot 
1653926deccbSFrançois Tigeot 	if (rdev->wb.enabled) {
1654926deccbSFrançois Tigeot 		u32 next_rptr = ring->wptr + 4;
1655926deccbSFrançois Tigeot 		while ((next_rptr & 7) != 5)
1656926deccbSFrançois Tigeot 			next_rptr++;
1657926deccbSFrançois Tigeot 		next_rptr += 3;
1658926deccbSFrançois Tigeot 		radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_WRITE, 0, 0, 1));
1659926deccbSFrançois Tigeot 		radeon_ring_write(ring, ring->next_rptr_gpu_addr & 0xfffffffc);
1660926deccbSFrançois Tigeot 		radeon_ring_write(ring, upper_32_bits(ring->next_rptr_gpu_addr) & 0xff);
1661926deccbSFrançois Tigeot 		radeon_ring_write(ring, next_rptr);
1662926deccbSFrançois Tigeot 	}
1663926deccbSFrançois Tigeot 
1664926deccbSFrançois Tigeot 	/* The indirect buffer packet must end on an 8 DW boundary in the DMA ring.
1665926deccbSFrançois Tigeot 	 * Pad as necessary with NOPs.
1666926deccbSFrançois Tigeot 	 */
1667926deccbSFrançois Tigeot 	while ((ring->wptr & 7) != 5)
1668926deccbSFrançois Tigeot 		radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0));
1669926deccbSFrançois Tigeot 	radeon_ring_write(ring, DMA_IB_PACKET(DMA_PACKET_INDIRECT_BUFFER, ib->vm ? ib->vm->id : 0, 0));
1670926deccbSFrançois Tigeot 	radeon_ring_write(ring, (ib->gpu_addr & 0xFFFFFFE0));
1671926deccbSFrançois Tigeot 	radeon_ring_write(ring, (ib->length_dw << 12) | (upper_32_bits(ib->gpu_addr) & 0xFF));
1672926deccbSFrançois Tigeot 
1673926deccbSFrançois Tigeot }
1674926deccbSFrançois Tigeot 
1675926deccbSFrançois Tigeot /**
1676926deccbSFrançois Tigeot  * cayman_dma_stop - stop the async dma engines
1677926deccbSFrançois Tigeot  *
1678926deccbSFrançois Tigeot  * @rdev: radeon_device pointer
1679926deccbSFrançois Tigeot  *
1680926deccbSFrançois Tigeot  * Stop the async dma engines (cayman-SI).
1681926deccbSFrançois Tigeot  */
1682926deccbSFrançois Tigeot void cayman_dma_stop(struct radeon_device *rdev)
1683926deccbSFrançois Tigeot {
1684926deccbSFrançois Tigeot 	u32 rb_cntl;
1685926deccbSFrançois Tigeot 
1686926deccbSFrançois Tigeot 	radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size);
1687926deccbSFrançois Tigeot 
1688926deccbSFrançois Tigeot 	/* dma0 */
1689926deccbSFrançois Tigeot 	rb_cntl = RREG32(DMA_RB_CNTL + DMA0_REGISTER_OFFSET);
1690926deccbSFrançois Tigeot 	rb_cntl &= ~DMA_RB_ENABLE;
1691926deccbSFrançois Tigeot 	WREG32(DMA_RB_CNTL + DMA0_REGISTER_OFFSET, rb_cntl);
1692926deccbSFrançois Tigeot 
1693926deccbSFrançois Tigeot 	/* dma1 */
1694926deccbSFrançois Tigeot 	rb_cntl = RREG32(DMA_RB_CNTL + DMA1_REGISTER_OFFSET);
1695926deccbSFrançois Tigeot 	rb_cntl &= ~DMA_RB_ENABLE;
1696926deccbSFrançois Tigeot 	WREG32(DMA_RB_CNTL + DMA1_REGISTER_OFFSET, rb_cntl);
1697926deccbSFrançois Tigeot 
1698926deccbSFrançois Tigeot 	rdev->ring[R600_RING_TYPE_DMA_INDEX].ready = false;
1699926deccbSFrançois Tigeot 	rdev->ring[CAYMAN_RING_TYPE_DMA1_INDEX].ready = false;
1700926deccbSFrançois Tigeot }
1701926deccbSFrançois Tigeot 
1702926deccbSFrançois Tigeot /**
1703926deccbSFrançois Tigeot  * cayman_dma_resume - setup and start the async dma engines
1704926deccbSFrançois Tigeot  *
1705926deccbSFrançois Tigeot  * @rdev: radeon_device pointer
1706926deccbSFrançois Tigeot  *
1707926deccbSFrançois Tigeot  * Set up the DMA ring buffers and enable them. (cayman-SI).
1708926deccbSFrançois Tigeot  * Returns 0 for success, error for failure.
1709926deccbSFrançois Tigeot  */
1710926deccbSFrançois Tigeot int cayman_dma_resume(struct radeon_device *rdev)
1711926deccbSFrançois Tigeot {
1712926deccbSFrançois Tigeot 	struct radeon_ring *ring;
1713926deccbSFrançois Tigeot 	u32 rb_cntl, dma_cntl, ib_cntl;
1714926deccbSFrançois Tigeot 	u32 rb_bufsz;
1715926deccbSFrançois Tigeot 	u32 reg_offset, wb_offset;
1716926deccbSFrançois Tigeot 	int i, r;
1717926deccbSFrançois Tigeot 
1718926deccbSFrançois Tigeot 	/* Reset dma */
1719926deccbSFrançois Tigeot 	WREG32(SRBM_SOFT_RESET, SOFT_RESET_DMA | SOFT_RESET_DMA1);
1720926deccbSFrançois Tigeot 	RREG32(SRBM_SOFT_RESET);
1721926deccbSFrançois Tigeot 	DRM_UDELAY(50);
1722926deccbSFrançois Tigeot 	WREG32(SRBM_SOFT_RESET, 0);
1723926deccbSFrançois Tigeot 
1724926deccbSFrançois Tigeot 	for (i = 0; i < 2; i++) {
1725926deccbSFrançois Tigeot 		if (i == 0) {
1726926deccbSFrançois Tigeot 			ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX];
1727926deccbSFrançois Tigeot 			reg_offset = DMA0_REGISTER_OFFSET;
1728926deccbSFrançois Tigeot 			wb_offset = R600_WB_DMA_RPTR_OFFSET;
1729926deccbSFrançois Tigeot 		} else {
1730926deccbSFrançois Tigeot 			ring = &rdev->ring[CAYMAN_RING_TYPE_DMA1_INDEX];
1731926deccbSFrançois Tigeot 			reg_offset = DMA1_REGISTER_OFFSET;
1732926deccbSFrançois Tigeot 			wb_offset = CAYMAN_WB_DMA1_RPTR_OFFSET;
1733926deccbSFrançois Tigeot 		}
1734926deccbSFrançois Tigeot 
1735926deccbSFrançois Tigeot 		WREG32(DMA_SEM_INCOMPLETE_TIMER_CNTL + reg_offset, 0);
1736926deccbSFrançois Tigeot 		WREG32(DMA_SEM_WAIT_FAIL_TIMER_CNTL + reg_offset, 0);
1737926deccbSFrançois Tigeot 
1738926deccbSFrançois Tigeot 		/* Set ring buffer size in dwords */
1739926deccbSFrançois Tigeot 		rb_bufsz = drm_order(ring->ring_size / 4);
1740926deccbSFrançois Tigeot 		rb_cntl = rb_bufsz << 1;
1741926deccbSFrançois Tigeot #ifdef __BIG_ENDIAN
1742926deccbSFrançois Tigeot 		rb_cntl |= DMA_RB_SWAP_ENABLE | DMA_RPTR_WRITEBACK_SWAP_ENABLE;
1743926deccbSFrançois Tigeot #endif
1744926deccbSFrançois Tigeot 		WREG32(DMA_RB_CNTL + reg_offset, rb_cntl);
1745926deccbSFrançois Tigeot 
1746926deccbSFrançois Tigeot 		/* Initialize the ring buffer's read and write pointers */
1747926deccbSFrançois Tigeot 		WREG32(DMA_RB_RPTR + reg_offset, 0);
1748926deccbSFrançois Tigeot 		WREG32(DMA_RB_WPTR + reg_offset, 0);
1749926deccbSFrançois Tigeot 
1750926deccbSFrançois Tigeot 		/* set the wb address whether it's enabled or not */
1751926deccbSFrançois Tigeot 		WREG32(DMA_RB_RPTR_ADDR_HI + reg_offset,
1752926deccbSFrançois Tigeot 		       upper_32_bits(rdev->wb.gpu_addr + wb_offset) & 0xFF);
1753926deccbSFrançois Tigeot 		WREG32(DMA_RB_RPTR_ADDR_LO + reg_offset,
1754926deccbSFrançois Tigeot 		       ((rdev->wb.gpu_addr + wb_offset) & 0xFFFFFFFC));
1755926deccbSFrançois Tigeot 
1756926deccbSFrançois Tigeot 		if (rdev->wb.enabled)
1757926deccbSFrançois Tigeot 			rb_cntl |= DMA_RPTR_WRITEBACK_ENABLE;
1758926deccbSFrançois Tigeot 
1759926deccbSFrançois Tigeot 		WREG32(DMA_RB_BASE + reg_offset, ring->gpu_addr >> 8);
1760926deccbSFrançois Tigeot 
1761926deccbSFrançois Tigeot 		/* enable DMA IBs */
1762926deccbSFrançois Tigeot 		ib_cntl = DMA_IB_ENABLE | CMD_VMID_FORCE;
1763926deccbSFrançois Tigeot #ifdef __BIG_ENDIAN
1764926deccbSFrançois Tigeot 		ib_cntl |= DMA_IB_SWAP_ENABLE;
1765926deccbSFrançois Tigeot #endif
1766926deccbSFrançois Tigeot 		WREG32(DMA_IB_CNTL + reg_offset, ib_cntl);
1767926deccbSFrançois Tigeot 
1768926deccbSFrançois Tigeot 		dma_cntl = RREG32(DMA_CNTL + reg_offset);
1769926deccbSFrançois Tigeot 		dma_cntl &= ~CTXEMPTY_INT_ENABLE;
1770926deccbSFrançois Tigeot 		WREG32(DMA_CNTL + reg_offset, dma_cntl);
1771926deccbSFrançois Tigeot 
1772926deccbSFrançois Tigeot 		ring->wptr = 0;
1773926deccbSFrançois Tigeot 		WREG32(DMA_RB_WPTR + reg_offset, ring->wptr << 2);
1774926deccbSFrançois Tigeot 
1775926deccbSFrançois Tigeot 		ring->rptr = RREG32(DMA_RB_RPTR + reg_offset) >> 2;
1776926deccbSFrançois Tigeot 
1777926deccbSFrançois Tigeot 		WREG32(DMA_RB_CNTL + reg_offset, rb_cntl | DMA_RB_ENABLE);
1778926deccbSFrançois Tigeot 
1779926deccbSFrançois Tigeot 		ring->ready = true;
1780926deccbSFrançois Tigeot 
1781926deccbSFrançois Tigeot 		r = radeon_ring_test(rdev, ring->idx, ring);
1782926deccbSFrançois Tigeot 		if (r) {
1783926deccbSFrançois Tigeot 			ring->ready = false;
1784926deccbSFrançois Tigeot 			return r;
1785926deccbSFrançois Tigeot 		}
1786926deccbSFrançois Tigeot 	}
1787926deccbSFrançois Tigeot 
1788926deccbSFrançois Tigeot 	radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size);
1789926deccbSFrançois Tigeot 
1790926deccbSFrançois Tigeot 	return 0;
1791926deccbSFrançois Tigeot }
1792926deccbSFrançois Tigeot 
1793926deccbSFrançois Tigeot /**
1794926deccbSFrançois Tigeot  * cayman_dma_fini - tear down the async dma engines
1795926deccbSFrançois Tigeot  *
1796926deccbSFrançois Tigeot  * @rdev: radeon_device pointer
1797926deccbSFrançois Tigeot  *
1798926deccbSFrançois Tigeot  * Stop the async dma engines and free the rings (cayman-SI).
1799926deccbSFrançois Tigeot  */
1800926deccbSFrançois Tigeot void cayman_dma_fini(struct radeon_device *rdev)
1801926deccbSFrançois Tigeot {
1802926deccbSFrançois Tigeot 	cayman_dma_stop(rdev);
1803926deccbSFrançois Tigeot 	radeon_ring_fini(rdev, &rdev->ring[R600_RING_TYPE_DMA_INDEX]);
1804926deccbSFrançois Tigeot 	radeon_ring_fini(rdev, &rdev->ring[CAYMAN_RING_TYPE_DMA1_INDEX]);
1805926deccbSFrançois Tigeot }
1806926deccbSFrançois Tigeot 
1807b403bed8SMichael Neumann static u32 cayman_gpu_check_soft_reset(struct radeon_device *rdev)
1808926deccbSFrançois Tigeot {
1809b403bed8SMichael Neumann 	u32 reset_mask = 0;
1810b403bed8SMichael Neumann 	u32 tmp;
1811926deccbSFrançois Tigeot 
1812b403bed8SMichael Neumann 	/* GRBM_STATUS */
1813b403bed8SMichael Neumann 	tmp = RREG32(GRBM_STATUS);
1814b403bed8SMichael Neumann 	if (tmp & (PA_BUSY | SC_BUSY |
1815b403bed8SMichael Neumann 		   SH_BUSY | SX_BUSY |
1816b403bed8SMichael Neumann 		   TA_BUSY | VGT_BUSY |
1817b403bed8SMichael Neumann 		   DB_BUSY | CB_BUSY |
1818b403bed8SMichael Neumann 		   GDS_BUSY | SPI_BUSY |
1819b403bed8SMichael Neumann 		   IA_BUSY | IA_BUSY_NO_DMA))
1820b403bed8SMichael Neumann 		reset_mask |= RADEON_RESET_GFX;
1821b403bed8SMichael Neumann 
1822b403bed8SMichael Neumann 	if (tmp & (CF_RQ_PENDING | PF_RQ_PENDING |
1823b403bed8SMichael Neumann 		   CP_BUSY | CP_COHERENCY_BUSY))
1824b403bed8SMichael Neumann 		reset_mask |= RADEON_RESET_CP;
1825b403bed8SMichael Neumann 
1826b403bed8SMichael Neumann 	if (tmp & GRBM_EE_BUSY)
1827b403bed8SMichael Neumann 		reset_mask |= RADEON_RESET_GRBM | RADEON_RESET_GFX | RADEON_RESET_CP;
1828b403bed8SMichael Neumann 
1829b403bed8SMichael Neumann 	/* DMA_STATUS_REG 0 */
1830b403bed8SMichael Neumann 	tmp = RREG32(DMA_STATUS_REG + DMA0_REGISTER_OFFSET);
1831b403bed8SMichael Neumann 	if (!(tmp & DMA_IDLE))
1832b403bed8SMichael Neumann 		reset_mask |= RADEON_RESET_DMA;
1833b403bed8SMichael Neumann 
1834b403bed8SMichael Neumann 	/* DMA_STATUS_REG 1 */
1835b403bed8SMichael Neumann 	tmp = RREG32(DMA_STATUS_REG + DMA1_REGISTER_OFFSET);
1836b403bed8SMichael Neumann 	if (!(tmp & DMA_IDLE))
1837b403bed8SMichael Neumann 		reset_mask |= RADEON_RESET_DMA1;
1838b403bed8SMichael Neumann 
1839b403bed8SMichael Neumann 	/* SRBM_STATUS2 */
1840b403bed8SMichael Neumann 	tmp = RREG32(SRBM_STATUS2);
1841b403bed8SMichael Neumann 	if (tmp & DMA_BUSY)
1842b403bed8SMichael Neumann 		reset_mask |= RADEON_RESET_DMA;
1843b403bed8SMichael Neumann 
1844b403bed8SMichael Neumann 	if (tmp & DMA1_BUSY)
1845b403bed8SMichael Neumann 		reset_mask |= RADEON_RESET_DMA1;
1846b403bed8SMichael Neumann 
1847b403bed8SMichael Neumann 	/* SRBM_STATUS */
1848b403bed8SMichael Neumann 	tmp = RREG32(SRBM_STATUS);
1849b403bed8SMichael Neumann 	if (tmp & (RLC_RQ_PENDING | RLC_BUSY))
1850b403bed8SMichael Neumann 		reset_mask |= RADEON_RESET_RLC;
1851b403bed8SMichael Neumann 
1852b403bed8SMichael Neumann 	if (tmp & IH_BUSY)
1853b403bed8SMichael Neumann 		reset_mask |= RADEON_RESET_IH;
1854b403bed8SMichael Neumann 
1855b403bed8SMichael Neumann 	if (tmp & SEM_BUSY)
1856b403bed8SMichael Neumann 		reset_mask |= RADEON_RESET_SEM;
1857b403bed8SMichael Neumann 
1858b403bed8SMichael Neumann 	if (tmp & GRBM_RQ_PENDING)
1859b403bed8SMichael Neumann 		reset_mask |= RADEON_RESET_GRBM;
1860b403bed8SMichael Neumann 
1861b403bed8SMichael Neumann 	if (tmp & VMC_BUSY)
1862b403bed8SMichael Neumann 		reset_mask |= RADEON_RESET_VMC;
1863b403bed8SMichael Neumann 
1864b403bed8SMichael Neumann 	if (tmp & (MCB_BUSY | MCB_NON_DISPLAY_BUSY |
1865b403bed8SMichael Neumann 		   MCC_BUSY | MCD_BUSY))
1866b403bed8SMichael Neumann 		reset_mask |= RADEON_RESET_MC;
1867b403bed8SMichael Neumann 
1868b403bed8SMichael Neumann 	if (evergreen_is_display_hung(rdev))
1869b403bed8SMichael Neumann 		reset_mask |= RADEON_RESET_DISPLAY;
1870b403bed8SMichael Neumann 
1871b403bed8SMichael Neumann 	/* VM_L2_STATUS */
1872b403bed8SMichael Neumann 	tmp = RREG32(VM_L2_STATUS);
1873b403bed8SMichael Neumann 	if (tmp & L2_BUSY)
1874b403bed8SMichael Neumann 		reset_mask |= RADEON_RESET_VMC;
1875b403bed8SMichael Neumann 
1876b403bed8SMichael Neumann 	/* Skip MC reset as it's mostly likely not hung, just busy */
1877b403bed8SMichael Neumann 	if (reset_mask & RADEON_RESET_MC) {
1878b403bed8SMichael Neumann 		DRM_DEBUG("MC busy: 0x%08X, clearing.\n", reset_mask);
1879b403bed8SMichael Neumann 		reset_mask &= ~RADEON_RESET_MC;
1880b403bed8SMichael Neumann 	}
1881b403bed8SMichael Neumann 
1882b403bed8SMichael Neumann 	return reset_mask;
1883b403bed8SMichael Neumann }
1884b403bed8SMichael Neumann 
1885b403bed8SMichael Neumann static void cayman_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask)
1886b403bed8SMichael Neumann {
1887b403bed8SMichael Neumann 	struct evergreen_mc_save save;
1888b403bed8SMichael Neumann 	u32 grbm_soft_reset = 0, srbm_soft_reset = 0;
1889b403bed8SMichael Neumann 	u32 tmp;
1890b403bed8SMichael Neumann 
1891b403bed8SMichael Neumann 	if (reset_mask == 0)
1892926deccbSFrançois Tigeot 		return;
1893926deccbSFrançois Tigeot 
1894b403bed8SMichael Neumann 	dev_info(rdev->dev, "GPU softreset: 0x%08X\n", reset_mask);
1895b403bed8SMichael Neumann 
1896b403bed8SMichael Neumann 	evergreen_print_gpu_status_regs(rdev);
1897b403bed8SMichael Neumann 	dev_info(rdev->dev, "  VM_CONTEXT0_PROTECTION_FAULT_ADDR   0x%08X\n",
1898b403bed8SMichael Neumann 		 RREG32(0x14F8));
1899b403bed8SMichael Neumann 	dev_info(rdev->dev, "  VM_CONTEXT0_PROTECTION_FAULT_STATUS 0x%08X\n",
1900b403bed8SMichael Neumann 		 RREG32(0x14D8));
1901b403bed8SMichael Neumann 	dev_info(rdev->dev, "  VM_CONTEXT1_PROTECTION_FAULT_ADDR   0x%08X\n",
1902b403bed8SMichael Neumann 		 RREG32(0x14FC));
1903b403bed8SMichael Neumann 	dev_info(rdev->dev, "  VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x%08X\n",
1904b403bed8SMichael Neumann 		 RREG32(0x14DC));
1905926deccbSFrançois Tigeot 
1906926deccbSFrançois Tigeot 	/* Disable CP parsing/prefetching */
1907926deccbSFrançois Tigeot 	WREG32(CP_ME_CNTL, CP_ME_HALT | CP_PFP_HALT);
1908926deccbSFrançois Tigeot 
1909b403bed8SMichael Neumann 	if (reset_mask & RADEON_RESET_DMA) {
1910b403bed8SMichael Neumann 		/* dma0 */
1911b403bed8SMichael Neumann 		tmp = RREG32(DMA_RB_CNTL + DMA0_REGISTER_OFFSET);
1912b403bed8SMichael Neumann 		tmp &= ~DMA_RB_ENABLE;
1913b403bed8SMichael Neumann 		WREG32(DMA_RB_CNTL + DMA0_REGISTER_OFFSET, tmp);
1914b403bed8SMichael Neumann 	}
1915b403bed8SMichael Neumann 
1916b403bed8SMichael Neumann 	if (reset_mask & RADEON_RESET_DMA1) {
1917b403bed8SMichael Neumann 		/* dma1 */
1918b403bed8SMichael Neumann 		tmp = RREG32(DMA_RB_CNTL + DMA1_REGISTER_OFFSET);
1919b403bed8SMichael Neumann 		tmp &= ~DMA_RB_ENABLE;
1920b403bed8SMichael Neumann 		WREG32(DMA_RB_CNTL + DMA1_REGISTER_OFFSET, tmp);
1921b403bed8SMichael Neumann 	}
1922b403bed8SMichael Neumann 
1923b403bed8SMichael Neumann 	DRM_UDELAY(50);
1924b403bed8SMichael Neumann 
1925b403bed8SMichael Neumann 	evergreen_mc_stop(rdev, &save);
1926b403bed8SMichael Neumann 	if (evergreen_mc_wait_for_idle(rdev)) {
1927b403bed8SMichael Neumann 		dev_warn(rdev->dev, "Wait for MC idle timedout !\n");
1928b403bed8SMichael Neumann 	}
1929b403bed8SMichael Neumann 
1930b403bed8SMichael Neumann 	if (reset_mask & (RADEON_RESET_GFX | RADEON_RESET_COMPUTE)) {
1931b403bed8SMichael Neumann 		grbm_soft_reset = SOFT_RESET_CB |
1932926deccbSFrançois Tigeot 			SOFT_RESET_DB |
1933926deccbSFrançois Tigeot 			SOFT_RESET_GDS |
1934926deccbSFrançois Tigeot 			SOFT_RESET_PA |
1935926deccbSFrançois Tigeot 			SOFT_RESET_SC |
1936926deccbSFrançois Tigeot 			SOFT_RESET_SPI |
1937926deccbSFrançois Tigeot 			SOFT_RESET_SH |
1938926deccbSFrançois Tigeot 			SOFT_RESET_SX |
1939926deccbSFrançois Tigeot 			SOFT_RESET_TC |
1940926deccbSFrançois Tigeot 			SOFT_RESET_TA |
1941926deccbSFrançois Tigeot 			SOFT_RESET_VGT |
1942b403bed8SMichael Neumann 			SOFT_RESET_IA;
1943926deccbSFrançois Tigeot 	}
1944926deccbSFrançois Tigeot 
1945b403bed8SMichael Neumann 	if (reset_mask & RADEON_RESET_CP) {
1946b403bed8SMichael Neumann 		grbm_soft_reset |= SOFT_RESET_CP | SOFT_RESET_VGT;
1947926deccbSFrançois Tigeot 
1948b403bed8SMichael Neumann 		srbm_soft_reset |= SOFT_RESET_GRBM;
1949926deccbSFrançois Tigeot 	}
1950926deccbSFrançois Tigeot 
1951926deccbSFrançois Tigeot 	if (reset_mask & RADEON_RESET_DMA)
1952b403bed8SMichael Neumann 		srbm_soft_reset |= SOFT_RESET_DMA;
1953b403bed8SMichael Neumann 
1954b403bed8SMichael Neumann 	if (reset_mask & RADEON_RESET_DMA1)
1955b403bed8SMichael Neumann 		srbm_soft_reset |= SOFT_RESET_DMA1;
1956b403bed8SMichael Neumann 
1957b403bed8SMichael Neumann 	if (reset_mask & RADEON_RESET_DISPLAY)
1958b403bed8SMichael Neumann 		srbm_soft_reset |= SOFT_RESET_DC;
1959b403bed8SMichael Neumann 
1960b403bed8SMichael Neumann 	if (reset_mask & RADEON_RESET_RLC)
1961b403bed8SMichael Neumann 		srbm_soft_reset |= SOFT_RESET_RLC;
1962b403bed8SMichael Neumann 
1963b403bed8SMichael Neumann 	if (reset_mask & RADEON_RESET_SEM)
1964b403bed8SMichael Neumann 		srbm_soft_reset |= SOFT_RESET_SEM;
1965b403bed8SMichael Neumann 
1966b403bed8SMichael Neumann 	if (reset_mask & RADEON_RESET_IH)
1967b403bed8SMichael Neumann 		srbm_soft_reset |= SOFT_RESET_IH;
1968b403bed8SMichael Neumann 
1969b403bed8SMichael Neumann 	if (reset_mask & RADEON_RESET_GRBM)
1970b403bed8SMichael Neumann 		srbm_soft_reset |= SOFT_RESET_GRBM;
1971b403bed8SMichael Neumann 
1972b403bed8SMichael Neumann 	if (reset_mask & RADEON_RESET_VMC)
1973b403bed8SMichael Neumann 		srbm_soft_reset |= SOFT_RESET_VMC;
1974b403bed8SMichael Neumann 
1975b403bed8SMichael Neumann 	if (!(rdev->flags & RADEON_IS_IGP)) {
1976b403bed8SMichael Neumann 		if (reset_mask & RADEON_RESET_MC)
1977b403bed8SMichael Neumann 			srbm_soft_reset |= SOFT_RESET_MC;
1978b403bed8SMichael Neumann 	}
1979b403bed8SMichael Neumann 
1980b403bed8SMichael Neumann 	if (grbm_soft_reset) {
1981b403bed8SMichael Neumann 		tmp = RREG32(GRBM_SOFT_RESET);
1982b403bed8SMichael Neumann 		tmp |= grbm_soft_reset;
1983b403bed8SMichael Neumann 		dev_info(rdev->dev, "GRBM_SOFT_RESET=0x%08X\n", tmp);
1984b403bed8SMichael Neumann 		WREG32(GRBM_SOFT_RESET, tmp);
1985b403bed8SMichael Neumann 		tmp = RREG32(GRBM_SOFT_RESET);
1986b403bed8SMichael Neumann 
1987b403bed8SMichael Neumann 		DRM_UDELAY(50);
1988b403bed8SMichael Neumann 
1989b403bed8SMichael Neumann 		tmp &= ~grbm_soft_reset;
1990b403bed8SMichael Neumann 		WREG32(GRBM_SOFT_RESET, tmp);
1991b403bed8SMichael Neumann 		tmp = RREG32(GRBM_SOFT_RESET);
1992b403bed8SMichael Neumann 	}
1993b403bed8SMichael Neumann 
1994b403bed8SMichael Neumann 	if (srbm_soft_reset) {
1995b403bed8SMichael Neumann 		tmp = RREG32(SRBM_SOFT_RESET);
1996b403bed8SMichael Neumann 		tmp |= srbm_soft_reset;
1997b403bed8SMichael Neumann 		dev_info(rdev->dev, "SRBM_SOFT_RESET=0x%08X\n", tmp);
1998b403bed8SMichael Neumann 		WREG32(SRBM_SOFT_RESET, tmp);
1999b403bed8SMichael Neumann 		tmp = RREG32(SRBM_SOFT_RESET);
2000b403bed8SMichael Neumann 
2001b403bed8SMichael Neumann 		DRM_UDELAY(50);
2002b403bed8SMichael Neumann 
2003b403bed8SMichael Neumann 		tmp &= ~srbm_soft_reset;
2004b403bed8SMichael Neumann 		WREG32(SRBM_SOFT_RESET, tmp);
2005b403bed8SMichael Neumann 		tmp = RREG32(SRBM_SOFT_RESET);
2006b403bed8SMichael Neumann 	}
2007926deccbSFrançois Tigeot 
2008926deccbSFrançois Tigeot 	/* Wait a little for things to settle down */
2009926deccbSFrançois Tigeot 	DRM_UDELAY(50);
2010926deccbSFrançois Tigeot 
2011926deccbSFrançois Tigeot 	evergreen_mc_resume(rdev, &save);
2012b403bed8SMichael Neumann 	DRM_UDELAY(50);
2013b403bed8SMichael Neumann 
2014b403bed8SMichael Neumann 	evergreen_print_gpu_status_regs(rdev);
2015926deccbSFrançois Tigeot }
2016926deccbSFrançois Tigeot 
2017926deccbSFrançois Tigeot int cayman_asic_reset(struct radeon_device *rdev)
2018926deccbSFrançois Tigeot {
2019b403bed8SMichael Neumann 	u32 reset_mask;
2020b403bed8SMichael Neumann 
2021b403bed8SMichael Neumann 	reset_mask = cayman_gpu_check_soft_reset(rdev);
2022b403bed8SMichael Neumann 
2023b403bed8SMichael Neumann 	if (reset_mask)
2024b403bed8SMichael Neumann 		r600_set_bios_scratch_engine_hung(rdev, true);
2025b403bed8SMichael Neumann 
2026b403bed8SMichael Neumann 	cayman_gpu_soft_reset(rdev, reset_mask);
2027b403bed8SMichael Neumann 
2028b403bed8SMichael Neumann 	reset_mask = cayman_gpu_check_soft_reset(rdev);
2029b403bed8SMichael Neumann 
2030b403bed8SMichael Neumann 	if (!reset_mask)
2031b403bed8SMichael Neumann 		r600_set_bios_scratch_engine_hung(rdev, false);
2032b403bed8SMichael Neumann 
2033b403bed8SMichael Neumann 	return 0;
2034b403bed8SMichael Neumann }
2035b403bed8SMichael Neumann 
2036b403bed8SMichael Neumann /**
2037b403bed8SMichael Neumann  * cayman_gfx_is_lockup - Check if the GFX engine is locked up
2038b403bed8SMichael Neumann  *
2039b403bed8SMichael Neumann  * @rdev: radeon_device pointer
2040b403bed8SMichael Neumann  * @ring: radeon_ring structure holding ring information
2041b403bed8SMichael Neumann  *
2042b403bed8SMichael Neumann  * Check if the GFX engine is locked up.
2043b403bed8SMichael Neumann  * Returns true if the engine appears to be locked up, false if not.
2044b403bed8SMichael Neumann  */
2045b403bed8SMichael Neumann bool cayman_gfx_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring)
2046b403bed8SMichael Neumann {
2047b403bed8SMichael Neumann 	u32 reset_mask = cayman_gpu_check_soft_reset(rdev);
2048b403bed8SMichael Neumann 
2049b403bed8SMichael Neumann 	if (!(reset_mask & (RADEON_RESET_GFX |
2050926deccbSFrançois Tigeot 			    RADEON_RESET_COMPUTE |
2051b403bed8SMichael Neumann 			    RADEON_RESET_CP))) {
2052b403bed8SMichael Neumann 		radeon_ring_lockup_update(ring);
2053b403bed8SMichael Neumann 		return false;
2054b403bed8SMichael Neumann 	}
2055b403bed8SMichael Neumann 	/* force CP activities */
2056b403bed8SMichael Neumann 	radeon_ring_force_activity(rdev, ring);
2057b403bed8SMichael Neumann 	return radeon_ring_test_lockup(rdev, ring);
2058926deccbSFrançois Tigeot }
2059926deccbSFrançois Tigeot 
2060926deccbSFrançois Tigeot /**
2061926deccbSFrançois Tigeot  * cayman_dma_is_lockup - Check if the DMA engine is locked up
2062926deccbSFrançois Tigeot  *
2063926deccbSFrançois Tigeot  * @rdev: radeon_device pointer
2064926deccbSFrançois Tigeot  * @ring: radeon_ring structure holding ring information
2065926deccbSFrançois Tigeot  *
2066b403bed8SMichael Neumann  * Check if the async DMA engine is locked up.
2067926deccbSFrançois Tigeot  * Returns true if the engine appears to be locked up, false if not.
2068926deccbSFrançois Tigeot  */
2069926deccbSFrançois Tigeot bool cayman_dma_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring)
2070926deccbSFrançois Tigeot {
2071b403bed8SMichael Neumann 	u32 reset_mask = cayman_gpu_check_soft_reset(rdev);
2072b403bed8SMichael Neumann 	u32 mask;
2073926deccbSFrançois Tigeot 
2074926deccbSFrançois Tigeot 	if (ring->idx == R600_RING_TYPE_DMA_INDEX)
2075b403bed8SMichael Neumann 		mask = RADEON_RESET_DMA;
2076926deccbSFrançois Tigeot 	else
2077b403bed8SMichael Neumann 		mask = RADEON_RESET_DMA1;
2078b403bed8SMichael Neumann 
2079b403bed8SMichael Neumann 	if (!(reset_mask & mask)) {
2080926deccbSFrançois Tigeot 		radeon_ring_lockup_update(ring);
2081926deccbSFrançois Tigeot 		return false;
2082926deccbSFrançois Tigeot 	}
2083926deccbSFrançois Tigeot 	/* force ring activities */
2084926deccbSFrançois Tigeot 	radeon_ring_force_activity(rdev, ring);
2085926deccbSFrançois Tigeot 	return radeon_ring_test_lockup(rdev, ring);
2086926deccbSFrançois Tigeot }
2087926deccbSFrançois Tigeot 
2088926deccbSFrançois Tigeot static int cayman_startup(struct radeon_device *rdev)
2089926deccbSFrançois Tigeot {
2090926deccbSFrançois Tigeot 	struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
2091926deccbSFrançois Tigeot 	int r;
2092926deccbSFrançois Tigeot 
2093926deccbSFrançois Tigeot 	/* enable pcie gen2 link */
2094926deccbSFrançois Tigeot 	evergreen_pcie_gen2_enable(rdev);
209557e252bfSMichael Neumann 	/* enable aspm */
209657e252bfSMichael Neumann 	evergreen_program_aspm(rdev);
209757e252bfSMichael Neumann 
209857e252bfSMichael Neumann 	evergreen_mc_program(rdev);
2099926deccbSFrançois Tigeot 
2100926deccbSFrançois Tigeot 	if (rdev->flags & RADEON_IS_IGP) {
2101926deccbSFrançois Tigeot 		if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) {
2102926deccbSFrançois Tigeot 			r = ni_init_microcode(rdev);
2103926deccbSFrançois Tigeot 			if (r) {
2104926deccbSFrançois Tigeot 				DRM_ERROR("Failed to load firmware!\n");
2105926deccbSFrançois Tigeot 				return r;
2106926deccbSFrançois Tigeot 			}
2107926deccbSFrançois Tigeot 		}
2108926deccbSFrançois Tigeot 	} else {
2109926deccbSFrançois Tigeot 		if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw || !rdev->mc_fw) {
2110926deccbSFrançois Tigeot 			r = ni_init_microcode(rdev);
2111926deccbSFrançois Tigeot 			if (r) {
2112926deccbSFrançois Tigeot 				DRM_ERROR("Failed to load firmware!\n");
2113926deccbSFrançois Tigeot 				return r;
2114926deccbSFrançois Tigeot 			}
2115926deccbSFrançois Tigeot 		}
2116926deccbSFrançois Tigeot 
2117926deccbSFrançois Tigeot 		r = ni_mc_load_microcode(rdev);
2118926deccbSFrançois Tigeot 		if (r) {
2119926deccbSFrançois Tigeot 			DRM_ERROR("Failed to load MC firmware!\n");
2120926deccbSFrançois Tigeot 			return r;
2121926deccbSFrançois Tigeot 		}
2122926deccbSFrançois Tigeot 	}
2123926deccbSFrançois Tigeot 
2124926deccbSFrançois Tigeot 	r = r600_vram_scratch_init(rdev);
2125926deccbSFrançois Tigeot 	if (r)
2126926deccbSFrançois Tigeot 		return r;
2127926deccbSFrançois Tigeot 
2128926deccbSFrançois Tigeot 	r = cayman_pcie_gart_enable(rdev);
2129926deccbSFrançois Tigeot 	if (r)
2130926deccbSFrançois Tigeot 		return r;
2131926deccbSFrançois Tigeot 	cayman_gpu_init(rdev);
2132926deccbSFrançois Tigeot 
2133926deccbSFrançois Tigeot 	r = evergreen_blit_init(rdev);
2134926deccbSFrançois Tigeot 	if (r) {
2135926deccbSFrançois Tigeot 		r600_blit_fini(rdev);
2136926deccbSFrançois Tigeot 		rdev->asic->copy.copy = NULL;
2137926deccbSFrançois Tigeot 		dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r);
2138926deccbSFrançois Tigeot 	}
2139926deccbSFrançois Tigeot 
2140926deccbSFrançois Tigeot 	/* allocate rlc buffers */
2141926deccbSFrançois Tigeot 	if (rdev->flags & RADEON_IS_IGP) {
214257e252bfSMichael Neumann 		rdev->rlc.reg_list = tn_rlc_save_restore_register_list;
214357e252bfSMichael Neumann 		rdev->rlc.reg_list_size = tn_rlc_save_restore_register_list_size;
214457e252bfSMichael Neumann 		rdev->rlc.cs_data = cayman_cs_data;
214557e252bfSMichael Neumann 		r = sumo_rlc_init(rdev);
2146926deccbSFrançois Tigeot 		if (r) {
2147926deccbSFrançois Tigeot 			DRM_ERROR("Failed to init rlc BOs!\n");
2148926deccbSFrançois Tigeot 			return r;
2149926deccbSFrançois Tigeot 		}
2150926deccbSFrançois Tigeot 	}
2151926deccbSFrançois Tigeot 
2152926deccbSFrançois Tigeot 	/* allocate wb buffer */
2153926deccbSFrançois Tigeot 	r = radeon_wb_init(rdev);
2154926deccbSFrançois Tigeot 	if (r)
2155926deccbSFrançois Tigeot 		return r;
2156926deccbSFrançois Tigeot 
2157926deccbSFrançois Tigeot 	r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX);
2158926deccbSFrançois Tigeot 	if (r) {
2159926deccbSFrançois Tigeot 		dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r);
2160926deccbSFrançois Tigeot 		return r;
2161926deccbSFrançois Tigeot 	}
2162926deccbSFrançois Tigeot 
2163f43cf1b1SMichael Neumann 	r = rv770_uvd_resume(rdev);
2164f43cf1b1SMichael Neumann 	if (!r) {
2165f43cf1b1SMichael Neumann 		r = radeon_fence_driver_start_ring(rdev,
2166f43cf1b1SMichael Neumann 						   R600_RING_TYPE_UVD_INDEX);
2167f43cf1b1SMichael Neumann 		if (r)
2168f43cf1b1SMichael Neumann 			dev_err(rdev->dev, "UVD fences init error (%d).\n", r);
2169f43cf1b1SMichael Neumann 	}
2170f43cf1b1SMichael Neumann 	if (r)
2171f43cf1b1SMichael Neumann 		rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;
2172f43cf1b1SMichael Neumann 
2173926deccbSFrançois Tigeot 	r = radeon_fence_driver_start_ring(rdev, CAYMAN_RING_TYPE_CP1_INDEX);
2174926deccbSFrançois Tigeot 	if (r) {
2175926deccbSFrançois Tigeot 		dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r);
2176926deccbSFrançois Tigeot 		return r;
2177926deccbSFrançois Tigeot 	}
2178926deccbSFrançois Tigeot 
2179926deccbSFrançois Tigeot 	r = radeon_fence_driver_start_ring(rdev, CAYMAN_RING_TYPE_CP2_INDEX);
2180926deccbSFrançois Tigeot 	if (r) {
2181926deccbSFrançois Tigeot 		dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r);
2182926deccbSFrançois Tigeot 		return r;
2183926deccbSFrançois Tigeot 	}
2184926deccbSFrançois Tigeot 
2185926deccbSFrançois Tigeot 	r = radeon_fence_driver_start_ring(rdev, R600_RING_TYPE_DMA_INDEX);
2186926deccbSFrançois Tigeot 	if (r) {
2187926deccbSFrançois Tigeot 		dev_err(rdev->dev, "failed initializing DMA fences (%d).\n", r);
2188926deccbSFrançois Tigeot 		return r;
2189926deccbSFrançois Tigeot 	}
2190926deccbSFrançois Tigeot 
2191926deccbSFrançois Tigeot 	r = radeon_fence_driver_start_ring(rdev, CAYMAN_RING_TYPE_DMA1_INDEX);
2192926deccbSFrançois Tigeot 	if (r) {
2193926deccbSFrançois Tigeot 		dev_err(rdev->dev, "failed initializing DMA fences (%d).\n", r);
2194926deccbSFrançois Tigeot 		return r;
2195926deccbSFrançois Tigeot 	}
2196926deccbSFrançois Tigeot 
2197926deccbSFrançois Tigeot 	/* Enable IRQ */
2198f43cf1b1SMichael Neumann 	if (!rdev->irq.installed) {
2199f43cf1b1SMichael Neumann 		r = radeon_irq_kms_init(rdev);
2200f43cf1b1SMichael Neumann 		if (r)
2201f43cf1b1SMichael Neumann 			return r;
2202f43cf1b1SMichael Neumann 	}
2203f43cf1b1SMichael Neumann 
2204926deccbSFrançois Tigeot 	r = r600_irq_init(rdev);
2205926deccbSFrançois Tigeot 	if (r) {
2206926deccbSFrançois Tigeot 		DRM_ERROR("radeon: IH init failed (%d).\n", r);
2207926deccbSFrançois Tigeot 		radeon_irq_kms_fini(rdev);
2208926deccbSFrançois Tigeot 		return r;
2209926deccbSFrançois Tigeot 	}
2210926deccbSFrançois Tigeot 	evergreen_irq_set(rdev);
2211926deccbSFrançois Tigeot 
2212926deccbSFrançois Tigeot 	r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET,
2213926deccbSFrançois Tigeot 			     CP_RB0_RPTR, CP_RB0_WPTR,
2214926deccbSFrançois Tigeot 			     0, 0xfffff, RADEON_CP_PACKET2);
2215926deccbSFrançois Tigeot 	if (r)
2216926deccbSFrançois Tigeot 		return r;
2217926deccbSFrançois Tigeot 
2218926deccbSFrançois Tigeot 	ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX];
2219926deccbSFrançois Tigeot 	r = radeon_ring_init(rdev, ring, ring->ring_size, R600_WB_DMA_RPTR_OFFSET,
2220926deccbSFrançois Tigeot 			     DMA_RB_RPTR + DMA0_REGISTER_OFFSET,
2221926deccbSFrançois Tigeot 			     DMA_RB_WPTR + DMA0_REGISTER_OFFSET,
2222926deccbSFrançois Tigeot 			     2, 0x3fffc, DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0));
2223926deccbSFrançois Tigeot 	if (r)
2224926deccbSFrançois Tigeot 		return r;
2225926deccbSFrançois Tigeot 
2226926deccbSFrançois Tigeot 	ring = &rdev->ring[CAYMAN_RING_TYPE_DMA1_INDEX];
2227926deccbSFrançois Tigeot 	r = radeon_ring_init(rdev, ring, ring->ring_size, CAYMAN_WB_DMA1_RPTR_OFFSET,
2228926deccbSFrançois Tigeot 			     DMA_RB_RPTR + DMA1_REGISTER_OFFSET,
2229926deccbSFrançois Tigeot 			     DMA_RB_WPTR + DMA1_REGISTER_OFFSET,
2230926deccbSFrançois Tigeot 			     2, 0x3fffc, DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0));
2231926deccbSFrançois Tigeot 	if (r)
2232926deccbSFrançois Tigeot 		return r;
2233926deccbSFrançois Tigeot 
2234926deccbSFrançois Tigeot 	r = cayman_cp_load_microcode(rdev);
2235926deccbSFrançois Tigeot 	if (r)
2236926deccbSFrançois Tigeot 		return r;
2237926deccbSFrançois Tigeot 	r = cayman_cp_resume(rdev);
2238926deccbSFrançois Tigeot 	if (r)
2239926deccbSFrançois Tigeot 		return r;
2240926deccbSFrançois Tigeot 
2241926deccbSFrançois Tigeot 	r = cayman_dma_resume(rdev);
2242926deccbSFrançois Tigeot 	if (r)
2243926deccbSFrançois Tigeot 		return r;
2244926deccbSFrançois Tigeot 
2245f43cf1b1SMichael Neumann 	ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
2246f43cf1b1SMichael Neumann 	if (ring->ring_size) {
2247f43cf1b1SMichael Neumann 		r = radeon_ring_init(rdev, ring, ring->ring_size,
2248f43cf1b1SMichael Neumann 				     R600_WB_UVD_RPTR_OFFSET,
2249f43cf1b1SMichael Neumann 				     UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR,
2250f43cf1b1SMichael Neumann 				     0, 0xfffff, RADEON_CP_PACKET2);
2251f43cf1b1SMichael Neumann 		if (!r)
2252f43cf1b1SMichael Neumann 			r = r600_uvd_init(rdev);
2253f43cf1b1SMichael Neumann 		if (r)
2254f43cf1b1SMichael Neumann 			DRM_ERROR("radeon: failed initializing UVD (%d).\n", r);
2255f43cf1b1SMichael Neumann 	}
2256f43cf1b1SMichael Neumann 
2257926deccbSFrançois Tigeot 	r = radeon_ib_pool_init(rdev);
2258926deccbSFrançois Tigeot 	if (r) {
2259926deccbSFrançois Tigeot 		dev_err(rdev->dev, "IB initialization failed (%d).\n", r);
2260926deccbSFrançois Tigeot 		return r;
2261926deccbSFrançois Tigeot 	}
2262926deccbSFrançois Tigeot 
2263926deccbSFrançois Tigeot 	r = radeon_vm_manager_init(rdev);
2264926deccbSFrançois Tigeot 	if (r) {
2265926deccbSFrançois Tigeot 		dev_err(rdev->dev, "vm manager initialization failed (%d).\n", r);
2266926deccbSFrançois Tigeot 		return r;
2267926deccbSFrançois Tigeot 	}
2268926deccbSFrançois Tigeot 
2269926deccbSFrançois Tigeot 	r = r600_audio_init(rdev);
2270926deccbSFrançois Tigeot 	if (r)
2271926deccbSFrançois Tigeot 		return r;
2272926deccbSFrançois Tigeot 
2273926deccbSFrançois Tigeot 	return 0;
2274926deccbSFrançois Tigeot }
2275926deccbSFrançois Tigeot 
2276926deccbSFrançois Tigeot int cayman_resume(struct radeon_device *rdev)
2277926deccbSFrançois Tigeot {
2278926deccbSFrançois Tigeot 	int r;
2279926deccbSFrançois Tigeot 
2280926deccbSFrançois Tigeot 	/* Do not reset GPU before posting, on rv770 hw unlike on r500 hw,
2281926deccbSFrançois Tigeot 	 * posting will perform necessary task to bring back GPU into good
2282926deccbSFrançois Tigeot 	 * shape.
2283926deccbSFrançois Tigeot 	 */
2284926deccbSFrançois Tigeot 	/* post card */
2285926deccbSFrançois Tigeot 	atom_asic_init(rdev->mode_info.atom_context);
2286926deccbSFrançois Tigeot 
2287f43cf1b1SMichael Neumann 	/* init golden registers */
2288f43cf1b1SMichael Neumann 	ni_init_golden_registers(rdev);
2289f43cf1b1SMichael Neumann 
2290926deccbSFrançois Tigeot 	rdev->accel_working = true;
2291926deccbSFrançois Tigeot 	r = cayman_startup(rdev);
2292926deccbSFrançois Tigeot 	if (r) {
2293926deccbSFrançois Tigeot 		DRM_ERROR("cayman startup failed on resume\n");
2294926deccbSFrançois Tigeot 		rdev->accel_working = false;
2295926deccbSFrançois Tigeot 		return r;
2296926deccbSFrançois Tigeot 	}
2297926deccbSFrançois Tigeot 	return r;
2298926deccbSFrançois Tigeot }
2299926deccbSFrançois Tigeot 
2300926deccbSFrançois Tigeot int cayman_suspend(struct radeon_device *rdev)
2301926deccbSFrançois Tigeot {
2302926deccbSFrançois Tigeot 	r600_audio_fini(rdev);
2303b403bed8SMichael Neumann 	radeon_vm_manager_fini(rdev);
2304926deccbSFrançois Tigeot 	cayman_cp_enable(rdev, false);
2305926deccbSFrançois Tigeot 	cayman_dma_stop(rdev);
230657e252bfSMichael Neumann 	r600_uvd_stop(rdev);
2307f43cf1b1SMichael Neumann 	radeon_uvd_suspend(rdev);
2308926deccbSFrançois Tigeot 	evergreen_irq_suspend(rdev);
2309926deccbSFrançois Tigeot 	radeon_wb_disable(rdev);
2310926deccbSFrançois Tigeot 	cayman_pcie_gart_disable(rdev);
2311926deccbSFrançois Tigeot 	return 0;
2312926deccbSFrançois Tigeot }
2313926deccbSFrançois Tigeot 
2314926deccbSFrançois Tigeot /* Plan is to move initialization in that function and use
2315926deccbSFrançois Tigeot  * helper function so that radeon_device_init pretty much
2316926deccbSFrançois Tigeot  * do nothing more than calling asic specific function. This
2317926deccbSFrançois Tigeot  * should also allow to remove a bunch of callback function
2318926deccbSFrançois Tigeot  * like vram_info.
2319926deccbSFrançois Tigeot  */
2320926deccbSFrançois Tigeot int cayman_init(struct radeon_device *rdev)
2321926deccbSFrançois Tigeot {
2322926deccbSFrançois Tigeot 	struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
2323926deccbSFrançois Tigeot 	int r;
2324926deccbSFrançois Tigeot 
2325926deccbSFrançois Tigeot 	/* Read BIOS */
2326926deccbSFrançois Tigeot 	if (!radeon_get_bios(rdev)) {
2327926deccbSFrançois Tigeot 		if (ASIC_IS_AVIVO(rdev))
2328926deccbSFrançois Tigeot 			return -EINVAL;
2329926deccbSFrançois Tigeot 	}
2330926deccbSFrançois Tigeot 	/* Must be an ATOMBIOS */
2331926deccbSFrançois Tigeot 	if (!rdev->is_atom_bios) {
2332926deccbSFrançois Tigeot 		dev_err(rdev->dev, "Expecting atombios for cayman GPU\n");
2333926deccbSFrançois Tigeot 		return -EINVAL;
2334926deccbSFrançois Tigeot 	}
2335926deccbSFrançois Tigeot 	r = radeon_atombios_init(rdev);
2336926deccbSFrançois Tigeot 	if (r)
2337926deccbSFrançois Tigeot 		return r;
2338926deccbSFrançois Tigeot 
2339926deccbSFrançois Tigeot 	/* Post card if necessary */
2340926deccbSFrançois Tigeot 	if (!radeon_card_posted(rdev)) {
2341926deccbSFrançois Tigeot 		if (!rdev->bios) {
2342926deccbSFrançois Tigeot 			dev_err(rdev->dev, "Card not posted and no BIOS - ignoring\n");
2343926deccbSFrançois Tigeot 			return -EINVAL;
2344926deccbSFrançois Tigeot 		}
2345926deccbSFrançois Tigeot 		DRM_INFO("GPU not posted. posting now...\n");
2346926deccbSFrançois Tigeot 		atom_asic_init(rdev->mode_info.atom_context);
2347926deccbSFrançois Tigeot 	}
2348f43cf1b1SMichael Neumann 	/* init golden registers */
2349f43cf1b1SMichael Neumann 	ni_init_golden_registers(rdev);
2350926deccbSFrançois Tigeot 	/* Initialize scratch registers */
2351926deccbSFrançois Tigeot 	r600_scratch_init(rdev);
2352926deccbSFrançois Tigeot 	/* Initialize surface registers */
2353926deccbSFrançois Tigeot 	radeon_surface_init(rdev);
2354926deccbSFrançois Tigeot 	/* Initialize clocks */
2355926deccbSFrançois Tigeot 	radeon_get_clock_info(rdev->ddev);
2356926deccbSFrançois Tigeot 	/* Fence driver */
2357926deccbSFrançois Tigeot 	r = radeon_fence_driver_init(rdev);
2358926deccbSFrançois Tigeot 	if (r)
2359926deccbSFrançois Tigeot 		return r;
2360926deccbSFrançois Tigeot 	/* initialize memory controller */
2361926deccbSFrançois Tigeot 	r = evergreen_mc_init(rdev);
2362926deccbSFrançois Tigeot 	if (r)
2363926deccbSFrançois Tigeot 		return r;
2364926deccbSFrançois Tigeot 	/* Memory manager */
2365926deccbSFrançois Tigeot 	r = radeon_bo_init(rdev);
2366926deccbSFrançois Tigeot 	if (r)
2367926deccbSFrançois Tigeot 		return r;
2368926deccbSFrançois Tigeot 
2369926deccbSFrançois Tigeot 	ring->ring_obj = NULL;
2370926deccbSFrançois Tigeot 	r600_ring_init(rdev, ring, 1024 * 1024);
2371926deccbSFrançois Tigeot 
2372926deccbSFrançois Tigeot 	ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX];
2373926deccbSFrançois Tigeot 	ring->ring_obj = NULL;
2374926deccbSFrançois Tigeot 	r600_ring_init(rdev, ring, 64 * 1024);
2375926deccbSFrançois Tigeot 
2376926deccbSFrançois Tigeot 	ring = &rdev->ring[CAYMAN_RING_TYPE_DMA1_INDEX];
2377926deccbSFrançois Tigeot 	ring->ring_obj = NULL;
2378926deccbSFrançois Tigeot 	r600_ring_init(rdev, ring, 64 * 1024);
2379926deccbSFrançois Tigeot 
2380f43cf1b1SMichael Neumann 	r = radeon_uvd_init(rdev);
2381f43cf1b1SMichael Neumann 	if (!r) {
2382f43cf1b1SMichael Neumann 		ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
2383f43cf1b1SMichael Neumann 		ring->ring_obj = NULL;
2384f43cf1b1SMichael Neumann 		r600_ring_init(rdev, ring, 4096);
2385f43cf1b1SMichael Neumann 	}
2386f43cf1b1SMichael Neumann 
2387926deccbSFrançois Tigeot 	rdev->ih.ring_obj = NULL;
2388926deccbSFrançois Tigeot 	r600_ih_ring_init(rdev, 64 * 1024);
2389926deccbSFrançois Tigeot 
2390926deccbSFrançois Tigeot 	r = r600_pcie_gart_init(rdev);
2391926deccbSFrançois Tigeot 	if (r)
2392926deccbSFrançois Tigeot 		return r;
2393926deccbSFrançois Tigeot 
2394926deccbSFrançois Tigeot 	rdev->accel_working = true;
2395926deccbSFrançois Tigeot 	r = cayman_startup(rdev);
2396926deccbSFrançois Tigeot 	if (r) {
2397926deccbSFrançois Tigeot 		dev_err(rdev->dev, "disabling GPU acceleration\n");
2398926deccbSFrançois Tigeot 		cayman_cp_fini(rdev);
2399926deccbSFrançois Tigeot 		cayman_dma_fini(rdev);
2400926deccbSFrançois Tigeot 		r600_irq_fini(rdev);
2401926deccbSFrançois Tigeot 		if (rdev->flags & RADEON_IS_IGP)
240257e252bfSMichael Neumann 			sumo_rlc_fini(rdev);
2403926deccbSFrançois Tigeot 		radeon_wb_fini(rdev);
2404926deccbSFrançois Tigeot 		radeon_ib_pool_fini(rdev);
2405926deccbSFrançois Tigeot 		radeon_vm_manager_fini(rdev);
2406926deccbSFrançois Tigeot 		radeon_irq_kms_fini(rdev);
2407926deccbSFrançois Tigeot 		cayman_pcie_gart_fini(rdev);
2408926deccbSFrançois Tigeot 		rdev->accel_working = false;
2409926deccbSFrançois Tigeot 	}
2410926deccbSFrançois Tigeot 
2411926deccbSFrançois Tigeot 	/* Don't start up if the MC ucode is missing.
2412926deccbSFrançois Tigeot 	 * The default clocks and voltages before the MC ucode
2413926deccbSFrançois Tigeot 	 * is loaded are not suffient for advanced operations.
2414926deccbSFrançois Tigeot 	 *
2415926deccbSFrançois Tigeot 	 * We can skip this check for TN, because there is no MC
2416926deccbSFrançois Tigeot 	 * ucode.
2417926deccbSFrançois Tigeot 	 */
2418926deccbSFrançois Tigeot 	if (!rdev->mc_fw && !(rdev->flags & RADEON_IS_IGP)) {
2419926deccbSFrançois Tigeot 		DRM_ERROR("radeon: MC ucode required for NI+.\n");
2420926deccbSFrançois Tigeot 		return -EINVAL;
2421926deccbSFrançois Tigeot 	}
2422926deccbSFrançois Tigeot 
2423926deccbSFrançois Tigeot 	return 0;
2424926deccbSFrançois Tigeot }
2425926deccbSFrançois Tigeot 
2426926deccbSFrançois Tigeot void cayman_fini(struct radeon_device *rdev)
2427926deccbSFrançois Tigeot {
2428926deccbSFrançois Tigeot 	r600_blit_fini(rdev);
2429926deccbSFrançois Tigeot 	cayman_cp_fini(rdev);
2430926deccbSFrançois Tigeot 	cayman_dma_fini(rdev);
2431926deccbSFrançois Tigeot 	r600_irq_fini(rdev);
2432926deccbSFrançois Tigeot 	if (rdev->flags & RADEON_IS_IGP)
243357e252bfSMichael Neumann 		sumo_rlc_fini(rdev);
2434926deccbSFrançois Tigeot 	radeon_wb_fini(rdev);
2435926deccbSFrançois Tigeot 	radeon_vm_manager_fini(rdev);
2436926deccbSFrançois Tigeot 	radeon_ib_pool_fini(rdev);
2437926deccbSFrançois Tigeot 	radeon_irq_kms_fini(rdev);
243857e252bfSMichael Neumann 	r600_uvd_stop(rdev);
2439f43cf1b1SMichael Neumann 	radeon_uvd_fini(rdev);
2440926deccbSFrançois Tigeot 	cayman_pcie_gart_fini(rdev);
2441926deccbSFrançois Tigeot 	r600_vram_scratch_fini(rdev);
2442926deccbSFrançois Tigeot 	radeon_gem_fini(rdev);
2443926deccbSFrançois Tigeot 	radeon_fence_driver_fini(rdev);
2444926deccbSFrançois Tigeot 	radeon_bo_fini(rdev);
2445926deccbSFrançois Tigeot 	radeon_atombios_fini(rdev);
2446926deccbSFrançois Tigeot 	ni_fini_microcode(rdev);
24475a3b77d5SFrançois Tigeot 	drm_free(rdev->bios, M_DRM);
2448926deccbSFrançois Tigeot 	rdev->bios = NULL;
2449926deccbSFrançois Tigeot }
2450926deccbSFrançois Tigeot 
2451926deccbSFrançois Tigeot /*
2452926deccbSFrançois Tigeot  * vm
2453926deccbSFrançois Tigeot  */
2454926deccbSFrançois Tigeot int cayman_vm_init(struct radeon_device *rdev)
2455926deccbSFrançois Tigeot {
2456926deccbSFrançois Tigeot 	/* number of VMs */
2457926deccbSFrançois Tigeot 	rdev->vm_manager.nvm = 8;
2458926deccbSFrançois Tigeot 	/* base offset of vram pages */
2459926deccbSFrançois Tigeot 	if (rdev->flags & RADEON_IS_IGP) {
2460926deccbSFrançois Tigeot 		u64 tmp = RREG32(FUS_MC_VM_FB_OFFSET);
2461926deccbSFrançois Tigeot 		tmp <<= 22;
2462926deccbSFrançois Tigeot 		rdev->vm_manager.vram_base_offset = tmp;
2463926deccbSFrançois Tigeot 	} else
2464926deccbSFrançois Tigeot 		rdev->vm_manager.vram_base_offset = 0;
2465926deccbSFrançois Tigeot 	return 0;
2466926deccbSFrançois Tigeot }
2467926deccbSFrançois Tigeot 
2468926deccbSFrançois Tigeot void cayman_vm_fini(struct radeon_device *rdev)
2469926deccbSFrançois Tigeot {
2470926deccbSFrançois Tigeot }
2471926deccbSFrançois Tigeot 
247257e252bfSMichael Neumann /**
247357e252bfSMichael Neumann  * cayman_vm_decode_fault - print human readable fault info
247457e252bfSMichael Neumann  *
247557e252bfSMichael Neumann  * @rdev: radeon_device pointer
247657e252bfSMichael Neumann  * @status: VM_CONTEXT1_PROTECTION_FAULT_STATUS register value
247757e252bfSMichael Neumann  * @addr: VM_CONTEXT1_PROTECTION_FAULT_ADDR register value
247857e252bfSMichael Neumann  *
247957e252bfSMichael Neumann  * Print human readable fault information (cayman/TN).
248057e252bfSMichael Neumann  */
248157e252bfSMichael Neumann void cayman_vm_decode_fault(struct radeon_device *rdev,
248257e252bfSMichael Neumann 			    u32 status, u32 addr)
248357e252bfSMichael Neumann {
248457e252bfSMichael Neumann 	u32 mc_id = (status & MEMORY_CLIENT_ID_MASK) >> MEMORY_CLIENT_ID_SHIFT;
248557e252bfSMichael Neumann 	u32 vmid = (status & FAULT_VMID_MASK) >> FAULT_VMID_SHIFT;
248657e252bfSMichael Neumann 	u32 protections = (status & PROTECTIONS_MASK) >> PROTECTIONS_SHIFT;
248757e252bfSMichael Neumann 	char *block;
248857e252bfSMichael Neumann 
248957e252bfSMichael Neumann 	switch (mc_id) {
249057e252bfSMichael Neumann 	case 32:
249157e252bfSMichael Neumann 	case 16:
249257e252bfSMichael Neumann 	case 96:
249357e252bfSMichael Neumann 	case 80:
249457e252bfSMichael Neumann 	case 160:
249557e252bfSMichael Neumann 	case 144:
249657e252bfSMichael Neumann 	case 224:
249757e252bfSMichael Neumann 	case 208:
249857e252bfSMichael Neumann 		block = "CB";
249957e252bfSMichael Neumann 		break;
250057e252bfSMichael Neumann 	case 33:
250157e252bfSMichael Neumann 	case 17:
250257e252bfSMichael Neumann 	case 97:
250357e252bfSMichael Neumann 	case 81:
250457e252bfSMichael Neumann 	case 161:
250557e252bfSMichael Neumann 	case 145:
250657e252bfSMichael Neumann 	case 225:
250757e252bfSMichael Neumann 	case 209:
250857e252bfSMichael Neumann 		block = "CB_FMASK";
250957e252bfSMichael Neumann 		break;
251057e252bfSMichael Neumann 	case 34:
251157e252bfSMichael Neumann 	case 18:
251257e252bfSMichael Neumann 	case 98:
251357e252bfSMichael Neumann 	case 82:
251457e252bfSMichael Neumann 	case 162:
251557e252bfSMichael Neumann 	case 146:
251657e252bfSMichael Neumann 	case 226:
251757e252bfSMichael Neumann 	case 210:
251857e252bfSMichael Neumann 		block = "CB_CMASK";
251957e252bfSMichael Neumann 		break;
252057e252bfSMichael Neumann 	case 35:
252157e252bfSMichael Neumann 	case 19:
252257e252bfSMichael Neumann 	case 99:
252357e252bfSMichael Neumann 	case 83:
252457e252bfSMichael Neumann 	case 163:
252557e252bfSMichael Neumann 	case 147:
252657e252bfSMichael Neumann 	case 227:
252757e252bfSMichael Neumann 	case 211:
252857e252bfSMichael Neumann 		block = "CB_IMMED";
252957e252bfSMichael Neumann 		break;
253057e252bfSMichael Neumann 	case 36:
253157e252bfSMichael Neumann 	case 20:
253257e252bfSMichael Neumann 	case 100:
253357e252bfSMichael Neumann 	case 84:
253457e252bfSMichael Neumann 	case 164:
253557e252bfSMichael Neumann 	case 148:
253657e252bfSMichael Neumann 	case 228:
253757e252bfSMichael Neumann 	case 212:
253857e252bfSMichael Neumann 		block = "DB";
253957e252bfSMichael Neumann 		break;
254057e252bfSMichael Neumann 	case 37:
254157e252bfSMichael Neumann 	case 21:
254257e252bfSMichael Neumann 	case 101:
254357e252bfSMichael Neumann 	case 85:
254457e252bfSMichael Neumann 	case 165:
254557e252bfSMichael Neumann 	case 149:
254657e252bfSMichael Neumann 	case 229:
254757e252bfSMichael Neumann 	case 213:
254857e252bfSMichael Neumann 		block = "DB_HTILE";
254957e252bfSMichael Neumann 		break;
255057e252bfSMichael Neumann 	case 38:
255157e252bfSMichael Neumann 	case 22:
255257e252bfSMichael Neumann 	case 102:
255357e252bfSMichael Neumann 	case 86:
255457e252bfSMichael Neumann 	case 166:
255557e252bfSMichael Neumann 	case 150:
255657e252bfSMichael Neumann 	case 230:
255757e252bfSMichael Neumann 	case 214:
255857e252bfSMichael Neumann 		block = "SX";
255957e252bfSMichael Neumann 		break;
256057e252bfSMichael Neumann 	case 39:
256157e252bfSMichael Neumann 	case 23:
256257e252bfSMichael Neumann 	case 103:
256357e252bfSMichael Neumann 	case 87:
256457e252bfSMichael Neumann 	case 167:
256557e252bfSMichael Neumann 	case 151:
256657e252bfSMichael Neumann 	case 231:
256757e252bfSMichael Neumann 	case 215:
256857e252bfSMichael Neumann 		block = "DB_STEN";
256957e252bfSMichael Neumann 		break;
257057e252bfSMichael Neumann 	case 40:
257157e252bfSMichael Neumann 	case 24:
257257e252bfSMichael Neumann 	case 104:
257357e252bfSMichael Neumann 	case 88:
257457e252bfSMichael Neumann 	case 232:
257557e252bfSMichael Neumann 	case 216:
257657e252bfSMichael Neumann 	case 168:
257757e252bfSMichael Neumann 	case 152:
257857e252bfSMichael Neumann 		block = "TC_TFETCH";
257957e252bfSMichael Neumann 		break;
258057e252bfSMichael Neumann 	case 41:
258157e252bfSMichael Neumann 	case 25:
258257e252bfSMichael Neumann 	case 105:
258357e252bfSMichael Neumann 	case 89:
258457e252bfSMichael Neumann 	case 233:
258557e252bfSMichael Neumann 	case 217:
258657e252bfSMichael Neumann 	case 169:
258757e252bfSMichael Neumann 	case 153:
258857e252bfSMichael Neumann 		block = "TC_VFETCH";
258957e252bfSMichael Neumann 		break;
259057e252bfSMichael Neumann 	case 42:
259157e252bfSMichael Neumann 	case 26:
259257e252bfSMichael Neumann 	case 106:
259357e252bfSMichael Neumann 	case 90:
259457e252bfSMichael Neumann 	case 234:
259557e252bfSMichael Neumann 	case 218:
259657e252bfSMichael Neumann 	case 170:
259757e252bfSMichael Neumann 	case 154:
259857e252bfSMichael Neumann 		block = "VC";
259957e252bfSMichael Neumann 		break;
260057e252bfSMichael Neumann 	case 112:
260157e252bfSMichael Neumann 		block = "CP";
260257e252bfSMichael Neumann 		break;
260357e252bfSMichael Neumann 	case 113:
260457e252bfSMichael Neumann 	case 114:
260557e252bfSMichael Neumann 		block = "SH";
260657e252bfSMichael Neumann 		break;
260757e252bfSMichael Neumann 	case 115:
260857e252bfSMichael Neumann 		block = "VGT";
260957e252bfSMichael Neumann 		break;
261057e252bfSMichael Neumann 	case 178:
261157e252bfSMichael Neumann 		block = "IH";
261257e252bfSMichael Neumann 		break;
261357e252bfSMichael Neumann 	case 51:
261457e252bfSMichael Neumann 		block = "RLC";
261557e252bfSMichael Neumann 		break;
261657e252bfSMichael Neumann 	case 55:
261757e252bfSMichael Neumann 		block = "DMA";
261857e252bfSMichael Neumann 		break;
261957e252bfSMichael Neumann 	case 56:
262057e252bfSMichael Neumann 		block = "HDP";
262157e252bfSMichael Neumann 		break;
262257e252bfSMichael Neumann 	default:
262357e252bfSMichael Neumann 		block = "unknown";
262457e252bfSMichael Neumann 		break;
262557e252bfSMichael Neumann 	}
262657e252bfSMichael Neumann 
262757e252bfSMichael Neumann 	printk("VM fault (0x%02x, vmid %d) at page %u, %s from %s (%d)\n",
262857e252bfSMichael Neumann 	       protections, vmid, addr,
262957e252bfSMichael Neumann 	       (status & MEMORY_CLIENT_RW_MASK) ? "write" : "read",
263057e252bfSMichael Neumann 	       block, mc_id);
263157e252bfSMichael Neumann }
263257e252bfSMichael Neumann 
2633926deccbSFrançois Tigeot #define R600_ENTRY_VALID   (1 << 0)
2634926deccbSFrançois Tigeot #define R600_PTE_SYSTEM    (1 << 1)
2635926deccbSFrançois Tigeot #define R600_PTE_SNOOPED   (1 << 2)
2636926deccbSFrançois Tigeot #define R600_PTE_READABLE  (1 << 5)
2637926deccbSFrançois Tigeot #define R600_PTE_WRITEABLE (1 << 6)
2638926deccbSFrançois Tigeot 
2639926deccbSFrançois Tigeot uint32_t cayman_vm_page_flags(struct radeon_device *rdev, uint32_t flags)
2640926deccbSFrançois Tigeot {
2641926deccbSFrançois Tigeot 	uint32_t r600_flags = 0;
2642926deccbSFrançois Tigeot 	r600_flags |= (flags & RADEON_VM_PAGE_VALID) ? R600_ENTRY_VALID : 0;
2643926deccbSFrançois Tigeot 	r600_flags |= (flags & RADEON_VM_PAGE_READABLE) ? R600_PTE_READABLE : 0;
2644926deccbSFrançois Tigeot 	r600_flags |= (flags & RADEON_VM_PAGE_WRITEABLE) ? R600_PTE_WRITEABLE : 0;
2645926deccbSFrançois Tigeot 	if (flags & RADEON_VM_PAGE_SYSTEM) {
2646926deccbSFrançois Tigeot 		r600_flags |= R600_PTE_SYSTEM;
2647926deccbSFrançois Tigeot 		r600_flags |= (flags & RADEON_VM_PAGE_SNOOPED) ? R600_PTE_SNOOPED : 0;
2648926deccbSFrançois Tigeot 	}
2649926deccbSFrançois Tigeot 	return r600_flags;
2650926deccbSFrançois Tigeot }
2651926deccbSFrançois Tigeot 
2652926deccbSFrançois Tigeot /**
2653926deccbSFrançois Tigeot  * cayman_vm_set_page - update the page tables using the CP
2654926deccbSFrançois Tigeot  *
2655926deccbSFrançois Tigeot  * @rdev: radeon_device pointer
2656b403bed8SMichael Neumann  * @ib: indirect buffer to fill with commands
2657926deccbSFrançois Tigeot  * @pe: addr of the page entry
2658926deccbSFrançois Tigeot  * @addr: dst addr to write into pe
2659926deccbSFrançois Tigeot  * @count: number of page entries to update
2660926deccbSFrançois Tigeot  * @incr: increase next addr by incr bytes
2661926deccbSFrançois Tigeot  * @flags: access flags
2662926deccbSFrançois Tigeot  *
2663b403bed8SMichael Neumann  * Update the page tables using the CP (cayman/TN).
2664926deccbSFrançois Tigeot  */
2665b403bed8SMichael Neumann void cayman_vm_set_page(struct radeon_device *rdev,
2666b403bed8SMichael Neumann 			struct radeon_ib *ib,
2667b403bed8SMichael Neumann 			uint64_t pe,
2668926deccbSFrançois Tigeot 			uint64_t addr, unsigned count,
2669926deccbSFrançois Tigeot 			uint32_t incr, uint32_t flags)
2670926deccbSFrançois Tigeot {
2671926deccbSFrançois Tigeot 	uint32_t r600_flags = cayman_vm_page_flags(rdev, flags);
2672926deccbSFrançois Tigeot 	uint64_t value;
2673926deccbSFrançois Tigeot 	unsigned ndw;
2674926deccbSFrançois Tigeot 
2675926deccbSFrançois Tigeot 	if (rdev->asic->vm.pt_ring_index == RADEON_RING_TYPE_GFX_INDEX) {
2676926deccbSFrançois Tigeot 		while (count) {
2677926deccbSFrançois Tigeot 			ndw = 1 + count * 2;
2678926deccbSFrançois Tigeot 			if (ndw > 0x3FFF)
2679926deccbSFrançois Tigeot 				ndw = 0x3FFF;
2680926deccbSFrançois Tigeot 
2681b403bed8SMichael Neumann 			ib->ptr[ib->length_dw++] = PACKET3(PACKET3_ME_WRITE, ndw);
2682b403bed8SMichael Neumann 			ib->ptr[ib->length_dw++] = pe;
2683b403bed8SMichael Neumann 			ib->ptr[ib->length_dw++] = upper_32_bits(pe) & 0xff;
2684926deccbSFrançois Tigeot 			for (; ndw > 1; ndw -= 2, --count, pe += 8) {
2685926deccbSFrançois Tigeot 				if (flags & RADEON_VM_PAGE_SYSTEM) {
2686926deccbSFrançois Tigeot 					value = radeon_vm_map_gart(rdev, addr);
2687926deccbSFrançois Tigeot 					value &= 0xFFFFFFFFFFFFF000ULL;
2688926deccbSFrançois Tigeot 				} else if (flags & RADEON_VM_PAGE_VALID) {
2689926deccbSFrançois Tigeot 					value = addr;
2690926deccbSFrançois Tigeot 				} else {
2691926deccbSFrançois Tigeot 					value = 0;
2692926deccbSFrançois Tigeot 				}
2693926deccbSFrançois Tigeot 				addr += incr;
2694926deccbSFrançois Tigeot 				value |= r600_flags;
2695b403bed8SMichael Neumann 				ib->ptr[ib->length_dw++] = value;
2696b403bed8SMichael Neumann 				ib->ptr[ib->length_dw++] = upper_32_bits(value);
2697926deccbSFrançois Tigeot 			}
2698926deccbSFrançois Tigeot 		}
2699926deccbSFrançois Tigeot 	} else {
2700f43cf1b1SMichael Neumann 		if ((flags & RADEON_VM_PAGE_SYSTEM) ||
2701f43cf1b1SMichael Neumann 		    (count == 1)) {
2702926deccbSFrançois Tigeot 			while (count) {
2703926deccbSFrançois Tigeot 				ndw = count * 2;
2704926deccbSFrançois Tigeot 				if (ndw > 0xFFFFE)
2705926deccbSFrançois Tigeot 					ndw = 0xFFFFE;
2706926deccbSFrançois Tigeot 
2707926deccbSFrançois Tigeot 				/* for non-physically contiguous pages (system) */
2708b403bed8SMichael Neumann 				ib->ptr[ib->length_dw++] = DMA_PACKET(DMA_PACKET_WRITE, 0, 0, ndw);
2709b403bed8SMichael Neumann 				ib->ptr[ib->length_dw++] = pe;
2710b403bed8SMichael Neumann 				ib->ptr[ib->length_dw++] = upper_32_bits(pe) & 0xff;
2711926deccbSFrançois Tigeot 				for (; ndw > 0; ndw -= 2, --count, pe += 8) {
2712926deccbSFrançois Tigeot 					if (flags & RADEON_VM_PAGE_SYSTEM) {
2713926deccbSFrançois Tigeot 						value = radeon_vm_map_gart(rdev, addr);
2714926deccbSFrançois Tigeot 						value &= 0xFFFFFFFFFFFFF000ULL;
2715926deccbSFrançois Tigeot 					} else if (flags & RADEON_VM_PAGE_VALID) {
2716926deccbSFrançois Tigeot 						value = addr;
2717926deccbSFrançois Tigeot 					} else {
2718926deccbSFrançois Tigeot 						value = 0;
2719926deccbSFrançois Tigeot 					}
2720926deccbSFrançois Tigeot 					addr += incr;
2721926deccbSFrançois Tigeot 					value |= r600_flags;
2722b403bed8SMichael Neumann 					ib->ptr[ib->length_dw++] = value;
2723b403bed8SMichael Neumann 					ib->ptr[ib->length_dw++] = upper_32_bits(value);
2724926deccbSFrançois Tigeot 				}
2725926deccbSFrançois Tigeot 			}
2726b403bed8SMichael Neumann 			while (ib->length_dw & 0x7)
2727b403bed8SMichael Neumann 				ib->ptr[ib->length_dw++] = DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0);
2728f43cf1b1SMichael Neumann 		} else {
2729f43cf1b1SMichael Neumann 			while (count) {
2730f43cf1b1SMichael Neumann 				ndw = count * 2;
2731f43cf1b1SMichael Neumann 				if (ndw > 0xFFFFE)
2732f43cf1b1SMichael Neumann 					ndw = 0xFFFFE;
2733f43cf1b1SMichael Neumann 
2734f43cf1b1SMichael Neumann 				if (flags & RADEON_VM_PAGE_VALID)
2735f43cf1b1SMichael Neumann 					value = addr;
2736f43cf1b1SMichael Neumann 				else
2737f43cf1b1SMichael Neumann 					value = 0;
2738f43cf1b1SMichael Neumann 				/* for physically contiguous pages (vram) */
2739f43cf1b1SMichael Neumann 				ib->ptr[ib->length_dw++] = DMA_PTE_PDE_PACKET(ndw);
2740f43cf1b1SMichael Neumann 				ib->ptr[ib->length_dw++] = pe; /* dst addr */
2741f43cf1b1SMichael Neumann 				ib->ptr[ib->length_dw++] = upper_32_bits(pe) & 0xff;
2742f43cf1b1SMichael Neumann 				ib->ptr[ib->length_dw++] = r600_flags; /* mask */
2743f43cf1b1SMichael Neumann 				ib->ptr[ib->length_dw++] = 0;
2744f43cf1b1SMichael Neumann 				ib->ptr[ib->length_dw++] = value; /* value */
2745f43cf1b1SMichael Neumann 				ib->ptr[ib->length_dw++] = upper_32_bits(value);
2746f43cf1b1SMichael Neumann 				ib->ptr[ib->length_dw++] = incr; /* increment size */
2747f43cf1b1SMichael Neumann 				ib->ptr[ib->length_dw++] = 0;
2748f43cf1b1SMichael Neumann 				pe += ndw * 4;
2749f43cf1b1SMichael Neumann 				addr += (ndw / 2) * incr;
2750f43cf1b1SMichael Neumann 				count -= ndw / 2;
2751f43cf1b1SMichael Neumann 			}
2752f43cf1b1SMichael Neumann 		}
2753f43cf1b1SMichael Neumann 		while (ib->length_dw & 0x7)
2754f43cf1b1SMichael Neumann 			ib->ptr[ib->length_dw++] = DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0);
2755926deccbSFrançois Tigeot 	}
2756926deccbSFrançois Tigeot }
2757926deccbSFrançois Tigeot 
2758926deccbSFrançois Tigeot /**
2759926deccbSFrançois Tigeot  * cayman_vm_flush - vm flush using the CP
2760926deccbSFrançois Tigeot  *
2761926deccbSFrançois Tigeot  * @rdev: radeon_device pointer
2762926deccbSFrançois Tigeot  *
2763926deccbSFrançois Tigeot  * Update the page table base and flush the VM TLB
2764926deccbSFrançois Tigeot  * using the CP (cayman-si).
2765926deccbSFrançois Tigeot  */
2766926deccbSFrançois Tigeot void cayman_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm)
2767926deccbSFrançois Tigeot {
2768926deccbSFrançois Tigeot 	struct radeon_ring *ring = &rdev->ring[ridx];
2769926deccbSFrançois Tigeot 
2770926deccbSFrançois Tigeot 	if (vm == NULL)
2771926deccbSFrançois Tigeot 		return;
2772926deccbSFrançois Tigeot 
2773926deccbSFrançois Tigeot 	radeon_ring_write(ring, PACKET0(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (vm->id << 2), 0));
2774926deccbSFrançois Tigeot 	radeon_ring_write(ring, vm->pd_gpu_addr >> 12);
2775926deccbSFrançois Tigeot 
2776926deccbSFrançois Tigeot 	/* flush hdp cache */
2777926deccbSFrançois Tigeot 	radeon_ring_write(ring, PACKET0(HDP_MEM_COHERENCY_FLUSH_CNTL, 0));
2778926deccbSFrançois Tigeot 	radeon_ring_write(ring, 0x1);
2779926deccbSFrançois Tigeot 
2780926deccbSFrançois Tigeot 	/* bits 0-7 are the VM contexts0-7 */
2781926deccbSFrançois Tigeot 	radeon_ring_write(ring, PACKET0(VM_INVALIDATE_REQUEST, 0));
2782926deccbSFrançois Tigeot 	radeon_ring_write(ring, 1 << vm->id);
2783926deccbSFrançois Tigeot 
2784926deccbSFrançois Tigeot 	/* sync PFP to ME, otherwise we might get invalid PFP reads */
2785926deccbSFrançois Tigeot 	radeon_ring_write(ring, PACKET3(PACKET3_PFP_SYNC_ME, 0));
2786926deccbSFrançois Tigeot 	radeon_ring_write(ring, 0x0);
2787926deccbSFrançois Tigeot }
2788926deccbSFrançois Tigeot 
2789926deccbSFrançois Tigeot void cayman_dma_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm)
2790926deccbSFrançois Tigeot {
2791926deccbSFrançois Tigeot 	struct radeon_ring *ring = &rdev->ring[ridx];
2792926deccbSFrançois Tigeot 
2793926deccbSFrançois Tigeot 	if (vm == NULL)
2794926deccbSFrançois Tigeot 		return;
2795926deccbSFrançois Tigeot 
2796926deccbSFrançois Tigeot 	radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_SRBM_WRITE, 0, 0, 0));
2797926deccbSFrançois Tigeot 	radeon_ring_write(ring, (0xf << 16) | ((VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (vm->id << 2)) >> 2));
2798926deccbSFrançois Tigeot 	radeon_ring_write(ring, vm->pd_gpu_addr >> 12);
2799926deccbSFrançois Tigeot 
2800926deccbSFrançois Tigeot 	/* flush hdp cache */
2801926deccbSFrançois Tigeot 	radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_SRBM_WRITE, 0, 0, 0));
2802926deccbSFrançois Tigeot 	radeon_ring_write(ring, (0xf << 16) | (HDP_MEM_COHERENCY_FLUSH_CNTL >> 2));
2803926deccbSFrançois Tigeot 	radeon_ring_write(ring, 1);
2804926deccbSFrançois Tigeot 
2805926deccbSFrançois Tigeot 	/* bits 0-7 are the VM contexts0-7 */
2806926deccbSFrançois Tigeot 	radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_SRBM_WRITE, 0, 0, 0));
2807926deccbSFrançois Tigeot 	radeon_ring_write(ring, (0xf << 16) | (VM_INVALIDATE_REQUEST >> 2));
2808926deccbSFrançois Tigeot 	radeon_ring_write(ring, 1 << vm->id);
2809926deccbSFrançois Tigeot }
2810926deccbSFrançois Tigeot 
2811