From 112ad1617856134c8fe1fcdd8eef33be4a0070b7 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 23 Feb 2009 10:27:24 -0500 Subject: [PATCH] RS600: add initial support (untested) The RS600 gart setup is more like R6xx/R7xx than older IGP chips. If you have an RS600, please test! --- shared-core/drm_pciids.txt | 3 + shared-core/r600_cp.c | 8 ++- shared-core/radeon_cp.c | 126 +++++++++++++++++++++++++++++++++++-- shared-core/radeon_drv.h | 56 ++++++++++++++++- 4 files changed, 186 insertions(+), 7 deletions(-) diff --git a/shared-core/drm_pciids.txt b/shared-core/drm_pciids.txt index 5792eb3b..05844eb5 100644 --- a/shared-core/drm_pciids.txt +++ b/shared-core/drm_pciids.txt @@ -233,6 +233,9 @@ 0x1002 0x7297 CHIP_RV560|RADEON_NEW_MEMMAP "ATI RV560" 0x1002 0x7834 CHIP_RS300|RADEON_IS_IGP|RADEON_NEW_MEMMAP "ATI Radeon RS350 9000/9100 IGP" 0x1002 0x7835 CHIP_RS300|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Radeon RS350 Mobility IGP" +0x1002 0x793f CHIP_RS600|RADEON_IS_IGP|RADEON_NEW_MEMMAP "ATI Radeon X1200" +0x1002 0x7941 CHIP_RS600|RADEON_IS_IGP|RADEON_NEW_MEMMAP "ATI Radeon X1200" +0x1002 0x7942 CHIP_RS600|RADEON_IS_IGP|RADEON_NEW_MEMMAP "ATI Radeon X1200" 0x1002 0x791e CHIP_RS690|RADEON_IS_IGP|RADEON_NEW_MEMMAP|RADEON_IS_IGPGART "ATI Radeon RS690 X1250 IGP" 0x1002 0x791f CHIP_RS690|RADEON_IS_IGP|RADEON_NEW_MEMMAP|RADEON_IS_IGPGART "ATI Radeon RS690 X1270 IGP" 0x1002 0x796c CHIP_RS740|RADEON_IS_IGP|RADEON_NEW_MEMMAP|RADEON_IS_IGPGART "ATI Radeon RS740 HD2100 IGP" diff --git a/shared-core/r600_cp.c b/shared-core/r600_cp.c index 8d4f6495..a318cdc6 100644 --- a/shared-core/r600_cp.c +++ b/shared-core/r600_cp.c @@ -454,7 +454,7 @@ static void r600_page_table_cleanup(struct drm_device *dev, struct drm_ati_pciga } /* R600 has page table setup */ -static int r600_page_table_init(struct drm_device *dev) +int r600_page_table_init(struct drm_device *dev) { drm_radeon_private_t *dev_priv = dev->dev_private; struct drm_ati_pcigart_info *gart_info = &dev_priv->gart_info; @@ -2460,7 +2460,11 @@ int r600_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init) dev_priv->gart_info.addr, dev_priv->pcigart_offset); - r600_page_table_init(dev); + if (!r600_page_table_init(dev)) { + DRM_ERROR("Failed to init GART table\n"); + r600_do_cleanup_cp(dev); + return -EINVAL; + } if (((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770)) r700_vm_init(dev); diff --git a/shared-core/radeon_cp.c b/shared-core/radeon_cp.c index 77b7363c..f5bbb1a4 100644 --- a/shared-core/radeon_cp.c +++ b/shared-core/radeon_cp.c @@ -82,11 +82,22 @@ static u32 RS690_READ_MCIND(drm_radeon_private_t *dev_priv, int addr) return ret; } +static u32 RS600_READ_MCIND(drm_radeon_private_t *dev_priv, int addr) +{ + u32 ret; + RADEON_WRITE(RS600_MC_INDEX, ((addr & RS600_MC_ADDR_MASK) | + RS600_MC_IND_CITF_ARB0)); + ret = RADEON_READ(RS600_MC_DATA); + return ret; +} + static u32 IGP_READ_MCIND(drm_radeon_private_t *dev_priv, int addr) { if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) || ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740)) return RS690_READ_MCIND(dev_priv, addr); + else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS600) + return RS600_READ_MCIND(dev_priv, addr); else return RS480_READ_MCIND(dev_priv, addr); } @@ -102,6 +113,8 @@ u32 radeon_read_fb_location(drm_radeon_private_t *dev_priv) else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) || ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740)) return RS690_READ_MCIND(dev_priv, RS690_MC_FB_LOCATION); + else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS600) + return RS600_READ_MCIND(dev_priv, RS600_MC_FB_LOCATION); else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515) return R500_READ_MCIND(dev_priv, R520_MC_FB_LOCATION); else @@ -119,6 +132,8 @@ void radeon_write_fb_location(drm_radeon_private_t *dev_priv, u32 fb_loc) else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) || ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740)) RS690_WRITE_MCIND(RS690_MC_FB_LOCATION, fb_loc); + else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS600) + RS600_WRITE_MCIND(RS600_MC_FB_LOCATION, fb_loc); else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515) R500_WRITE_MCIND(R520_MC_FB_LOCATION, fb_loc); else @@ -139,6 +154,8 @@ void radeon_write_agp_location(drm_radeon_private_t *dev_priv, u32 agp_loc) else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) || ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740)) RS690_WRITE_MCIND(RS690_MC_AGP_LOCATION, agp_loc); + else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS600) + RS600_WRITE_MCIND(RS600_MC_AGP_LOCATION, agp_loc); else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515) R500_WRITE_MCIND(R520_MC_AGP_LOCATION, agp_loc); else @@ -163,6 +180,9 @@ void radeon_write_agp_base(drm_radeon_private_t *dev_priv, u64 agp_base) ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740)) { RS690_WRITE_MCIND(RS690_MC_AGP_BASE, agp_base_lo); RS690_WRITE_MCIND(RS690_MC_AGP_BASE_2, agp_base_hi); + } else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS600) { + RS690_WRITE_MCIND(RS600_AGP_BASE, agp_base_lo); + RS690_WRITE_MCIND(RS600_AGP_BASE_2, agp_base_hi); } else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515) { R500_WRITE_MCIND(R520_MC_AGP_BASE, agp_base_lo); R500_WRITE_MCIND(R520_MC_AGP_BASE_2, agp_base_hi); @@ -452,6 +472,14 @@ static void radeon_cp_load_microcode(drm_radeon_private_t * dev_priv) RADEON_WRITE(RADEON_CP_ME_RAM_DATAL, RS690_cp_microcode[i][0]); } + } else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS600) { + DRM_INFO("Loading RS600 Microcode\n"); + for (i = 0; i < 256; i++) { + RADEON_WRITE(RADEON_CP_ME_RAM_DATAH, + RS600_cp_microcode[i][1]); + RADEON_WRITE(RADEON_CP_ME_RAM_DATAL, + RS600_cp_microcode[i][0]); + } } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515) || ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R520) || ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV530) || @@ -886,6 +914,82 @@ static void radeon_set_igpgart(drm_radeon_private_t * dev_priv, int on) } } +/* Enable or disable IGP GART on the chip */ +static void rs600_set_igpgart(drm_radeon_private_t * dev_priv, int on) +{ + u32 temp; + int i; + + if (on) { + DRM_DEBUG("programming igp gart %08X %08lX %08X\n", + dev_priv->gart_vm_start, + (long)dev_priv->gart_info.bus_addr, + dev_priv->gart_size); + + temp = IGP_READ_MCIND(dev_priv, RS600_MC_PT0_CNTL); + + IGP_WRITE_MCIND(RS600_MC_PT0_CNTL, (RS600_EFFECTIVE_L2_CACHE_SIZE(6) | + RS600_EFFECTIVE_L2_QUEUE_SIZE(6))); + + temp = IGP_READ_MCIND(dev_priv, RS600_MC_PT0_CLIENT0_CNTL); + for (i = 0; i < 19; i++) + IGP_WRITE_MCIND(RS600_MC_PT0_CLIENT0_CNTL + i, + (RS600_ENABLE_TRANSLATION_MODE_OVERRIDE | + RS600_SYSTEM_ACCESS_MODE(0) | //??? + RS600_SYSTEM_APERTURE_UNMAPPED_ACCESS_PASSTHROUGH | + RS600_EFFECTIVE_L1_CACHE_SIZE(3) | + RS600_EFFECTIVE_L1_QUEUE_SIZE(3))); + + IGP_WRITE_MCIND(RS600_MC_PT0_CONTEXT0_CNTL, (RS600_ENABLE_PAGE_TABLE | + RS600_PAGE_TABLE_TYPE_FLAT)); + + IGP_WRITE_MCIND(RS600_MC_PT0_CONTEXT0_FLAT_BASE_ADDR, + dev_priv->gart_info.bus_addr >> 12); + IGP_WRITE_MCIND(RS600_MC_PT0_CONTEXT0_FLAT_START_ADDR, + dev_priv->gart_vm_start >> 12); + IGP_WRITE_MCIND(RS600_MC_PT0_CONTEXT0_FLAT_END_ADDR, + (dev_priv->gart_vm_start + dev_priv->gart_size - 1) >> 12); + IGP_WRITE_MCIND(RS600_MC_PT0_CONTEXT0_DEFAULT_READ_ADDR, 0); + + temp = IGP_READ_MCIND(dev_priv, RS600_MC_FB_LOCATION); + IGP_WRITE_MCIND(RS600_MC_PT0_SYSTEM_APERTURE_LOW_ADDR, + dev_priv->gart_vm_start >> 12); + IGP_WRITE_MCIND(RS600_MC_PT0_SYSTEM_APERTURE_HIGH_ADDR, + (dev_priv->gart_vm_start + dev_priv->gart_size - 1) >> 12); + + temp = IGP_READ_MCIND(dev_priv, RS600_MC_PT0_CNTL); + IGP_WRITE_MCIND(RS600_MC_PT0_CNTL, (temp | RS600_ENABLE_PT)); + + temp = IGP_READ_MCIND(dev_priv, RS600_MC_CNTL1); + IGP_WRITE_MCIND(RS600_MC_CNTL1, (temp | RS600_ENABLE_PAGE_TABLES)); + + do { + temp = IGP_READ_MCIND(dev_priv, RS600_MC_PT0_CNTL); + if ((temp & (RS600_INVALIDATE_ALL_L1_TLBS | RS600_INVALIDATE_L2_CACHE)) == 0) + break; + DRM_UDELAY(1); + } while(1); + + temp = IGP_READ_MCIND(dev_priv, RS600_MC_PT0_CNTL); + IGP_WRITE_MCIND(RS600_MC_PT0_CNTL, (temp | + RS600_INVALIDATE_ALL_L1_TLBS | + RS600_INVALIDATE_L2_CACHE)); + + do { + temp = IGP_READ_MCIND(dev_priv, RS600_MC_PT0_CNTL); + if ((temp & (RS600_INVALIDATE_ALL_L1_TLBS | RS600_INVALIDATE_L2_CACHE)) == 0) + break; + DRM_UDELAY(1); + } while(1); + + } else { + IGP_WRITE_MCIND(RS600_MC_PT0_CNTL, 0); + temp = IGP_READ_MCIND(dev_priv, RS600_MC_CNTL1); + temp &= ~RS600_ENABLE_PAGE_TABLES; + IGP_WRITE_MCIND(RS600_MC_CNTL1, temp); + } +} + static void radeon_set_pciegart(drm_radeon_private_t * dev_priv, int on) { u32 tmp = RADEON_READ_PCIE(dev_priv, RADEON_PCIE_TX_GART_CNTL); @@ -927,6 +1031,11 @@ static void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on) return; } + if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS600) { + rs600_set_igpgart(dev_priv, on); + return; + } + if (dev_priv->flags & RADEON_IS_PCIE) { radeon_set_pciegart(dev_priv, on); return; @@ -1275,6 +1384,7 @@ static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init) DRM_DEBUG("Setting phys_pci_gart to %p %08lX\n", dev_priv->gart_info.addr, dev_priv->pcigart_offset); + } else { if (dev_priv->flags & RADEON_IS_IGPGART) dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_IGP; @@ -1292,10 +1402,18 @@ static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init) } } - if (!drm_ati_pcigart_init(dev, &dev_priv->gart_info)) { - DRM_ERROR("failed to init PCI GART!\n"); - radeon_do_cleanup_cp(dev); - return -ENOMEM; + if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS600) { + if (!r600_page_table_init(dev)) { + DRM_ERROR("failed to init PCI GART!\n"); + radeon_do_cleanup_cp(dev); + return -ENOMEM; + } + } else { + if (!drm_ati_pcigart_init(dev, &dev_priv->gart_info)) { + DRM_ERROR("failed to init PCI GART!\n"); + radeon_do_cleanup_cp(dev); + return -ENOMEM; + } } /* Turn on PCI GART */ diff --git a/shared-core/radeon_drv.h b/shared-core/radeon_drv.h index 477f0d79..ee792921 100644 --- a/shared-core/radeon_drv.h +++ b/shared-core/radeon_drv.h @@ -127,6 +127,7 @@ enum radeon_family { CHIP_RV410, CHIP_RS400, CHIP_RS480, + CHIP_RS600, CHIP_RS690, CHIP_RS740, CHIP_RV515, @@ -457,6 +458,7 @@ void r600_do_cp_stop(drm_radeon_private_t * dev_priv); int r600_engine_reset(struct drm_device * dev); void r600_do_cp_reset(drm_radeon_private_t * dev_priv); int r600_do_cleanup_cp(struct drm_device * dev); +int r600_page_table_init(struct drm_device *dev); /* Flags for stats.boxes */ @@ -593,6 +595,50 @@ int r600_do_cleanup_cp(struct drm_device * dev); #define RS690_MC_AGP_BASE 0x102 #define RS690_MC_AGP_BASE_2 0x103 +#define RS600_MC_INDEX 0x70 +# define RS600_MC_ADDR_MASK 0xff +# define RS600_MC_IND_SEQ_RBS_0 (1 << 16) +# define RS600_MC_IND_SEQ_RBS_1 (1 << 17) +# define RS600_MC_IND_SEQ_RBS_2 (1 << 18) +# define RS600_MC_IND_SEQ_RBS_3 (1 << 19) +# define RS600_MC_IND_AIC_RBS (1 << 20) +# define RS600_MC_IND_CITF_ARB0 (1 << 21) +# define RS600_MC_IND_CITF_ARB1 (1 << 22) +# define RS600_MC_IND_WR_EN (1 << 23) +#define RS600_MC_DATA 0x74 + +#define RS600_MC_STATUS 0x0 +# define RS600_MC_IDLE (1 << 1) +#define RS600_MC_FB_LOCATION 0x4 +#define RS600_MC_AGP_LOCATION 0x5 +#define RS600_AGP_BASE 0x6 +#define RS600_AGP_BASE_2 0x7 +#define RS600_MC_CNTL1 0x9 +# define RS600_ENABLE_PAGE_TABLES (1 << 26) +#define RS600_MC_PT0_CNTL 0x100 +# define RS600_ENABLE_PT (1 << 0) +# define RS600_EFFECTIVE_L2_CACHE_SIZE(x) ((x) << 15) +# define RS600_EFFECTIVE_L2_QUEUE_SIZE(x) ((x) << 21) +# define RS600_INVALIDATE_ALL_L1_TLBS (1 << 28) +# define RS600_INVALIDATE_L2_CACHE (1 << 29) +#define RS600_MC_PT0_CONTEXT0_CNTL 0x102 +# define RS600_ENABLE_PAGE_TABLE (1 << 0) +# define RS600_PAGE_TABLE_TYPE_FLAT (0 << 1) +#define RS600_MC_PT0_SYSTEM_APERTURE_LOW_ADDR 0x112 +#define RS600_MC_PT0_SYSTEM_APERTURE_HIGH_ADDR 0x114 +#define RS600_MC_PT0_CONTEXT0_DEFAULT_READ_ADDR 0x11c +#define RS600_MC_PT0_CONTEXT0_FLAT_BASE_ADDR 0x12c +#define RS600_MC_PT0_CONTEXT0_FLAT_START_ADDR 0x13c +#define RS600_MC_PT0_CONTEXT0_FLAT_END_ADDR 0x14c +#define RS600_MC_PT0_CLIENT0_CNTL 0x16c +# define RS600_ENABLE_TRANSLATION_MODE_OVERRIDE (1 << 0) +# define RS600_TRANSLATION_MODE_OVERRIDE (1 << 1) +# define RS600_SYSTEM_ACCESS_MODE(x) ((x) << 8) +# define RS600_SYSTEM_APERTURE_UNMAPPED_ACCESS_PASSTHROUGH (0 << 10) +# define RS600_EFFECTIVE_L1_CACHE_SIZE(x) ((x) << 11) +# define RS600_EFFECTIVE_L1_QUEUE_SIZE(x) ((x) << 15) +# define RS600_INVALIDATE_L1_TLB (1 << 20) + #define R520_MC_IND_INDEX 0x70 #define R520_MC_IND_WR_EN (1 << 24) #define R520_MC_IND_DATA 0x74 @@ -1395,12 +1441,20 @@ do { \ RADEON_WRITE(RS690_MC_INDEX, RS690_MC_INDEX_WR_ACK); \ } while (0) +#define RS600_WRITE_MCIND( addr, val ) \ +do { \ + RADEON_WRITE(RS600_MC_INDEX, RS600_MC_IND_WR_EN | RS600_MC_IND_CITF_ARB0 | ((addr) & RS600_MC_ADDR_MASK)); \ + RADEON_WRITE(RS600_MC_DATA, val); \ +} while (0) + #define IGP_WRITE_MCIND( addr, val ) \ do { \ if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) || \ ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740)) \ RS690_WRITE_MCIND( addr, val ); \ - else \ + else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS600) \ + RS600_WRITE_MCIND( addr, val ); \ + else \ RS480_WRITE_MCIND( addr, val ); \ } while (0)