18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright 2008 Advanced Micro Devices, Inc. 38c2ecf20Sopenharmony_ci * Copyright 2008 Red Hat Inc. 48c2ecf20Sopenharmony_ci * Copyright 2009 Jerome Glisse. 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 78c2ecf20Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 88c2ecf20Sopenharmony_ci * to deal in the Software without restriction, including without limitation 98c2ecf20Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 108c2ecf20Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 118c2ecf20Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 128c2ecf20Sopenharmony_ci * 138c2ecf20Sopenharmony_ci * The above copyright notice and this permission notice shall be included in 148c2ecf20Sopenharmony_ci * all copies or substantial portions of the Software. 158c2ecf20Sopenharmony_ci * 168c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 178c2ecf20Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 188c2ecf20Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 198c2ecf20Sopenharmony_ci * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 208c2ecf20Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 218c2ecf20Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 228c2ecf20Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE. 238c2ecf20Sopenharmony_ci * 248c2ecf20Sopenharmony_ci * Authors: Dave Airlie 258c2ecf20Sopenharmony_ci * Alex Deucher 268c2ecf20Sopenharmony_ci * Jerome Glisse 278c2ecf20Sopenharmony_ci */ 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci#include <linux/seq_file.h> 308c2ecf20Sopenharmony_ci#include <linux/slab.h> 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci#include <drm/drm_debugfs.h> 338c2ecf20Sopenharmony_ci#include <drm/drm_device.h> 348c2ecf20Sopenharmony_ci#include <drm/drm_file.h> 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci#include "radeon.h" 378c2ecf20Sopenharmony_ci#include "radeon_asic.h" 388c2ecf20Sopenharmony_ci#include "rs400d.h" 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci/* This files gather functions specifics to : rs400,rs480 */ 418c2ecf20Sopenharmony_cistatic int rs400_debugfs_pcie_gart_info_init(struct radeon_device *rdev); 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_civoid rs400_gart_adjust_size(struct radeon_device *rdev) 448c2ecf20Sopenharmony_ci{ 458c2ecf20Sopenharmony_ci /* Check gart size */ 468c2ecf20Sopenharmony_ci switch (rdev->mc.gtt_size/(1024*1024)) { 478c2ecf20Sopenharmony_ci case 32: 488c2ecf20Sopenharmony_ci case 64: 498c2ecf20Sopenharmony_ci case 128: 508c2ecf20Sopenharmony_ci case 256: 518c2ecf20Sopenharmony_ci case 512: 528c2ecf20Sopenharmony_ci case 1024: 538c2ecf20Sopenharmony_ci case 2048: 548c2ecf20Sopenharmony_ci break; 558c2ecf20Sopenharmony_ci default: 568c2ecf20Sopenharmony_ci DRM_ERROR("Unable to use IGP GART size %uM\n", 578c2ecf20Sopenharmony_ci (unsigned)(rdev->mc.gtt_size >> 20)); 588c2ecf20Sopenharmony_ci DRM_ERROR("Valid GART size for IGP are 32M,64M,128M,256M,512M,1G,2G\n"); 598c2ecf20Sopenharmony_ci DRM_ERROR("Forcing to 32M GART size\n"); 608c2ecf20Sopenharmony_ci rdev->mc.gtt_size = 32 * 1024 * 1024; 618c2ecf20Sopenharmony_ci return; 628c2ecf20Sopenharmony_ci } 638c2ecf20Sopenharmony_ci} 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_civoid rs400_gart_tlb_flush(struct radeon_device *rdev) 668c2ecf20Sopenharmony_ci{ 678c2ecf20Sopenharmony_ci uint32_t tmp; 688c2ecf20Sopenharmony_ci unsigned int timeout = rdev->usec_timeout; 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci WREG32_MC(RS480_GART_CACHE_CNTRL, RS480_GART_CACHE_INVALIDATE); 718c2ecf20Sopenharmony_ci do { 728c2ecf20Sopenharmony_ci tmp = RREG32_MC(RS480_GART_CACHE_CNTRL); 738c2ecf20Sopenharmony_ci if ((tmp & RS480_GART_CACHE_INVALIDATE) == 0) 748c2ecf20Sopenharmony_ci break; 758c2ecf20Sopenharmony_ci udelay(1); 768c2ecf20Sopenharmony_ci timeout--; 778c2ecf20Sopenharmony_ci } while (timeout > 0); 788c2ecf20Sopenharmony_ci WREG32_MC(RS480_GART_CACHE_CNTRL, 0); 798c2ecf20Sopenharmony_ci} 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ciint rs400_gart_init(struct radeon_device *rdev) 828c2ecf20Sopenharmony_ci{ 838c2ecf20Sopenharmony_ci int r; 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci if (rdev->gart.ptr) { 868c2ecf20Sopenharmony_ci WARN(1, "RS400 GART already initialized\n"); 878c2ecf20Sopenharmony_ci return 0; 888c2ecf20Sopenharmony_ci } 898c2ecf20Sopenharmony_ci /* Check gart size */ 908c2ecf20Sopenharmony_ci switch(rdev->mc.gtt_size / (1024 * 1024)) { 918c2ecf20Sopenharmony_ci case 32: 928c2ecf20Sopenharmony_ci case 64: 938c2ecf20Sopenharmony_ci case 128: 948c2ecf20Sopenharmony_ci case 256: 958c2ecf20Sopenharmony_ci case 512: 968c2ecf20Sopenharmony_ci case 1024: 978c2ecf20Sopenharmony_ci case 2048: 988c2ecf20Sopenharmony_ci break; 998c2ecf20Sopenharmony_ci default: 1008c2ecf20Sopenharmony_ci return -EINVAL; 1018c2ecf20Sopenharmony_ci } 1028c2ecf20Sopenharmony_ci /* Initialize common gart structure */ 1038c2ecf20Sopenharmony_ci r = radeon_gart_init(rdev); 1048c2ecf20Sopenharmony_ci if (r) 1058c2ecf20Sopenharmony_ci return r; 1068c2ecf20Sopenharmony_ci if (rs400_debugfs_pcie_gart_info_init(rdev)) 1078c2ecf20Sopenharmony_ci DRM_ERROR("Failed to register debugfs file for RS400 GART !\n"); 1088c2ecf20Sopenharmony_ci rdev->gart.table_size = rdev->gart.num_gpu_pages * 4; 1098c2ecf20Sopenharmony_ci return radeon_gart_table_ram_alloc(rdev); 1108c2ecf20Sopenharmony_ci} 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ciint rs400_gart_enable(struct radeon_device *rdev) 1138c2ecf20Sopenharmony_ci{ 1148c2ecf20Sopenharmony_ci uint32_t size_reg; 1158c2ecf20Sopenharmony_ci uint32_t tmp; 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci tmp = RREG32_MC(RS690_AIC_CTRL_SCRATCH); 1188c2ecf20Sopenharmony_ci tmp |= RS690_DIS_OUT_OF_PCI_GART_ACCESS; 1198c2ecf20Sopenharmony_ci WREG32_MC(RS690_AIC_CTRL_SCRATCH, tmp); 1208c2ecf20Sopenharmony_ci /* Check gart size */ 1218c2ecf20Sopenharmony_ci switch(rdev->mc.gtt_size / (1024 * 1024)) { 1228c2ecf20Sopenharmony_ci case 32: 1238c2ecf20Sopenharmony_ci size_reg = RS480_VA_SIZE_32MB; 1248c2ecf20Sopenharmony_ci break; 1258c2ecf20Sopenharmony_ci case 64: 1268c2ecf20Sopenharmony_ci size_reg = RS480_VA_SIZE_64MB; 1278c2ecf20Sopenharmony_ci break; 1288c2ecf20Sopenharmony_ci case 128: 1298c2ecf20Sopenharmony_ci size_reg = RS480_VA_SIZE_128MB; 1308c2ecf20Sopenharmony_ci break; 1318c2ecf20Sopenharmony_ci case 256: 1328c2ecf20Sopenharmony_ci size_reg = RS480_VA_SIZE_256MB; 1338c2ecf20Sopenharmony_ci break; 1348c2ecf20Sopenharmony_ci case 512: 1358c2ecf20Sopenharmony_ci size_reg = RS480_VA_SIZE_512MB; 1368c2ecf20Sopenharmony_ci break; 1378c2ecf20Sopenharmony_ci case 1024: 1388c2ecf20Sopenharmony_ci size_reg = RS480_VA_SIZE_1GB; 1398c2ecf20Sopenharmony_ci break; 1408c2ecf20Sopenharmony_ci case 2048: 1418c2ecf20Sopenharmony_ci size_reg = RS480_VA_SIZE_2GB; 1428c2ecf20Sopenharmony_ci break; 1438c2ecf20Sopenharmony_ci default: 1448c2ecf20Sopenharmony_ci return -EINVAL; 1458c2ecf20Sopenharmony_ci } 1468c2ecf20Sopenharmony_ci /* It should be fine to program it to max value */ 1478c2ecf20Sopenharmony_ci if (rdev->family == CHIP_RS690 || (rdev->family == CHIP_RS740)) { 1488c2ecf20Sopenharmony_ci WREG32_MC(RS690_MCCFG_AGP_BASE, 0xFFFFFFFF); 1498c2ecf20Sopenharmony_ci WREG32_MC(RS690_MCCFG_AGP_BASE_2, 0); 1508c2ecf20Sopenharmony_ci } else { 1518c2ecf20Sopenharmony_ci WREG32(RADEON_AGP_BASE, 0xFFFFFFFF); 1528c2ecf20Sopenharmony_ci WREG32(RS480_AGP_BASE_2, 0); 1538c2ecf20Sopenharmony_ci } 1548c2ecf20Sopenharmony_ci tmp = REG_SET(RS690_MC_AGP_TOP, rdev->mc.gtt_end >> 16); 1558c2ecf20Sopenharmony_ci tmp |= REG_SET(RS690_MC_AGP_START, rdev->mc.gtt_start >> 16); 1568c2ecf20Sopenharmony_ci if ((rdev->family == CHIP_RS690) || (rdev->family == CHIP_RS740)) { 1578c2ecf20Sopenharmony_ci WREG32_MC(RS690_MCCFG_AGP_LOCATION, tmp); 1588c2ecf20Sopenharmony_ci tmp = RREG32(RADEON_BUS_CNTL) & ~RS600_BUS_MASTER_DIS; 1598c2ecf20Sopenharmony_ci WREG32(RADEON_BUS_CNTL, tmp); 1608c2ecf20Sopenharmony_ci } else { 1618c2ecf20Sopenharmony_ci WREG32(RADEON_MC_AGP_LOCATION, tmp); 1628c2ecf20Sopenharmony_ci tmp = RREG32(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS; 1638c2ecf20Sopenharmony_ci WREG32(RADEON_BUS_CNTL, tmp); 1648c2ecf20Sopenharmony_ci } 1658c2ecf20Sopenharmony_ci /* Table should be in 32bits address space so ignore bits above. */ 1668c2ecf20Sopenharmony_ci tmp = (u32)rdev->gart.table_addr & 0xfffff000; 1678c2ecf20Sopenharmony_ci tmp |= (upper_32_bits(rdev->gart.table_addr) & 0xff) << 4; 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci WREG32_MC(RS480_GART_BASE, tmp); 1708c2ecf20Sopenharmony_ci /* TODO: more tweaking here */ 1718c2ecf20Sopenharmony_ci WREG32_MC(RS480_GART_FEATURE_ID, 1728c2ecf20Sopenharmony_ci (RS480_TLB_ENABLE | 1738c2ecf20Sopenharmony_ci RS480_GTW_LAC_EN | RS480_1LEVEL_GART)); 1748c2ecf20Sopenharmony_ci /* Disable snooping */ 1758c2ecf20Sopenharmony_ci WREG32_MC(RS480_AGP_MODE_CNTL, 1768c2ecf20Sopenharmony_ci (1 << RS480_REQ_TYPE_SNOOP_SHIFT) | RS480_REQ_TYPE_SNOOP_DIS); 1778c2ecf20Sopenharmony_ci /* Disable AGP mode */ 1788c2ecf20Sopenharmony_ci /* FIXME: according to doc we should set HIDE_MMCFG_BAR=0, 1798c2ecf20Sopenharmony_ci * AGPMODE30=0 & AGP30ENHANCED=0 in NB_CNTL */ 1808c2ecf20Sopenharmony_ci if ((rdev->family == CHIP_RS690) || (rdev->family == CHIP_RS740)) { 1818c2ecf20Sopenharmony_ci tmp = RREG32_MC(RS480_MC_MISC_CNTL); 1828c2ecf20Sopenharmony_ci tmp |= RS480_GART_INDEX_REG_EN | RS690_BLOCK_GFX_D3_EN; 1838c2ecf20Sopenharmony_ci WREG32_MC(RS480_MC_MISC_CNTL, tmp); 1848c2ecf20Sopenharmony_ci } else { 1858c2ecf20Sopenharmony_ci tmp = RREG32_MC(RS480_MC_MISC_CNTL); 1868c2ecf20Sopenharmony_ci tmp |= RS480_GART_INDEX_REG_EN; 1878c2ecf20Sopenharmony_ci WREG32_MC(RS480_MC_MISC_CNTL, tmp); 1888c2ecf20Sopenharmony_ci } 1898c2ecf20Sopenharmony_ci /* Enable gart */ 1908c2ecf20Sopenharmony_ci WREG32_MC(RS480_AGP_ADDRESS_SPACE_SIZE, (RS480_GART_EN | size_reg)); 1918c2ecf20Sopenharmony_ci rs400_gart_tlb_flush(rdev); 1928c2ecf20Sopenharmony_ci DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n", 1938c2ecf20Sopenharmony_ci (unsigned)(rdev->mc.gtt_size >> 20), 1948c2ecf20Sopenharmony_ci (unsigned long long)rdev->gart.table_addr); 1958c2ecf20Sopenharmony_ci rdev->gart.ready = true; 1968c2ecf20Sopenharmony_ci return 0; 1978c2ecf20Sopenharmony_ci} 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_civoid rs400_gart_disable(struct radeon_device *rdev) 2008c2ecf20Sopenharmony_ci{ 2018c2ecf20Sopenharmony_ci uint32_t tmp; 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ci tmp = RREG32_MC(RS690_AIC_CTRL_SCRATCH); 2048c2ecf20Sopenharmony_ci tmp |= RS690_DIS_OUT_OF_PCI_GART_ACCESS; 2058c2ecf20Sopenharmony_ci WREG32_MC(RS690_AIC_CTRL_SCRATCH, tmp); 2068c2ecf20Sopenharmony_ci WREG32_MC(RS480_AGP_ADDRESS_SPACE_SIZE, 0); 2078c2ecf20Sopenharmony_ci} 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_civoid rs400_gart_fini(struct radeon_device *rdev) 2108c2ecf20Sopenharmony_ci{ 2118c2ecf20Sopenharmony_ci radeon_gart_fini(rdev); 2128c2ecf20Sopenharmony_ci rs400_gart_disable(rdev); 2138c2ecf20Sopenharmony_ci radeon_gart_table_ram_free(rdev); 2148c2ecf20Sopenharmony_ci} 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci#define RS400_PTE_UNSNOOPED (1 << 0) 2178c2ecf20Sopenharmony_ci#define RS400_PTE_WRITEABLE (1 << 2) 2188c2ecf20Sopenharmony_ci#define RS400_PTE_READABLE (1 << 3) 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ciuint64_t rs400_gart_get_page_entry(uint64_t addr, uint32_t flags) 2218c2ecf20Sopenharmony_ci{ 2228c2ecf20Sopenharmony_ci uint32_t entry; 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci entry = (lower_32_bits(addr) & PAGE_MASK) | 2258c2ecf20Sopenharmony_ci ((upper_32_bits(addr) & 0xff) << 4); 2268c2ecf20Sopenharmony_ci if (flags & RADEON_GART_PAGE_READ) 2278c2ecf20Sopenharmony_ci entry |= RS400_PTE_READABLE; 2288c2ecf20Sopenharmony_ci if (flags & RADEON_GART_PAGE_WRITE) 2298c2ecf20Sopenharmony_ci entry |= RS400_PTE_WRITEABLE; 2308c2ecf20Sopenharmony_ci if (!(flags & RADEON_GART_PAGE_SNOOP)) 2318c2ecf20Sopenharmony_ci entry |= RS400_PTE_UNSNOOPED; 2328c2ecf20Sopenharmony_ci return entry; 2338c2ecf20Sopenharmony_ci} 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_civoid rs400_gart_set_page(struct radeon_device *rdev, unsigned i, 2368c2ecf20Sopenharmony_ci uint64_t entry) 2378c2ecf20Sopenharmony_ci{ 2388c2ecf20Sopenharmony_ci u32 *gtt = rdev->gart.ptr; 2398c2ecf20Sopenharmony_ci gtt[i] = cpu_to_le32(lower_32_bits(entry)); 2408c2ecf20Sopenharmony_ci} 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ciint rs400_mc_wait_for_idle(struct radeon_device *rdev) 2438c2ecf20Sopenharmony_ci{ 2448c2ecf20Sopenharmony_ci unsigned i; 2458c2ecf20Sopenharmony_ci uint32_t tmp; 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci for (i = 0; i < rdev->usec_timeout; i++) { 2488c2ecf20Sopenharmony_ci /* read MC_STATUS */ 2498c2ecf20Sopenharmony_ci tmp = RREG32(RADEON_MC_STATUS); 2508c2ecf20Sopenharmony_ci if (tmp & RADEON_MC_IDLE) { 2518c2ecf20Sopenharmony_ci return 0; 2528c2ecf20Sopenharmony_ci } 2538c2ecf20Sopenharmony_ci udelay(1); 2548c2ecf20Sopenharmony_ci } 2558c2ecf20Sopenharmony_ci return -1; 2568c2ecf20Sopenharmony_ci} 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_cistatic void rs400_gpu_init(struct radeon_device *rdev) 2598c2ecf20Sopenharmony_ci{ 2608c2ecf20Sopenharmony_ci /* FIXME: is this correct ? */ 2618c2ecf20Sopenharmony_ci r420_pipes_init(rdev); 2628c2ecf20Sopenharmony_ci if (rs400_mc_wait_for_idle(rdev)) { 2638c2ecf20Sopenharmony_ci pr_warn("rs400: Failed to wait MC idle while programming pipes. Bad things might happen. %08x\n", 2648c2ecf20Sopenharmony_ci RREG32(RADEON_MC_STATUS)); 2658c2ecf20Sopenharmony_ci } 2668c2ecf20Sopenharmony_ci} 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_cistatic void rs400_mc_init(struct radeon_device *rdev) 2698c2ecf20Sopenharmony_ci{ 2708c2ecf20Sopenharmony_ci u64 base; 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci rs400_gart_adjust_size(rdev); 2738c2ecf20Sopenharmony_ci rdev->mc.igp_sideport_enabled = radeon_combios_sideport_present(rdev); 2748c2ecf20Sopenharmony_ci /* DDR for all card after R300 & IGP */ 2758c2ecf20Sopenharmony_ci rdev->mc.vram_is_ddr = true; 2768c2ecf20Sopenharmony_ci rdev->mc.vram_width = 128; 2778c2ecf20Sopenharmony_ci r100_vram_init_sizes(rdev); 2788c2ecf20Sopenharmony_ci base = (RREG32(RADEON_NB_TOM) & 0xffff) << 16; 2798c2ecf20Sopenharmony_ci radeon_vram_location(rdev, &rdev->mc, base); 2808c2ecf20Sopenharmony_ci rdev->mc.gtt_base_align = rdev->mc.gtt_size - 1; 2818c2ecf20Sopenharmony_ci radeon_gtt_location(rdev, &rdev->mc); 2828c2ecf20Sopenharmony_ci radeon_update_bandwidth_info(rdev); 2838c2ecf20Sopenharmony_ci} 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ciuint32_t rs400_mc_rreg(struct radeon_device *rdev, uint32_t reg) 2868c2ecf20Sopenharmony_ci{ 2878c2ecf20Sopenharmony_ci unsigned long flags; 2888c2ecf20Sopenharmony_ci uint32_t r; 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci spin_lock_irqsave(&rdev->mc_idx_lock, flags); 2918c2ecf20Sopenharmony_ci WREG32(RS480_NB_MC_INDEX, reg & 0xff); 2928c2ecf20Sopenharmony_ci r = RREG32(RS480_NB_MC_DATA); 2938c2ecf20Sopenharmony_ci WREG32(RS480_NB_MC_INDEX, 0xff); 2948c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&rdev->mc_idx_lock, flags); 2958c2ecf20Sopenharmony_ci return r; 2968c2ecf20Sopenharmony_ci} 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_civoid rs400_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) 2998c2ecf20Sopenharmony_ci{ 3008c2ecf20Sopenharmony_ci unsigned long flags; 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci spin_lock_irqsave(&rdev->mc_idx_lock, flags); 3038c2ecf20Sopenharmony_ci WREG32(RS480_NB_MC_INDEX, ((reg) & 0xff) | RS480_NB_MC_IND_WR_EN); 3048c2ecf20Sopenharmony_ci WREG32(RS480_NB_MC_DATA, (v)); 3058c2ecf20Sopenharmony_ci WREG32(RS480_NB_MC_INDEX, 0xff); 3068c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&rdev->mc_idx_lock, flags); 3078c2ecf20Sopenharmony_ci} 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci#if defined(CONFIG_DEBUG_FS) 3108c2ecf20Sopenharmony_cistatic int rs400_debugfs_gart_info(struct seq_file *m, void *data) 3118c2ecf20Sopenharmony_ci{ 3128c2ecf20Sopenharmony_ci struct drm_info_node *node = (struct drm_info_node *) m->private; 3138c2ecf20Sopenharmony_ci struct drm_device *dev = node->minor->dev; 3148c2ecf20Sopenharmony_ci struct radeon_device *rdev = dev->dev_private; 3158c2ecf20Sopenharmony_ci uint32_t tmp; 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci tmp = RREG32(RADEON_HOST_PATH_CNTL); 3188c2ecf20Sopenharmony_ci seq_printf(m, "HOST_PATH_CNTL 0x%08x\n", tmp); 3198c2ecf20Sopenharmony_ci tmp = RREG32(RADEON_BUS_CNTL); 3208c2ecf20Sopenharmony_ci seq_printf(m, "BUS_CNTL 0x%08x\n", tmp); 3218c2ecf20Sopenharmony_ci tmp = RREG32_MC(RS690_AIC_CTRL_SCRATCH); 3228c2ecf20Sopenharmony_ci seq_printf(m, "AIC_CTRL_SCRATCH 0x%08x\n", tmp); 3238c2ecf20Sopenharmony_ci if (rdev->family == CHIP_RS690 || (rdev->family == CHIP_RS740)) { 3248c2ecf20Sopenharmony_ci tmp = RREG32_MC(RS690_MCCFG_AGP_BASE); 3258c2ecf20Sopenharmony_ci seq_printf(m, "MCCFG_AGP_BASE 0x%08x\n", tmp); 3268c2ecf20Sopenharmony_ci tmp = RREG32_MC(RS690_MCCFG_AGP_BASE_2); 3278c2ecf20Sopenharmony_ci seq_printf(m, "MCCFG_AGP_BASE_2 0x%08x\n", tmp); 3288c2ecf20Sopenharmony_ci tmp = RREG32_MC(RS690_MCCFG_AGP_LOCATION); 3298c2ecf20Sopenharmony_ci seq_printf(m, "MCCFG_AGP_LOCATION 0x%08x\n", tmp); 3308c2ecf20Sopenharmony_ci tmp = RREG32_MC(RS690_MCCFG_FB_LOCATION); 3318c2ecf20Sopenharmony_ci seq_printf(m, "MCCFG_FB_LOCATION 0x%08x\n", tmp); 3328c2ecf20Sopenharmony_ci tmp = RREG32(RS690_HDP_FB_LOCATION); 3338c2ecf20Sopenharmony_ci seq_printf(m, "HDP_FB_LOCATION 0x%08x\n", tmp); 3348c2ecf20Sopenharmony_ci } else { 3358c2ecf20Sopenharmony_ci tmp = RREG32(RADEON_AGP_BASE); 3368c2ecf20Sopenharmony_ci seq_printf(m, "AGP_BASE 0x%08x\n", tmp); 3378c2ecf20Sopenharmony_ci tmp = RREG32(RS480_AGP_BASE_2); 3388c2ecf20Sopenharmony_ci seq_printf(m, "AGP_BASE_2 0x%08x\n", tmp); 3398c2ecf20Sopenharmony_ci tmp = RREG32(RADEON_MC_AGP_LOCATION); 3408c2ecf20Sopenharmony_ci seq_printf(m, "MC_AGP_LOCATION 0x%08x\n", tmp); 3418c2ecf20Sopenharmony_ci } 3428c2ecf20Sopenharmony_ci tmp = RREG32_MC(RS480_GART_BASE); 3438c2ecf20Sopenharmony_ci seq_printf(m, "GART_BASE 0x%08x\n", tmp); 3448c2ecf20Sopenharmony_ci tmp = RREG32_MC(RS480_GART_FEATURE_ID); 3458c2ecf20Sopenharmony_ci seq_printf(m, "GART_FEATURE_ID 0x%08x\n", tmp); 3468c2ecf20Sopenharmony_ci tmp = RREG32_MC(RS480_AGP_MODE_CNTL); 3478c2ecf20Sopenharmony_ci seq_printf(m, "AGP_MODE_CONTROL 0x%08x\n", tmp); 3488c2ecf20Sopenharmony_ci tmp = RREG32_MC(RS480_MC_MISC_CNTL); 3498c2ecf20Sopenharmony_ci seq_printf(m, "MC_MISC_CNTL 0x%08x\n", tmp); 3508c2ecf20Sopenharmony_ci tmp = RREG32_MC(0x5F); 3518c2ecf20Sopenharmony_ci seq_printf(m, "MC_MISC_UMA_CNTL 0x%08x\n", tmp); 3528c2ecf20Sopenharmony_ci tmp = RREG32_MC(RS480_AGP_ADDRESS_SPACE_SIZE); 3538c2ecf20Sopenharmony_ci seq_printf(m, "AGP_ADDRESS_SPACE_SIZE 0x%08x\n", tmp); 3548c2ecf20Sopenharmony_ci tmp = RREG32_MC(RS480_GART_CACHE_CNTRL); 3558c2ecf20Sopenharmony_ci seq_printf(m, "GART_CACHE_CNTRL 0x%08x\n", tmp); 3568c2ecf20Sopenharmony_ci tmp = RREG32_MC(0x3B); 3578c2ecf20Sopenharmony_ci seq_printf(m, "MC_GART_ERROR_ADDRESS 0x%08x\n", tmp); 3588c2ecf20Sopenharmony_ci tmp = RREG32_MC(0x3C); 3598c2ecf20Sopenharmony_ci seq_printf(m, "MC_GART_ERROR_ADDRESS_HI 0x%08x\n", tmp); 3608c2ecf20Sopenharmony_ci tmp = RREG32_MC(0x30); 3618c2ecf20Sopenharmony_ci seq_printf(m, "GART_ERROR_0 0x%08x\n", tmp); 3628c2ecf20Sopenharmony_ci tmp = RREG32_MC(0x31); 3638c2ecf20Sopenharmony_ci seq_printf(m, "GART_ERROR_1 0x%08x\n", tmp); 3648c2ecf20Sopenharmony_ci tmp = RREG32_MC(0x32); 3658c2ecf20Sopenharmony_ci seq_printf(m, "GART_ERROR_2 0x%08x\n", tmp); 3668c2ecf20Sopenharmony_ci tmp = RREG32_MC(0x33); 3678c2ecf20Sopenharmony_ci seq_printf(m, "GART_ERROR_3 0x%08x\n", tmp); 3688c2ecf20Sopenharmony_ci tmp = RREG32_MC(0x34); 3698c2ecf20Sopenharmony_ci seq_printf(m, "GART_ERROR_4 0x%08x\n", tmp); 3708c2ecf20Sopenharmony_ci tmp = RREG32_MC(0x35); 3718c2ecf20Sopenharmony_ci seq_printf(m, "GART_ERROR_5 0x%08x\n", tmp); 3728c2ecf20Sopenharmony_ci tmp = RREG32_MC(0x36); 3738c2ecf20Sopenharmony_ci seq_printf(m, "GART_ERROR_6 0x%08x\n", tmp); 3748c2ecf20Sopenharmony_ci tmp = RREG32_MC(0x37); 3758c2ecf20Sopenharmony_ci seq_printf(m, "GART_ERROR_7 0x%08x\n", tmp); 3768c2ecf20Sopenharmony_ci return 0; 3778c2ecf20Sopenharmony_ci} 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_cistatic struct drm_info_list rs400_gart_info_list[] = { 3808c2ecf20Sopenharmony_ci {"rs400_gart_info", rs400_debugfs_gart_info, 0, NULL}, 3818c2ecf20Sopenharmony_ci}; 3828c2ecf20Sopenharmony_ci#endif 3838c2ecf20Sopenharmony_ci 3848c2ecf20Sopenharmony_cistatic int rs400_debugfs_pcie_gart_info_init(struct radeon_device *rdev) 3858c2ecf20Sopenharmony_ci{ 3868c2ecf20Sopenharmony_ci#if defined(CONFIG_DEBUG_FS) 3878c2ecf20Sopenharmony_ci return radeon_debugfs_add_files(rdev, rs400_gart_info_list, 1); 3888c2ecf20Sopenharmony_ci#else 3898c2ecf20Sopenharmony_ci return 0; 3908c2ecf20Sopenharmony_ci#endif 3918c2ecf20Sopenharmony_ci} 3928c2ecf20Sopenharmony_ci 3938c2ecf20Sopenharmony_cistatic void rs400_mc_program(struct radeon_device *rdev) 3948c2ecf20Sopenharmony_ci{ 3958c2ecf20Sopenharmony_ci struct r100_mc_save save; 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ci /* Stops all mc clients */ 3988c2ecf20Sopenharmony_ci r100_mc_stop(rdev, &save); 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_ci /* Wait for mc idle */ 4018c2ecf20Sopenharmony_ci if (rs400_mc_wait_for_idle(rdev)) 4028c2ecf20Sopenharmony_ci dev_warn(rdev->dev, "rs400: Wait MC idle timeout before updating MC.\n"); 4038c2ecf20Sopenharmony_ci WREG32(R_000148_MC_FB_LOCATION, 4048c2ecf20Sopenharmony_ci S_000148_MC_FB_START(rdev->mc.vram_start >> 16) | 4058c2ecf20Sopenharmony_ci S_000148_MC_FB_TOP(rdev->mc.vram_end >> 16)); 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_ci r100_mc_resume(rdev, &save); 4088c2ecf20Sopenharmony_ci} 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_cistatic int rs400_startup(struct radeon_device *rdev) 4118c2ecf20Sopenharmony_ci{ 4128c2ecf20Sopenharmony_ci int r; 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_ci r100_set_common_regs(rdev); 4158c2ecf20Sopenharmony_ci 4168c2ecf20Sopenharmony_ci rs400_mc_program(rdev); 4178c2ecf20Sopenharmony_ci /* Resume clock */ 4188c2ecf20Sopenharmony_ci r300_clock_startup(rdev); 4198c2ecf20Sopenharmony_ci /* Initialize GPU configuration (# pipes, ...) */ 4208c2ecf20Sopenharmony_ci rs400_gpu_init(rdev); 4218c2ecf20Sopenharmony_ci r100_enable_bm(rdev); 4228c2ecf20Sopenharmony_ci /* Initialize GART (initialize after TTM so we can allocate 4238c2ecf20Sopenharmony_ci * memory through TTM but finalize after TTM) */ 4248c2ecf20Sopenharmony_ci r = rs400_gart_enable(rdev); 4258c2ecf20Sopenharmony_ci if (r) 4268c2ecf20Sopenharmony_ci return r; 4278c2ecf20Sopenharmony_ci 4288c2ecf20Sopenharmony_ci /* allocate wb buffer */ 4298c2ecf20Sopenharmony_ci r = radeon_wb_init(rdev); 4308c2ecf20Sopenharmony_ci if (r) 4318c2ecf20Sopenharmony_ci return r; 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_ci r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX); 4348c2ecf20Sopenharmony_ci if (r) { 4358c2ecf20Sopenharmony_ci dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); 4368c2ecf20Sopenharmony_ci return r; 4378c2ecf20Sopenharmony_ci } 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ci /* Enable IRQ */ 4408c2ecf20Sopenharmony_ci if (!rdev->irq.installed) { 4418c2ecf20Sopenharmony_ci r = radeon_irq_kms_init(rdev); 4428c2ecf20Sopenharmony_ci if (r) 4438c2ecf20Sopenharmony_ci return r; 4448c2ecf20Sopenharmony_ci } 4458c2ecf20Sopenharmony_ci 4468c2ecf20Sopenharmony_ci r100_irq_set(rdev); 4478c2ecf20Sopenharmony_ci rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL); 4488c2ecf20Sopenharmony_ci /* 1M ring buffer */ 4498c2ecf20Sopenharmony_ci r = r100_cp_init(rdev, 1024 * 1024); 4508c2ecf20Sopenharmony_ci if (r) { 4518c2ecf20Sopenharmony_ci dev_err(rdev->dev, "failed initializing CP (%d).\n", r); 4528c2ecf20Sopenharmony_ci return r; 4538c2ecf20Sopenharmony_ci } 4548c2ecf20Sopenharmony_ci 4558c2ecf20Sopenharmony_ci r = radeon_ib_pool_init(rdev); 4568c2ecf20Sopenharmony_ci if (r) { 4578c2ecf20Sopenharmony_ci dev_err(rdev->dev, "IB initialization failed (%d).\n", r); 4588c2ecf20Sopenharmony_ci return r; 4598c2ecf20Sopenharmony_ci } 4608c2ecf20Sopenharmony_ci 4618c2ecf20Sopenharmony_ci return 0; 4628c2ecf20Sopenharmony_ci} 4638c2ecf20Sopenharmony_ci 4648c2ecf20Sopenharmony_ciint rs400_resume(struct radeon_device *rdev) 4658c2ecf20Sopenharmony_ci{ 4668c2ecf20Sopenharmony_ci int r; 4678c2ecf20Sopenharmony_ci 4688c2ecf20Sopenharmony_ci /* Make sur GART are not working */ 4698c2ecf20Sopenharmony_ci rs400_gart_disable(rdev); 4708c2ecf20Sopenharmony_ci /* Resume clock before doing reset */ 4718c2ecf20Sopenharmony_ci r300_clock_startup(rdev); 4728c2ecf20Sopenharmony_ci /* setup MC before calling post tables */ 4738c2ecf20Sopenharmony_ci rs400_mc_program(rdev); 4748c2ecf20Sopenharmony_ci /* Reset gpu before posting otherwise ATOM will enter infinite loop */ 4758c2ecf20Sopenharmony_ci if (radeon_asic_reset(rdev)) { 4768c2ecf20Sopenharmony_ci dev_warn(rdev->dev, "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n", 4778c2ecf20Sopenharmony_ci RREG32(R_000E40_RBBM_STATUS), 4788c2ecf20Sopenharmony_ci RREG32(R_0007C0_CP_STAT)); 4798c2ecf20Sopenharmony_ci } 4808c2ecf20Sopenharmony_ci /* post */ 4818c2ecf20Sopenharmony_ci radeon_combios_asic_init(rdev->ddev); 4828c2ecf20Sopenharmony_ci /* Resume clock after posting */ 4838c2ecf20Sopenharmony_ci r300_clock_startup(rdev); 4848c2ecf20Sopenharmony_ci /* Initialize surface registers */ 4858c2ecf20Sopenharmony_ci radeon_surface_init(rdev); 4868c2ecf20Sopenharmony_ci 4878c2ecf20Sopenharmony_ci rdev->accel_working = true; 4888c2ecf20Sopenharmony_ci r = rs400_startup(rdev); 4898c2ecf20Sopenharmony_ci if (r) { 4908c2ecf20Sopenharmony_ci rdev->accel_working = false; 4918c2ecf20Sopenharmony_ci } 4928c2ecf20Sopenharmony_ci return r; 4938c2ecf20Sopenharmony_ci} 4948c2ecf20Sopenharmony_ci 4958c2ecf20Sopenharmony_ciint rs400_suspend(struct radeon_device *rdev) 4968c2ecf20Sopenharmony_ci{ 4978c2ecf20Sopenharmony_ci radeon_pm_suspend(rdev); 4988c2ecf20Sopenharmony_ci r100_cp_disable(rdev); 4998c2ecf20Sopenharmony_ci radeon_wb_disable(rdev); 5008c2ecf20Sopenharmony_ci r100_irq_disable(rdev); 5018c2ecf20Sopenharmony_ci rs400_gart_disable(rdev); 5028c2ecf20Sopenharmony_ci return 0; 5038c2ecf20Sopenharmony_ci} 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_civoid rs400_fini(struct radeon_device *rdev) 5068c2ecf20Sopenharmony_ci{ 5078c2ecf20Sopenharmony_ci radeon_pm_fini(rdev); 5088c2ecf20Sopenharmony_ci r100_cp_fini(rdev); 5098c2ecf20Sopenharmony_ci radeon_wb_fini(rdev); 5108c2ecf20Sopenharmony_ci radeon_ib_pool_fini(rdev); 5118c2ecf20Sopenharmony_ci radeon_gem_fini(rdev); 5128c2ecf20Sopenharmony_ci rs400_gart_fini(rdev); 5138c2ecf20Sopenharmony_ci radeon_irq_kms_fini(rdev); 5148c2ecf20Sopenharmony_ci radeon_fence_driver_fini(rdev); 5158c2ecf20Sopenharmony_ci radeon_bo_fini(rdev); 5168c2ecf20Sopenharmony_ci radeon_atombios_fini(rdev); 5178c2ecf20Sopenharmony_ci kfree(rdev->bios); 5188c2ecf20Sopenharmony_ci rdev->bios = NULL; 5198c2ecf20Sopenharmony_ci} 5208c2ecf20Sopenharmony_ci 5218c2ecf20Sopenharmony_ciint rs400_init(struct radeon_device *rdev) 5228c2ecf20Sopenharmony_ci{ 5238c2ecf20Sopenharmony_ci int r; 5248c2ecf20Sopenharmony_ci 5258c2ecf20Sopenharmony_ci /* Disable VGA */ 5268c2ecf20Sopenharmony_ci r100_vga_render_disable(rdev); 5278c2ecf20Sopenharmony_ci /* Initialize scratch registers */ 5288c2ecf20Sopenharmony_ci radeon_scratch_init(rdev); 5298c2ecf20Sopenharmony_ci /* Initialize surface registers */ 5308c2ecf20Sopenharmony_ci radeon_surface_init(rdev); 5318c2ecf20Sopenharmony_ci /* TODO: disable VGA need to use VGA request */ 5328c2ecf20Sopenharmony_ci /* restore some register to sane defaults */ 5338c2ecf20Sopenharmony_ci r100_restore_sanity(rdev); 5348c2ecf20Sopenharmony_ci /* BIOS*/ 5358c2ecf20Sopenharmony_ci if (!radeon_get_bios(rdev)) { 5368c2ecf20Sopenharmony_ci if (ASIC_IS_AVIVO(rdev)) 5378c2ecf20Sopenharmony_ci return -EINVAL; 5388c2ecf20Sopenharmony_ci } 5398c2ecf20Sopenharmony_ci if (rdev->is_atom_bios) { 5408c2ecf20Sopenharmony_ci dev_err(rdev->dev, "Expecting combios for RS400/RS480 GPU\n"); 5418c2ecf20Sopenharmony_ci return -EINVAL; 5428c2ecf20Sopenharmony_ci } else { 5438c2ecf20Sopenharmony_ci r = radeon_combios_init(rdev); 5448c2ecf20Sopenharmony_ci if (r) 5458c2ecf20Sopenharmony_ci return r; 5468c2ecf20Sopenharmony_ci } 5478c2ecf20Sopenharmony_ci /* Reset gpu before posting otherwise ATOM will enter infinite loop */ 5488c2ecf20Sopenharmony_ci if (radeon_asic_reset(rdev)) { 5498c2ecf20Sopenharmony_ci dev_warn(rdev->dev, 5508c2ecf20Sopenharmony_ci "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n", 5518c2ecf20Sopenharmony_ci RREG32(R_000E40_RBBM_STATUS), 5528c2ecf20Sopenharmony_ci RREG32(R_0007C0_CP_STAT)); 5538c2ecf20Sopenharmony_ci } 5548c2ecf20Sopenharmony_ci /* check if cards are posted or not */ 5558c2ecf20Sopenharmony_ci if (radeon_boot_test_post_card(rdev) == false) 5568c2ecf20Sopenharmony_ci return -EINVAL; 5578c2ecf20Sopenharmony_ci 5588c2ecf20Sopenharmony_ci /* Initialize clocks */ 5598c2ecf20Sopenharmony_ci radeon_get_clock_info(rdev->ddev); 5608c2ecf20Sopenharmony_ci /* initialize memory controller */ 5618c2ecf20Sopenharmony_ci rs400_mc_init(rdev); 5628c2ecf20Sopenharmony_ci /* Fence driver */ 5638c2ecf20Sopenharmony_ci r = radeon_fence_driver_init(rdev); 5648c2ecf20Sopenharmony_ci if (r) 5658c2ecf20Sopenharmony_ci return r; 5668c2ecf20Sopenharmony_ci /* Memory manager */ 5678c2ecf20Sopenharmony_ci r = radeon_bo_init(rdev); 5688c2ecf20Sopenharmony_ci if (r) 5698c2ecf20Sopenharmony_ci return r; 5708c2ecf20Sopenharmony_ci r = rs400_gart_init(rdev); 5718c2ecf20Sopenharmony_ci if (r) 5728c2ecf20Sopenharmony_ci return r; 5738c2ecf20Sopenharmony_ci r300_set_reg_safe(rdev); 5748c2ecf20Sopenharmony_ci 5758c2ecf20Sopenharmony_ci /* Initialize power management */ 5768c2ecf20Sopenharmony_ci radeon_pm_init(rdev); 5778c2ecf20Sopenharmony_ci 5788c2ecf20Sopenharmony_ci rdev->accel_working = true; 5798c2ecf20Sopenharmony_ci r = rs400_startup(rdev); 5808c2ecf20Sopenharmony_ci if (r) { 5818c2ecf20Sopenharmony_ci /* Somethings want wront with the accel init stop accel */ 5828c2ecf20Sopenharmony_ci dev_err(rdev->dev, "Disabling GPU acceleration\n"); 5838c2ecf20Sopenharmony_ci r100_cp_fini(rdev); 5848c2ecf20Sopenharmony_ci radeon_wb_fini(rdev); 5858c2ecf20Sopenharmony_ci radeon_ib_pool_fini(rdev); 5868c2ecf20Sopenharmony_ci rs400_gart_fini(rdev); 5878c2ecf20Sopenharmony_ci radeon_irq_kms_fini(rdev); 5888c2ecf20Sopenharmony_ci rdev->accel_working = false; 5898c2ecf20Sopenharmony_ci } 5908c2ecf20Sopenharmony_ci return 0; 5918c2ecf20Sopenharmony_ci} 592