1254885Sdumbbell/* 2254885Sdumbbell * Copyright 2010 Advanced Micro Devices, Inc. 3254885Sdumbbell * 4254885Sdumbbell * Permission is hereby granted, free of charge, to any person obtaining a 5254885Sdumbbell * copy of this software and associated documentation files (the "Software"), 6254885Sdumbbell * to deal in the Software without restriction, including without limitation 7254885Sdumbbell * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8254885Sdumbbell * and/or sell copies of the Software, and to permit persons to whom the 9254885Sdumbbell * Software is furnished to do so, subject to the following conditions: 10254885Sdumbbell * 11254885Sdumbbell * The above copyright notice and this permission notice shall be included in 12254885Sdumbbell * all copies or substantial portions of the Software. 13254885Sdumbbell * 14254885Sdumbbell * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15254885Sdumbbell * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16254885Sdumbbell * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17254885Sdumbbell * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18254885Sdumbbell * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19254885Sdumbbell * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20254885Sdumbbell * OTHER DEALINGS IN THE SOFTWARE. 21254885Sdumbbell * 22254885Sdumbbell * Authors: Alex Deucher 23254885Sdumbbell */ 24254885Sdumbbell 25254885Sdumbbell#include <sys/cdefs.h> 26254885Sdumbbell__FBSDID("$FreeBSD$"); 27254885Sdumbbell 28254885Sdumbbell#include <dev/drm2/drmP.h> 29254885Sdumbbell#include "radeon.h" 30254885Sdumbbell#include "radeon_asic.h" 31254885Sdumbbell#include <dev/drm2/radeon/radeon_drm.h> 32254885Sdumbbell#include "nid.h" 33254885Sdumbbell#include "atom.h" 34254885Sdumbbell#include "ni_reg.h" 35254885Sdumbbell#include "cayman_blit_shaders.h" 36254885Sdumbbell 37280183Sdumbbell#ifdef FREEBSD_WIP /* FreeBSD: to please GCC 4.2. */ 38280183Sdumbbellextern void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save); 39280183Sdumbbellextern void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save); 40280183Sdumbbellextern int evergreen_mc_wait_for_idle(struct radeon_device *rdev); 41280183Sdumbbellextern void evergreen_mc_program(struct radeon_device *rdev); 42280183Sdumbbellextern void evergreen_irq_suspend(struct radeon_device *rdev); 43280183Sdumbbellextern int evergreen_mc_init(struct radeon_device *rdev); 44280183Sdumbbellextern void evergreen_fix_pci_max_read_req_size(struct radeon_device *rdev); 45280183Sdumbbell#endif 46254885Sdumbbellextern void evergreen_pcie_gen2_enable(struct radeon_device *rdev); 47280183Sdumbbell#ifdef FREEBSD_WIP /* FreeBSD: to please GCC 4.2. */ 48280183Sdumbbellextern void si_rlc_fini(struct radeon_device *rdev); 49280183Sdumbbellextern int si_rlc_init(struct radeon_device *rdev); 50280183Sdumbbell#endif 51254885Sdumbbell 52254885Sdumbbell#define EVERGREEN_PFP_UCODE_SIZE 1120 53254885Sdumbbell#define EVERGREEN_PM4_UCODE_SIZE 1376 54254885Sdumbbell#define EVERGREEN_RLC_UCODE_SIZE 768 55254885Sdumbbell#define BTC_MC_UCODE_SIZE 6024 56254885Sdumbbell 57254885Sdumbbell#define CAYMAN_PFP_UCODE_SIZE 2176 58254885Sdumbbell#define CAYMAN_PM4_UCODE_SIZE 2176 59254885Sdumbbell#define CAYMAN_RLC_UCODE_SIZE 1024 60254885Sdumbbell#define CAYMAN_MC_UCODE_SIZE 6037 61254885Sdumbbell 62254885Sdumbbell#define ARUBA_RLC_UCODE_SIZE 1536 63254885Sdumbbell 64280183Sdumbbell#ifdef __linux__ 65280183Sdumbbell/* Firmware Names */ 66280183SdumbbellMODULE_FIRMWARE("radeon/BARTS_pfp.bin"); 67280183SdumbbellMODULE_FIRMWARE("radeon/BARTS_me.bin"); 68280183SdumbbellMODULE_FIRMWARE("radeon/BARTS_mc.bin"); 69280183SdumbbellMODULE_FIRMWARE("radeon/BTC_rlc.bin"); 70280183SdumbbellMODULE_FIRMWARE("radeon/TURKS_pfp.bin"); 71280183SdumbbellMODULE_FIRMWARE("radeon/TURKS_me.bin"); 72280183SdumbbellMODULE_FIRMWARE("radeon/TURKS_mc.bin"); 73280183SdumbbellMODULE_FIRMWARE("radeon/CAICOS_pfp.bin"); 74280183SdumbbellMODULE_FIRMWARE("radeon/CAICOS_me.bin"); 75280183SdumbbellMODULE_FIRMWARE("radeon/CAICOS_mc.bin"); 76280183SdumbbellMODULE_FIRMWARE("radeon/CAYMAN_pfp.bin"); 77280183SdumbbellMODULE_FIRMWARE("radeon/CAYMAN_me.bin"); 78280183SdumbbellMODULE_FIRMWARE("radeon/CAYMAN_mc.bin"); 79280183SdumbbellMODULE_FIRMWARE("radeon/CAYMAN_rlc.bin"); 80280183SdumbbellMODULE_FIRMWARE("radeon/ARUBA_pfp.bin"); 81280183SdumbbellMODULE_FIRMWARE("radeon/ARUBA_me.bin"); 82280183SdumbbellMODULE_FIRMWARE("radeon/ARUBA_rlc.bin"); 83280183Sdumbbell#endif 84280183Sdumbbell 85254885Sdumbbell#define BTC_IO_MC_REGS_SIZE 29 86254885Sdumbbell 87254885Sdumbbellstatic const u32 barts_io_mc_regs[BTC_IO_MC_REGS_SIZE][2] = { 88254885Sdumbbell {0x00000077, 0xff010100}, 89254885Sdumbbell {0x00000078, 0x00000000}, 90254885Sdumbbell {0x00000079, 0x00001434}, 91254885Sdumbbell {0x0000007a, 0xcc08ec08}, 92254885Sdumbbell {0x0000007b, 0x00040000}, 93254885Sdumbbell {0x0000007c, 0x000080c0}, 94254885Sdumbbell {0x0000007d, 0x09000000}, 95254885Sdumbbell {0x0000007e, 0x00210404}, 96254885Sdumbbell {0x00000081, 0x08a8e800}, 97254885Sdumbbell {0x00000082, 0x00030444}, 98254885Sdumbbell {0x00000083, 0x00000000}, 99254885Sdumbbell {0x00000085, 0x00000001}, 100254885Sdumbbell {0x00000086, 0x00000002}, 101254885Sdumbbell {0x00000087, 0x48490000}, 102254885Sdumbbell {0x00000088, 0x20244647}, 103254885Sdumbbell {0x00000089, 0x00000005}, 104254885Sdumbbell {0x0000008b, 0x66030000}, 105254885Sdumbbell {0x0000008c, 0x00006603}, 106254885Sdumbbell {0x0000008d, 0x00000100}, 107254885Sdumbbell {0x0000008f, 0x00001c0a}, 108254885Sdumbbell {0x00000090, 0xff000001}, 109254885Sdumbbell {0x00000094, 0x00101101}, 110254885Sdumbbell {0x00000095, 0x00000fff}, 111254885Sdumbbell {0x00000096, 0x00116fff}, 112254885Sdumbbell {0x00000097, 0x60010000}, 113254885Sdumbbell {0x00000098, 0x10010000}, 114254885Sdumbbell {0x00000099, 0x00006000}, 115254885Sdumbbell {0x0000009a, 0x00001000}, 116254885Sdumbbell {0x0000009f, 0x00946a00} 117254885Sdumbbell}; 118254885Sdumbbell 119254885Sdumbbellstatic const u32 turks_io_mc_regs[BTC_IO_MC_REGS_SIZE][2] = { 120254885Sdumbbell {0x00000077, 0xff010100}, 121254885Sdumbbell {0x00000078, 0x00000000}, 122254885Sdumbbell {0x00000079, 0x00001434}, 123254885Sdumbbell {0x0000007a, 0xcc08ec08}, 124254885Sdumbbell {0x0000007b, 0x00040000}, 125254885Sdumbbell {0x0000007c, 0x000080c0}, 126254885Sdumbbell {0x0000007d, 0x09000000}, 127254885Sdumbbell {0x0000007e, 0x00210404}, 128254885Sdumbbell {0x00000081, 0x08a8e800}, 129254885Sdumbbell {0x00000082, 0x00030444}, 130254885Sdumbbell {0x00000083, 0x00000000}, 131254885Sdumbbell {0x00000085, 0x00000001}, 132254885Sdumbbell {0x00000086, 0x00000002}, 133254885Sdumbbell {0x00000087, 0x48490000}, 134254885Sdumbbell {0x00000088, 0x20244647}, 135254885Sdumbbell {0x00000089, 0x00000005}, 136254885Sdumbbell {0x0000008b, 0x66030000}, 137254885Sdumbbell {0x0000008c, 0x00006603}, 138254885Sdumbbell {0x0000008d, 0x00000100}, 139254885Sdumbbell {0x0000008f, 0x00001c0a}, 140254885Sdumbbell {0x00000090, 0xff000001}, 141254885Sdumbbell {0x00000094, 0x00101101}, 142254885Sdumbbell {0x00000095, 0x00000fff}, 143254885Sdumbbell {0x00000096, 0x00116fff}, 144254885Sdumbbell {0x00000097, 0x60010000}, 145254885Sdumbbell {0x00000098, 0x10010000}, 146254885Sdumbbell {0x00000099, 0x00006000}, 147254885Sdumbbell {0x0000009a, 0x00001000}, 148254885Sdumbbell {0x0000009f, 0x00936a00} 149254885Sdumbbell}; 150254885Sdumbbell 151254885Sdumbbellstatic const u32 caicos_io_mc_regs[BTC_IO_MC_REGS_SIZE][2] = { 152254885Sdumbbell {0x00000077, 0xff010100}, 153254885Sdumbbell {0x00000078, 0x00000000}, 154254885Sdumbbell {0x00000079, 0x00001434}, 155254885Sdumbbell {0x0000007a, 0xcc08ec08}, 156254885Sdumbbell {0x0000007b, 0x00040000}, 157254885Sdumbbell {0x0000007c, 0x000080c0}, 158254885Sdumbbell {0x0000007d, 0x09000000}, 159254885Sdumbbell {0x0000007e, 0x00210404}, 160254885Sdumbbell {0x00000081, 0x08a8e800}, 161254885Sdumbbell {0x00000082, 0x00030444}, 162254885Sdumbbell {0x00000083, 0x00000000}, 163254885Sdumbbell {0x00000085, 0x00000001}, 164254885Sdumbbell {0x00000086, 0x00000002}, 165254885Sdumbbell {0x00000087, 0x48490000}, 166254885Sdumbbell {0x00000088, 0x20244647}, 167254885Sdumbbell {0x00000089, 0x00000005}, 168254885Sdumbbell {0x0000008b, 0x66030000}, 169254885Sdumbbell {0x0000008c, 0x00006603}, 170254885Sdumbbell {0x0000008d, 0x00000100}, 171254885Sdumbbell {0x0000008f, 0x00001c0a}, 172254885Sdumbbell {0x00000090, 0xff000001}, 173254885Sdumbbell {0x00000094, 0x00101101}, 174254885Sdumbbell {0x00000095, 0x00000fff}, 175254885Sdumbbell {0x00000096, 0x00116fff}, 176254885Sdumbbell {0x00000097, 0x60010000}, 177254885Sdumbbell {0x00000098, 0x10010000}, 178254885Sdumbbell {0x00000099, 0x00006000}, 179254885Sdumbbell {0x0000009a, 0x00001000}, 180254885Sdumbbell {0x0000009f, 0x00916a00} 181254885Sdumbbell}; 182254885Sdumbbell 183254885Sdumbbellstatic const u32 cayman_io_mc_regs[BTC_IO_MC_REGS_SIZE][2] = { 184254885Sdumbbell {0x00000077, 0xff010100}, 185254885Sdumbbell {0x00000078, 0x00000000}, 186254885Sdumbbell {0x00000079, 0x00001434}, 187254885Sdumbbell {0x0000007a, 0xcc08ec08}, 188254885Sdumbbell {0x0000007b, 0x00040000}, 189254885Sdumbbell {0x0000007c, 0x000080c0}, 190254885Sdumbbell {0x0000007d, 0x09000000}, 191254885Sdumbbell {0x0000007e, 0x00210404}, 192254885Sdumbbell {0x00000081, 0x08a8e800}, 193254885Sdumbbell {0x00000082, 0x00030444}, 194254885Sdumbbell {0x00000083, 0x00000000}, 195254885Sdumbbell {0x00000085, 0x00000001}, 196254885Sdumbbell {0x00000086, 0x00000002}, 197254885Sdumbbell {0x00000087, 0x48490000}, 198254885Sdumbbell {0x00000088, 0x20244647}, 199254885Sdumbbell {0x00000089, 0x00000005}, 200254885Sdumbbell {0x0000008b, 0x66030000}, 201254885Sdumbbell {0x0000008c, 0x00006603}, 202254885Sdumbbell {0x0000008d, 0x00000100}, 203254885Sdumbbell {0x0000008f, 0x00001c0a}, 204254885Sdumbbell {0x00000090, 0xff000001}, 205254885Sdumbbell {0x00000094, 0x00101101}, 206254885Sdumbbell {0x00000095, 0x00000fff}, 207254885Sdumbbell {0x00000096, 0x00116fff}, 208254885Sdumbbell {0x00000097, 0x60010000}, 209254885Sdumbbell {0x00000098, 0x10010000}, 210254885Sdumbbell {0x00000099, 0x00006000}, 211254885Sdumbbell {0x0000009a, 0x00001000}, 212254885Sdumbbell {0x0000009f, 0x00976b00} 213254885Sdumbbell}; 214254885Sdumbbell 215254885Sdumbbellint ni_mc_load_microcode(struct radeon_device *rdev) 216254885Sdumbbell{ 217254885Sdumbbell const __be32 *fw_data; 218254885Sdumbbell u32 mem_type, running, blackout = 0; 219278004Sdim const u32 *io_mc_regs; 220254885Sdumbbell int i, ucode_size, regs_size; 221254885Sdumbbell 222254885Sdumbbell if (!rdev->mc_fw) 223254885Sdumbbell return -EINVAL; 224254885Sdumbbell 225254885Sdumbbell switch (rdev->family) { 226254885Sdumbbell case CHIP_BARTS: 227278438Sdim io_mc_regs = &barts_io_mc_regs[0][0]; 228254885Sdumbbell ucode_size = BTC_MC_UCODE_SIZE; 229254885Sdumbbell regs_size = BTC_IO_MC_REGS_SIZE; 230254885Sdumbbell break; 231254885Sdumbbell case CHIP_TURKS: 232278438Sdim io_mc_regs = &turks_io_mc_regs[0][0]; 233254885Sdumbbell ucode_size = BTC_MC_UCODE_SIZE; 234254885Sdumbbell regs_size = BTC_IO_MC_REGS_SIZE; 235254885Sdumbbell break; 236254885Sdumbbell case CHIP_CAICOS: 237254885Sdumbbell default: 238278438Sdim io_mc_regs = &caicos_io_mc_regs[0][0]; 239254885Sdumbbell ucode_size = BTC_MC_UCODE_SIZE; 240254885Sdumbbell regs_size = BTC_IO_MC_REGS_SIZE; 241254885Sdumbbell break; 242254885Sdumbbell case CHIP_CAYMAN: 243278438Sdim io_mc_regs = &cayman_io_mc_regs[0][0]; 244254885Sdumbbell ucode_size = CAYMAN_MC_UCODE_SIZE; 245254885Sdumbbell regs_size = BTC_IO_MC_REGS_SIZE; 246254885Sdumbbell break; 247254885Sdumbbell } 248254885Sdumbbell 249254885Sdumbbell mem_type = (RREG32(MC_SEQ_MISC0) & MC_SEQ_MISC0_GDDR5_MASK) >> MC_SEQ_MISC0_GDDR5_SHIFT; 250254885Sdumbbell running = RREG32(MC_SEQ_SUP_CNTL) & RUN_MASK; 251254885Sdumbbell 252254885Sdumbbell if ((mem_type == MC_SEQ_MISC0_GDDR5_VALUE) && (running == 0)) { 253254885Sdumbbell if (running) { 254254885Sdumbbell blackout = RREG32(MC_SHARED_BLACKOUT_CNTL); 255254885Sdumbbell WREG32(MC_SHARED_BLACKOUT_CNTL, 1); 256254885Sdumbbell } 257254885Sdumbbell 258254885Sdumbbell /* reset the engine and set to writable */ 259254885Sdumbbell WREG32(MC_SEQ_SUP_CNTL, 0x00000008); 260254885Sdumbbell WREG32(MC_SEQ_SUP_CNTL, 0x00000010); 261254885Sdumbbell 262254885Sdumbbell /* load mc io regs */ 263254885Sdumbbell for (i = 0; i < regs_size; i++) { 264254885Sdumbbell WREG32(MC_SEQ_IO_DEBUG_INDEX, io_mc_regs[(i << 1)]); 265254885Sdumbbell WREG32(MC_SEQ_IO_DEBUG_DATA, io_mc_regs[(i << 1) + 1]); 266254885Sdumbbell } 267254885Sdumbbell /* load the MC ucode */ 268254885Sdumbbell fw_data = (const __be32 *)rdev->mc_fw->data; 269254885Sdumbbell for (i = 0; i < ucode_size; i++) 270254885Sdumbbell WREG32(MC_SEQ_SUP_PGM, be32_to_cpup(fw_data++)); 271254885Sdumbbell 272254885Sdumbbell /* put the engine back into the active state */ 273254885Sdumbbell WREG32(MC_SEQ_SUP_CNTL, 0x00000008); 274254885Sdumbbell WREG32(MC_SEQ_SUP_CNTL, 0x00000004); 275254885Sdumbbell WREG32(MC_SEQ_SUP_CNTL, 0x00000001); 276254885Sdumbbell 277254885Sdumbbell /* wait for training to complete */ 278254885Sdumbbell for (i = 0; i < rdev->usec_timeout; i++) { 279254885Sdumbbell if (RREG32(MC_IO_PAD_CNTL_D0) & MEM_FALL_OUT_CMD) 280254885Sdumbbell break; 281280183Sdumbbell udelay(1); 282254885Sdumbbell } 283254885Sdumbbell 284254885Sdumbbell if (running) 285254885Sdumbbell WREG32(MC_SHARED_BLACKOUT_CNTL, blackout); 286254885Sdumbbell } 287254885Sdumbbell 288254885Sdumbbell return 0; 289254885Sdumbbell} 290254885Sdumbbell 291254885Sdumbbellint ni_init_microcode(struct radeon_device *rdev) 292254885Sdumbbell{ 293254885Sdumbbell const char *chip_name; 294254885Sdumbbell const char *rlc_chip_name; 295254885Sdumbbell size_t pfp_req_size, me_req_size, rlc_req_size, mc_req_size; 296254885Sdumbbell char fw_name[30]; 297254885Sdumbbell int err; 298254885Sdumbbell 299254885Sdumbbell DRM_DEBUG("\n"); 300254885Sdumbbell 301254885Sdumbbell switch (rdev->family) { 302254885Sdumbbell case CHIP_BARTS: 303254885Sdumbbell chip_name = "BARTS"; 304254885Sdumbbell rlc_chip_name = "BTC"; 305254885Sdumbbell pfp_req_size = EVERGREEN_PFP_UCODE_SIZE * 4; 306254885Sdumbbell me_req_size = EVERGREEN_PM4_UCODE_SIZE * 4; 307254885Sdumbbell rlc_req_size = EVERGREEN_RLC_UCODE_SIZE * 4; 308254885Sdumbbell mc_req_size = BTC_MC_UCODE_SIZE * 4; 309254885Sdumbbell break; 310254885Sdumbbell case CHIP_TURKS: 311254885Sdumbbell chip_name = "TURKS"; 312254885Sdumbbell rlc_chip_name = "BTC"; 313254885Sdumbbell pfp_req_size = EVERGREEN_PFP_UCODE_SIZE * 4; 314254885Sdumbbell me_req_size = EVERGREEN_PM4_UCODE_SIZE * 4; 315254885Sdumbbell rlc_req_size = EVERGREEN_RLC_UCODE_SIZE * 4; 316254885Sdumbbell mc_req_size = BTC_MC_UCODE_SIZE * 4; 317254885Sdumbbell break; 318254885Sdumbbell case CHIP_CAICOS: 319254885Sdumbbell chip_name = "CAICOS"; 320254885Sdumbbell rlc_chip_name = "BTC"; 321254885Sdumbbell pfp_req_size = EVERGREEN_PFP_UCODE_SIZE * 4; 322254885Sdumbbell me_req_size = EVERGREEN_PM4_UCODE_SIZE * 4; 323254885Sdumbbell rlc_req_size = EVERGREEN_RLC_UCODE_SIZE * 4; 324254885Sdumbbell mc_req_size = BTC_MC_UCODE_SIZE * 4; 325254885Sdumbbell break; 326254885Sdumbbell case CHIP_CAYMAN: 327254885Sdumbbell chip_name = "CAYMAN"; 328254885Sdumbbell rlc_chip_name = "CAYMAN"; 329254885Sdumbbell pfp_req_size = CAYMAN_PFP_UCODE_SIZE * 4; 330254885Sdumbbell me_req_size = CAYMAN_PM4_UCODE_SIZE * 4; 331254885Sdumbbell rlc_req_size = CAYMAN_RLC_UCODE_SIZE * 4; 332254885Sdumbbell mc_req_size = CAYMAN_MC_UCODE_SIZE * 4; 333254885Sdumbbell break; 334254885Sdumbbell case CHIP_ARUBA: 335254885Sdumbbell chip_name = "ARUBA"; 336254885Sdumbbell rlc_chip_name = "ARUBA"; 337254885Sdumbbell /* pfp/me same size as CAYMAN */ 338254885Sdumbbell pfp_req_size = CAYMAN_PFP_UCODE_SIZE * 4; 339254885Sdumbbell me_req_size = CAYMAN_PM4_UCODE_SIZE * 4; 340254885Sdumbbell rlc_req_size = ARUBA_RLC_UCODE_SIZE * 4; 341254885Sdumbbell mc_req_size = 0; 342254885Sdumbbell break; 343254885Sdumbbell default: panic("%s: Unsupported family %d", __func__, rdev->family); 344254885Sdumbbell } 345254885Sdumbbell 346254885Sdumbbell DRM_INFO("Loading %s Microcode\n", chip_name); 347254885Sdumbbell err = 0; 348254885Sdumbbell 349254885Sdumbbell snprintf(fw_name, sizeof(fw_name), "radeonkmsfw_%s_pfp", chip_name); 350254885Sdumbbell rdev->pfp_fw = firmware_get(fw_name); 351254885Sdumbbell if (rdev->pfp_fw == NULL) { 352254885Sdumbbell err = -ENOENT; 353254885Sdumbbell goto out; 354254885Sdumbbell } 355254885Sdumbbell if (rdev->pfp_fw->datasize != pfp_req_size) { 356254885Sdumbbell DRM_ERROR( 357254885Sdumbbell "ni_cp: Bogus length %zu in firmware \"%s\"\n", 358254885Sdumbbell rdev->pfp_fw->datasize, fw_name); 359254885Sdumbbell err = -EINVAL; 360254885Sdumbbell goto out; 361254885Sdumbbell } 362254885Sdumbbell 363254885Sdumbbell snprintf(fw_name, sizeof(fw_name), "radeonkmsfw_%s_me", chip_name); 364254885Sdumbbell rdev->me_fw = firmware_get(fw_name); 365254885Sdumbbell if (rdev->me_fw == NULL) { 366254885Sdumbbell err = -ENOENT; 367254885Sdumbbell goto out; 368254885Sdumbbell } 369254885Sdumbbell if (rdev->me_fw->datasize != me_req_size) { 370254885Sdumbbell DRM_ERROR( 371254885Sdumbbell "ni_cp: Bogus length %zu in firmware \"%s\"\n", 372254885Sdumbbell rdev->me_fw->datasize, fw_name); 373254885Sdumbbell err = -EINVAL; 374254885Sdumbbell } 375254885Sdumbbell 376254885Sdumbbell snprintf(fw_name, sizeof(fw_name), "radeonkmsfw_%s_rlc", rlc_chip_name); 377254885Sdumbbell rdev->rlc_fw = firmware_get(fw_name); 378254885Sdumbbell if (rdev->rlc_fw == NULL) { 379254885Sdumbbell err = -ENOENT; 380254885Sdumbbell goto out; 381254885Sdumbbell } 382254885Sdumbbell if (rdev->rlc_fw->datasize != rlc_req_size) { 383254885Sdumbbell DRM_ERROR( 384254885Sdumbbell "ni_rlc: Bogus length %zu in firmware \"%s\"\n", 385254885Sdumbbell rdev->rlc_fw->datasize, fw_name); 386254885Sdumbbell err = -EINVAL; 387254885Sdumbbell } 388254885Sdumbbell 389254885Sdumbbell /* no MC ucode on TN */ 390254885Sdumbbell if (!(rdev->flags & RADEON_IS_IGP)) { 391254885Sdumbbell snprintf(fw_name, sizeof(fw_name), "radeonkmsfw_%s_mc", chip_name); 392254885Sdumbbell rdev->mc_fw = firmware_get(fw_name); 393254885Sdumbbell if (rdev->mc_fw == NULL) { 394254885Sdumbbell err = -ENOENT; 395254885Sdumbbell goto out; 396254885Sdumbbell } 397254885Sdumbbell if (rdev->mc_fw->datasize != mc_req_size) { 398254885Sdumbbell DRM_ERROR( 399254885Sdumbbell "ni_mc: Bogus length %zu in firmware \"%s\"\n", 400254885Sdumbbell rdev->mc_fw->datasize, fw_name); 401254885Sdumbbell err = -EINVAL; 402254885Sdumbbell } 403254885Sdumbbell } 404254885Sdumbbellout: 405254885Sdumbbell if (err) { 406254885Sdumbbell if (err != -EINVAL) 407254885Sdumbbell DRM_ERROR( 408254885Sdumbbell "ni_cp: Failed to load firmware \"%s\"\n", 409254885Sdumbbell fw_name); 410254885Sdumbbell if (rdev->pfp_fw != NULL) { 411254885Sdumbbell firmware_put(rdev->pfp_fw, FIRMWARE_UNLOAD); 412254885Sdumbbell rdev->pfp_fw = NULL; 413254885Sdumbbell } 414254885Sdumbbell if (rdev->me_fw != NULL) { 415254885Sdumbbell firmware_put(rdev->me_fw, FIRMWARE_UNLOAD); 416254885Sdumbbell rdev->me_fw = NULL; 417254885Sdumbbell } 418254885Sdumbbell if (rdev->rlc_fw != NULL) { 419254885Sdumbbell firmware_put(rdev->rlc_fw, FIRMWARE_UNLOAD); 420254885Sdumbbell rdev->rlc_fw = NULL; 421254885Sdumbbell } 422254885Sdumbbell if (rdev->mc_fw != NULL) { 423254885Sdumbbell firmware_put(rdev->mc_fw, FIRMWARE_UNLOAD); 424254885Sdumbbell rdev->mc_fw = NULL; 425254885Sdumbbell } 426254885Sdumbbell } 427254885Sdumbbell return err; 428254885Sdumbbell} 429254885Sdumbbell 430254885Sdumbbell/** 431254885Sdumbbell * ni_fini_microcode - drop the firmwares image references 432254885Sdumbbell * 433254885Sdumbbell * @rdev: radeon_device pointer 434254885Sdumbbell * 435254885Sdumbbell * Drop the pfp, me, mc and rlc firmwares image references. 436254885Sdumbbell * Called at driver shutdown. 437254885Sdumbbell */ 438254885Sdumbbellvoid ni_fini_microcode(struct radeon_device *rdev) 439254885Sdumbbell{ 440254885Sdumbbell 441254885Sdumbbell if (rdev->pfp_fw != NULL) { 442254885Sdumbbell firmware_put(rdev->pfp_fw, FIRMWARE_UNLOAD); 443254885Sdumbbell rdev->pfp_fw = NULL; 444254885Sdumbbell } 445254885Sdumbbell 446254885Sdumbbell if (rdev->me_fw != NULL) { 447254885Sdumbbell firmware_put(rdev->me_fw, FIRMWARE_UNLOAD); 448254885Sdumbbell rdev->me_fw = NULL; 449254885Sdumbbell } 450254885Sdumbbell 451254885Sdumbbell if (rdev->rlc_fw != NULL) { 452254885Sdumbbell firmware_put(rdev->rlc_fw, FIRMWARE_UNLOAD); 453254885Sdumbbell rdev->rlc_fw = NULL; 454254885Sdumbbell } 455254885Sdumbbell 456254885Sdumbbell if (rdev->mc_fw != NULL) { 457254885Sdumbbell firmware_put(rdev->mc_fw, FIRMWARE_UNLOAD); 458254885Sdumbbell rdev->mc_fw = NULL; 459254885Sdumbbell } 460254885Sdumbbell} 461254885Sdumbbell 462254885Sdumbbell 463254885Sdumbbell/* 464254885Sdumbbell * Core functions 465254885Sdumbbell */ 466254885Sdumbbellstatic void cayman_gpu_init(struct radeon_device *rdev) 467254885Sdumbbell{ 468254885Sdumbbell u32 gb_addr_config = 0; 469254885Sdumbbell u32 mc_shared_chmap, mc_arb_ramcfg; 470254885Sdumbbell u32 cgts_tcc_disable; 471254885Sdumbbell u32 sx_debug_1; 472254885Sdumbbell u32 smx_dc_ctl0; 473254885Sdumbbell u32 cgts_sm_ctrl_reg; 474254885Sdumbbell u32 hdp_host_path_cntl; 475254885Sdumbbell u32 tmp; 476254885Sdumbbell u32 disabled_rb_mask; 477254885Sdumbbell int i, j; 478254885Sdumbbell 479254885Sdumbbell switch (rdev->family) { 480254885Sdumbbell case CHIP_CAYMAN: 481254885Sdumbbell rdev->config.cayman.max_shader_engines = 2; 482254885Sdumbbell rdev->config.cayman.max_pipes_per_simd = 4; 483254885Sdumbbell rdev->config.cayman.max_tile_pipes = 8; 484254885Sdumbbell rdev->config.cayman.max_simds_per_se = 12; 485254885Sdumbbell rdev->config.cayman.max_backends_per_se = 4; 486254885Sdumbbell rdev->config.cayman.max_texture_channel_caches = 8; 487254885Sdumbbell rdev->config.cayman.max_gprs = 256; 488254885Sdumbbell rdev->config.cayman.max_threads = 256; 489254885Sdumbbell rdev->config.cayman.max_gs_threads = 32; 490254885Sdumbbell rdev->config.cayman.max_stack_entries = 512; 491254885Sdumbbell rdev->config.cayman.sx_num_of_sets = 8; 492254885Sdumbbell rdev->config.cayman.sx_max_export_size = 256; 493254885Sdumbbell rdev->config.cayman.sx_max_export_pos_size = 64; 494254885Sdumbbell rdev->config.cayman.sx_max_export_smx_size = 192; 495254885Sdumbbell rdev->config.cayman.max_hw_contexts = 8; 496254885Sdumbbell rdev->config.cayman.sq_num_cf_insts = 2; 497254885Sdumbbell 498254885Sdumbbell rdev->config.cayman.sc_prim_fifo_size = 0x100; 499254885Sdumbbell rdev->config.cayman.sc_hiz_tile_fifo_size = 0x30; 500254885Sdumbbell rdev->config.cayman.sc_earlyz_tile_fifo_size = 0x130; 501254885Sdumbbell gb_addr_config = CAYMAN_GB_ADDR_CONFIG_GOLDEN; 502254885Sdumbbell break; 503254885Sdumbbell case CHIP_ARUBA: 504254885Sdumbbell default: 505254885Sdumbbell rdev->config.cayman.max_shader_engines = 1; 506254885Sdumbbell rdev->config.cayman.max_pipes_per_simd = 4; 507254885Sdumbbell rdev->config.cayman.max_tile_pipes = 2; 508254885Sdumbbell if ((rdev->ddev->pci_device == 0x9900) || 509254885Sdumbbell (rdev->ddev->pci_device == 0x9901) || 510254885Sdumbbell (rdev->ddev->pci_device == 0x9905) || 511254885Sdumbbell (rdev->ddev->pci_device == 0x9906) || 512254885Sdumbbell (rdev->ddev->pci_device == 0x9907) || 513254885Sdumbbell (rdev->ddev->pci_device == 0x9908) || 514254885Sdumbbell (rdev->ddev->pci_device == 0x9909) || 515280183Sdumbbell (rdev->ddev->pci_device == 0x990B) || 516280183Sdumbbell (rdev->ddev->pci_device == 0x990C) || 517280183Sdumbbell (rdev->ddev->pci_device == 0x990F) || 518254885Sdumbbell (rdev->ddev->pci_device == 0x9910) || 519280183Sdumbbell (rdev->ddev->pci_device == 0x9917) || 520280183Sdumbbell (rdev->ddev->pci_device == 0x9999) || 521280183Sdumbbell (rdev->ddev->pci_device == 0x999C)) { 522254885Sdumbbell rdev->config.cayman.max_simds_per_se = 6; 523254885Sdumbbell rdev->config.cayman.max_backends_per_se = 2; 524254885Sdumbbell } else if ((rdev->ddev->pci_device == 0x9903) || 525254885Sdumbbell (rdev->ddev->pci_device == 0x9904) || 526254885Sdumbbell (rdev->ddev->pci_device == 0x990A) || 527280183Sdumbbell (rdev->ddev->pci_device == 0x990D) || 528280183Sdumbbell (rdev->ddev->pci_device == 0x990E) || 529254885Sdumbbell (rdev->ddev->pci_device == 0x9913) || 530280183Sdumbbell (rdev->ddev->pci_device == 0x9918) || 531280183Sdumbbell (rdev->ddev->pci_device == 0x999D)) { 532254885Sdumbbell rdev->config.cayman.max_simds_per_se = 4; 533254885Sdumbbell rdev->config.cayman.max_backends_per_se = 2; 534254885Sdumbbell } else if ((rdev->ddev->pci_device == 0x9919) || 535254885Sdumbbell (rdev->ddev->pci_device == 0x9990) || 536254885Sdumbbell (rdev->ddev->pci_device == 0x9991) || 537254885Sdumbbell (rdev->ddev->pci_device == 0x9994) || 538280183Sdumbbell (rdev->ddev->pci_device == 0x9995) || 539280183Sdumbbell (rdev->ddev->pci_device == 0x9996) || 540280183Sdumbbell (rdev->ddev->pci_device == 0x999A) || 541254885Sdumbbell (rdev->ddev->pci_device == 0x99A0)) { 542254885Sdumbbell rdev->config.cayman.max_simds_per_se = 3; 543254885Sdumbbell rdev->config.cayman.max_backends_per_se = 1; 544254885Sdumbbell } else { 545254885Sdumbbell rdev->config.cayman.max_simds_per_se = 2; 546254885Sdumbbell rdev->config.cayman.max_backends_per_se = 1; 547254885Sdumbbell } 548254885Sdumbbell rdev->config.cayman.max_texture_channel_caches = 2; 549254885Sdumbbell rdev->config.cayman.max_gprs = 256; 550254885Sdumbbell rdev->config.cayman.max_threads = 256; 551254885Sdumbbell rdev->config.cayman.max_gs_threads = 32; 552254885Sdumbbell rdev->config.cayman.max_stack_entries = 512; 553254885Sdumbbell rdev->config.cayman.sx_num_of_sets = 8; 554254885Sdumbbell rdev->config.cayman.sx_max_export_size = 256; 555254885Sdumbbell rdev->config.cayman.sx_max_export_pos_size = 64; 556254885Sdumbbell rdev->config.cayman.sx_max_export_smx_size = 192; 557254885Sdumbbell rdev->config.cayman.max_hw_contexts = 8; 558254885Sdumbbell rdev->config.cayman.sq_num_cf_insts = 2; 559254885Sdumbbell 560254885Sdumbbell rdev->config.cayman.sc_prim_fifo_size = 0x40; 561254885Sdumbbell rdev->config.cayman.sc_hiz_tile_fifo_size = 0x30; 562254885Sdumbbell rdev->config.cayman.sc_earlyz_tile_fifo_size = 0x130; 563254885Sdumbbell gb_addr_config = ARUBA_GB_ADDR_CONFIG_GOLDEN; 564254885Sdumbbell break; 565254885Sdumbbell } 566254885Sdumbbell 567254885Sdumbbell /* Initialize HDP */ 568254885Sdumbbell for (i = 0, j = 0; i < 32; i++, j += 0x18) { 569254885Sdumbbell WREG32((0x2c14 + j), 0x00000000); 570254885Sdumbbell WREG32((0x2c18 + j), 0x00000000); 571254885Sdumbbell WREG32((0x2c1c + j), 0x00000000); 572254885Sdumbbell WREG32((0x2c20 + j), 0x00000000); 573254885Sdumbbell WREG32((0x2c24 + j), 0x00000000); 574254885Sdumbbell } 575254885Sdumbbell 576254885Sdumbbell WREG32(GRBM_CNTL, GRBM_READ_TIMEOUT(0xff)); 577254885Sdumbbell 578254885Sdumbbell evergreen_fix_pci_max_read_req_size(rdev); 579254885Sdumbbell 580254885Sdumbbell mc_shared_chmap = RREG32(MC_SHARED_CHMAP); 581254885Sdumbbell mc_arb_ramcfg = RREG32(MC_ARB_RAMCFG); 582254885Sdumbbell 583254885Sdumbbell tmp = (mc_arb_ramcfg & NOOFCOLS_MASK) >> NOOFCOLS_SHIFT; 584254885Sdumbbell rdev->config.cayman.mem_row_size_in_kb = (4 * (1 << (8 + tmp))) / 1024; 585254885Sdumbbell if (rdev->config.cayman.mem_row_size_in_kb > 4) 586254885Sdumbbell rdev->config.cayman.mem_row_size_in_kb = 4; 587254885Sdumbbell /* XXX use MC settings? */ 588254885Sdumbbell rdev->config.cayman.shader_engine_tile_size = 32; 589254885Sdumbbell rdev->config.cayman.num_gpus = 1; 590254885Sdumbbell rdev->config.cayman.multi_gpu_tile_size = 64; 591254885Sdumbbell 592254885Sdumbbell tmp = (gb_addr_config & NUM_PIPES_MASK) >> NUM_PIPES_SHIFT; 593254885Sdumbbell rdev->config.cayman.num_tile_pipes = (1 << tmp); 594254885Sdumbbell tmp = (gb_addr_config & PIPE_INTERLEAVE_SIZE_MASK) >> PIPE_INTERLEAVE_SIZE_SHIFT; 595254885Sdumbbell rdev->config.cayman.mem_max_burst_length_bytes = (tmp + 1) * 256; 596254885Sdumbbell tmp = (gb_addr_config & NUM_SHADER_ENGINES_MASK) >> NUM_SHADER_ENGINES_SHIFT; 597254885Sdumbbell rdev->config.cayman.num_shader_engines = tmp + 1; 598254885Sdumbbell tmp = (gb_addr_config & NUM_GPUS_MASK) >> NUM_GPUS_SHIFT; 599254885Sdumbbell rdev->config.cayman.num_gpus = tmp + 1; 600254885Sdumbbell tmp = (gb_addr_config & MULTI_GPU_TILE_SIZE_MASK) >> MULTI_GPU_TILE_SIZE_SHIFT; 601254885Sdumbbell rdev->config.cayman.multi_gpu_tile_size = 1 << tmp; 602254885Sdumbbell tmp = (gb_addr_config & ROW_SIZE_MASK) >> ROW_SIZE_SHIFT; 603254885Sdumbbell rdev->config.cayman.mem_row_size_in_kb = 1 << tmp; 604254885Sdumbbell 605254885Sdumbbell 606254885Sdumbbell /* setup tiling info dword. gb_addr_config is not adequate since it does 607254885Sdumbbell * not have bank info, so create a custom tiling dword. 608254885Sdumbbell * bits 3:0 num_pipes 609254885Sdumbbell * bits 7:4 num_banks 610254885Sdumbbell * bits 11:8 group_size 611254885Sdumbbell * bits 15:12 row_size 612254885Sdumbbell */ 613254885Sdumbbell rdev->config.cayman.tile_config = 0; 614254885Sdumbbell switch (rdev->config.cayman.num_tile_pipes) { 615254885Sdumbbell case 1: 616254885Sdumbbell default: 617254885Sdumbbell rdev->config.cayman.tile_config |= (0 << 0); 618254885Sdumbbell break; 619254885Sdumbbell case 2: 620254885Sdumbbell rdev->config.cayman.tile_config |= (1 << 0); 621254885Sdumbbell break; 622254885Sdumbbell case 4: 623254885Sdumbbell rdev->config.cayman.tile_config |= (2 << 0); 624254885Sdumbbell break; 625254885Sdumbbell case 8: 626254885Sdumbbell rdev->config.cayman.tile_config |= (3 << 0); 627254885Sdumbbell break; 628254885Sdumbbell } 629254885Sdumbbell 630254885Sdumbbell /* num banks is 8 on all fusion asics. 0 = 4, 1 = 8, 2 = 16 */ 631254885Sdumbbell if (rdev->flags & RADEON_IS_IGP) 632254885Sdumbbell rdev->config.cayman.tile_config |= 1 << 4; 633254885Sdumbbell else { 634254885Sdumbbell switch ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) { 635254885Sdumbbell case 0: /* four banks */ 636254885Sdumbbell rdev->config.cayman.tile_config |= 0 << 4; 637254885Sdumbbell break; 638254885Sdumbbell case 1: /* eight banks */ 639254885Sdumbbell rdev->config.cayman.tile_config |= 1 << 4; 640254885Sdumbbell break; 641254885Sdumbbell case 2: /* sixteen banks */ 642254885Sdumbbell default: 643254885Sdumbbell rdev->config.cayman.tile_config |= 2 << 4; 644254885Sdumbbell break; 645254885Sdumbbell } 646254885Sdumbbell } 647254885Sdumbbell rdev->config.cayman.tile_config |= 648254885Sdumbbell ((gb_addr_config & PIPE_INTERLEAVE_SIZE_MASK) >> PIPE_INTERLEAVE_SIZE_SHIFT) << 8; 649254885Sdumbbell rdev->config.cayman.tile_config |= 650254885Sdumbbell ((gb_addr_config & ROW_SIZE_MASK) >> ROW_SIZE_SHIFT) << 12; 651254885Sdumbbell 652254885Sdumbbell tmp = 0; 653254885Sdumbbell for (i = (rdev->config.cayman.max_shader_engines - 1); i >= 0; i--) { 654254885Sdumbbell u32 rb_disable_bitmap; 655254885Sdumbbell 656254885Sdumbbell WREG32(GRBM_GFX_INDEX, INSTANCE_BROADCAST_WRITES | SE_INDEX(i)); 657254885Sdumbbell WREG32(RLC_GFX_INDEX, INSTANCE_BROADCAST_WRITES | SE_INDEX(i)); 658254885Sdumbbell rb_disable_bitmap = (RREG32(CC_RB_BACKEND_DISABLE) & 0x00ff0000) >> 16; 659254885Sdumbbell tmp <<= 4; 660254885Sdumbbell tmp |= rb_disable_bitmap; 661254885Sdumbbell } 662254885Sdumbbell /* enabled rb are just the one not disabled :) */ 663254885Sdumbbell disabled_rb_mask = tmp; 664254885Sdumbbell 665254885Sdumbbell WREG32(GRBM_GFX_INDEX, INSTANCE_BROADCAST_WRITES | SE_BROADCAST_WRITES); 666254885Sdumbbell WREG32(RLC_GFX_INDEX, INSTANCE_BROADCAST_WRITES | SE_BROADCAST_WRITES); 667254885Sdumbbell 668254885Sdumbbell WREG32(GB_ADDR_CONFIG, gb_addr_config); 669254885Sdumbbell WREG32(DMIF_ADDR_CONFIG, gb_addr_config); 670280183Sdumbbell if (ASIC_IS_DCE6(rdev)) 671280183Sdumbbell WREG32(DMIF_ADDR_CALC, gb_addr_config); 672254885Sdumbbell WREG32(HDP_ADDR_CONFIG, gb_addr_config); 673254885Sdumbbell WREG32(DMA_TILING_CONFIG + DMA0_REGISTER_OFFSET, gb_addr_config); 674254885Sdumbbell WREG32(DMA_TILING_CONFIG + DMA1_REGISTER_OFFSET, gb_addr_config); 675254885Sdumbbell 676280183Sdumbbell if ((rdev->config.cayman.max_backends_per_se == 1) && 677280183Sdumbbell (rdev->flags & RADEON_IS_IGP)) { 678280183Sdumbbell if ((disabled_rb_mask & 3) == 1) { 679280183Sdumbbell /* RB0 disabled, RB1 enabled */ 680280183Sdumbbell tmp = 0x11111111; 681280183Sdumbbell } else { 682280183Sdumbbell /* RB1 disabled, RB0 enabled */ 683280183Sdumbbell tmp = 0x00000000; 684280183Sdumbbell } 685280183Sdumbbell } else { 686280183Sdumbbell tmp = gb_addr_config & NUM_PIPES_MASK; 687280183Sdumbbell tmp = r6xx_remap_render_backend(rdev, tmp, 688280183Sdumbbell rdev->config.cayman.max_backends_per_se * 689280183Sdumbbell rdev->config.cayman.max_shader_engines, 690280183Sdumbbell CAYMAN_MAX_BACKENDS, disabled_rb_mask); 691280183Sdumbbell } 692254885Sdumbbell WREG32(GB_BACKEND_MAP, tmp); 693254885Sdumbbell 694254885Sdumbbell cgts_tcc_disable = 0xffff0000; 695254885Sdumbbell for (i = 0; i < rdev->config.cayman.max_texture_channel_caches; i++) 696254885Sdumbbell cgts_tcc_disable &= ~(1 << (16 + i)); 697254885Sdumbbell WREG32(CGTS_TCC_DISABLE, cgts_tcc_disable); 698254885Sdumbbell WREG32(CGTS_SYS_TCC_DISABLE, cgts_tcc_disable); 699254885Sdumbbell WREG32(CGTS_USER_SYS_TCC_DISABLE, cgts_tcc_disable); 700254885Sdumbbell WREG32(CGTS_USER_TCC_DISABLE, cgts_tcc_disable); 701254885Sdumbbell 702254885Sdumbbell /* reprogram the shader complex */ 703254885Sdumbbell cgts_sm_ctrl_reg = RREG32(CGTS_SM_CTRL_REG); 704254885Sdumbbell for (i = 0; i < 16; i++) 705254885Sdumbbell WREG32(CGTS_SM_CTRL_REG, OVERRIDE); 706254885Sdumbbell WREG32(CGTS_SM_CTRL_REG, cgts_sm_ctrl_reg); 707254885Sdumbbell 708254885Sdumbbell /* set HW defaults for 3D engine */ 709254885Sdumbbell WREG32(CP_MEQ_THRESHOLDS, MEQ1_START(0x30) | MEQ2_START(0x60)); 710254885Sdumbbell 711254885Sdumbbell sx_debug_1 = RREG32(SX_DEBUG_1); 712254885Sdumbbell sx_debug_1 |= ENABLE_NEW_SMX_ADDRESS; 713254885Sdumbbell WREG32(SX_DEBUG_1, sx_debug_1); 714254885Sdumbbell 715254885Sdumbbell smx_dc_ctl0 = RREG32(SMX_DC_CTL0); 716254885Sdumbbell smx_dc_ctl0 &= ~NUMBER_OF_SETS(0x1ff); 717254885Sdumbbell smx_dc_ctl0 |= NUMBER_OF_SETS(rdev->config.cayman.sx_num_of_sets); 718254885Sdumbbell WREG32(SMX_DC_CTL0, smx_dc_ctl0); 719254885Sdumbbell 720254885Sdumbbell WREG32(SPI_CONFIG_CNTL_1, VTX_DONE_DELAY(4) | CRC_SIMD_ID_WADDR_DISABLE); 721254885Sdumbbell 722254885Sdumbbell /* need to be explicitly zero-ed */ 723254885Sdumbbell WREG32(VGT_OFFCHIP_LDS_BASE, 0); 724254885Sdumbbell WREG32(SQ_LSTMP_RING_BASE, 0); 725254885Sdumbbell WREG32(SQ_HSTMP_RING_BASE, 0); 726254885Sdumbbell WREG32(SQ_ESTMP_RING_BASE, 0); 727254885Sdumbbell WREG32(SQ_GSTMP_RING_BASE, 0); 728254885Sdumbbell WREG32(SQ_VSTMP_RING_BASE, 0); 729254885Sdumbbell WREG32(SQ_PSTMP_RING_BASE, 0); 730254885Sdumbbell 731254885Sdumbbell WREG32(TA_CNTL_AUX, DISABLE_CUBE_ANISO); 732254885Sdumbbell 733254885Sdumbbell WREG32(SX_EXPORT_BUFFER_SIZES, (COLOR_BUFFER_SIZE((rdev->config.cayman.sx_max_export_size / 4) - 1) | 734254885Sdumbbell POSITION_BUFFER_SIZE((rdev->config.cayman.sx_max_export_pos_size / 4) - 1) | 735254885Sdumbbell SMX_BUFFER_SIZE((rdev->config.cayman.sx_max_export_smx_size / 4) - 1))); 736254885Sdumbbell 737254885Sdumbbell WREG32(PA_SC_FIFO_SIZE, (SC_PRIM_FIFO_SIZE(rdev->config.cayman.sc_prim_fifo_size) | 738254885Sdumbbell SC_HIZ_TILE_FIFO_SIZE(rdev->config.cayman.sc_hiz_tile_fifo_size) | 739254885Sdumbbell SC_EARLYZ_TILE_FIFO_SIZE(rdev->config.cayman.sc_earlyz_tile_fifo_size))); 740254885Sdumbbell 741254885Sdumbbell 742254885Sdumbbell WREG32(VGT_NUM_INSTANCES, 1); 743254885Sdumbbell 744254885Sdumbbell WREG32(CP_PERFMON_CNTL, 0); 745254885Sdumbbell 746254885Sdumbbell WREG32(SQ_MS_FIFO_SIZES, (CACHE_FIFO_SIZE(16 * rdev->config.cayman.sq_num_cf_insts) | 747254885Sdumbbell FETCH_FIFO_HIWATER(0x4) | 748254885Sdumbbell DONE_FIFO_HIWATER(0xe0) | 749254885Sdumbbell ALU_UPDATE_FIFO_HIWATER(0x8))); 750254885Sdumbbell 751254885Sdumbbell WREG32(SQ_GPR_RESOURCE_MGMT_1, NUM_CLAUSE_TEMP_GPRS(4)); 752254885Sdumbbell WREG32(SQ_CONFIG, (VC_ENABLE | 753254885Sdumbbell EXPORT_SRC_C | 754254885Sdumbbell GFX_PRIO(0) | 755254885Sdumbbell CS1_PRIO(0) | 756254885Sdumbbell CS2_PRIO(1))); 757254885Sdumbbell WREG32(SQ_DYN_GPR_CNTL_PS_FLUSH_REQ, DYN_GPR_ENABLE); 758254885Sdumbbell 759254885Sdumbbell WREG32(PA_SC_FORCE_EOV_MAX_CNTS, (FORCE_EOV_MAX_CLK_CNT(4095) | 760254885Sdumbbell FORCE_EOV_MAX_REZ_CNT(255))); 761254885Sdumbbell 762254885Sdumbbell WREG32(VGT_CACHE_INVALIDATION, CACHE_INVALIDATION(VC_AND_TC) | 763254885Sdumbbell AUTO_INVLD_EN(ES_AND_GS_AUTO)); 764254885Sdumbbell 765254885Sdumbbell WREG32(VGT_GS_VERTEX_REUSE, 16); 766254885Sdumbbell WREG32(PA_SC_LINE_STIPPLE_STATE, 0); 767254885Sdumbbell 768254885Sdumbbell WREG32(CB_PERF_CTR0_SEL_0, 0); 769254885Sdumbbell WREG32(CB_PERF_CTR0_SEL_1, 0); 770254885Sdumbbell WREG32(CB_PERF_CTR1_SEL_0, 0); 771254885Sdumbbell WREG32(CB_PERF_CTR1_SEL_1, 0); 772254885Sdumbbell WREG32(CB_PERF_CTR2_SEL_0, 0); 773254885Sdumbbell WREG32(CB_PERF_CTR2_SEL_1, 0); 774254885Sdumbbell WREG32(CB_PERF_CTR3_SEL_0, 0); 775254885Sdumbbell WREG32(CB_PERF_CTR3_SEL_1, 0); 776254885Sdumbbell 777254885Sdumbbell tmp = RREG32(HDP_MISC_CNTL); 778254885Sdumbbell tmp |= HDP_FLUSH_INVALIDATE_CACHE; 779254885Sdumbbell WREG32(HDP_MISC_CNTL, tmp); 780254885Sdumbbell 781254885Sdumbbell hdp_host_path_cntl = RREG32(HDP_HOST_PATH_CNTL); 782254885Sdumbbell WREG32(HDP_HOST_PATH_CNTL, hdp_host_path_cntl); 783254885Sdumbbell 784254885Sdumbbell WREG32(PA_CL_ENHANCE, CLIP_VTX_REORDER_ENA | NUM_CLIP_SEQ(3)); 785254885Sdumbbell 786280183Sdumbbell udelay(50); 787254885Sdumbbell} 788254885Sdumbbell 789254885Sdumbbell/* 790254885Sdumbbell * GART 791254885Sdumbbell */ 792254885Sdumbbellvoid cayman_pcie_gart_tlb_flush(struct radeon_device *rdev) 793254885Sdumbbell{ 794254885Sdumbbell /* flush hdp cache */ 795254885Sdumbbell WREG32(HDP_MEM_COHERENCY_FLUSH_CNTL, 0x1); 796254885Sdumbbell 797254885Sdumbbell /* bits 0-7 are the VM contexts0-7 */ 798254885Sdumbbell WREG32(VM_INVALIDATE_REQUEST, 1); 799254885Sdumbbell} 800254885Sdumbbell 801254885Sdumbbellstatic int cayman_pcie_gart_enable(struct radeon_device *rdev) 802254885Sdumbbell{ 803254885Sdumbbell int i, r; 804254885Sdumbbell 805254885Sdumbbell if (rdev->gart.robj == NULL) { 806254885Sdumbbell dev_err(rdev->dev, "No VRAM object for PCIE GART.\n"); 807254885Sdumbbell return -EINVAL; 808254885Sdumbbell } 809254885Sdumbbell r = radeon_gart_table_vram_pin(rdev); 810254885Sdumbbell if (r) 811254885Sdumbbell return r; 812254885Sdumbbell radeon_gart_restore(rdev); 813254885Sdumbbell /* Setup TLB control */ 814254885Sdumbbell WREG32(MC_VM_MX_L1_TLB_CNTL, 815254885Sdumbbell (0xA << 7) | 816254885Sdumbbell ENABLE_L1_TLB | 817254885Sdumbbell ENABLE_L1_FRAGMENT_PROCESSING | 818254885Sdumbbell SYSTEM_ACCESS_MODE_NOT_IN_SYS | 819254885Sdumbbell ENABLE_ADVANCED_DRIVER_MODEL | 820254885Sdumbbell SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU); 821254885Sdumbbell /* Setup L2 cache */ 822254885Sdumbbell WREG32(VM_L2_CNTL, ENABLE_L2_CACHE | 823254885Sdumbbell ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE | 824254885Sdumbbell ENABLE_L2_PDE0_CACHE_LRU_UPDATE_BY_WRITE | 825254885Sdumbbell EFFECTIVE_L2_QUEUE_SIZE(7) | 826254885Sdumbbell CONTEXT1_IDENTITY_ACCESS_MODE(1)); 827254885Sdumbbell WREG32(VM_L2_CNTL2, INVALIDATE_ALL_L1_TLBS | INVALIDATE_L2_CACHE); 828254885Sdumbbell WREG32(VM_L2_CNTL3, L2_CACHE_BIGK_ASSOCIATIVITY | 829254885Sdumbbell L2_CACHE_BIGK_FRAGMENT_SIZE(6)); 830254885Sdumbbell /* setup context0 */ 831254885Sdumbbell WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR, rdev->mc.gtt_start >> 12); 832254885Sdumbbell WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR, rdev->mc.gtt_end >> 12); 833254885Sdumbbell WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR, rdev->gart.table_addr >> 12); 834254885Sdumbbell WREG32(VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR, 835254885Sdumbbell (u32)(rdev->dummy_page.addr >> 12)); 836254885Sdumbbell WREG32(VM_CONTEXT0_CNTL2, 0); 837254885Sdumbbell WREG32(VM_CONTEXT0_CNTL, ENABLE_CONTEXT | PAGE_TABLE_DEPTH(0) | 838254885Sdumbbell RANGE_PROTECTION_FAULT_ENABLE_DEFAULT); 839254885Sdumbbell 840254885Sdumbbell WREG32(0x15D4, 0); 841254885Sdumbbell WREG32(0x15D8, 0); 842254885Sdumbbell WREG32(0x15DC, 0); 843254885Sdumbbell 844254885Sdumbbell /* empty context1-7 */ 845254885Sdumbbell /* Assign the pt base to something valid for now; the pts used for 846254885Sdumbbell * the VMs are determined by the application and setup and assigned 847254885Sdumbbell * on the fly in the vm part of radeon_gart.c 848254885Sdumbbell */ 849254885Sdumbbell for (i = 1; i < 8; i++) { 850254885Sdumbbell WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR + (i << 2), 0); 851254885Sdumbbell WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR + (i << 2), rdev->vm_manager.max_pfn); 852254885Sdumbbell WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (i << 2), 853254885Sdumbbell rdev->gart.table_addr >> 12); 854254885Sdumbbell } 855254885Sdumbbell 856254885Sdumbbell /* enable context1-7 */ 857254885Sdumbbell WREG32(VM_CONTEXT1_PROTECTION_FAULT_DEFAULT_ADDR, 858254885Sdumbbell (u32)(rdev->dummy_page.addr >> 12)); 859254885Sdumbbell WREG32(VM_CONTEXT1_CNTL2, 4); 860254885Sdumbbell WREG32(VM_CONTEXT1_CNTL, ENABLE_CONTEXT | PAGE_TABLE_DEPTH(1) | 861254885Sdumbbell RANGE_PROTECTION_FAULT_ENABLE_INTERRUPT | 862254885Sdumbbell RANGE_PROTECTION_FAULT_ENABLE_DEFAULT | 863254885Sdumbbell DUMMY_PAGE_PROTECTION_FAULT_ENABLE_INTERRUPT | 864254885Sdumbbell DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT | 865254885Sdumbbell PDE0_PROTECTION_FAULT_ENABLE_INTERRUPT | 866254885Sdumbbell PDE0_PROTECTION_FAULT_ENABLE_DEFAULT | 867254885Sdumbbell VALID_PROTECTION_FAULT_ENABLE_INTERRUPT | 868254885Sdumbbell VALID_PROTECTION_FAULT_ENABLE_DEFAULT | 869254885Sdumbbell READ_PROTECTION_FAULT_ENABLE_INTERRUPT | 870254885Sdumbbell READ_PROTECTION_FAULT_ENABLE_DEFAULT | 871254885Sdumbbell WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT | 872254885Sdumbbell WRITE_PROTECTION_FAULT_ENABLE_DEFAULT); 873254885Sdumbbell 874254885Sdumbbell cayman_pcie_gart_tlb_flush(rdev); 875254885Sdumbbell DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n", 876254885Sdumbbell (unsigned)(rdev->mc.gtt_size >> 20), 877254885Sdumbbell (unsigned long long)rdev->gart.table_addr); 878254885Sdumbbell rdev->gart.ready = true; 879254885Sdumbbell return 0; 880254885Sdumbbell} 881254885Sdumbbell 882254885Sdumbbellstatic void cayman_pcie_gart_disable(struct radeon_device *rdev) 883254885Sdumbbell{ 884254885Sdumbbell /* Disable all tables */ 885254885Sdumbbell WREG32(VM_CONTEXT0_CNTL, 0); 886254885Sdumbbell WREG32(VM_CONTEXT1_CNTL, 0); 887254885Sdumbbell /* Setup TLB control */ 888254885Sdumbbell WREG32(MC_VM_MX_L1_TLB_CNTL, ENABLE_L1_FRAGMENT_PROCESSING | 889254885Sdumbbell SYSTEM_ACCESS_MODE_NOT_IN_SYS | 890254885Sdumbbell SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU); 891254885Sdumbbell /* Setup L2 cache */ 892254885Sdumbbell WREG32(VM_L2_CNTL, ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE | 893254885Sdumbbell ENABLE_L2_PDE0_CACHE_LRU_UPDATE_BY_WRITE | 894254885Sdumbbell EFFECTIVE_L2_QUEUE_SIZE(7) | 895254885Sdumbbell CONTEXT1_IDENTITY_ACCESS_MODE(1)); 896254885Sdumbbell WREG32(VM_L2_CNTL2, 0); 897254885Sdumbbell WREG32(VM_L2_CNTL3, L2_CACHE_BIGK_ASSOCIATIVITY | 898254885Sdumbbell L2_CACHE_BIGK_FRAGMENT_SIZE(6)); 899254885Sdumbbell radeon_gart_table_vram_unpin(rdev); 900254885Sdumbbell} 901254885Sdumbbell 902254885Sdumbbellstatic void cayman_pcie_gart_fini(struct radeon_device *rdev) 903254885Sdumbbell{ 904254885Sdumbbell cayman_pcie_gart_disable(rdev); 905254885Sdumbbell radeon_gart_table_vram_free(rdev); 906254885Sdumbbell radeon_gart_fini(rdev); 907254885Sdumbbell} 908254885Sdumbbell 909254885Sdumbbellvoid cayman_cp_int_cntl_setup(struct radeon_device *rdev, 910254885Sdumbbell int ring, u32 cp_int_cntl) 911254885Sdumbbell{ 912254885Sdumbbell u32 srbm_gfx_cntl = RREG32(SRBM_GFX_CNTL) & ~3; 913254885Sdumbbell 914254885Sdumbbell WREG32(SRBM_GFX_CNTL, srbm_gfx_cntl | (ring & 3)); 915254885Sdumbbell WREG32(CP_INT_CNTL, cp_int_cntl); 916254885Sdumbbell} 917254885Sdumbbell 918254885Sdumbbell/* 919254885Sdumbbell * CP. 920254885Sdumbbell */ 921254885Sdumbbellvoid cayman_fence_ring_emit(struct radeon_device *rdev, 922254885Sdumbbell struct radeon_fence *fence) 923254885Sdumbbell{ 924254885Sdumbbell struct radeon_ring *ring = &rdev->ring[fence->ring]; 925254885Sdumbbell u64 addr = rdev->fence_drv[fence->ring].gpu_addr; 926254885Sdumbbell 927254885Sdumbbell /* flush read cache over gart for this vmid */ 928254885Sdumbbell radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); 929254885Sdumbbell radeon_ring_write(ring, (CP_COHER_CNTL2 - PACKET3_SET_CONFIG_REG_START) >> 2); 930254885Sdumbbell radeon_ring_write(ring, 0); 931254885Sdumbbell radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3)); 932254885Sdumbbell radeon_ring_write(ring, PACKET3_TC_ACTION_ENA | PACKET3_SH_ACTION_ENA); 933254885Sdumbbell radeon_ring_write(ring, 0xFFFFFFFF); 934254885Sdumbbell radeon_ring_write(ring, 0); 935254885Sdumbbell radeon_ring_write(ring, 10); /* poll interval */ 936254885Sdumbbell /* EVENT_WRITE_EOP - flush caches, send int */ 937254885Sdumbbell radeon_ring_write(ring, PACKET3(PACKET3_EVENT_WRITE_EOP, 4)); 938254885Sdumbbell radeon_ring_write(ring, EVENT_TYPE(CACHE_FLUSH_AND_INV_EVENT_TS) | EVENT_INDEX(5)); 939254885Sdumbbell radeon_ring_write(ring, addr & 0xffffffff); 940254885Sdumbbell radeon_ring_write(ring, (upper_32_bits(addr) & 0xff) | DATA_SEL(1) | INT_SEL(2)); 941254885Sdumbbell radeon_ring_write(ring, fence->seq); 942254885Sdumbbell radeon_ring_write(ring, 0); 943254885Sdumbbell} 944254885Sdumbbell 945254885Sdumbbellvoid cayman_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) 946254885Sdumbbell{ 947254885Sdumbbell struct radeon_ring *ring = &rdev->ring[ib->ring]; 948254885Sdumbbell 949254885Sdumbbell /* set to DX10/11 mode */ 950254885Sdumbbell radeon_ring_write(ring, PACKET3(PACKET3_MODE_CONTROL, 0)); 951254885Sdumbbell radeon_ring_write(ring, 1); 952254885Sdumbbell 953254885Sdumbbell if (ring->rptr_save_reg) { 954254885Sdumbbell uint32_t next_rptr = ring->wptr + 3 + 4 + 8; 955254885Sdumbbell radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); 956254885Sdumbbell radeon_ring_write(ring, ((ring->rptr_save_reg - 957254885Sdumbbell PACKET3_SET_CONFIG_REG_START) >> 2)); 958254885Sdumbbell radeon_ring_write(ring, next_rptr); 959254885Sdumbbell } 960254885Sdumbbell 961254885Sdumbbell radeon_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2)); 962254885Sdumbbell radeon_ring_write(ring, 963254885Sdumbbell#ifdef __BIG_ENDIAN 964254885Sdumbbell (2 << 0) | 965254885Sdumbbell#endif 966254885Sdumbbell (ib->gpu_addr & 0xFFFFFFFC)); 967254885Sdumbbell radeon_ring_write(ring, upper_32_bits(ib->gpu_addr) & 0xFF); 968254885Sdumbbell radeon_ring_write(ring, ib->length_dw | 969254885Sdumbbell (ib->vm ? (ib->vm->id << 24) : 0)); 970254885Sdumbbell 971254885Sdumbbell /* flush read cache over gart for this vmid */ 972254885Sdumbbell radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); 973254885Sdumbbell radeon_ring_write(ring, (CP_COHER_CNTL2 - PACKET3_SET_CONFIG_REG_START) >> 2); 974254885Sdumbbell radeon_ring_write(ring, ib->vm ? ib->vm->id : 0); 975254885Sdumbbell radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3)); 976254885Sdumbbell radeon_ring_write(ring, PACKET3_TC_ACTION_ENA | PACKET3_SH_ACTION_ENA); 977254885Sdumbbell radeon_ring_write(ring, 0xFFFFFFFF); 978254885Sdumbbell radeon_ring_write(ring, 0); 979254885Sdumbbell radeon_ring_write(ring, 10); /* poll interval */ 980254885Sdumbbell} 981254885Sdumbbell 982254885Sdumbbellstatic void cayman_cp_enable(struct radeon_device *rdev, bool enable) 983254885Sdumbbell{ 984254885Sdumbbell if (enable) 985254885Sdumbbell WREG32(CP_ME_CNTL, 0); 986254885Sdumbbell else { 987254885Sdumbbell radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); 988254885Sdumbbell WREG32(CP_ME_CNTL, (CP_ME_HALT | CP_PFP_HALT)); 989254885Sdumbbell WREG32(SCRATCH_UMSK, 0); 990254885Sdumbbell rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; 991254885Sdumbbell } 992254885Sdumbbell} 993254885Sdumbbell 994254885Sdumbbellstatic int cayman_cp_load_microcode(struct radeon_device *rdev) 995254885Sdumbbell{ 996254885Sdumbbell const __be32 *fw_data; 997254885Sdumbbell int i; 998254885Sdumbbell 999254885Sdumbbell if (!rdev->me_fw || !rdev->pfp_fw) 1000254885Sdumbbell return -EINVAL; 1001254885Sdumbbell 1002254885Sdumbbell cayman_cp_enable(rdev, false); 1003254885Sdumbbell 1004254885Sdumbbell fw_data = (const __be32 *)rdev->pfp_fw->data; 1005254885Sdumbbell WREG32(CP_PFP_UCODE_ADDR, 0); 1006254885Sdumbbell for (i = 0; i < CAYMAN_PFP_UCODE_SIZE; i++) 1007254885Sdumbbell WREG32(CP_PFP_UCODE_DATA, be32_to_cpup(fw_data++)); 1008254885Sdumbbell WREG32(CP_PFP_UCODE_ADDR, 0); 1009254885Sdumbbell 1010254885Sdumbbell fw_data = (const __be32 *)rdev->me_fw->data; 1011254885Sdumbbell WREG32(CP_ME_RAM_WADDR, 0); 1012254885Sdumbbell for (i = 0; i < CAYMAN_PM4_UCODE_SIZE; i++) 1013254885Sdumbbell WREG32(CP_ME_RAM_DATA, be32_to_cpup(fw_data++)); 1014254885Sdumbbell 1015254885Sdumbbell WREG32(CP_PFP_UCODE_ADDR, 0); 1016254885Sdumbbell WREG32(CP_ME_RAM_WADDR, 0); 1017254885Sdumbbell WREG32(CP_ME_RAM_RADDR, 0); 1018254885Sdumbbell return 0; 1019254885Sdumbbell} 1020254885Sdumbbell 1021254885Sdumbbellstatic int cayman_cp_start(struct radeon_device *rdev) 1022254885Sdumbbell{ 1023254885Sdumbbell struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; 1024254885Sdumbbell int r, i; 1025254885Sdumbbell 1026254885Sdumbbell r = radeon_ring_lock(rdev, ring, 7); 1027254885Sdumbbell if (r) { 1028254885Sdumbbell DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r); 1029254885Sdumbbell return r; 1030254885Sdumbbell } 1031254885Sdumbbell radeon_ring_write(ring, PACKET3(PACKET3_ME_INITIALIZE, 5)); 1032254885Sdumbbell radeon_ring_write(ring, 0x1); 1033254885Sdumbbell radeon_ring_write(ring, 0x0); 1034254885Sdumbbell radeon_ring_write(ring, rdev->config.cayman.max_hw_contexts - 1); 1035254885Sdumbbell radeon_ring_write(ring, PACKET3_ME_INITIALIZE_DEVICE_ID(1)); 1036254885Sdumbbell radeon_ring_write(ring, 0); 1037254885Sdumbbell radeon_ring_write(ring, 0); 1038254885Sdumbbell radeon_ring_unlock_commit(rdev, ring); 1039254885Sdumbbell 1040254885Sdumbbell cayman_cp_enable(rdev, true); 1041254885Sdumbbell 1042254885Sdumbbell r = radeon_ring_lock(rdev, ring, cayman_default_size + 19); 1043254885Sdumbbell if (r) { 1044254885Sdumbbell DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r); 1045254885Sdumbbell return r; 1046254885Sdumbbell } 1047254885Sdumbbell 1048254885Sdumbbell /* setup clear context state */ 1049254885Sdumbbell radeon_ring_write(ring, PACKET3(PACKET3_PREAMBLE_CNTL, 0)); 1050254885Sdumbbell radeon_ring_write(ring, PACKET3_PREAMBLE_BEGIN_CLEAR_STATE); 1051254885Sdumbbell 1052254885Sdumbbell for (i = 0; i < cayman_default_size; i++) 1053254885Sdumbbell radeon_ring_write(ring, cayman_default_state[i]); 1054254885Sdumbbell 1055254885Sdumbbell radeon_ring_write(ring, PACKET3(PACKET3_PREAMBLE_CNTL, 0)); 1056254885Sdumbbell radeon_ring_write(ring, PACKET3_PREAMBLE_END_CLEAR_STATE); 1057254885Sdumbbell 1058254885Sdumbbell /* set clear context state */ 1059254885Sdumbbell radeon_ring_write(ring, PACKET3(PACKET3_CLEAR_STATE, 0)); 1060254885Sdumbbell radeon_ring_write(ring, 0); 1061254885Sdumbbell 1062254885Sdumbbell /* SQ_VTX_BASE_VTX_LOC */ 1063254885Sdumbbell radeon_ring_write(ring, 0xc0026f00); 1064254885Sdumbbell radeon_ring_write(ring, 0x00000000); 1065254885Sdumbbell radeon_ring_write(ring, 0x00000000); 1066254885Sdumbbell radeon_ring_write(ring, 0x00000000); 1067254885Sdumbbell 1068254885Sdumbbell /* Clear consts */ 1069254885Sdumbbell radeon_ring_write(ring, 0xc0036f00); 1070254885Sdumbbell radeon_ring_write(ring, 0x00000bc4); 1071254885Sdumbbell radeon_ring_write(ring, 0xffffffff); 1072254885Sdumbbell radeon_ring_write(ring, 0xffffffff); 1073254885Sdumbbell radeon_ring_write(ring, 0xffffffff); 1074254885Sdumbbell 1075254885Sdumbbell radeon_ring_write(ring, 0xc0026900); 1076254885Sdumbbell radeon_ring_write(ring, 0x00000316); 1077254885Sdumbbell radeon_ring_write(ring, 0x0000000e); /* VGT_VERTEX_REUSE_BLOCK_CNTL */ 1078254885Sdumbbell radeon_ring_write(ring, 0x00000010); /* */ 1079254885Sdumbbell 1080254885Sdumbbell radeon_ring_unlock_commit(rdev, ring); 1081254885Sdumbbell 1082254885Sdumbbell /* XXX init other rings */ 1083254885Sdumbbell 1084254885Sdumbbell return 0; 1085254885Sdumbbell} 1086254885Sdumbbell 1087254885Sdumbbellstatic void cayman_cp_fini(struct radeon_device *rdev) 1088254885Sdumbbell{ 1089254885Sdumbbell struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; 1090254885Sdumbbell cayman_cp_enable(rdev, false); 1091254885Sdumbbell radeon_ring_fini(rdev, ring); 1092254885Sdumbbell radeon_scratch_free(rdev, ring->rptr_save_reg); 1093254885Sdumbbell} 1094254885Sdumbbell 1095254885Sdumbbellstatic int cayman_cp_resume(struct radeon_device *rdev) 1096254885Sdumbbell{ 1097254885Sdumbbell static const int ridx[] = { 1098254885Sdumbbell RADEON_RING_TYPE_GFX_INDEX, 1099254885Sdumbbell CAYMAN_RING_TYPE_CP1_INDEX, 1100254885Sdumbbell CAYMAN_RING_TYPE_CP2_INDEX 1101254885Sdumbbell }; 1102254885Sdumbbell static const unsigned cp_rb_cntl[] = { 1103254885Sdumbbell CP_RB0_CNTL, 1104254885Sdumbbell CP_RB1_CNTL, 1105254885Sdumbbell CP_RB2_CNTL, 1106254885Sdumbbell }; 1107254885Sdumbbell static const unsigned cp_rb_rptr_addr[] = { 1108254885Sdumbbell CP_RB0_RPTR_ADDR, 1109254885Sdumbbell CP_RB1_RPTR_ADDR, 1110254885Sdumbbell CP_RB2_RPTR_ADDR 1111254885Sdumbbell }; 1112254885Sdumbbell static const unsigned cp_rb_rptr_addr_hi[] = { 1113254885Sdumbbell CP_RB0_RPTR_ADDR_HI, 1114254885Sdumbbell CP_RB1_RPTR_ADDR_HI, 1115254885Sdumbbell CP_RB2_RPTR_ADDR_HI 1116254885Sdumbbell }; 1117254885Sdumbbell static const unsigned cp_rb_base[] = { 1118254885Sdumbbell CP_RB0_BASE, 1119254885Sdumbbell CP_RB1_BASE, 1120254885Sdumbbell CP_RB2_BASE 1121254885Sdumbbell }; 1122254885Sdumbbell struct radeon_ring *ring; 1123254885Sdumbbell int i, r; 1124254885Sdumbbell 1125254885Sdumbbell /* Reset cp; if cp is reset, then PA, SH, VGT also need to be reset */ 1126254885Sdumbbell WREG32(GRBM_SOFT_RESET, (SOFT_RESET_CP | 1127254885Sdumbbell SOFT_RESET_PA | 1128254885Sdumbbell SOFT_RESET_SH | 1129254885Sdumbbell SOFT_RESET_VGT | 1130254885Sdumbbell SOFT_RESET_SPI | 1131254885Sdumbbell SOFT_RESET_SX)); 1132254885Sdumbbell RREG32(GRBM_SOFT_RESET); 1133280183Sdumbbell mdelay(15); 1134254885Sdumbbell WREG32(GRBM_SOFT_RESET, 0); 1135254885Sdumbbell RREG32(GRBM_SOFT_RESET); 1136254885Sdumbbell 1137254885Sdumbbell WREG32(CP_SEM_WAIT_TIMER, 0x0); 1138254885Sdumbbell WREG32(CP_SEM_INCOMPLETE_TIMER_CNTL, 0x0); 1139254885Sdumbbell 1140254885Sdumbbell /* Set the write pointer delay */ 1141254885Sdumbbell WREG32(CP_RB_WPTR_DELAY, 0); 1142254885Sdumbbell 1143254885Sdumbbell WREG32(CP_DEBUG, (1 << 27)); 1144254885Sdumbbell 1145254885Sdumbbell /* set the wb address whether it's enabled or not */ 1146254885Sdumbbell WREG32(SCRATCH_ADDR, ((rdev->wb.gpu_addr + RADEON_WB_SCRATCH_OFFSET) >> 8) & 0xFFFFFFFF); 1147254885Sdumbbell WREG32(SCRATCH_UMSK, 0xff); 1148254885Sdumbbell 1149254885Sdumbbell for (i = 0; i < 3; ++i) { 1150254885Sdumbbell uint32_t rb_cntl; 1151254885Sdumbbell uint64_t addr; 1152254885Sdumbbell 1153254885Sdumbbell /* Set ring buffer size */ 1154254885Sdumbbell ring = &rdev->ring[ridx[i]]; 1155254885Sdumbbell rb_cntl = drm_order(ring->ring_size / 8); 1156254885Sdumbbell rb_cntl |= drm_order(RADEON_GPU_PAGE_SIZE/8) << 8; 1157254885Sdumbbell#ifdef __BIG_ENDIAN 1158254885Sdumbbell rb_cntl |= BUF_SWAP_32BIT; 1159254885Sdumbbell#endif 1160254885Sdumbbell WREG32(cp_rb_cntl[i], rb_cntl); 1161254885Sdumbbell 1162254885Sdumbbell /* set the wb address whether it's enabled or not */ 1163254885Sdumbbell addr = rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET; 1164254885Sdumbbell WREG32(cp_rb_rptr_addr[i], addr & 0xFFFFFFFC); 1165254885Sdumbbell WREG32(cp_rb_rptr_addr_hi[i], upper_32_bits(addr) & 0xFF); 1166254885Sdumbbell } 1167254885Sdumbbell 1168254885Sdumbbell /* set the rb base addr, this causes an internal reset of ALL rings */ 1169254885Sdumbbell for (i = 0; i < 3; ++i) { 1170254885Sdumbbell ring = &rdev->ring[ridx[i]]; 1171254885Sdumbbell WREG32(cp_rb_base[i], ring->gpu_addr >> 8); 1172254885Sdumbbell } 1173254885Sdumbbell 1174254885Sdumbbell for (i = 0; i < 3; ++i) { 1175254885Sdumbbell /* Initialize the ring buffer's read and write pointers */ 1176254885Sdumbbell ring = &rdev->ring[ridx[i]]; 1177254885Sdumbbell WREG32_P(cp_rb_cntl[i], RB_RPTR_WR_ENA, ~RB_RPTR_WR_ENA); 1178254885Sdumbbell 1179254885Sdumbbell ring->rptr = ring->wptr = 0; 1180254885Sdumbbell WREG32(ring->rptr_reg, ring->rptr); 1181254885Sdumbbell WREG32(ring->wptr_reg, ring->wptr); 1182254885Sdumbbell 1183280183Sdumbbell mdelay(1); 1184254885Sdumbbell WREG32_P(cp_rb_cntl[i], 0, ~RB_RPTR_WR_ENA); 1185254885Sdumbbell } 1186254885Sdumbbell 1187254885Sdumbbell /* start the rings */ 1188254885Sdumbbell cayman_cp_start(rdev); 1189254885Sdumbbell rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = true; 1190254885Sdumbbell rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX].ready = false; 1191254885Sdumbbell rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX].ready = false; 1192254885Sdumbbell /* this only test cp0 */ 1193254885Sdumbbell r = radeon_ring_test(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); 1194254885Sdumbbell if (r) { 1195254885Sdumbbell rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; 1196254885Sdumbbell rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX].ready = false; 1197254885Sdumbbell rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX].ready = false; 1198254885Sdumbbell return r; 1199254885Sdumbbell } 1200254885Sdumbbell 1201254885Sdumbbell return 0; 1202254885Sdumbbell} 1203254885Sdumbbell 1204254885Sdumbbell/* 1205254885Sdumbbell * DMA 1206254885Sdumbbell * Starting with R600, the GPU has an asynchronous 1207254885Sdumbbell * DMA engine. The programming model is very similar 1208254885Sdumbbell * to the 3D engine (ring buffer, IBs, etc.), but the 1209254885Sdumbbell * DMA controller has it's own packet format that is 1210254885Sdumbbell * different form the PM4 format used by the 3D engine. 1211254885Sdumbbell * It supports copying data, writing embedded data, 1212254885Sdumbbell * solid fills, and a number of other things. It also 1213254885Sdumbbell * has support for tiling/detiling of buffers. 1214254885Sdumbbell * Cayman and newer support two asynchronous DMA engines. 1215254885Sdumbbell */ 1216254885Sdumbbell/** 1217254885Sdumbbell * cayman_dma_ring_ib_execute - Schedule an IB on the DMA engine 1218254885Sdumbbell * 1219254885Sdumbbell * @rdev: radeon_device pointer 1220254885Sdumbbell * @ib: IB object to schedule 1221254885Sdumbbell * 1222254885Sdumbbell * Schedule an IB in the DMA ring (cayman-SI). 1223254885Sdumbbell */ 1224254885Sdumbbellvoid cayman_dma_ring_ib_execute(struct radeon_device *rdev, 1225254885Sdumbbell struct radeon_ib *ib) 1226254885Sdumbbell{ 1227254885Sdumbbell struct radeon_ring *ring = &rdev->ring[ib->ring]; 1228254885Sdumbbell 1229254885Sdumbbell if (rdev->wb.enabled) { 1230254885Sdumbbell u32 next_rptr = ring->wptr + 4; 1231254885Sdumbbell while ((next_rptr & 7) != 5) 1232254885Sdumbbell next_rptr++; 1233254885Sdumbbell next_rptr += 3; 1234254885Sdumbbell radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_WRITE, 0, 0, 1)); 1235254885Sdumbbell radeon_ring_write(ring, ring->next_rptr_gpu_addr & 0xfffffffc); 1236254885Sdumbbell radeon_ring_write(ring, upper_32_bits(ring->next_rptr_gpu_addr) & 0xff); 1237254885Sdumbbell radeon_ring_write(ring, next_rptr); 1238254885Sdumbbell } 1239254885Sdumbbell 1240254885Sdumbbell /* The indirect buffer packet must end on an 8 DW boundary in the DMA ring. 1241254885Sdumbbell * Pad as necessary with NOPs. 1242254885Sdumbbell */ 1243254885Sdumbbell while ((ring->wptr & 7) != 5) 1244254885Sdumbbell radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0)); 1245254885Sdumbbell radeon_ring_write(ring, DMA_IB_PACKET(DMA_PACKET_INDIRECT_BUFFER, ib->vm ? ib->vm->id : 0, 0)); 1246254885Sdumbbell radeon_ring_write(ring, (ib->gpu_addr & 0xFFFFFFE0)); 1247254885Sdumbbell radeon_ring_write(ring, (ib->length_dw << 12) | (upper_32_bits(ib->gpu_addr) & 0xFF)); 1248254885Sdumbbell 1249254885Sdumbbell} 1250254885Sdumbbell 1251254885Sdumbbell/** 1252254885Sdumbbell * cayman_dma_stop - stop the async dma engines 1253254885Sdumbbell * 1254254885Sdumbbell * @rdev: radeon_device pointer 1255254885Sdumbbell * 1256254885Sdumbbell * Stop the async dma engines (cayman-SI). 1257254885Sdumbbell */ 1258254885Sdumbbellvoid cayman_dma_stop(struct radeon_device *rdev) 1259254885Sdumbbell{ 1260254885Sdumbbell u32 rb_cntl; 1261254885Sdumbbell 1262254885Sdumbbell radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); 1263254885Sdumbbell 1264254885Sdumbbell /* dma0 */ 1265254885Sdumbbell rb_cntl = RREG32(DMA_RB_CNTL + DMA0_REGISTER_OFFSET); 1266254885Sdumbbell rb_cntl &= ~DMA_RB_ENABLE; 1267254885Sdumbbell WREG32(DMA_RB_CNTL + DMA0_REGISTER_OFFSET, rb_cntl); 1268254885Sdumbbell 1269254885Sdumbbell /* dma1 */ 1270254885Sdumbbell rb_cntl = RREG32(DMA_RB_CNTL + DMA1_REGISTER_OFFSET); 1271254885Sdumbbell rb_cntl &= ~DMA_RB_ENABLE; 1272254885Sdumbbell WREG32(DMA_RB_CNTL + DMA1_REGISTER_OFFSET, rb_cntl); 1273254885Sdumbbell 1274254885Sdumbbell rdev->ring[R600_RING_TYPE_DMA_INDEX].ready = false; 1275254885Sdumbbell rdev->ring[CAYMAN_RING_TYPE_DMA1_INDEX].ready = false; 1276254885Sdumbbell} 1277254885Sdumbbell 1278254885Sdumbbell/** 1279254885Sdumbbell * cayman_dma_resume - setup and start the async dma engines 1280254885Sdumbbell * 1281254885Sdumbbell * @rdev: radeon_device pointer 1282254885Sdumbbell * 1283254885Sdumbbell * Set up the DMA ring buffers and enable them. (cayman-SI). 1284254885Sdumbbell * Returns 0 for success, error for failure. 1285254885Sdumbbell */ 1286254885Sdumbbellint cayman_dma_resume(struct radeon_device *rdev) 1287254885Sdumbbell{ 1288254885Sdumbbell struct radeon_ring *ring; 1289254885Sdumbbell u32 rb_cntl, dma_cntl, ib_cntl; 1290254885Sdumbbell u32 rb_bufsz; 1291254885Sdumbbell u32 reg_offset, wb_offset; 1292254885Sdumbbell int i, r; 1293254885Sdumbbell 1294254885Sdumbbell /* Reset dma */ 1295254885Sdumbbell WREG32(SRBM_SOFT_RESET, SOFT_RESET_DMA | SOFT_RESET_DMA1); 1296254885Sdumbbell RREG32(SRBM_SOFT_RESET); 1297280183Sdumbbell udelay(50); 1298254885Sdumbbell WREG32(SRBM_SOFT_RESET, 0); 1299254885Sdumbbell 1300254885Sdumbbell for (i = 0; i < 2; i++) { 1301254885Sdumbbell if (i == 0) { 1302254885Sdumbbell ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX]; 1303254885Sdumbbell reg_offset = DMA0_REGISTER_OFFSET; 1304254885Sdumbbell wb_offset = R600_WB_DMA_RPTR_OFFSET; 1305254885Sdumbbell } else { 1306254885Sdumbbell ring = &rdev->ring[CAYMAN_RING_TYPE_DMA1_INDEX]; 1307254885Sdumbbell reg_offset = DMA1_REGISTER_OFFSET; 1308254885Sdumbbell wb_offset = CAYMAN_WB_DMA1_RPTR_OFFSET; 1309254885Sdumbbell } 1310254885Sdumbbell 1311254885Sdumbbell WREG32(DMA_SEM_INCOMPLETE_TIMER_CNTL + reg_offset, 0); 1312254885Sdumbbell WREG32(DMA_SEM_WAIT_FAIL_TIMER_CNTL + reg_offset, 0); 1313254885Sdumbbell 1314254885Sdumbbell /* Set ring buffer size in dwords */ 1315254885Sdumbbell rb_bufsz = drm_order(ring->ring_size / 4); 1316254885Sdumbbell rb_cntl = rb_bufsz << 1; 1317254885Sdumbbell#ifdef __BIG_ENDIAN 1318254885Sdumbbell rb_cntl |= DMA_RB_SWAP_ENABLE | DMA_RPTR_WRITEBACK_SWAP_ENABLE; 1319254885Sdumbbell#endif 1320254885Sdumbbell WREG32(DMA_RB_CNTL + reg_offset, rb_cntl); 1321254885Sdumbbell 1322254885Sdumbbell /* Initialize the ring buffer's read and write pointers */ 1323254885Sdumbbell WREG32(DMA_RB_RPTR + reg_offset, 0); 1324254885Sdumbbell WREG32(DMA_RB_WPTR + reg_offset, 0); 1325254885Sdumbbell 1326254885Sdumbbell /* set the wb address whether it's enabled or not */ 1327254885Sdumbbell WREG32(DMA_RB_RPTR_ADDR_HI + reg_offset, 1328254885Sdumbbell upper_32_bits(rdev->wb.gpu_addr + wb_offset) & 0xFF); 1329254885Sdumbbell WREG32(DMA_RB_RPTR_ADDR_LO + reg_offset, 1330254885Sdumbbell ((rdev->wb.gpu_addr + wb_offset) & 0xFFFFFFFC)); 1331254885Sdumbbell 1332254885Sdumbbell if (rdev->wb.enabled) 1333254885Sdumbbell rb_cntl |= DMA_RPTR_WRITEBACK_ENABLE; 1334254885Sdumbbell 1335254885Sdumbbell WREG32(DMA_RB_BASE + reg_offset, ring->gpu_addr >> 8); 1336254885Sdumbbell 1337254885Sdumbbell /* enable DMA IBs */ 1338254885Sdumbbell ib_cntl = DMA_IB_ENABLE | CMD_VMID_FORCE; 1339254885Sdumbbell#ifdef __BIG_ENDIAN 1340254885Sdumbbell ib_cntl |= DMA_IB_SWAP_ENABLE; 1341254885Sdumbbell#endif 1342254885Sdumbbell WREG32(DMA_IB_CNTL + reg_offset, ib_cntl); 1343254885Sdumbbell 1344254885Sdumbbell dma_cntl = RREG32(DMA_CNTL + reg_offset); 1345254885Sdumbbell dma_cntl &= ~CTXEMPTY_INT_ENABLE; 1346254885Sdumbbell WREG32(DMA_CNTL + reg_offset, dma_cntl); 1347254885Sdumbbell 1348254885Sdumbbell ring->wptr = 0; 1349254885Sdumbbell WREG32(DMA_RB_WPTR + reg_offset, ring->wptr << 2); 1350254885Sdumbbell 1351254885Sdumbbell ring->rptr = RREG32(DMA_RB_RPTR + reg_offset) >> 2; 1352254885Sdumbbell 1353254885Sdumbbell WREG32(DMA_RB_CNTL + reg_offset, rb_cntl | DMA_RB_ENABLE); 1354254885Sdumbbell 1355254885Sdumbbell ring->ready = true; 1356254885Sdumbbell 1357254885Sdumbbell r = radeon_ring_test(rdev, ring->idx, ring); 1358254885Sdumbbell if (r) { 1359254885Sdumbbell ring->ready = false; 1360254885Sdumbbell return r; 1361254885Sdumbbell } 1362254885Sdumbbell } 1363254885Sdumbbell 1364254885Sdumbbell radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); 1365254885Sdumbbell 1366254885Sdumbbell return 0; 1367254885Sdumbbell} 1368254885Sdumbbell 1369254885Sdumbbell/** 1370254885Sdumbbell * cayman_dma_fini - tear down the async dma engines 1371254885Sdumbbell * 1372254885Sdumbbell * @rdev: radeon_device pointer 1373254885Sdumbbell * 1374254885Sdumbbell * Stop the async dma engines and free the rings (cayman-SI). 1375254885Sdumbbell */ 1376254885Sdumbbellvoid cayman_dma_fini(struct radeon_device *rdev) 1377254885Sdumbbell{ 1378254885Sdumbbell cayman_dma_stop(rdev); 1379254885Sdumbbell radeon_ring_fini(rdev, &rdev->ring[R600_RING_TYPE_DMA_INDEX]); 1380254885Sdumbbell radeon_ring_fini(rdev, &rdev->ring[CAYMAN_RING_TYPE_DMA1_INDEX]); 1381254885Sdumbbell} 1382254885Sdumbbell 1383254885Sdumbbellstatic void cayman_gpu_soft_reset_gfx(struct radeon_device *rdev) 1384254885Sdumbbell{ 1385254885Sdumbbell u32 grbm_reset = 0; 1386254885Sdumbbell 1387254885Sdumbbell if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE)) 1388254885Sdumbbell return; 1389254885Sdumbbell 1390254885Sdumbbell dev_info(rdev->dev, " GRBM_STATUS = 0x%08X\n", 1391254885Sdumbbell RREG32(GRBM_STATUS)); 1392254885Sdumbbell dev_info(rdev->dev, " GRBM_STATUS_SE0 = 0x%08X\n", 1393254885Sdumbbell RREG32(GRBM_STATUS_SE0)); 1394254885Sdumbbell dev_info(rdev->dev, " GRBM_STATUS_SE1 = 0x%08X\n", 1395254885Sdumbbell RREG32(GRBM_STATUS_SE1)); 1396254885Sdumbbell dev_info(rdev->dev, " SRBM_STATUS = 0x%08X\n", 1397254885Sdumbbell RREG32(SRBM_STATUS)); 1398254885Sdumbbell dev_info(rdev->dev, " R_008674_CP_STALLED_STAT1 = 0x%08X\n", 1399254885Sdumbbell RREG32(CP_STALLED_STAT1)); 1400254885Sdumbbell dev_info(rdev->dev, " R_008678_CP_STALLED_STAT2 = 0x%08X\n", 1401254885Sdumbbell RREG32(CP_STALLED_STAT2)); 1402254885Sdumbbell dev_info(rdev->dev, " R_00867C_CP_BUSY_STAT = 0x%08X\n", 1403254885Sdumbbell RREG32(CP_BUSY_STAT)); 1404254885Sdumbbell dev_info(rdev->dev, " R_008680_CP_STAT = 0x%08X\n", 1405254885Sdumbbell RREG32(CP_STAT)); 1406254885Sdumbbell 1407254885Sdumbbell /* Disable CP parsing/prefetching */ 1408254885Sdumbbell WREG32(CP_ME_CNTL, CP_ME_HALT | CP_PFP_HALT); 1409254885Sdumbbell 1410254885Sdumbbell /* reset all the gfx blocks */ 1411254885Sdumbbell grbm_reset = (SOFT_RESET_CP | 1412254885Sdumbbell SOFT_RESET_CB | 1413254885Sdumbbell SOFT_RESET_DB | 1414254885Sdumbbell SOFT_RESET_GDS | 1415254885Sdumbbell SOFT_RESET_PA | 1416254885Sdumbbell SOFT_RESET_SC | 1417254885Sdumbbell SOFT_RESET_SPI | 1418254885Sdumbbell SOFT_RESET_SH | 1419254885Sdumbbell SOFT_RESET_SX | 1420254885Sdumbbell SOFT_RESET_TC | 1421254885Sdumbbell SOFT_RESET_TA | 1422254885Sdumbbell SOFT_RESET_VGT | 1423254885Sdumbbell SOFT_RESET_IA); 1424254885Sdumbbell 1425254885Sdumbbell dev_info(rdev->dev, " GRBM_SOFT_RESET=0x%08X\n", grbm_reset); 1426254885Sdumbbell WREG32(GRBM_SOFT_RESET, grbm_reset); 1427254885Sdumbbell (void)RREG32(GRBM_SOFT_RESET); 1428280183Sdumbbell udelay(50); 1429254885Sdumbbell WREG32(GRBM_SOFT_RESET, 0); 1430254885Sdumbbell (void)RREG32(GRBM_SOFT_RESET); 1431254885Sdumbbell 1432254885Sdumbbell dev_info(rdev->dev, " GRBM_STATUS = 0x%08X\n", 1433254885Sdumbbell RREG32(GRBM_STATUS)); 1434254885Sdumbbell dev_info(rdev->dev, " GRBM_STATUS_SE0 = 0x%08X\n", 1435254885Sdumbbell RREG32(GRBM_STATUS_SE0)); 1436254885Sdumbbell dev_info(rdev->dev, " GRBM_STATUS_SE1 = 0x%08X\n", 1437254885Sdumbbell RREG32(GRBM_STATUS_SE1)); 1438254885Sdumbbell dev_info(rdev->dev, " SRBM_STATUS = 0x%08X\n", 1439254885Sdumbbell RREG32(SRBM_STATUS)); 1440254885Sdumbbell dev_info(rdev->dev, " R_008674_CP_STALLED_STAT1 = 0x%08X\n", 1441254885Sdumbbell RREG32(CP_STALLED_STAT1)); 1442254885Sdumbbell dev_info(rdev->dev, " R_008678_CP_STALLED_STAT2 = 0x%08X\n", 1443254885Sdumbbell RREG32(CP_STALLED_STAT2)); 1444254885Sdumbbell dev_info(rdev->dev, " R_00867C_CP_BUSY_STAT = 0x%08X\n", 1445254885Sdumbbell RREG32(CP_BUSY_STAT)); 1446254885Sdumbbell dev_info(rdev->dev, " R_008680_CP_STAT = 0x%08X\n", 1447254885Sdumbbell RREG32(CP_STAT)); 1448254885Sdumbbell 1449254885Sdumbbell} 1450254885Sdumbbell 1451254885Sdumbbellstatic void cayman_gpu_soft_reset_dma(struct radeon_device *rdev) 1452254885Sdumbbell{ 1453254885Sdumbbell u32 tmp; 1454254885Sdumbbell 1455254885Sdumbbell if (RREG32(DMA_STATUS_REG) & DMA_IDLE) 1456254885Sdumbbell return; 1457254885Sdumbbell 1458254885Sdumbbell dev_info(rdev->dev, " R_00D034_DMA_STATUS_REG = 0x%08X\n", 1459254885Sdumbbell RREG32(DMA_STATUS_REG)); 1460254885Sdumbbell 1461254885Sdumbbell /* dma0 */ 1462254885Sdumbbell tmp = RREG32(DMA_RB_CNTL + DMA0_REGISTER_OFFSET); 1463254885Sdumbbell tmp &= ~DMA_RB_ENABLE; 1464254885Sdumbbell WREG32(DMA_RB_CNTL + DMA0_REGISTER_OFFSET, tmp); 1465254885Sdumbbell 1466254885Sdumbbell /* dma1 */ 1467254885Sdumbbell tmp = RREG32(DMA_RB_CNTL + DMA1_REGISTER_OFFSET); 1468254885Sdumbbell tmp &= ~DMA_RB_ENABLE; 1469254885Sdumbbell WREG32(DMA_RB_CNTL + DMA1_REGISTER_OFFSET, tmp); 1470254885Sdumbbell 1471254885Sdumbbell /* Reset dma */ 1472254885Sdumbbell WREG32(SRBM_SOFT_RESET, SOFT_RESET_DMA | SOFT_RESET_DMA1); 1473254885Sdumbbell RREG32(SRBM_SOFT_RESET); 1474280183Sdumbbell udelay(50); 1475254885Sdumbbell WREG32(SRBM_SOFT_RESET, 0); 1476254885Sdumbbell 1477254885Sdumbbell dev_info(rdev->dev, " R_00D034_DMA_STATUS_REG = 0x%08X\n", 1478254885Sdumbbell RREG32(DMA_STATUS_REG)); 1479254885Sdumbbell 1480254885Sdumbbell} 1481254885Sdumbbell 1482254885Sdumbbellstatic int cayman_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask) 1483254885Sdumbbell{ 1484254885Sdumbbell struct evergreen_mc_save save; 1485254885Sdumbbell 1486254885Sdumbbell if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE)) 1487254885Sdumbbell reset_mask &= ~(RADEON_RESET_GFX | RADEON_RESET_COMPUTE); 1488254885Sdumbbell 1489254885Sdumbbell if (RREG32(DMA_STATUS_REG) & DMA_IDLE) 1490254885Sdumbbell reset_mask &= ~RADEON_RESET_DMA; 1491254885Sdumbbell 1492254885Sdumbbell if (reset_mask == 0) 1493254885Sdumbbell return 0; 1494254885Sdumbbell 1495254885Sdumbbell dev_info(rdev->dev, "GPU softreset: 0x%08X\n", reset_mask); 1496254885Sdumbbell 1497254885Sdumbbell dev_info(rdev->dev, " VM_CONTEXT0_PROTECTION_FAULT_ADDR 0x%08X\n", 1498254885Sdumbbell RREG32(0x14F8)); 1499254885Sdumbbell dev_info(rdev->dev, " VM_CONTEXT0_PROTECTION_FAULT_STATUS 0x%08X\n", 1500254885Sdumbbell RREG32(0x14D8)); 1501254885Sdumbbell dev_info(rdev->dev, " VM_CONTEXT1_PROTECTION_FAULT_ADDR 0x%08X\n", 1502254885Sdumbbell RREG32(0x14FC)); 1503254885Sdumbbell dev_info(rdev->dev, " VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x%08X\n", 1504254885Sdumbbell RREG32(0x14DC)); 1505254885Sdumbbell 1506254885Sdumbbell evergreen_mc_stop(rdev, &save); 1507254885Sdumbbell if (evergreen_mc_wait_for_idle(rdev)) { 1508254885Sdumbbell dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); 1509254885Sdumbbell } 1510254885Sdumbbell 1511254885Sdumbbell if (reset_mask & (RADEON_RESET_GFX | RADEON_RESET_COMPUTE)) 1512254885Sdumbbell cayman_gpu_soft_reset_gfx(rdev); 1513254885Sdumbbell 1514254885Sdumbbell if (reset_mask & RADEON_RESET_DMA) 1515254885Sdumbbell cayman_gpu_soft_reset_dma(rdev); 1516254885Sdumbbell 1517254885Sdumbbell /* Wait a little for things to settle down */ 1518280183Sdumbbell udelay(50); 1519254885Sdumbbell 1520254885Sdumbbell evergreen_mc_resume(rdev, &save); 1521254885Sdumbbell return 0; 1522254885Sdumbbell} 1523254885Sdumbbell 1524254885Sdumbbellint cayman_asic_reset(struct radeon_device *rdev) 1525254885Sdumbbell{ 1526254885Sdumbbell return cayman_gpu_soft_reset(rdev, (RADEON_RESET_GFX | 1527254885Sdumbbell RADEON_RESET_COMPUTE | 1528254885Sdumbbell RADEON_RESET_DMA)); 1529254885Sdumbbell} 1530254885Sdumbbell 1531254885Sdumbbell/** 1532254885Sdumbbell * cayman_dma_is_lockup - Check if the DMA engine is locked up 1533254885Sdumbbell * 1534254885Sdumbbell * @rdev: radeon_device pointer 1535254885Sdumbbell * @ring: radeon_ring structure holding ring information 1536254885Sdumbbell * 1537254885Sdumbbell * Check if the async DMA engine is locked up (cayman-SI). 1538254885Sdumbbell * Returns true if the engine appears to be locked up, false if not. 1539254885Sdumbbell */ 1540254885Sdumbbellbool cayman_dma_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring) 1541254885Sdumbbell{ 1542254885Sdumbbell u32 dma_status_reg; 1543254885Sdumbbell 1544254885Sdumbbell if (ring->idx == R600_RING_TYPE_DMA_INDEX) 1545254885Sdumbbell dma_status_reg = RREG32(DMA_STATUS_REG + DMA0_REGISTER_OFFSET); 1546254885Sdumbbell else 1547254885Sdumbbell dma_status_reg = RREG32(DMA_STATUS_REG + DMA1_REGISTER_OFFSET); 1548254885Sdumbbell if (dma_status_reg & DMA_IDLE) { 1549254885Sdumbbell radeon_ring_lockup_update(ring); 1550254885Sdumbbell return false; 1551254885Sdumbbell } 1552254885Sdumbbell /* force ring activities */ 1553254885Sdumbbell radeon_ring_force_activity(rdev, ring); 1554254885Sdumbbell return radeon_ring_test_lockup(rdev, ring); 1555254885Sdumbbell} 1556254885Sdumbbell 1557254885Sdumbbellstatic int cayman_startup(struct radeon_device *rdev) 1558254885Sdumbbell{ 1559254885Sdumbbell struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; 1560254885Sdumbbell int r; 1561254885Sdumbbell 1562254885Sdumbbell /* enable pcie gen2 link */ 1563254885Sdumbbell evergreen_pcie_gen2_enable(rdev); 1564254885Sdumbbell 1565254885Sdumbbell if (rdev->flags & RADEON_IS_IGP) { 1566254885Sdumbbell if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) { 1567254885Sdumbbell r = ni_init_microcode(rdev); 1568254885Sdumbbell if (r) { 1569254885Sdumbbell DRM_ERROR("Failed to load firmware!\n"); 1570254885Sdumbbell return r; 1571254885Sdumbbell } 1572254885Sdumbbell } 1573254885Sdumbbell } else { 1574254885Sdumbbell if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw || !rdev->mc_fw) { 1575254885Sdumbbell r = ni_init_microcode(rdev); 1576254885Sdumbbell if (r) { 1577254885Sdumbbell DRM_ERROR("Failed to load firmware!\n"); 1578254885Sdumbbell return r; 1579254885Sdumbbell } 1580254885Sdumbbell } 1581254885Sdumbbell 1582254885Sdumbbell r = ni_mc_load_microcode(rdev); 1583254885Sdumbbell if (r) { 1584254885Sdumbbell DRM_ERROR("Failed to load MC firmware!\n"); 1585254885Sdumbbell return r; 1586254885Sdumbbell } 1587254885Sdumbbell } 1588254885Sdumbbell 1589254885Sdumbbell r = r600_vram_scratch_init(rdev); 1590254885Sdumbbell if (r) 1591254885Sdumbbell return r; 1592254885Sdumbbell 1593254885Sdumbbell evergreen_mc_program(rdev); 1594254885Sdumbbell r = cayman_pcie_gart_enable(rdev); 1595254885Sdumbbell if (r) 1596254885Sdumbbell return r; 1597254885Sdumbbell cayman_gpu_init(rdev); 1598254885Sdumbbell 1599254885Sdumbbell r = evergreen_blit_init(rdev); 1600254885Sdumbbell if (r) { 1601254885Sdumbbell r600_blit_fini(rdev); 1602254885Sdumbbell rdev->asic->copy.copy = NULL; 1603254885Sdumbbell dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r); 1604254885Sdumbbell } 1605254885Sdumbbell 1606254885Sdumbbell /* allocate rlc buffers */ 1607254885Sdumbbell if (rdev->flags & RADEON_IS_IGP) { 1608254885Sdumbbell r = si_rlc_init(rdev); 1609254885Sdumbbell if (r) { 1610254885Sdumbbell DRM_ERROR("Failed to init rlc BOs!\n"); 1611254885Sdumbbell return r; 1612254885Sdumbbell } 1613254885Sdumbbell } 1614254885Sdumbbell 1615254885Sdumbbell /* allocate wb buffer */ 1616254885Sdumbbell r = radeon_wb_init(rdev); 1617254885Sdumbbell if (r) 1618254885Sdumbbell return r; 1619254885Sdumbbell 1620254885Sdumbbell r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX); 1621254885Sdumbbell if (r) { 1622254885Sdumbbell dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); 1623254885Sdumbbell return r; 1624254885Sdumbbell } 1625254885Sdumbbell 1626254885Sdumbbell r = radeon_fence_driver_start_ring(rdev, CAYMAN_RING_TYPE_CP1_INDEX); 1627254885Sdumbbell if (r) { 1628254885Sdumbbell dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); 1629254885Sdumbbell return r; 1630254885Sdumbbell } 1631254885Sdumbbell 1632254885Sdumbbell r = radeon_fence_driver_start_ring(rdev, CAYMAN_RING_TYPE_CP2_INDEX); 1633254885Sdumbbell if (r) { 1634254885Sdumbbell dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); 1635254885Sdumbbell return r; 1636254885Sdumbbell } 1637254885Sdumbbell 1638254885Sdumbbell r = radeon_fence_driver_start_ring(rdev, R600_RING_TYPE_DMA_INDEX); 1639254885Sdumbbell if (r) { 1640254885Sdumbbell dev_err(rdev->dev, "failed initializing DMA fences (%d).\n", r); 1641254885Sdumbbell return r; 1642254885Sdumbbell } 1643254885Sdumbbell 1644254885Sdumbbell r = radeon_fence_driver_start_ring(rdev, CAYMAN_RING_TYPE_DMA1_INDEX); 1645254885Sdumbbell if (r) { 1646254885Sdumbbell dev_err(rdev->dev, "failed initializing DMA fences (%d).\n", r); 1647254885Sdumbbell return r; 1648254885Sdumbbell } 1649254885Sdumbbell 1650254885Sdumbbell /* Enable IRQ */ 1651254885Sdumbbell r = r600_irq_init(rdev); 1652254885Sdumbbell if (r) { 1653254885Sdumbbell DRM_ERROR("radeon: IH init failed (%d).\n", r); 1654254885Sdumbbell radeon_irq_kms_fini(rdev); 1655254885Sdumbbell return r; 1656254885Sdumbbell } 1657254885Sdumbbell evergreen_irq_set(rdev); 1658254885Sdumbbell 1659254885Sdumbbell r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET, 1660254885Sdumbbell CP_RB0_RPTR, CP_RB0_WPTR, 1661254885Sdumbbell 0, 0xfffff, RADEON_CP_PACKET2); 1662254885Sdumbbell if (r) 1663254885Sdumbbell return r; 1664254885Sdumbbell 1665254885Sdumbbell ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX]; 1666254885Sdumbbell r = radeon_ring_init(rdev, ring, ring->ring_size, R600_WB_DMA_RPTR_OFFSET, 1667254885Sdumbbell DMA_RB_RPTR + DMA0_REGISTER_OFFSET, 1668254885Sdumbbell DMA_RB_WPTR + DMA0_REGISTER_OFFSET, 1669254885Sdumbbell 2, 0x3fffc, DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0)); 1670254885Sdumbbell if (r) 1671254885Sdumbbell return r; 1672254885Sdumbbell 1673254885Sdumbbell ring = &rdev->ring[CAYMAN_RING_TYPE_DMA1_INDEX]; 1674254885Sdumbbell r = radeon_ring_init(rdev, ring, ring->ring_size, CAYMAN_WB_DMA1_RPTR_OFFSET, 1675254885Sdumbbell DMA_RB_RPTR + DMA1_REGISTER_OFFSET, 1676254885Sdumbbell DMA_RB_WPTR + DMA1_REGISTER_OFFSET, 1677254885Sdumbbell 2, 0x3fffc, DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0)); 1678254885Sdumbbell if (r) 1679254885Sdumbbell return r; 1680254885Sdumbbell 1681254885Sdumbbell r = cayman_cp_load_microcode(rdev); 1682254885Sdumbbell if (r) 1683254885Sdumbbell return r; 1684254885Sdumbbell r = cayman_cp_resume(rdev); 1685254885Sdumbbell if (r) 1686254885Sdumbbell return r; 1687254885Sdumbbell 1688254885Sdumbbell r = cayman_dma_resume(rdev); 1689254885Sdumbbell if (r) 1690254885Sdumbbell return r; 1691254885Sdumbbell 1692254885Sdumbbell r = radeon_ib_pool_init(rdev); 1693254885Sdumbbell if (r) { 1694254885Sdumbbell dev_err(rdev->dev, "IB initialization failed (%d).\n", r); 1695254885Sdumbbell return r; 1696254885Sdumbbell } 1697254885Sdumbbell 1698254885Sdumbbell r = radeon_vm_manager_init(rdev); 1699254885Sdumbbell if (r) { 1700254885Sdumbbell dev_err(rdev->dev, "vm manager initialization failed (%d).\n", r); 1701254885Sdumbbell return r; 1702254885Sdumbbell } 1703254885Sdumbbell 1704254885Sdumbbell r = r600_audio_init(rdev); 1705254885Sdumbbell if (r) 1706254885Sdumbbell return r; 1707254885Sdumbbell 1708254885Sdumbbell return 0; 1709254885Sdumbbell} 1710254885Sdumbbell 1711254885Sdumbbellint cayman_resume(struct radeon_device *rdev) 1712254885Sdumbbell{ 1713254885Sdumbbell int r; 1714254885Sdumbbell 1715254885Sdumbbell /* Do not reset GPU before posting, on rv770 hw unlike on r500 hw, 1716254885Sdumbbell * posting will perform necessary task to bring back GPU into good 1717254885Sdumbbell * shape. 1718254885Sdumbbell */ 1719254885Sdumbbell /* post card */ 1720254885Sdumbbell atom_asic_init(rdev->mode_info.atom_context); 1721254885Sdumbbell 1722254885Sdumbbell rdev->accel_working = true; 1723254885Sdumbbell r = cayman_startup(rdev); 1724254885Sdumbbell if (r) { 1725254885Sdumbbell DRM_ERROR("cayman startup failed on resume\n"); 1726254885Sdumbbell rdev->accel_working = false; 1727254885Sdumbbell return r; 1728254885Sdumbbell } 1729254885Sdumbbell return r; 1730254885Sdumbbell} 1731254885Sdumbbell 1732254885Sdumbbellint cayman_suspend(struct radeon_device *rdev) 1733254885Sdumbbell{ 1734254885Sdumbbell r600_audio_fini(rdev); 1735280183Sdumbbell radeon_vm_manager_fini(rdev); 1736254885Sdumbbell cayman_cp_enable(rdev, false); 1737254885Sdumbbell cayman_dma_stop(rdev); 1738254885Sdumbbell evergreen_irq_suspend(rdev); 1739254885Sdumbbell radeon_wb_disable(rdev); 1740254885Sdumbbell cayman_pcie_gart_disable(rdev); 1741254885Sdumbbell return 0; 1742254885Sdumbbell} 1743254885Sdumbbell 1744254885Sdumbbell/* Plan is to move initialization in that function and use 1745254885Sdumbbell * helper function so that radeon_device_init pretty much 1746254885Sdumbbell * do nothing more than calling asic specific function. This 1747254885Sdumbbell * should also allow to remove a bunch of callback function 1748254885Sdumbbell * like vram_info. 1749254885Sdumbbell */ 1750254885Sdumbbellint cayman_init(struct radeon_device *rdev) 1751254885Sdumbbell{ 1752254885Sdumbbell struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; 1753254885Sdumbbell int r; 1754254885Sdumbbell 1755254885Sdumbbell /* Read BIOS */ 1756254885Sdumbbell if (!radeon_get_bios(rdev)) { 1757254885Sdumbbell if (ASIC_IS_AVIVO(rdev)) 1758254885Sdumbbell return -EINVAL; 1759254885Sdumbbell } 1760254885Sdumbbell /* Must be an ATOMBIOS */ 1761254885Sdumbbell if (!rdev->is_atom_bios) { 1762254885Sdumbbell dev_err(rdev->dev, "Expecting atombios for cayman GPU\n"); 1763254885Sdumbbell return -EINVAL; 1764254885Sdumbbell } 1765254885Sdumbbell r = radeon_atombios_init(rdev); 1766254885Sdumbbell if (r) 1767254885Sdumbbell return r; 1768254885Sdumbbell 1769254885Sdumbbell /* Post card if necessary */ 1770254885Sdumbbell if (!radeon_card_posted(rdev)) { 1771254885Sdumbbell if (!rdev->bios) { 1772254885Sdumbbell dev_err(rdev->dev, "Card not posted and no BIOS - ignoring\n"); 1773254885Sdumbbell return -EINVAL; 1774254885Sdumbbell } 1775254885Sdumbbell DRM_INFO("GPU not posted. posting now...\n"); 1776254885Sdumbbell atom_asic_init(rdev->mode_info.atom_context); 1777254885Sdumbbell } 1778254885Sdumbbell /* Initialize scratch registers */ 1779254885Sdumbbell r600_scratch_init(rdev); 1780254885Sdumbbell /* Initialize surface registers */ 1781254885Sdumbbell radeon_surface_init(rdev); 1782254885Sdumbbell /* Initialize clocks */ 1783254885Sdumbbell radeon_get_clock_info(rdev->ddev); 1784254885Sdumbbell /* Fence driver */ 1785254885Sdumbbell r = radeon_fence_driver_init(rdev); 1786254885Sdumbbell if (r) 1787254885Sdumbbell return r; 1788254885Sdumbbell /* initialize memory controller */ 1789254885Sdumbbell r = evergreen_mc_init(rdev); 1790254885Sdumbbell if (r) 1791254885Sdumbbell return r; 1792254885Sdumbbell /* Memory manager */ 1793254885Sdumbbell r = radeon_bo_init(rdev); 1794254885Sdumbbell if (r) 1795254885Sdumbbell return r; 1796254885Sdumbbell 1797254885Sdumbbell r = radeon_irq_kms_init(rdev); 1798254885Sdumbbell if (r) 1799254885Sdumbbell return r; 1800254885Sdumbbell 1801254885Sdumbbell ring->ring_obj = NULL; 1802254885Sdumbbell r600_ring_init(rdev, ring, 1024 * 1024); 1803254885Sdumbbell 1804254885Sdumbbell ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX]; 1805254885Sdumbbell ring->ring_obj = NULL; 1806254885Sdumbbell r600_ring_init(rdev, ring, 64 * 1024); 1807254885Sdumbbell 1808254885Sdumbbell ring = &rdev->ring[CAYMAN_RING_TYPE_DMA1_INDEX]; 1809254885Sdumbbell ring->ring_obj = NULL; 1810254885Sdumbbell r600_ring_init(rdev, ring, 64 * 1024); 1811254885Sdumbbell 1812254885Sdumbbell rdev->ih.ring_obj = NULL; 1813254885Sdumbbell r600_ih_ring_init(rdev, 64 * 1024); 1814254885Sdumbbell 1815254885Sdumbbell r = r600_pcie_gart_init(rdev); 1816254885Sdumbbell if (r) 1817254885Sdumbbell return r; 1818254885Sdumbbell 1819254885Sdumbbell rdev->accel_working = true; 1820254885Sdumbbell r = cayman_startup(rdev); 1821254885Sdumbbell if (r) { 1822254885Sdumbbell dev_err(rdev->dev, "disabling GPU acceleration\n"); 1823254885Sdumbbell cayman_cp_fini(rdev); 1824254885Sdumbbell cayman_dma_fini(rdev); 1825254885Sdumbbell r600_irq_fini(rdev); 1826254885Sdumbbell if (rdev->flags & RADEON_IS_IGP) 1827254885Sdumbbell si_rlc_fini(rdev); 1828254885Sdumbbell radeon_wb_fini(rdev); 1829254885Sdumbbell radeon_ib_pool_fini(rdev); 1830254885Sdumbbell radeon_vm_manager_fini(rdev); 1831254885Sdumbbell radeon_irq_kms_fini(rdev); 1832254885Sdumbbell cayman_pcie_gart_fini(rdev); 1833254885Sdumbbell rdev->accel_working = false; 1834254885Sdumbbell } 1835254885Sdumbbell 1836254885Sdumbbell /* Don't start up if the MC ucode is missing. 1837254885Sdumbbell * The default clocks and voltages before the MC ucode 1838254885Sdumbbell * is loaded are not suffient for advanced operations. 1839254885Sdumbbell * 1840254885Sdumbbell * We can skip this check for TN, because there is no MC 1841254885Sdumbbell * ucode. 1842254885Sdumbbell */ 1843254885Sdumbbell if (!rdev->mc_fw && !(rdev->flags & RADEON_IS_IGP)) { 1844254885Sdumbbell DRM_ERROR("radeon: MC ucode required for NI+.\n"); 1845254885Sdumbbell return -EINVAL; 1846254885Sdumbbell } 1847254885Sdumbbell 1848254885Sdumbbell return 0; 1849254885Sdumbbell} 1850254885Sdumbbell 1851254885Sdumbbellvoid cayman_fini(struct radeon_device *rdev) 1852254885Sdumbbell{ 1853254885Sdumbbell r600_blit_fini(rdev); 1854254885Sdumbbell cayman_cp_fini(rdev); 1855254885Sdumbbell cayman_dma_fini(rdev); 1856254885Sdumbbell r600_irq_fini(rdev); 1857254885Sdumbbell if (rdev->flags & RADEON_IS_IGP) 1858254885Sdumbbell si_rlc_fini(rdev); 1859254885Sdumbbell radeon_wb_fini(rdev); 1860254885Sdumbbell radeon_vm_manager_fini(rdev); 1861254885Sdumbbell radeon_ib_pool_fini(rdev); 1862254885Sdumbbell radeon_irq_kms_fini(rdev); 1863254885Sdumbbell cayman_pcie_gart_fini(rdev); 1864254885Sdumbbell r600_vram_scratch_fini(rdev); 1865254885Sdumbbell radeon_gem_fini(rdev); 1866254885Sdumbbell radeon_fence_driver_fini(rdev); 1867254885Sdumbbell radeon_bo_fini(rdev); 1868254885Sdumbbell radeon_atombios_fini(rdev); 1869254885Sdumbbell ni_fini_microcode(rdev); 1870254885Sdumbbell free(rdev->bios, DRM_MEM_DRIVER); 1871254885Sdumbbell rdev->bios = NULL; 1872254885Sdumbbell} 1873254885Sdumbbell 1874254885Sdumbbell/* 1875254885Sdumbbell * vm 1876254885Sdumbbell */ 1877254885Sdumbbellint cayman_vm_init(struct radeon_device *rdev) 1878254885Sdumbbell{ 1879254885Sdumbbell /* number of VMs */ 1880254885Sdumbbell rdev->vm_manager.nvm = 8; 1881254885Sdumbbell /* base offset of vram pages */ 1882254885Sdumbbell if (rdev->flags & RADEON_IS_IGP) { 1883254885Sdumbbell u64 tmp = RREG32(FUS_MC_VM_FB_OFFSET); 1884254885Sdumbbell tmp <<= 22; 1885254885Sdumbbell rdev->vm_manager.vram_base_offset = tmp; 1886254885Sdumbbell } else 1887254885Sdumbbell rdev->vm_manager.vram_base_offset = 0; 1888254885Sdumbbell return 0; 1889254885Sdumbbell} 1890254885Sdumbbell 1891254885Sdumbbellvoid cayman_vm_fini(struct radeon_device *rdev) 1892254885Sdumbbell{ 1893254885Sdumbbell} 1894254885Sdumbbell 1895254885Sdumbbell#define R600_ENTRY_VALID (1 << 0) 1896254885Sdumbbell#define R600_PTE_SYSTEM (1 << 1) 1897254885Sdumbbell#define R600_PTE_SNOOPED (1 << 2) 1898254885Sdumbbell#define R600_PTE_READABLE (1 << 5) 1899254885Sdumbbell#define R600_PTE_WRITEABLE (1 << 6) 1900254885Sdumbbell 1901254885Sdumbbelluint32_t cayman_vm_page_flags(struct radeon_device *rdev, uint32_t flags) 1902254885Sdumbbell{ 1903254885Sdumbbell uint32_t r600_flags = 0; 1904254885Sdumbbell r600_flags |= (flags & RADEON_VM_PAGE_VALID) ? R600_ENTRY_VALID : 0; 1905254885Sdumbbell r600_flags |= (flags & RADEON_VM_PAGE_READABLE) ? R600_PTE_READABLE : 0; 1906254885Sdumbbell r600_flags |= (flags & RADEON_VM_PAGE_WRITEABLE) ? R600_PTE_WRITEABLE : 0; 1907254885Sdumbbell if (flags & RADEON_VM_PAGE_SYSTEM) { 1908254885Sdumbbell r600_flags |= R600_PTE_SYSTEM; 1909254885Sdumbbell r600_flags |= (flags & RADEON_VM_PAGE_SNOOPED) ? R600_PTE_SNOOPED : 0; 1910254885Sdumbbell } 1911254885Sdumbbell return r600_flags; 1912254885Sdumbbell} 1913254885Sdumbbell 1914254885Sdumbbell/** 1915254885Sdumbbell * cayman_vm_set_page - update the page tables using the CP 1916254885Sdumbbell * 1917254885Sdumbbell * @rdev: radeon_device pointer 1918254885Sdumbbell * @pe: addr of the page entry 1919254885Sdumbbell * @addr: dst addr to write into pe 1920254885Sdumbbell * @count: number of page entries to update 1921254885Sdumbbell * @incr: increase next addr by incr bytes 1922254885Sdumbbell * @flags: access flags 1923254885Sdumbbell * 1924254885Sdumbbell * Update the page tables using the CP (cayman-si). 1925254885Sdumbbell */ 1926254885Sdumbbellvoid cayman_vm_set_page(struct radeon_device *rdev, uint64_t pe, 1927254885Sdumbbell uint64_t addr, unsigned count, 1928254885Sdumbbell uint32_t incr, uint32_t flags) 1929254885Sdumbbell{ 1930254885Sdumbbell struct radeon_ring *ring = &rdev->ring[rdev->asic->vm.pt_ring_index]; 1931254885Sdumbbell uint32_t r600_flags = cayman_vm_page_flags(rdev, flags); 1932254885Sdumbbell uint64_t value; 1933254885Sdumbbell unsigned ndw; 1934254885Sdumbbell 1935254885Sdumbbell if (rdev->asic->vm.pt_ring_index == RADEON_RING_TYPE_GFX_INDEX) { 1936254885Sdumbbell while (count) { 1937254885Sdumbbell ndw = 1 + count * 2; 1938254885Sdumbbell if (ndw > 0x3FFF) 1939254885Sdumbbell ndw = 0x3FFF; 1940254885Sdumbbell 1941254885Sdumbbell radeon_ring_write(ring, PACKET3(PACKET3_ME_WRITE, ndw)); 1942254885Sdumbbell radeon_ring_write(ring, pe); 1943254885Sdumbbell radeon_ring_write(ring, upper_32_bits(pe) & 0xff); 1944254885Sdumbbell for (; ndw > 1; ndw -= 2, --count, pe += 8) { 1945254885Sdumbbell if (flags & RADEON_VM_PAGE_SYSTEM) { 1946254885Sdumbbell value = radeon_vm_map_gart(rdev, addr); 1947254885Sdumbbell value &= 0xFFFFFFFFFFFFF000ULL; 1948254885Sdumbbell } else if (flags & RADEON_VM_PAGE_VALID) { 1949254885Sdumbbell value = addr; 1950254885Sdumbbell } else { 1951254885Sdumbbell value = 0; 1952254885Sdumbbell } 1953254885Sdumbbell addr += incr; 1954254885Sdumbbell value |= r600_flags; 1955254885Sdumbbell radeon_ring_write(ring, value); 1956254885Sdumbbell radeon_ring_write(ring, upper_32_bits(value)); 1957254885Sdumbbell } 1958254885Sdumbbell } 1959254885Sdumbbell } else { 1960254885Sdumbbell while (count) { 1961254885Sdumbbell ndw = count * 2; 1962254885Sdumbbell if (ndw > 0xFFFFE) 1963254885Sdumbbell ndw = 0xFFFFE; 1964254885Sdumbbell 1965254885Sdumbbell /* for non-physically contiguous pages (system) */ 1966254885Sdumbbell radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_WRITE, 0, 0, ndw)); 1967254885Sdumbbell radeon_ring_write(ring, pe); 1968254885Sdumbbell radeon_ring_write(ring, upper_32_bits(pe) & 0xff); 1969254885Sdumbbell for (; ndw > 0; ndw -= 2, --count, pe += 8) { 1970254885Sdumbbell if (flags & RADEON_VM_PAGE_SYSTEM) { 1971254885Sdumbbell value = radeon_vm_map_gart(rdev, addr); 1972254885Sdumbbell value &= 0xFFFFFFFFFFFFF000ULL; 1973254885Sdumbbell } else if (flags & RADEON_VM_PAGE_VALID) { 1974254885Sdumbbell value = addr; 1975254885Sdumbbell } else { 1976254885Sdumbbell value = 0; 1977254885Sdumbbell } 1978254885Sdumbbell addr += incr; 1979254885Sdumbbell value |= r600_flags; 1980254885Sdumbbell radeon_ring_write(ring, value); 1981254885Sdumbbell radeon_ring_write(ring, upper_32_bits(value)); 1982254885Sdumbbell } 1983254885Sdumbbell } 1984254885Sdumbbell } 1985254885Sdumbbell} 1986254885Sdumbbell 1987254885Sdumbbell/** 1988254885Sdumbbell * cayman_vm_flush - vm flush using the CP 1989254885Sdumbbell * 1990254885Sdumbbell * @rdev: radeon_device pointer 1991254885Sdumbbell * 1992254885Sdumbbell * Update the page table base and flush the VM TLB 1993254885Sdumbbell * using the CP (cayman-si). 1994254885Sdumbbell */ 1995254885Sdumbbellvoid cayman_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm) 1996254885Sdumbbell{ 1997254885Sdumbbell struct radeon_ring *ring = &rdev->ring[ridx]; 1998254885Sdumbbell 1999254885Sdumbbell if (vm == NULL) 2000254885Sdumbbell return; 2001254885Sdumbbell 2002254885Sdumbbell radeon_ring_write(ring, PACKET0(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (vm->id << 2), 0)); 2003254885Sdumbbell radeon_ring_write(ring, vm->pd_gpu_addr >> 12); 2004254885Sdumbbell 2005254885Sdumbbell /* flush hdp cache */ 2006254885Sdumbbell radeon_ring_write(ring, PACKET0(HDP_MEM_COHERENCY_FLUSH_CNTL, 0)); 2007254885Sdumbbell radeon_ring_write(ring, 0x1); 2008254885Sdumbbell 2009254885Sdumbbell /* bits 0-7 are the VM contexts0-7 */ 2010254885Sdumbbell radeon_ring_write(ring, PACKET0(VM_INVALIDATE_REQUEST, 0)); 2011254885Sdumbbell radeon_ring_write(ring, 1 << vm->id); 2012254885Sdumbbell 2013254885Sdumbbell /* sync PFP to ME, otherwise we might get invalid PFP reads */ 2014254885Sdumbbell radeon_ring_write(ring, PACKET3(PACKET3_PFP_SYNC_ME, 0)); 2015254885Sdumbbell radeon_ring_write(ring, 0x0); 2016254885Sdumbbell} 2017254885Sdumbbell 2018254885Sdumbbellvoid cayman_dma_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm) 2019254885Sdumbbell{ 2020254885Sdumbbell struct radeon_ring *ring = &rdev->ring[ridx]; 2021254885Sdumbbell 2022254885Sdumbbell if (vm == NULL) 2023254885Sdumbbell return; 2024254885Sdumbbell 2025254885Sdumbbell radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_SRBM_WRITE, 0, 0, 0)); 2026254885Sdumbbell radeon_ring_write(ring, (0xf << 16) | ((VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (vm->id << 2)) >> 2)); 2027254885Sdumbbell radeon_ring_write(ring, vm->pd_gpu_addr >> 12); 2028254885Sdumbbell 2029254885Sdumbbell /* flush hdp cache */ 2030254885Sdumbbell radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_SRBM_WRITE, 0, 0, 0)); 2031254885Sdumbbell radeon_ring_write(ring, (0xf << 16) | (HDP_MEM_COHERENCY_FLUSH_CNTL >> 2)); 2032254885Sdumbbell radeon_ring_write(ring, 1); 2033254885Sdumbbell 2034254885Sdumbbell /* bits 0-7 are the VM contexts0-7 */ 2035254885Sdumbbell radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_SRBM_WRITE, 0, 0, 0)); 2036254885Sdumbbell radeon_ring_write(ring, (0xf << 16) | (VM_INVALIDATE_REQUEST >> 2)); 2037254885Sdumbbell radeon_ring_write(ring, 1 << vm->id); 2038254885Sdumbbell} 2039254885Sdumbbell 2040