1f51b7662SDaniel Vetter /* 2f51b7662SDaniel Vetter * Intel GTT (Graphics Translation Table) routines 3f51b7662SDaniel Vetter * 4f51b7662SDaniel Vetter * Caveat: This driver implements the linux agp interface, but this is far from 5f51b7662SDaniel Vetter * a agp driver! GTT support ended up here for purely historical reasons: The 6f51b7662SDaniel Vetter * old userspace intel graphics drivers needed an interface to map memory into 7f51b7662SDaniel Vetter * the GTT. And the drm provides a default interface for graphic devices sitting 8f51b7662SDaniel Vetter * on an agp port. So it made sense to fake the GTT support as an agp port to 9f51b7662SDaniel Vetter * avoid having to create a new api. 10f51b7662SDaniel Vetter * 11f51b7662SDaniel Vetter * With gem this does not make much sense anymore, just needlessly complicates 12f51b7662SDaniel Vetter * the code. But as long as the old graphics stack is still support, it's stuck 13f51b7662SDaniel Vetter * here. 14f51b7662SDaniel Vetter * 15f51b7662SDaniel Vetter * /fairy-tale-mode off 16f51b7662SDaniel Vetter */ 17f51b7662SDaniel Vetter 18e2404e7cSDaniel Vetter #include <linux/module.h> 19e2404e7cSDaniel Vetter #include <linux/pci.h> 20e2404e7cSDaniel Vetter #include <linux/init.h> 21e2404e7cSDaniel Vetter #include <linux/kernel.h> 22e2404e7cSDaniel Vetter #include <linux/pagemap.h> 23e2404e7cSDaniel Vetter #include <linux/agp_backend.h> 24bdb8b975SChris Wilson #include <linux/delay.h> 25e2404e7cSDaniel Vetter #include <asm/smp.h> 26e2404e7cSDaniel Vetter #include "agp.h" 27e2404e7cSDaniel Vetter #include "intel-agp.h" 280ade6386SDaniel Vetter #include <drm/intel-gtt.h> 29e2404e7cSDaniel Vetter 30f51b7662SDaniel Vetter /* 31f51b7662SDaniel Vetter * If we have Intel graphics, we're not going to have anything other than 32f51b7662SDaniel Vetter * an Intel IOMMU. So make the correct use of the PCI DMA API contingent 33d3f13810SSuresh Siddha * on the Intel IOMMU support (CONFIG_INTEL_IOMMU). 34f51b7662SDaniel Vetter * Only newer chipsets need to bother with this, of course. 35f51b7662SDaniel Vetter */ 36d3f13810SSuresh Siddha #ifdef CONFIG_INTEL_IOMMU 37f51b7662SDaniel Vetter #define USE_PCI_DMA_API 1 380e87d2b0SDaniel Vetter #else 390e87d2b0SDaniel Vetter #define USE_PCI_DMA_API 0 40f51b7662SDaniel Vetter #endif 41f51b7662SDaniel Vetter 421a997ff2SDaniel Vetter struct intel_gtt_driver { 431a997ff2SDaniel Vetter unsigned int gen : 8; 441a997ff2SDaniel Vetter unsigned int is_g33 : 1; 451a997ff2SDaniel Vetter unsigned int is_pineview : 1; 461a997ff2SDaniel Vetter unsigned int is_ironlake : 1; 47100519e2SChris Wilson unsigned int has_pgtbl_enable : 1; 4822533b49SDaniel Vetter unsigned int dma_mask_size : 8; 4973800422SDaniel Vetter /* Chipset specific GTT setup */ 5073800422SDaniel Vetter int (*setup)(void); 51ae83dd5cSDaniel Vetter /* This should undo anything done in ->setup() save the unmapping 52ae83dd5cSDaniel Vetter * of the mmio register file, that's done in the generic code. */ 53ae83dd5cSDaniel Vetter void (*cleanup)(void); 54351bb278SDaniel Vetter void (*write_entry)(dma_addr_t addr, unsigned int entry, unsigned int flags); 55351bb278SDaniel Vetter /* Flags is a more or less chipset specific opaque value. 56351bb278SDaniel Vetter * For chipsets that need to support old ums (non-gem) code, this 57351bb278SDaniel Vetter * needs to be identical to the various supported agp memory types! */ 585cbecafcSDaniel Vetter bool (*check_flags)(unsigned int flags); 591b263f24SDaniel Vetter void (*chipset_flush)(void); 601a997ff2SDaniel Vetter }; 611a997ff2SDaniel Vetter 62f51b7662SDaniel Vetter static struct _intel_private { 630ade6386SDaniel Vetter struct intel_gtt base; 641a997ff2SDaniel Vetter const struct intel_gtt_driver *driver; 65f51b7662SDaniel Vetter struct pci_dev *pcidev; /* device one */ 66d7cca2f7SDaniel Vetter struct pci_dev *bridge_dev; 67f51b7662SDaniel Vetter u8 __iomem *registers; 68f67eab66SDaniel Vetter phys_addr_t gtt_bus_addr; 69b3eafc5aSDaniel Vetter u32 PGETBL_save; 70f51b7662SDaniel Vetter u32 __iomem *gtt; /* I915G */ 71bee4a186SChris Wilson bool clear_fake_agp; /* on first access via agp, fill with scratch */ 72f51b7662SDaniel Vetter int num_dcache_entries; 73f51b7662SDaniel Vetter void __iomem *i9xx_flush_page; 74820647b9SDaniel Vetter char *i81x_gtt_table; 75f51b7662SDaniel Vetter struct resource ifp_resource; 76f51b7662SDaniel Vetter int resource_valid; 770e87d2b0SDaniel Vetter struct page *scratch_page; 7814be93ddSDaniel Vetter int refcount; 79f51b7662SDaniel Vetter } intel_private; 80f51b7662SDaniel Vetter 811a997ff2SDaniel Vetter #define INTEL_GTT_GEN intel_private.driver->gen 821a997ff2SDaniel Vetter #define IS_G33 intel_private.driver->is_g33 831a997ff2SDaniel Vetter #define IS_PINEVIEW intel_private.driver->is_pineview 841a997ff2SDaniel Vetter #define IS_IRONLAKE intel_private.driver->is_ironlake 85100519e2SChris Wilson #define HAS_PGTBL_EN intel_private.driver->has_pgtbl_enable 861a997ff2SDaniel Vetter 879da3da66SChris Wilson static int intel_gtt_map_memory(struct page **pages, 889da3da66SChris Wilson unsigned int num_entries, 899da3da66SChris Wilson struct sg_table *st) 90f51b7662SDaniel Vetter { 91f51b7662SDaniel Vetter struct scatterlist *sg; 92f51b7662SDaniel Vetter int i; 93f51b7662SDaniel Vetter 944080775bSDaniel Vetter DBG("try mapping %lu pages\n", (unsigned long)num_entries); 95f51b7662SDaniel Vetter 969da3da66SChris Wilson if (sg_alloc_table(st, num_entries, GFP_KERNEL)) 97831cd445SChris Wilson goto err; 98f51b7662SDaniel Vetter 999da3da66SChris Wilson for_each_sg(st->sgl, sg, num_entries, i) 1004080775bSDaniel Vetter sg_set_page(sg, pages[i], PAGE_SIZE, 0); 101f51b7662SDaniel Vetter 1029da3da66SChris Wilson if (!pci_map_sg(intel_private.pcidev, 1039da3da66SChris Wilson st->sgl, st->nents, PCI_DMA_BIDIRECTIONAL)) 104831cd445SChris Wilson goto err; 105831cd445SChris Wilson 106f51b7662SDaniel Vetter return 0; 107831cd445SChris Wilson 108831cd445SChris Wilson err: 1099da3da66SChris Wilson sg_free_table(st); 110831cd445SChris Wilson return -ENOMEM; 111f51b7662SDaniel Vetter } 112f51b7662SDaniel Vetter 1139da3da66SChris Wilson static void intel_gtt_unmap_memory(struct scatterlist *sg_list, int num_sg) 114f51b7662SDaniel Vetter { 1154080775bSDaniel Vetter struct sg_table st; 116f51b7662SDaniel Vetter DBG("try unmapping %lu pages\n", (unsigned long)mem->page_count); 117f51b7662SDaniel Vetter 1184080775bSDaniel Vetter pci_unmap_sg(intel_private.pcidev, sg_list, 1194080775bSDaniel Vetter num_sg, PCI_DMA_BIDIRECTIONAL); 1204080775bSDaniel Vetter 1214080775bSDaniel Vetter st.sgl = sg_list; 1224080775bSDaniel Vetter st.orig_nents = st.nents = num_sg; 1234080775bSDaniel Vetter 1244080775bSDaniel Vetter sg_free_table(&st); 125f51b7662SDaniel Vetter } 126f51b7662SDaniel Vetter 127ffdd7510SDaniel Vetter static void intel_fake_agp_enable(struct agp_bridge_data *bridge, u32 mode) 128f51b7662SDaniel Vetter { 129f51b7662SDaniel Vetter return; 130f51b7662SDaniel Vetter } 131f51b7662SDaniel Vetter 132f51b7662SDaniel Vetter /* Exists to support ARGB cursors */ 133f51b7662SDaniel Vetter static struct page *i8xx_alloc_pages(void) 134f51b7662SDaniel Vetter { 135f51b7662SDaniel Vetter struct page *page; 136f51b7662SDaniel Vetter 137f51b7662SDaniel Vetter page = alloc_pages(GFP_KERNEL | GFP_DMA32, 2); 138f51b7662SDaniel Vetter if (page == NULL) 139f51b7662SDaniel Vetter return NULL; 140f51b7662SDaniel Vetter 141f51b7662SDaniel Vetter if (set_pages_uc(page, 4) < 0) { 142f51b7662SDaniel Vetter set_pages_wb(page, 4); 143f51b7662SDaniel Vetter __free_pages(page, 2); 144f51b7662SDaniel Vetter return NULL; 145f51b7662SDaniel Vetter } 146f51b7662SDaniel Vetter get_page(page); 147f51b7662SDaniel Vetter atomic_inc(&agp_bridge->current_memory_agp); 148f51b7662SDaniel Vetter return page; 149f51b7662SDaniel Vetter } 150f51b7662SDaniel Vetter 151f51b7662SDaniel Vetter static void i8xx_destroy_pages(struct page *page) 152f51b7662SDaniel Vetter { 153f51b7662SDaniel Vetter if (page == NULL) 154f51b7662SDaniel Vetter return; 155f51b7662SDaniel Vetter 156f51b7662SDaniel Vetter set_pages_wb(page, 4); 157f51b7662SDaniel Vetter put_page(page); 158f51b7662SDaniel Vetter __free_pages(page, 2); 159f51b7662SDaniel Vetter atomic_dec(&agp_bridge->current_memory_agp); 160f51b7662SDaniel Vetter } 161f51b7662SDaniel Vetter 162820647b9SDaniel Vetter #define I810_GTT_ORDER 4 163820647b9SDaniel Vetter static int i810_setup(void) 164820647b9SDaniel Vetter { 165820647b9SDaniel Vetter u32 reg_addr; 166820647b9SDaniel Vetter char *gtt_table; 167820647b9SDaniel Vetter 168820647b9SDaniel Vetter /* i81x does not preallocate the gtt. It's always 64kb in size. */ 169820647b9SDaniel Vetter gtt_table = alloc_gatt_pages(I810_GTT_ORDER); 170820647b9SDaniel Vetter if (gtt_table == NULL) 171820647b9SDaniel Vetter return -ENOMEM; 172820647b9SDaniel Vetter intel_private.i81x_gtt_table = gtt_table; 173820647b9SDaniel Vetter 174820647b9SDaniel Vetter pci_read_config_dword(intel_private.pcidev, I810_MMADDR, ®_addr); 175820647b9SDaniel Vetter reg_addr &= 0xfff80000; 176820647b9SDaniel Vetter 177820647b9SDaniel Vetter intel_private.registers = ioremap(reg_addr, KB(64)); 178820647b9SDaniel Vetter if (!intel_private.registers) 179820647b9SDaniel Vetter return -ENOMEM; 180820647b9SDaniel Vetter 181820647b9SDaniel Vetter writel(virt_to_phys(gtt_table) | I810_PGETBL_ENABLED, 182820647b9SDaniel Vetter intel_private.registers+I810_PGETBL_CTL); 183820647b9SDaniel Vetter 184820647b9SDaniel Vetter intel_private.gtt_bus_addr = reg_addr + I810_PTE_BASE; 185820647b9SDaniel Vetter 186820647b9SDaniel Vetter if ((readl(intel_private.registers+I810_DRAM_CTL) 187820647b9SDaniel Vetter & I810_DRAM_ROW_0) == I810_DRAM_ROW_0_SDRAM) { 188820647b9SDaniel Vetter dev_info(&intel_private.pcidev->dev, 189820647b9SDaniel Vetter "detected 4MB dedicated video ram\n"); 190820647b9SDaniel Vetter intel_private.num_dcache_entries = 1024; 191820647b9SDaniel Vetter } 192820647b9SDaniel Vetter 193820647b9SDaniel Vetter return 0; 194820647b9SDaniel Vetter } 195820647b9SDaniel Vetter 196820647b9SDaniel Vetter static void i810_cleanup(void) 197820647b9SDaniel Vetter { 198820647b9SDaniel Vetter writel(0, intel_private.registers+I810_PGETBL_CTL); 199820647b9SDaniel Vetter free_gatt_pages(intel_private.i81x_gtt_table, I810_GTT_ORDER); 200820647b9SDaniel Vetter } 201820647b9SDaniel Vetter 202ff26860fSDaniel Vetter static int i810_insert_dcache_entries(struct agp_memory *mem, off_t pg_start, 203f51b7662SDaniel Vetter int type) 204f51b7662SDaniel Vetter { 205f51b7662SDaniel Vetter int i; 206f51b7662SDaniel Vetter 207625dd9d3SDaniel Vetter if ((pg_start + mem->page_count) 208625dd9d3SDaniel Vetter > intel_private.num_dcache_entries) 209625dd9d3SDaniel Vetter return -EINVAL; 210f51b7662SDaniel Vetter 211625dd9d3SDaniel Vetter if (!mem->is_flushed) 212625dd9d3SDaniel Vetter global_cache_flush(); 213625dd9d3SDaniel Vetter 214625dd9d3SDaniel Vetter for (i = pg_start; i < (pg_start + mem->page_count); i++) { 215625dd9d3SDaniel Vetter dma_addr_t addr = i << PAGE_SHIFT; 216625dd9d3SDaniel Vetter intel_private.driver->write_entry(addr, 217625dd9d3SDaniel Vetter i, type); 218f51b7662SDaniel Vetter } 219625dd9d3SDaniel Vetter readl(intel_private.gtt+i-1); 220f51b7662SDaniel Vetter 221f51b7662SDaniel Vetter return 0; 222f51b7662SDaniel Vetter } 223f51b7662SDaniel Vetter 224f51b7662SDaniel Vetter /* 225f51b7662SDaniel Vetter * The i810/i830 requires a physical address to program its mouse 226f51b7662SDaniel Vetter * pointer into hardware. 227f51b7662SDaniel Vetter * However the Xserver still writes to it through the agp aperture. 228f51b7662SDaniel Vetter */ 229f51b7662SDaniel Vetter static struct agp_memory *alloc_agpphysmem_i8xx(size_t pg_count, int type) 230f51b7662SDaniel Vetter { 231f51b7662SDaniel Vetter struct agp_memory *new; 232f51b7662SDaniel Vetter struct page *page; 233f51b7662SDaniel Vetter 234f51b7662SDaniel Vetter switch (pg_count) { 235f51b7662SDaniel Vetter case 1: page = agp_bridge->driver->agp_alloc_page(agp_bridge); 236f51b7662SDaniel Vetter break; 237f51b7662SDaniel Vetter case 4: 238f51b7662SDaniel Vetter /* kludge to get 4 physical pages for ARGB cursor */ 239f51b7662SDaniel Vetter page = i8xx_alloc_pages(); 240f51b7662SDaniel Vetter break; 241f51b7662SDaniel Vetter default: 242f51b7662SDaniel Vetter return NULL; 243f51b7662SDaniel Vetter } 244f51b7662SDaniel Vetter 245f51b7662SDaniel Vetter if (page == NULL) 246f51b7662SDaniel Vetter return NULL; 247f51b7662SDaniel Vetter 248f51b7662SDaniel Vetter new = agp_create_memory(pg_count); 249f51b7662SDaniel Vetter if (new == NULL) 250f51b7662SDaniel Vetter return NULL; 251f51b7662SDaniel Vetter 252f51b7662SDaniel Vetter new->pages[0] = page; 253f51b7662SDaniel Vetter if (pg_count == 4) { 254f51b7662SDaniel Vetter /* kludge to get 4 physical pages for ARGB cursor */ 255f51b7662SDaniel Vetter new->pages[1] = new->pages[0] + 1; 256f51b7662SDaniel Vetter new->pages[2] = new->pages[1] + 1; 257f51b7662SDaniel Vetter new->pages[3] = new->pages[2] + 1; 258f51b7662SDaniel Vetter } 259f51b7662SDaniel Vetter new->page_count = pg_count; 260f51b7662SDaniel Vetter new->num_scratch_pages = pg_count; 261f51b7662SDaniel Vetter new->type = AGP_PHYS_MEMORY; 262f51b7662SDaniel Vetter new->physical = page_to_phys(new->pages[0]); 263f51b7662SDaniel Vetter return new; 264f51b7662SDaniel Vetter } 265f51b7662SDaniel Vetter 266f51b7662SDaniel Vetter static void intel_i810_free_by_type(struct agp_memory *curr) 267f51b7662SDaniel Vetter { 268f51b7662SDaniel Vetter agp_free_key(curr->key); 269f51b7662SDaniel Vetter if (curr->type == AGP_PHYS_MEMORY) { 270f51b7662SDaniel Vetter if (curr->page_count == 4) 271f51b7662SDaniel Vetter i8xx_destroy_pages(curr->pages[0]); 272f51b7662SDaniel Vetter else { 273f51b7662SDaniel Vetter agp_bridge->driver->agp_destroy_page(curr->pages[0], 274f51b7662SDaniel Vetter AGP_PAGE_DESTROY_UNMAP); 275f51b7662SDaniel Vetter agp_bridge->driver->agp_destroy_page(curr->pages[0], 276f51b7662SDaniel Vetter AGP_PAGE_DESTROY_FREE); 277f51b7662SDaniel Vetter } 278f51b7662SDaniel Vetter agp_free_page_array(curr); 279f51b7662SDaniel Vetter } 280f51b7662SDaniel Vetter kfree(curr); 281f51b7662SDaniel Vetter } 282f51b7662SDaniel Vetter 2830e87d2b0SDaniel Vetter static int intel_gtt_setup_scratch_page(void) 2840e87d2b0SDaniel Vetter { 2850e87d2b0SDaniel Vetter struct page *page; 2860e87d2b0SDaniel Vetter dma_addr_t dma_addr; 2870e87d2b0SDaniel Vetter 2880e87d2b0SDaniel Vetter page = alloc_page(GFP_KERNEL | GFP_DMA32 | __GFP_ZERO); 2890e87d2b0SDaniel Vetter if (page == NULL) 2900e87d2b0SDaniel Vetter return -ENOMEM; 2910e87d2b0SDaniel Vetter get_page(page); 2920e87d2b0SDaniel Vetter set_pages_uc(page, 1); 2930e87d2b0SDaniel Vetter 2944080775bSDaniel Vetter if (intel_private.base.needs_dmar) { 2950e87d2b0SDaniel Vetter dma_addr = pci_map_page(intel_private.pcidev, page, 0, 2960e87d2b0SDaniel Vetter PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); 2970e87d2b0SDaniel Vetter if (pci_dma_mapping_error(intel_private.pcidev, dma_addr)) 2980e87d2b0SDaniel Vetter return -EINVAL; 2990e87d2b0SDaniel Vetter 30050a4c4a9SDaniel Vetter intel_private.base.scratch_page_dma = dma_addr; 3010e87d2b0SDaniel Vetter } else 30250a4c4a9SDaniel Vetter intel_private.base.scratch_page_dma = page_to_phys(page); 3030e87d2b0SDaniel Vetter 3040e87d2b0SDaniel Vetter intel_private.scratch_page = page; 3050e87d2b0SDaniel Vetter 3060e87d2b0SDaniel Vetter return 0; 3070e87d2b0SDaniel Vetter } 3080e87d2b0SDaniel Vetter 309625dd9d3SDaniel Vetter static void i810_write_entry(dma_addr_t addr, unsigned int entry, 310625dd9d3SDaniel Vetter unsigned int flags) 311625dd9d3SDaniel Vetter { 312625dd9d3SDaniel Vetter u32 pte_flags = I810_PTE_VALID; 313625dd9d3SDaniel Vetter 314625dd9d3SDaniel Vetter switch (flags) { 315625dd9d3SDaniel Vetter case AGP_DCACHE_MEMORY: 316625dd9d3SDaniel Vetter pte_flags |= I810_PTE_LOCAL; 317625dd9d3SDaniel Vetter break; 318625dd9d3SDaniel Vetter case AGP_USER_CACHED_MEMORY: 319625dd9d3SDaniel Vetter pte_flags |= I830_PTE_SYSTEM_CACHED; 320625dd9d3SDaniel Vetter break; 321625dd9d3SDaniel Vetter } 322625dd9d3SDaniel Vetter 323625dd9d3SDaniel Vetter writel(addr | pte_flags, intel_private.gtt + entry); 324625dd9d3SDaniel Vetter } 325625dd9d3SDaniel Vetter 3267bdc9ab0SChris Wilson static const struct aper_size_info_fixed intel_fake_agp_sizes[] = { 327820647b9SDaniel Vetter {32, 8192, 3}, 328820647b9SDaniel Vetter {64, 16384, 4}, 329f51b7662SDaniel Vetter {128, 32768, 5}, 330f51b7662SDaniel Vetter {256, 65536, 6}, 331f51b7662SDaniel Vetter {512, 131072, 7}, 332f51b7662SDaniel Vetter }; 333f51b7662SDaniel Vetter 334c64f7ba5SChris Wilson static unsigned int intel_gtt_stolen_size(void) 335f51b7662SDaniel Vetter { 336f51b7662SDaniel Vetter u16 gmch_ctrl; 337f51b7662SDaniel Vetter u8 rdct; 338f51b7662SDaniel Vetter int local = 0; 339f51b7662SDaniel Vetter static const int ddt[4] = { 0, 16, 32, 64 }; 340d8d9abcdSDaniel Vetter unsigned int stolen_size = 0; 341f51b7662SDaniel Vetter 342820647b9SDaniel Vetter if (INTEL_GTT_GEN == 1) 343820647b9SDaniel Vetter return 0; /* no stolen mem on i81x */ 344820647b9SDaniel Vetter 345d7cca2f7SDaniel Vetter pci_read_config_word(intel_private.bridge_dev, 346d7cca2f7SDaniel Vetter I830_GMCH_CTRL, &gmch_ctrl); 347f51b7662SDaniel Vetter 348d7cca2f7SDaniel Vetter if (intel_private.bridge_dev->device == PCI_DEVICE_ID_INTEL_82830_HB || 349d7cca2f7SDaniel Vetter intel_private.bridge_dev->device == PCI_DEVICE_ID_INTEL_82845G_HB) { 350f51b7662SDaniel Vetter switch (gmch_ctrl & I830_GMCH_GMS_MASK) { 351f51b7662SDaniel Vetter case I830_GMCH_GMS_STOLEN_512: 352d8d9abcdSDaniel Vetter stolen_size = KB(512); 353f51b7662SDaniel Vetter break; 354f51b7662SDaniel Vetter case I830_GMCH_GMS_STOLEN_1024: 355d8d9abcdSDaniel Vetter stolen_size = MB(1); 356f51b7662SDaniel Vetter break; 357f51b7662SDaniel Vetter case I830_GMCH_GMS_STOLEN_8192: 358d8d9abcdSDaniel Vetter stolen_size = MB(8); 359f51b7662SDaniel Vetter break; 360f51b7662SDaniel Vetter case I830_GMCH_GMS_LOCAL: 361f51b7662SDaniel Vetter rdct = readb(intel_private.registers+I830_RDRAM_CHANNEL_TYPE); 362d8d9abcdSDaniel Vetter stolen_size = (I830_RDRAM_ND(rdct) + 1) * 363f51b7662SDaniel Vetter MB(ddt[I830_RDRAM_DDT(rdct)]); 364f51b7662SDaniel Vetter local = 1; 365f51b7662SDaniel Vetter break; 366f51b7662SDaniel Vetter default: 367d8d9abcdSDaniel Vetter stolen_size = 0; 368f51b7662SDaniel Vetter break; 369f51b7662SDaniel Vetter } 3701a997ff2SDaniel Vetter } else if (INTEL_GTT_GEN == 6) { 371f51b7662SDaniel Vetter /* 372f51b7662SDaniel Vetter * SandyBridge has new memory control reg at 0x50.w 373f51b7662SDaniel Vetter */ 374f51b7662SDaniel Vetter u16 snb_gmch_ctl; 375f51b7662SDaniel Vetter pci_read_config_word(intel_private.pcidev, SNB_GMCH_CTRL, &snb_gmch_ctl); 376f51b7662SDaniel Vetter switch (snb_gmch_ctl & SNB_GMCH_GMS_STOLEN_MASK) { 377f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_32M: 378d8d9abcdSDaniel Vetter stolen_size = MB(32); 379f51b7662SDaniel Vetter break; 380f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_64M: 381d8d9abcdSDaniel Vetter stolen_size = MB(64); 382f51b7662SDaniel Vetter break; 383f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_96M: 384d8d9abcdSDaniel Vetter stolen_size = MB(96); 385f51b7662SDaniel Vetter break; 386f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_128M: 387d8d9abcdSDaniel Vetter stolen_size = MB(128); 388f51b7662SDaniel Vetter break; 389f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_160M: 390d8d9abcdSDaniel Vetter stolen_size = MB(160); 391f51b7662SDaniel Vetter break; 392f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_192M: 393d8d9abcdSDaniel Vetter stolen_size = MB(192); 394f51b7662SDaniel Vetter break; 395f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_224M: 396d8d9abcdSDaniel Vetter stolen_size = MB(224); 397f51b7662SDaniel Vetter break; 398f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_256M: 399d8d9abcdSDaniel Vetter stolen_size = MB(256); 400f51b7662SDaniel Vetter break; 401f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_288M: 402d8d9abcdSDaniel Vetter stolen_size = MB(288); 403f51b7662SDaniel Vetter break; 404f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_320M: 405d8d9abcdSDaniel Vetter stolen_size = MB(320); 406f51b7662SDaniel Vetter break; 407f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_352M: 408d8d9abcdSDaniel Vetter stolen_size = MB(352); 409f51b7662SDaniel Vetter break; 410f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_384M: 411d8d9abcdSDaniel Vetter stolen_size = MB(384); 412f51b7662SDaniel Vetter break; 413f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_416M: 414d8d9abcdSDaniel Vetter stolen_size = MB(416); 415f51b7662SDaniel Vetter break; 416f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_448M: 417d8d9abcdSDaniel Vetter stolen_size = MB(448); 418f51b7662SDaniel Vetter break; 419f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_480M: 420d8d9abcdSDaniel Vetter stolen_size = MB(480); 421f51b7662SDaniel Vetter break; 422f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_512M: 423d8d9abcdSDaniel Vetter stolen_size = MB(512); 424f51b7662SDaniel Vetter break; 425f51b7662SDaniel Vetter } 426f51b7662SDaniel Vetter } else { 427f51b7662SDaniel Vetter switch (gmch_ctrl & I855_GMCH_GMS_MASK) { 428f51b7662SDaniel Vetter case I855_GMCH_GMS_STOLEN_1M: 429d8d9abcdSDaniel Vetter stolen_size = MB(1); 430f51b7662SDaniel Vetter break; 431f51b7662SDaniel Vetter case I855_GMCH_GMS_STOLEN_4M: 432d8d9abcdSDaniel Vetter stolen_size = MB(4); 433f51b7662SDaniel Vetter break; 434f51b7662SDaniel Vetter case I855_GMCH_GMS_STOLEN_8M: 435d8d9abcdSDaniel Vetter stolen_size = MB(8); 436f51b7662SDaniel Vetter break; 437f51b7662SDaniel Vetter case I855_GMCH_GMS_STOLEN_16M: 438d8d9abcdSDaniel Vetter stolen_size = MB(16); 439f51b7662SDaniel Vetter break; 440f51b7662SDaniel Vetter case I855_GMCH_GMS_STOLEN_32M: 441d8d9abcdSDaniel Vetter stolen_size = MB(32); 442f51b7662SDaniel Vetter break; 443f51b7662SDaniel Vetter case I915_GMCH_GMS_STOLEN_48M: 444d8d9abcdSDaniel Vetter stolen_size = MB(48); 445f51b7662SDaniel Vetter break; 446f51b7662SDaniel Vetter case I915_GMCH_GMS_STOLEN_64M: 447d8d9abcdSDaniel Vetter stolen_size = MB(64); 448f51b7662SDaniel Vetter break; 449f51b7662SDaniel Vetter case G33_GMCH_GMS_STOLEN_128M: 450d8d9abcdSDaniel Vetter stolen_size = MB(128); 451f51b7662SDaniel Vetter break; 452f51b7662SDaniel Vetter case G33_GMCH_GMS_STOLEN_256M: 453d8d9abcdSDaniel Vetter stolen_size = MB(256); 454f51b7662SDaniel Vetter break; 455f51b7662SDaniel Vetter case INTEL_GMCH_GMS_STOLEN_96M: 456d8d9abcdSDaniel Vetter stolen_size = MB(96); 457f51b7662SDaniel Vetter break; 458f51b7662SDaniel Vetter case INTEL_GMCH_GMS_STOLEN_160M: 459d8d9abcdSDaniel Vetter stolen_size = MB(160); 460f51b7662SDaniel Vetter break; 461f51b7662SDaniel Vetter case INTEL_GMCH_GMS_STOLEN_224M: 462d8d9abcdSDaniel Vetter stolen_size = MB(224); 463f51b7662SDaniel Vetter break; 464f51b7662SDaniel Vetter case INTEL_GMCH_GMS_STOLEN_352M: 465d8d9abcdSDaniel Vetter stolen_size = MB(352); 466f51b7662SDaniel Vetter break; 467f51b7662SDaniel Vetter default: 468d8d9abcdSDaniel Vetter stolen_size = 0; 469f51b7662SDaniel Vetter break; 470f51b7662SDaniel Vetter } 471f51b7662SDaniel Vetter } 4721784a5fbSDaniel Vetter 4731b6064d7SChris Wilson if (stolen_size > 0) { 474d7cca2f7SDaniel Vetter dev_info(&intel_private.bridge_dev->dev, "detected %dK %s memory\n", 475d8d9abcdSDaniel Vetter stolen_size / KB(1), local ? "local" : "stolen"); 476f51b7662SDaniel Vetter } else { 477d7cca2f7SDaniel Vetter dev_info(&intel_private.bridge_dev->dev, 478f51b7662SDaniel Vetter "no pre-allocated video memory detected\n"); 479d8d9abcdSDaniel Vetter stolen_size = 0; 480f51b7662SDaniel Vetter } 481f51b7662SDaniel Vetter 482c64f7ba5SChris Wilson return stolen_size; 483f51b7662SDaniel Vetter } 484f51b7662SDaniel Vetter 48520172842SDaniel Vetter static void i965_adjust_pgetbl_size(unsigned int size_flag) 48620172842SDaniel Vetter { 48720172842SDaniel Vetter u32 pgetbl_ctl, pgetbl_ctl2; 48820172842SDaniel Vetter 48920172842SDaniel Vetter /* ensure that ppgtt is disabled */ 49020172842SDaniel Vetter pgetbl_ctl2 = readl(intel_private.registers+I965_PGETBL_CTL2); 49120172842SDaniel Vetter pgetbl_ctl2 &= ~I810_PGETBL_ENABLED; 49220172842SDaniel Vetter writel(pgetbl_ctl2, intel_private.registers+I965_PGETBL_CTL2); 49320172842SDaniel Vetter 49420172842SDaniel Vetter /* write the new ggtt size */ 49520172842SDaniel Vetter pgetbl_ctl = readl(intel_private.registers+I810_PGETBL_CTL); 49620172842SDaniel Vetter pgetbl_ctl &= ~I965_PGETBL_SIZE_MASK; 49720172842SDaniel Vetter pgetbl_ctl |= size_flag; 49820172842SDaniel Vetter writel(pgetbl_ctl, intel_private.registers+I810_PGETBL_CTL); 49920172842SDaniel Vetter } 50020172842SDaniel Vetter 50120172842SDaniel Vetter static unsigned int i965_gtt_total_entries(void) 502fbe40783SDaniel Vetter { 503fbe40783SDaniel Vetter int size; 504fbe40783SDaniel Vetter u32 pgetbl_ctl; 50520172842SDaniel Vetter u16 gmch_ctl; 50620172842SDaniel Vetter 50720172842SDaniel Vetter pci_read_config_word(intel_private.bridge_dev, 50820172842SDaniel Vetter I830_GMCH_CTRL, &gmch_ctl); 50920172842SDaniel Vetter 51020172842SDaniel Vetter if (INTEL_GTT_GEN == 5) { 51120172842SDaniel Vetter switch (gmch_ctl & G4x_GMCH_SIZE_MASK) { 51220172842SDaniel Vetter case G4x_GMCH_SIZE_1M: 51320172842SDaniel Vetter case G4x_GMCH_SIZE_VT_1M: 51420172842SDaniel Vetter i965_adjust_pgetbl_size(I965_PGETBL_SIZE_1MB); 51520172842SDaniel Vetter break; 51620172842SDaniel Vetter case G4x_GMCH_SIZE_VT_1_5M: 51720172842SDaniel Vetter i965_adjust_pgetbl_size(I965_PGETBL_SIZE_1_5MB); 51820172842SDaniel Vetter break; 51920172842SDaniel Vetter case G4x_GMCH_SIZE_2M: 52020172842SDaniel Vetter case G4x_GMCH_SIZE_VT_2M: 52120172842SDaniel Vetter i965_adjust_pgetbl_size(I965_PGETBL_SIZE_2MB); 52220172842SDaniel Vetter break; 52320172842SDaniel Vetter } 52420172842SDaniel Vetter } 52520172842SDaniel Vetter 526fbe40783SDaniel Vetter pgetbl_ctl = readl(intel_private.registers+I810_PGETBL_CTL); 527fbe40783SDaniel Vetter 528fbe40783SDaniel Vetter switch (pgetbl_ctl & I965_PGETBL_SIZE_MASK) { 529fbe40783SDaniel Vetter case I965_PGETBL_SIZE_128KB: 530e5e408fcSDaniel Vetter size = KB(128); 531fbe40783SDaniel Vetter break; 532fbe40783SDaniel Vetter case I965_PGETBL_SIZE_256KB: 533e5e408fcSDaniel Vetter size = KB(256); 534fbe40783SDaniel Vetter break; 535fbe40783SDaniel Vetter case I965_PGETBL_SIZE_512KB: 536e5e408fcSDaniel Vetter size = KB(512); 537fbe40783SDaniel Vetter break; 53820172842SDaniel Vetter /* GTT pagetable sizes bigger than 512KB are not possible on G33! */ 539fbe40783SDaniel Vetter case I965_PGETBL_SIZE_1MB: 540e5e408fcSDaniel Vetter size = KB(1024); 541fbe40783SDaniel Vetter break; 542fbe40783SDaniel Vetter case I965_PGETBL_SIZE_2MB: 543e5e408fcSDaniel Vetter size = KB(2048); 544fbe40783SDaniel Vetter break; 545fbe40783SDaniel Vetter case I965_PGETBL_SIZE_1_5MB: 546e5e408fcSDaniel Vetter size = KB(1024 + 512); 547fbe40783SDaniel Vetter break; 548fbe40783SDaniel Vetter default: 549fbe40783SDaniel Vetter dev_info(&intel_private.pcidev->dev, 550fbe40783SDaniel Vetter "unknown page table size, assuming 512KB\n"); 551e5e408fcSDaniel Vetter size = KB(512); 552fbe40783SDaniel Vetter } 553e5e408fcSDaniel Vetter 554e5e408fcSDaniel Vetter return size/4; 55520172842SDaniel Vetter } 55620172842SDaniel Vetter 55720172842SDaniel Vetter static unsigned int intel_gtt_total_entries(void) 55820172842SDaniel Vetter { 55920172842SDaniel Vetter int size; 56020172842SDaniel Vetter 56120172842SDaniel Vetter if (IS_G33 || INTEL_GTT_GEN == 4 || INTEL_GTT_GEN == 5) 56220172842SDaniel Vetter return i965_gtt_total_entries(); 56320172842SDaniel Vetter else if (INTEL_GTT_GEN == 6) { 564210b23c2SDaniel Vetter u16 snb_gmch_ctl; 565210b23c2SDaniel Vetter 566210b23c2SDaniel Vetter pci_read_config_word(intel_private.pcidev, SNB_GMCH_CTRL, &snb_gmch_ctl); 567210b23c2SDaniel Vetter switch (snb_gmch_ctl & SNB_GTT_SIZE_MASK) { 568210b23c2SDaniel Vetter default: 569210b23c2SDaniel Vetter case SNB_GTT_SIZE_0M: 570210b23c2SDaniel Vetter printk(KERN_ERR "Bad GTT size mask: 0x%04x.\n", snb_gmch_ctl); 571210b23c2SDaniel Vetter size = MB(0); 572210b23c2SDaniel Vetter break; 573210b23c2SDaniel Vetter case SNB_GTT_SIZE_1M: 574210b23c2SDaniel Vetter size = MB(1); 575210b23c2SDaniel Vetter break; 576210b23c2SDaniel Vetter case SNB_GTT_SIZE_2M: 577210b23c2SDaniel Vetter size = MB(2); 578210b23c2SDaniel Vetter break; 579210b23c2SDaniel Vetter } 580210b23c2SDaniel Vetter return size/4; 581fbe40783SDaniel Vetter } else { 582fbe40783SDaniel Vetter /* On previous hardware, the GTT size was just what was 583fbe40783SDaniel Vetter * required to map the aperture. 584fbe40783SDaniel Vetter */ 585e5e408fcSDaniel Vetter return intel_private.base.gtt_mappable_entries; 586fbe40783SDaniel Vetter } 587fbe40783SDaniel Vetter } 588fbe40783SDaniel Vetter 5891784a5fbSDaniel Vetter static unsigned int intel_gtt_mappable_entries(void) 5901784a5fbSDaniel Vetter { 5911784a5fbSDaniel Vetter unsigned int aperture_size; 5921784a5fbSDaniel Vetter 593820647b9SDaniel Vetter if (INTEL_GTT_GEN == 1) { 594820647b9SDaniel Vetter u32 smram_miscc; 595820647b9SDaniel Vetter 596820647b9SDaniel Vetter pci_read_config_dword(intel_private.bridge_dev, 597820647b9SDaniel Vetter I810_SMRAM_MISCC, &smram_miscc); 598820647b9SDaniel Vetter 599820647b9SDaniel Vetter if ((smram_miscc & I810_GFX_MEM_WIN_SIZE) 600820647b9SDaniel Vetter == I810_GFX_MEM_WIN_32M) 601820647b9SDaniel Vetter aperture_size = MB(32); 602820647b9SDaniel Vetter else 603820647b9SDaniel Vetter aperture_size = MB(64); 604820647b9SDaniel Vetter } else if (INTEL_GTT_GEN == 2) { 605b1c5b0f8SChris Wilson u16 gmch_ctrl; 6061784a5fbSDaniel Vetter 6071784a5fbSDaniel Vetter pci_read_config_word(intel_private.bridge_dev, 6081784a5fbSDaniel Vetter I830_GMCH_CTRL, &gmch_ctrl); 6091784a5fbSDaniel Vetter 6101784a5fbSDaniel Vetter if ((gmch_ctrl & I830_GMCH_MEM_MASK) == I830_GMCH_MEM_64M) 611b1c5b0f8SChris Wilson aperture_size = MB(64); 6121784a5fbSDaniel Vetter else 613b1c5b0f8SChris Wilson aperture_size = MB(128); 614239918f7SDaniel Vetter } else { 6151784a5fbSDaniel Vetter /* 9xx supports large sizes, just look at the length */ 6161784a5fbSDaniel Vetter aperture_size = pci_resource_len(intel_private.pcidev, 2); 6171784a5fbSDaniel Vetter } 6181784a5fbSDaniel Vetter 6191784a5fbSDaniel Vetter return aperture_size >> PAGE_SHIFT; 6201784a5fbSDaniel Vetter } 6211784a5fbSDaniel Vetter 6220e87d2b0SDaniel Vetter static void intel_gtt_teardown_scratch_page(void) 6230e87d2b0SDaniel Vetter { 6240e87d2b0SDaniel Vetter set_pages_wb(intel_private.scratch_page, 1); 62550a4c4a9SDaniel Vetter pci_unmap_page(intel_private.pcidev, intel_private.base.scratch_page_dma, 6260e87d2b0SDaniel Vetter PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); 6270e87d2b0SDaniel Vetter put_page(intel_private.scratch_page); 6280e87d2b0SDaniel Vetter __free_page(intel_private.scratch_page); 6290e87d2b0SDaniel Vetter } 6300e87d2b0SDaniel Vetter 6310e87d2b0SDaniel Vetter static void intel_gtt_cleanup(void) 6320e87d2b0SDaniel Vetter { 633ae83dd5cSDaniel Vetter intel_private.driver->cleanup(); 634ae83dd5cSDaniel Vetter 6350e87d2b0SDaniel Vetter iounmap(intel_private.gtt); 6360e87d2b0SDaniel Vetter iounmap(intel_private.registers); 6370e87d2b0SDaniel Vetter 6380e87d2b0SDaniel Vetter intel_gtt_teardown_scratch_page(); 6390e87d2b0SDaniel Vetter } 6400e87d2b0SDaniel Vetter 6411784a5fbSDaniel Vetter static int intel_gtt_init(void) 6421784a5fbSDaniel Vetter { 64332e3cd6eSDaniel Vetter u32 gma_addr; 644f67eab66SDaniel Vetter u32 gtt_map_size; 6453b15a9d7SDaniel Vetter int ret; 6463b15a9d7SDaniel Vetter 6473b15a9d7SDaniel Vetter ret = intel_private.driver->setup(); 6483b15a9d7SDaniel Vetter if (ret != 0) 6493b15a9d7SDaniel Vetter return ret; 650f67eab66SDaniel Vetter 651f67eab66SDaniel Vetter intel_private.base.gtt_mappable_entries = intel_gtt_mappable_entries(); 652f67eab66SDaniel Vetter intel_private.base.gtt_total_entries = intel_gtt_total_entries(); 653f67eab66SDaniel Vetter 654b3eafc5aSDaniel Vetter /* save the PGETBL reg for resume */ 655b3eafc5aSDaniel Vetter intel_private.PGETBL_save = 656b3eafc5aSDaniel Vetter readl(intel_private.registers+I810_PGETBL_CTL) 657b3eafc5aSDaniel Vetter & ~I810_PGETBL_ENABLED; 658100519e2SChris Wilson /* we only ever restore the register when enabling the PGTBL... */ 659100519e2SChris Wilson if (HAS_PGTBL_EN) 660100519e2SChris Wilson intel_private.PGETBL_save |= I810_PGETBL_ENABLED; 661b3eafc5aSDaniel Vetter 6620af9e92eSDaniel Vetter dev_info(&intel_private.bridge_dev->dev, 6630af9e92eSDaniel Vetter "detected gtt size: %dK total, %dK mappable\n", 6640af9e92eSDaniel Vetter intel_private.base.gtt_total_entries * 4, 6650af9e92eSDaniel Vetter intel_private.base.gtt_mappable_entries * 4); 6660af9e92eSDaniel Vetter 667f67eab66SDaniel Vetter gtt_map_size = intel_private.base.gtt_total_entries * 4; 668f67eab66SDaniel Vetter 669f67eab66SDaniel Vetter intel_private.gtt = ioremap(intel_private.gtt_bus_addr, 670f67eab66SDaniel Vetter gtt_map_size); 671f67eab66SDaniel Vetter if (!intel_private.gtt) { 672ae83dd5cSDaniel Vetter intel_private.driver->cleanup(); 673f67eab66SDaniel Vetter iounmap(intel_private.registers); 674f67eab66SDaniel Vetter return -ENOMEM; 675f67eab66SDaniel Vetter } 676428ccb21SDaniel Vetter intel_private.base.gtt = intel_private.gtt; 677f67eab66SDaniel Vetter 678f67eab66SDaniel Vetter global_cache_flush(); /* FIXME: ? */ 679f67eab66SDaniel Vetter 680c64f7ba5SChris Wilson intel_private.base.stolen_size = intel_gtt_stolen_size(); 6811784a5fbSDaniel Vetter 682a46f3108SDave Airlie intel_private.base.needs_dmar = USE_PCI_DMA_API && INTEL_GTT_GEN > 2; 683a46f3108SDave Airlie 6840e87d2b0SDaniel Vetter ret = intel_gtt_setup_scratch_page(); 6850e87d2b0SDaniel Vetter if (ret != 0) { 6860e87d2b0SDaniel Vetter intel_gtt_cleanup(); 6870e87d2b0SDaniel Vetter return ret; 6880e87d2b0SDaniel Vetter } 6890e87d2b0SDaniel Vetter 69032e3cd6eSDaniel Vetter if (INTEL_GTT_GEN <= 2) 69132e3cd6eSDaniel Vetter pci_read_config_dword(intel_private.pcidev, I810_GMADDR, 69232e3cd6eSDaniel Vetter &gma_addr); 69332e3cd6eSDaniel Vetter else 69432e3cd6eSDaniel Vetter pci_read_config_dword(intel_private.pcidev, I915_GMADDR, 69532e3cd6eSDaniel Vetter &gma_addr); 69632e3cd6eSDaniel Vetter 69732e3cd6eSDaniel Vetter intel_private.base.gma_bus_addr = (gma_addr & PCI_BASE_ADDRESS_MEM_MASK); 69832e3cd6eSDaniel Vetter 6991784a5fbSDaniel Vetter return 0; 7001784a5fbSDaniel Vetter } 7011784a5fbSDaniel Vetter 7023e921f98SDaniel Vetter static int intel_fake_agp_fetch_size(void) 7033e921f98SDaniel Vetter { 7049e76e7b8SChris Wilson int num_sizes = ARRAY_SIZE(intel_fake_agp_sizes); 7053e921f98SDaniel Vetter unsigned int aper_size; 7063e921f98SDaniel Vetter int i; 7073e921f98SDaniel Vetter 7083e921f98SDaniel Vetter aper_size = (intel_private.base.gtt_mappable_entries << PAGE_SHIFT) 7093e921f98SDaniel Vetter / MB(1); 7103e921f98SDaniel Vetter 7113e921f98SDaniel Vetter for (i = 0; i < num_sizes; i++) { 712ffdd7510SDaniel Vetter if (aper_size == intel_fake_agp_sizes[i].size) { 7139e76e7b8SChris Wilson agp_bridge->current_size = 7149e76e7b8SChris Wilson (void *) (intel_fake_agp_sizes + i); 7153e921f98SDaniel Vetter return aper_size; 7163e921f98SDaniel Vetter } 7173e921f98SDaniel Vetter } 7183e921f98SDaniel Vetter 7193e921f98SDaniel Vetter return 0; 7203e921f98SDaniel Vetter } 7213e921f98SDaniel Vetter 722ae83dd5cSDaniel Vetter static void i830_cleanup(void) 723f51b7662SDaniel Vetter { 724f51b7662SDaniel Vetter } 725f51b7662SDaniel Vetter 726f51b7662SDaniel Vetter /* The chipset_flush interface needs to get data that has already been 727f51b7662SDaniel Vetter * flushed out of the CPU all the way out to main memory, because the GPU 728f51b7662SDaniel Vetter * doesn't snoop those buffers. 729f51b7662SDaniel Vetter * 730f51b7662SDaniel Vetter * The 8xx series doesn't have the same lovely interface for flushing the 731f51b7662SDaniel Vetter * chipset write buffers that the later chips do. According to the 865 732f51b7662SDaniel Vetter * specs, it's 64 octwords, or 1KB. So, to get those previous things in 733f51b7662SDaniel Vetter * that buffer out, we just fill 1KB and clflush it out, on the assumption 734f51b7662SDaniel Vetter * that it'll push whatever was in there out. It appears to work. 735f51b7662SDaniel Vetter */ 7361b263f24SDaniel Vetter static void i830_chipset_flush(void) 737f51b7662SDaniel Vetter { 738bdb8b975SChris Wilson unsigned long timeout = jiffies + msecs_to_jiffies(1000); 739f51b7662SDaniel Vetter 740bdb8b975SChris Wilson /* Forcibly evict everything from the CPU write buffers. 741bdb8b975SChris Wilson * clflush appears to be insufficient. 742bdb8b975SChris Wilson */ 743bdb8b975SChris Wilson wbinvd_on_all_cpus(); 744f51b7662SDaniel Vetter 745bdb8b975SChris Wilson /* Now we've only seen documents for this magic bit on 855GM, 746bdb8b975SChris Wilson * we hope it exists for the other gen2 chipsets... 747bdb8b975SChris Wilson * 748bdb8b975SChris Wilson * Also works as advertised on my 845G. 749bdb8b975SChris Wilson */ 750bdb8b975SChris Wilson writel(readl(intel_private.registers+I830_HIC) | (1<<31), 751bdb8b975SChris Wilson intel_private.registers+I830_HIC); 752bdb8b975SChris Wilson 753bdb8b975SChris Wilson while (readl(intel_private.registers+I830_HIC) & (1<<31)) { 754bdb8b975SChris Wilson if (time_after(jiffies, timeout)) 755bdb8b975SChris Wilson break; 756bdb8b975SChris Wilson 757bdb8b975SChris Wilson udelay(50); 758bdb8b975SChris Wilson } 759f51b7662SDaniel Vetter } 760f51b7662SDaniel Vetter 761351bb278SDaniel Vetter static void i830_write_entry(dma_addr_t addr, unsigned int entry, 762351bb278SDaniel Vetter unsigned int flags) 763351bb278SDaniel Vetter { 764351bb278SDaniel Vetter u32 pte_flags = I810_PTE_VALID; 765351bb278SDaniel Vetter 766b47cf66fSDaniel Vetter if (flags == AGP_USER_CACHED_MEMORY) 767351bb278SDaniel Vetter pte_flags |= I830_PTE_SYSTEM_CACHED; 768351bb278SDaniel Vetter 769351bb278SDaniel Vetter writel(addr | pte_flags, intel_private.gtt + entry); 770351bb278SDaniel Vetter } 771351bb278SDaniel Vetter 7728ecd1a66SDaniel Vetter bool intel_enable_gtt(void) 77373800422SDaniel Vetter { 774e380f60bSChris Wilson u8 __iomem *reg; 77573800422SDaniel Vetter 776e380f60bSChris Wilson if (INTEL_GTT_GEN >= 6) 777e380f60bSChris Wilson return true; 77873800422SDaniel Vetter 779100519e2SChris Wilson if (INTEL_GTT_GEN == 2) { 780100519e2SChris Wilson u16 gmch_ctrl; 781100519e2SChris Wilson 782e380f60bSChris Wilson pci_read_config_word(intel_private.bridge_dev, 783e380f60bSChris Wilson I830_GMCH_CTRL, &gmch_ctrl); 784e380f60bSChris Wilson gmch_ctrl |= I830_GMCH_ENABLED; 785e380f60bSChris Wilson pci_write_config_word(intel_private.bridge_dev, 786e380f60bSChris Wilson I830_GMCH_CTRL, gmch_ctrl); 787e380f60bSChris Wilson 788e380f60bSChris Wilson pci_read_config_word(intel_private.bridge_dev, 789e380f60bSChris Wilson I830_GMCH_CTRL, &gmch_ctrl); 790e380f60bSChris Wilson if ((gmch_ctrl & I830_GMCH_ENABLED) == 0) { 791e380f60bSChris Wilson dev_err(&intel_private.pcidev->dev, 792e380f60bSChris Wilson "failed to enable the GTT: GMCH_CTRL=%x\n", 793e380f60bSChris Wilson gmch_ctrl); 794e380f60bSChris Wilson return false; 795e380f60bSChris Wilson } 796100519e2SChris Wilson } 797e380f60bSChris Wilson 798c97689d8SChris Wilson /* On the resume path we may be adjusting the PGTBL value, so 799c97689d8SChris Wilson * be paranoid and flush all chipset write buffers... 800c97689d8SChris Wilson */ 801c97689d8SChris Wilson if (INTEL_GTT_GEN >= 3) 802c97689d8SChris Wilson writel(0, intel_private.registers+GFX_FLSH_CNTL); 803c97689d8SChris Wilson 804e380f60bSChris Wilson reg = intel_private.registers+I810_PGETBL_CTL; 805100519e2SChris Wilson writel(intel_private.PGETBL_save, reg); 806100519e2SChris Wilson if (HAS_PGTBL_EN && (readl(reg) & I810_PGETBL_ENABLED) == 0) { 807e380f60bSChris Wilson dev_err(&intel_private.pcidev->dev, 808100519e2SChris Wilson "failed to enable the GTT: PGETBL=%x [expected %x]\n", 809e380f60bSChris Wilson readl(reg), intel_private.PGETBL_save); 810e380f60bSChris Wilson return false; 811e380f60bSChris Wilson } 812e380f60bSChris Wilson 813c97689d8SChris Wilson if (INTEL_GTT_GEN >= 3) 814c97689d8SChris Wilson writel(0, intel_private.registers+GFX_FLSH_CNTL); 815c97689d8SChris Wilson 816e380f60bSChris Wilson return true; 81773800422SDaniel Vetter } 8188ecd1a66SDaniel Vetter EXPORT_SYMBOL(intel_enable_gtt); 81973800422SDaniel Vetter 82073800422SDaniel Vetter static int i830_setup(void) 82173800422SDaniel Vetter { 82273800422SDaniel Vetter u32 reg_addr; 82373800422SDaniel Vetter 82473800422SDaniel Vetter pci_read_config_dword(intel_private.pcidev, I810_MMADDR, ®_addr); 82573800422SDaniel Vetter reg_addr &= 0xfff80000; 82673800422SDaniel Vetter 82773800422SDaniel Vetter intel_private.registers = ioremap(reg_addr, KB(64)); 82873800422SDaniel Vetter if (!intel_private.registers) 82973800422SDaniel Vetter return -ENOMEM; 83073800422SDaniel Vetter 83173800422SDaniel Vetter intel_private.gtt_bus_addr = reg_addr + I810_PTE_BASE; 83273800422SDaniel Vetter 83373800422SDaniel Vetter return 0; 83473800422SDaniel Vetter } 83573800422SDaniel Vetter 8363b15a9d7SDaniel Vetter static int intel_fake_agp_create_gatt_table(struct agp_bridge_data *bridge) 837f51b7662SDaniel Vetter { 83873800422SDaniel Vetter agp_bridge->gatt_table_real = NULL; 839f51b7662SDaniel Vetter agp_bridge->gatt_table = NULL; 84073800422SDaniel Vetter agp_bridge->gatt_bus_addr = 0; 841f51b7662SDaniel Vetter 842f51b7662SDaniel Vetter return 0; 843f51b7662SDaniel Vetter } 844f51b7662SDaniel Vetter 845ffdd7510SDaniel Vetter static int intel_fake_agp_free_gatt_table(struct agp_bridge_data *bridge) 846f51b7662SDaniel Vetter { 847f51b7662SDaniel Vetter return 0; 848f51b7662SDaniel Vetter } 849f51b7662SDaniel Vetter 850351bb278SDaniel Vetter static int intel_fake_agp_configure(void) 851f51b7662SDaniel Vetter { 852e380f60bSChris Wilson if (!intel_enable_gtt()) 853e380f60bSChris Wilson return -EIO; 854f51b7662SDaniel Vetter 855bee4a186SChris Wilson intel_private.clear_fake_agp = true; 856dd2757f8SDaniel Vetter agp_bridge->gart_bus_addr = intel_private.base.gma_bus_addr; 857f51b7662SDaniel Vetter 858f51b7662SDaniel Vetter return 0; 859f51b7662SDaniel Vetter } 860f51b7662SDaniel Vetter 8615cbecafcSDaniel Vetter static bool i830_check_flags(unsigned int flags) 862f51b7662SDaniel Vetter { 8635cbecafcSDaniel Vetter switch (flags) { 8645cbecafcSDaniel Vetter case 0: 8655cbecafcSDaniel Vetter case AGP_PHYS_MEMORY: 8665cbecafcSDaniel Vetter case AGP_USER_CACHED_MEMORY: 8675cbecafcSDaniel Vetter case AGP_USER_MEMORY: 8685cbecafcSDaniel Vetter return true; 8695cbecafcSDaniel Vetter } 8705cbecafcSDaniel Vetter 8715cbecafcSDaniel Vetter return false; 8725cbecafcSDaniel Vetter } 8735cbecafcSDaniel Vetter 8749da3da66SChris Wilson void intel_gtt_insert_sg_entries(struct sg_table *st, 875fefaa70fSDaniel Vetter unsigned int pg_start, 876fefaa70fSDaniel Vetter unsigned int flags) 877fefaa70fSDaniel Vetter { 878fefaa70fSDaniel Vetter struct scatterlist *sg; 879fefaa70fSDaniel Vetter unsigned int len, m; 880fefaa70fSDaniel Vetter int i, j; 881fefaa70fSDaniel Vetter 882fefaa70fSDaniel Vetter j = pg_start; 883fefaa70fSDaniel Vetter 884fefaa70fSDaniel Vetter /* sg may merge pages, but we have to separate 885fefaa70fSDaniel Vetter * per-page addr for GTT */ 8869da3da66SChris Wilson for_each_sg(st->sgl, sg, st->nents, i) { 887fefaa70fSDaniel Vetter len = sg_dma_len(sg) >> PAGE_SHIFT; 888fefaa70fSDaniel Vetter for (m = 0; m < len; m++) { 889fefaa70fSDaniel Vetter dma_addr_t addr = sg_dma_address(sg) + (m << PAGE_SHIFT); 8909da3da66SChris Wilson intel_private.driver->write_entry(addr, j, flags); 891fefaa70fSDaniel Vetter j++; 892fefaa70fSDaniel Vetter } 893fefaa70fSDaniel Vetter } 894fefaa70fSDaniel Vetter readl(intel_private.gtt+j-1); 895fefaa70fSDaniel Vetter } 8964080775bSDaniel Vetter EXPORT_SYMBOL(intel_gtt_insert_sg_entries); 8974080775bSDaniel Vetter 8989da3da66SChris Wilson static void intel_gtt_insert_pages(unsigned int first_entry, 8999da3da66SChris Wilson unsigned int num_entries, 9009da3da66SChris Wilson struct page **pages, 9019da3da66SChris Wilson unsigned int flags) 9024080775bSDaniel Vetter { 9034080775bSDaniel Vetter int i, j; 9044080775bSDaniel Vetter 9054080775bSDaniel Vetter for (i = 0, j = first_entry; i < num_entries; i++, j++) { 9064080775bSDaniel Vetter dma_addr_t addr = page_to_phys(pages[i]); 9074080775bSDaniel Vetter intel_private.driver->write_entry(addr, 9084080775bSDaniel Vetter j, flags); 9094080775bSDaniel Vetter } 9104080775bSDaniel Vetter readl(intel_private.gtt+j-1); 9114080775bSDaniel Vetter } 912fefaa70fSDaniel Vetter 9135cbecafcSDaniel Vetter static int intel_fake_agp_insert_entries(struct agp_memory *mem, 9145cbecafcSDaniel Vetter off_t pg_start, int type) 9155cbecafcSDaniel Vetter { 916f51b7662SDaniel Vetter int ret = -EINVAL; 917f51b7662SDaniel Vetter 9185c042287SBen Widawsky if (intel_private.base.do_idle_maps) 9195c042287SBen Widawsky return -ENODEV; 9205c042287SBen Widawsky 921bee4a186SChris Wilson if (intel_private.clear_fake_agp) { 922bee4a186SChris Wilson int start = intel_private.base.stolen_size / PAGE_SIZE; 923bee4a186SChris Wilson int end = intel_private.base.gtt_mappable_entries; 924bee4a186SChris Wilson intel_gtt_clear_range(start, end - start); 925bee4a186SChris Wilson intel_private.clear_fake_agp = false; 926bee4a186SChris Wilson } 927bee4a186SChris Wilson 928ff26860fSDaniel Vetter if (INTEL_GTT_GEN == 1 && type == AGP_DCACHE_MEMORY) 929ff26860fSDaniel Vetter return i810_insert_dcache_entries(mem, pg_start, type); 930ff26860fSDaniel Vetter 931f51b7662SDaniel Vetter if (mem->page_count == 0) 932f51b7662SDaniel Vetter goto out; 933f51b7662SDaniel Vetter 934c64f7ba5SChris Wilson if (pg_start + mem->page_count > intel_private.base.gtt_total_entries) 935f51b7662SDaniel Vetter goto out_err; 936f51b7662SDaniel Vetter 937f51b7662SDaniel Vetter if (type != mem->type) 938f51b7662SDaniel Vetter goto out_err; 939f51b7662SDaniel Vetter 9405cbecafcSDaniel Vetter if (!intel_private.driver->check_flags(type)) 941f51b7662SDaniel Vetter goto out_err; 942f51b7662SDaniel Vetter 943f51b7662SDaniel Vetter if (!mem->is_flushed) 944f51b7662SDaniel Vetter global_cache_flush(); 945f51b7662SDaniel Vetter 9464080775bSDaniel Vetter if (intel_private.base.needs_dmar) { 9479da3da66SChris Wilson struct sg_table st; 9489da3da66SChris Wilson 9499da3da66SChris Wilson ret = intel_gtt_map_memory(mem->pages, mem->page_count, &st); 950fefaa70fSDaniel Vetter if (ret != 0) 951fefaa70fSDaniel Vetter return ret; 952fefaa70fSDaniel Vetter 9539da3da66SChris Wilson intel_gtt_insert_sg_entries(&st, pg_start, type); 9549da3da66SChris Wilson mem->sg_list = st.sgl; 9559da3da66SChris Wilson mem->num_sg = st.nents; 9564080775bSDaniel Vetter } else 9574080775bSDaniel Vetter intel_gtt_insert_pages(pg_start, mem->page_count, mem->pages, 9584080775bSDaniel Vetter type); 959f51b7662SDaniel Vetter 960f51b7662SDaniel Vetter out: 961f51b7662SDaniel Vetter ret = 0; 962f51b7662SDaniel Vetter out_err: 963f51b7662SDaniel Vetter mem->is_flushed = true; 964f51b7662SDaniel Vetter return ret; 965f51b7662SDaniel Vetter } 966f51b7662SDaniel Vetter 9674080775bSDaniel Vetter void intel_gtt_clear_range(unsigned int first_entry, unsigned int num_entries) 968f51b7662SDaniel Vetter { 9694080775bSDaniel Vetter unsigned int i; 970f51b7662SDaniel Vetter 9714080775bSDaniel Vetter for (i = first_entry; i < (first_entry + num_entries); i++) { 97250a4c4a9SDaniel Vetter intel_private.driver->write_entry(intel_private.base.scratch_page_dma, 9735cbecafcSDaniel Vetter i, 0); 974f51b7662SDaniel Vetter } 975fdfb58a9SDaniel Vetter readl(intel_private.gtt+i-1); 9764080775bSDaniel Vetter } 9774080775bSDaniel Vetter EXPORT_SYMBOL(intel_gtt_clear_range); 9784080775bSDaniel Vetter 9794080775bSDaniel Vetter static int intel_fake_agp_remove_entries(struct agp_memory *mem, 9804080775bSDaniel Vetter off_t pg_start, int type) 9814080775bSDaniel Vetter { 9824080775bSDaniel Vetter if (mem->page_count == 0) 9834080775bSDaniel Vetter return 0; 9844080775bSDaniel Vetter 9855c042287SBen Widawsky if (intel_private.base.do_idle_maps) 9865c042287SBen Widawsky return -ENODEV; 9875c042287SBen Widawsky 988d15eda5cSDave Airlie intel_gtt_clear_range(pg_start, mem->page_count); 989d15eda5cSDave Airlie 9904080775bSDaniel Vetter if (intel_private.base.needs_dmar) { 9914080775bSDaniel Vetter intel_gtt_unmap_memory(mem->sg_list, mem->num_sg); 9924080775bSDaniel Vetter mem->sg_list = NULL; 9934080775bSDaniel Vetter mem->num_sg = 0; 9944080775bSDaniel Vetter } 9954080775bSDaniel Vetter 996f51b7662SDaniel Vetter return 0; 997f51b7662SDaniel Vetter } 998f51b7662SDaniel Vetter 999ffdd7510SDaniel Vetter static struct agp_memory *intel_fake_agp_alloc_by_type(size_t pg_count, 1000ffdd7510SDaniel Vetter int type) 1001f51b7662SDaniel Vetter { 1002625dd9d3SDaniel Vetter struct agp_memory *new; 1003625dd9d3SDaniel Vetter 1004625dd9d3SDaniel Vetter if (type == AGP_DCACHE_MEMORY && INTEL_GTT_GEN == 1) { 1005625dd9d3SDaniel Vetter if (pg_count != intel_private.num_dcache_entries) 1006625dd9d3SDaniel Vetter return NULL; 1007625dd9d3SDaniel Vetter 1008625dd9d3SDaniel Vetter new = agp_create_memory(1); 1009625dd9d3SDaniel Vetter if (new == NULL) 1010625dd9d3SDaniel Vetter return NULL; 1011625dd9d3SDaniel Vetter 1012625dd9d3SDaniel Vetter new->type = AGP_DCACHE_MEMORY; 1013625dd9d3SDaniel Vetter new->page_count = pg_count; 1014625dd9d3SDaniel Vetter new->num_scratch_pages = 0; 1015625dd9d3SDaniel Vetter agp_free_page_array(new); 1016625dd9d3SDaniel Vetter return new; 1017625dd9d3SDaniel Vetter } 1018f51b7662SDaniel Vetter if (type == AGP_PHYS_MEMORY) 1019f51b7662SDaniel Vetter return alloc_agpphysmem_i8xx(pg_count, type); 1020f51b7662SDaniel Vetter /* always return NULL for other allocation types for now */ 1021f51b7662SDaniel Vetter return NULL; 1022f51b7662SDaniel Vetter } 1023f51b7662SDaniel Vetter 1024f51b7662SDaniel Vetter static int intel_alloc_chipset_flush_resource(void) 1025f51b7662SDaniel Vetter { 1026f51b7662SDaniel Vetter int ret; 1027d7cca2f7SDaniel Vetter ret = pci_bus_alloc_resource(intel_private.bridge_dev->bus, &intel_private.ifp_resource, PAGE_SIZE, 1028f51b7662SDaniel Vetter PAGE_SIZE, PCIBIOS_MIN_MEM, 0, 1029d7cca2f7SDaniel Vetter pcibios_align_resource, intel_private.bridge_dev); 1030f51b7662SDaniel Vetter 1031f51b7662SDaniel Vetter return ret; 1032f51b7662SDaniel Vetter } 1033f51b7662SDaniel Vetter 1034f51b7662SDaniel Vetter static void intel_i915_setup_chipset_flush(void) 1035f51b7662SDaniel Vetter { 1036f51b7662SDaniel Vetter int ret; 1037f51b7662SDaniel Vetter u32 temp; 1038f51b7662SDaniel Vetter 1039d7cca2f7SDaniel Vetter pci_read_config_dword(intel_private.bridge_dev, I915_IFPADDR, &temp); 1040f51b7662SDaniel Vetter if (!(temp & 0x1)) { 1041f51b7662SDaniel Vetter intel_alloc_chipset_flush_resource(); 1042f51b7662SDaniel Vetter intel_private.resource_valid = 1; 1043d7cca2f7SDaniel Vetter pci_write_config_dword(intel_private.bridge_dev, I915_IFPADDR, (intel_private.ifp_resource.start & 0xffffffff) | 0x1); 1044f51b7662SDaniel Vetter } else { 1045f51b7662SDaniel Vetter temp &= ~1; 1046f51b7662SDaniel Vetter 1047f51b7662SDaniel Vetter intel_private.resource_valid = 1; 1048f51b7662SDaniel Vetter intel_private.ifp_resource.start = temp; 1049f51b7662SDaniel Vetter intel_private.ifp_resource.end = temp + PAGE_SIZE; 1050f51b7662SDaniel Vetter ret = request_resource(&iomem_resource, &intel_private.ifp_resource); 1051f51b7662SDaniel Vetter /* some BIOSes reserve this area in a pnp some don't */ 1052f51b7662SDaniel Vetter if (ret) 1053f51b7662SDaniel Vetter intel_private.resource_valid = 0; 1054f51b7662SDaniel Vetter } 1055f51b7662SDaniel Vetter } 1056f51b7662SDaniel Vetter 1057f51b7662SDaniel Vetter static void intel_i965_g33_setup_chipset_flush(void) 1058f51b7662SDaniel Vetter { 1059f51b7662SDaniel Vetter u32 temp_hi, temp_lo; 1060f51b7662SDaniel Vetter int ret; 1061f51b7662SDaniel Vetter 1062d7cca2f7SDaniel Vetter pci_read_config_dword(intel_private.bridge_dev, I965_IFPADDR + 4, &temp_hi); 1063d7cca2f7SDaniel Vetter pci_read_config_dword(intel_private.bridge_dev, I965_IFPADDR, &temp_lo); 1064f51b7662SDaniel Vetter 1065f51b7662SDaniel Vetter if (!(temp_lo & 0x1)) { 1066f51b7662SDaniel Vetter 1067f51b7662SDaniel Vetter intel_alloc_chipset_flush_resource(); 1068f51b7662SDaniel Vetter 1069f51b7662SDaniel Vetter intel_private.resource_valid = 1; 1070d7cca2f7SDaniel Vetter pci_write_config_dword(intel_private.bridge_dev, I965_IFPADDR + 4, 1071f51b7662SDaniel Vetter upper_32_bits(intel_private.ifp_resource.start)); 1072d7cca2f7SDaniel Vetter pci_write_config_dword(intel_private.bridge_dev, I965_IFPADDR, (intel_private.ifp_resource.start & 0xffffffff) | 0x1); 1073f51b7662SDaniel Vetter } else { 1074f51b7662SDaniel Vetter u64 l64; 1075f51b7662SDaniel Vetter 1076f51b7662SDaniel Vetter temp_lo &= ~0x1; 1077f51b7662SDaniel Vetter l64 = ((u64)temp_hi << 32) | temp_lo; 1078f51b7662SDaniel Vetter 1079f51b7662SDaniel Vetter intel_private.resource_valid = 1; 1080f51b7662SDaniel Vetter intel_private.ifp_resource.start = l64; 1081f51b7662SDaniel Vetter intel_private.ifp_resource.end = l64 + PAGE_SIZE; 1082f51b7662SDaniel Vetter ret = request_resource(&iomem_resource, &intel_private.ifp_resource); 1083f51b7662SDaniel Vetter /* some BIOSes reserve this area in a pnp some don't */ 1084f51b7662SDaniel Vetter if (ret) 1085f51b7662SDaniel Vetter intel_private.resource_valid = 0; 1086f51b7662SDaniel Vetter } 1087f51b7662SDaniel Vetter } 1088f51b7662SDaniel Vetter 1089f51b7662SDaniel Vetter static void intel_i9xx_setup_flush(void) 1090f51b7662SDaniel Vetter { 1091f51b7662SDaniel Vetter /* return if already configured */ 1092f51b7662SDaniel Vetter if (intel_private.ifp_resource.start) 1093f51b7662SDaniel Vetter return; 1094f51b7662SDaniel Vetter 10951a997ff2SDaniel Vetter if (INTEL_GTT_GEN == 6) 1096f51b7662SDaniel Vetter return; 1097f51b7662SDaniel Vetter 1098f51b7662SDaniel Vetter /* setup a resource for this object */ 1099f51b7662SDaniel Vetter intel_private.ifp_resource.name = "Intel Flush Page"; 1100f51b7662SDaniel Vetter intel_private.ifp_resource.flags = IORESOURCE_MEM; 1101f51b7662SDaniel Vetter 1102f51b7662SDaniel Vetter /* Setup chipset flush for 915 */ 11031a997ff2SDaniel Vetter if (IS_G33 || INTEL_GTT_GEN >= 4) { 1104f51b7662SDaniel Vetter intel_i965_g33_setup_chipset_flush(); 1105f51b7662SDaniel Vetter } else { 1106f51b7662SDaniel Vetter intel_i915_setup_chipset_flush(); 1107f51b7662SDaniel Vetter } 1108f51b7662SDaniel Vetter 1109df51e7aaSChris Wilson if (intel_private.ifp_resource.start) 1110f51b7662SDaniel Vetter intel_private.i9xx_flush_page = ioremap_nocache(intel_private.ifp_resource.start, PAGE_SIZE); 1111f51b7662SDaniel Vetter if (!intel_private.i9xx_flush_page) 1112df51e7aaSChris Wilson dev_err(&intel_private.pcidev->dev, 1113df51e7aaSChris Wilson "can't ioremap flush page - no chipset flushing\n"); 1114f51b7662SDaniel Vetter } 1115f51b7662SDaniel Vetter 1116ae83dd5cSDaniel Vetter static void i9xx_cleanup(void) 1117ae83dd5cSDaniel Vetter { 1118ae83dd5cSDaniel Vetter if (intel_private.i9xx_flush_page) 1119ae83dd5cSDaniel Vetter iounmap(intel_private.i9xx_flush_page); 1120ae83dd5cSDaniel Vetter if (intel_private.resource_valid) 1121ae83dd5cSDaniel Vetter release_resource(&intel_private.ifp_resource); 1122ae83dd5cSDaniel Vetter intel_private.ifp_resource.start = 0; 1123ae83dd5cSDaniel Vetter intel_private.resource_valid = 0; 1124ae83dd5cSDaniel Vetter } 1125ae83dd5cSDaniel Vetter 11261b263f24SDaniel Vetter static void i9xx_chipset_flush(void) 1127f51b7662SDaniel Vetter { 1128f51b7662SDaniel Vetter if (intel_private.i9xx_flush_page) 1129f51b7662SDaniel Vetter writel(1, intel_private.i9xx_flush_page); 1130f51b7662SDaniel Vetter } 1131f51b7662SDaniel Vetter 113271f45660SChris Wilson static void i965_write_entry(dma_addr_t addr, 113371f45660SChris Wilson unsigned int entry, 1134a6963596SDaniel Vetter unsigned int flags) 1135a6963596SDaniel Vetter { 113671f45660SChris Wilson u32 pte_flags; 113771f45660SChris Wilson 113871f45660SChris Wilson pte_flags = I810_PTE_VALID; 113971f45660SChris Wilson if (flags == AGP_USER_CACHED_MEMORY) 114071f45660SChris Wilson pte_flags |= I830_PTE_SYSTEM_CACHED; 114171f45660SChris Wilson 1142a6963596SDaniel Vetter /* Shift high bits down */ 1143a6963596SDaniel Vetter addr |= (addr >> 28) & 0xf0; 114471f45660SChris Wilson writel(addr | pte_flags, intel_private.gtt + entry); 1145a6963596SDaniel Vetter } 1146a6963596SDaniel Vetter 114790cb149eSDaniel Vetter static bool gen6_check_flags(unsigned int flags) 114890cb149eSDaniel Vetter { 114990cb149eSDaniel Vetter return true; 115090cb149eSDaniel Vetter } 115190cb149eSDaniel Vetter 1152a843af18SDaniel Vetter static void haswell_write_entry(dma_addr_t addr, unsigned int entry, 1153a843af18SDaniel Vetter unsigned int flags) 1154a843af18SDaniel Vetter { 1155a843af18SDaniel Vetter unsigned int type_mask = flags & ~AGP_USER_CACHED_MEMORY_GFDT; 1156a843af18SDaniel Vetter unsigned int gfdt = flags & AGP_USER_CACHED_MEMORY_GFDT; 1157a843af18SDaniel Vetter u32 pte_flags; 1158a843af18SDaniel Vetter 1159a843af18SDaniel Vetter if (type_mask == AGP_USER_MEMORY) 1160a843af18SDaniel Vetter pte_flags = HSW_PTE_UNCACHED | I810_PTE_VALID; 1161a843af18SDaniel Vetter else if (type_mask == AGP_USER_CACHED_MEMORY_LLC_MLC) { 1162a843af18SDaniel Vetter pte_flags = GEN6_PTE_LLC_MLC | I810_PTE_VALID; 1163a843af18SDaniel Vetter if (gfdt) 1164a843af18SDaniel Vetter pte_flags |= GEN6_PTE_GFDT; 1165a843af18SDaniel Vetter } else { /* set 'normal'/'cached' to LLC by default */ 1166a843af18SDaniel Vetter pte_flags = GEN6_PTE_LLC | I810_PTE_VALID; 1167a843af18SDaniel Vetter if (gfdt) 1168a843af18SDaniel Vetter pte_flags |= GEN6_PTE_GFDT; 1169a843af18SDaniel Vetter } 1170a843af18SDaniel Vetter 1171a843af18SDaniel Vetter /* gen6 has bit11-4 for physical addr bit39-32 */ 1172a843af18SDaniel Vetter addr |= (addr >> 28) & 0xff0; 1173a843af18SDaniel Vetter writel(addr | pte_flags, intel_private.gtt + entry); 1174a843af18SDaniel Vetter } 1175a843af18SDaniel Vetter 117697ef1bddSDaniel Vetter static void gen6_write_entry(dma_addr_t addr, unsigned int entry, 117797ef1bddSDaniel Vetter unsigned int flags) 117897ef1bddSDaniel Vetter { 117997ef1bddSDaniel Vetter unsigned int type_mask = flags & ~AGP_USER_CACHED_MEMORY_GFDT; 118097ef1bddSDaniel Vetter unsigned int gfdt = flags & AGP_USER_CACHED_MEMORY_GFDT; 118197ef1bddSDaniel Vetter u32 pte_flags; 118297ef1bddSDaniel Vetter 1183897ef192SZhenyu Wang if (type_mask == AGP_USER_MEMORY) 118485ccc35bSChris Wilson pte_flags = GEN6_PTE_UNCACHED | I810_PTE_VALID; 118597ef1bddSDaniel Vetter else if (type_mask == AGP_USER_CACHED_MEMORY_LLC_MLC) { 1186d1108525SZhenyu Wang pte_flags = GEN6_PTE_LLC_MLC | I810_PTE_VALID; 118797ef1bddSDaniel Vetter if (gfdt) 118897ef1bddSDaniel Vetter pte_flags |= GEN6_PTE_GFDT; 118997ef1bddSDaniel Vetter } else { /* set 'normal'/'cached' to LLC by default */ 1190d1108525SZhenyu Wang pte_flags = GEN6_PTE_LLC | I810_PTE_VALID; 119197ef1bddSDaniel Vetter if (gfdt) 119297ef1bddSDaniel Vetter pte_flags |= GEN6_PTE_GFDT; 119397ef1bddSDaniel Vetter } 119497ef1bddSDaniel Vetter 119597ef1bddSDaniel Vetter /* gen6 has bit11-4 for physical addr bit39-32 */ 119697ef1bddSDaniel Vetter addr |= (addr >> 28) & 0xff0; 119797ef1bddSDaniel Vetter writel(addr | pte_flags, intel_private.gtt + entry); 119897ef1bddSDaniel Vetter } 119997ef1bddSDaniel Vetter 120064757876SJesse Barnes static void valleyview_write_entry(dma_addr_t addr, unsigned int entry, 120164757876SJesse Barnes unsigned int flags) 120264757876SJesse Barnes { 1203e87c4699SJesse Barnes unsigned int type_mask = flags & ~AGP_USER_CACHED_MEMORY_GFDT; 1204e87c4699SJesse Barnes unsigned int gfdt = flags & AGP_USER_CACHED_MEMORY_GFDT; 120564757876SJesse Barnes u32 pte_flags; 120664757876SJesse Barnes 1207e87c4699SJesse Barnes if (type_mask == AGP_USER_MEMORY) 120864757876SJesse Barnes pte_flags = GEN6_PTE_UNCACHED | I810_PTE_VALID; 1209e87c4699SJesse Barnes else { 1210e87c4699SJesse Barnes pte_flags = GEN6_PTE_LLC | I810_PTE_VALID; 1211e87c4699SJesse Barnes if (gfdt) 1212e87c4699SJesse Barnes pte_flags |= GEN6_PTE_GFDT; 1213e87c4699SJesse Barnes } 121464757876SJesse Barnes 121564757876SJesse Barnes /* gen6 has bit11-4 for physical addr bit39-32 */ 121664757876SJesse Barnes addr |= (addr >> 28) & 0xff0; 121764757876SJesse Barnes writel(addr | pte_flags, intel_private.gtt + entry); 121864757876SJesse Barnes 121964757876SJesse Barnes writel(1, intel_private.registers + GFX_FLSH_CNTL_VLV); 122064757876SJesse Barnes } 122164757876SJesse Barnes 1222ae83dd5cSDaniel Vetter static void gen6_cleanup(void) 1223ae83dd5cSDaniel Vetter { 1224ae83dd5cSDaniel Vetter } 1225ae83dd5cSDaniel Vetter 12265c042287SBen Widawsky /* Certain Gen5 chipsets require require idling the GPU before 12275c042287SBen Widawsky * unmapping anything from the GTT when VT-d is enabled. 12285c042287SBen Widawsky */ 12295c042287SBen Widawsky static inline int needs_idle_maps(void) 12305c042287SBen Widawsky { 1231a08185a3SKeith Packard #ifdef CONFIG_INTEL_IOMMU 12325c042287SBen Widawsky const unsigned short gpu_devid = intel_private.pcidev->device; 12335c042287SBen Widawsky 12345c042287SBen Widawsky /* Query intel_iommu to see if we need the workaround. Presumably that 12355c042287SBen Widawsky * was loaded first. 12365c042287SBen Widawsky */ 12375c042287SBen Widawsky if ((gpu_devid == PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB || 12385c042287SBen Widawsky gpu_devid == PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG) && 12395c042287SBen Widawsky intel_iommu_gfx_mapped) 12405c042287SBen Widawsky return 1; 1241a08185a3SKeith Packard #endif 12425c042287SBen Widawsky return 0; 12435c042287SBen Widawsky } 12445c042287SBen Widawsky 12452d2430cfSDaniel Vetter static int i9xx_setup(void) 12462d2430cfSDaniel Vetter { 12472d2430cfSDaniel Vetter u32 reg_addr; 12484b60d29eSJesse Barnes int size = KB(512); 12492d2430cfSDaniel Vetter 12502d2430cfSDaniel Vetter pci_read_config_dword(intel_private.pcidev, I915_MMADDR, ®_addr); 12512d2430cfSDaniel Vetter 12522d2430cfSDaniel Vetter reg_addr &= 0xfff80000; 12532d2430cfSDaniel Vetter 12544b60d29eSJesse Barnes if (INTEL_GTT_GEN >= 7) 12554b60d29eSJesse Barnes size = MB(2); 12564b60d29eSJesse Barnes 12574b60d29eSJesse Barnes intel_private.registers = ioremap(reg_addr, size); 12582d2430cfSDaniel Vetter if (!intel_private.registers) 12592d2430cfSDaniel Vetter return -ENOMEM; 12602d2430cfSDaniel Vetter 12612d2430cfSDaniel Vetter if (INTEL_GTT_GEN == 3) { 12622d2430cfSDaniel Vetter u32 gtt_addr; 12633f08e4efSChris Wilson 12642d2430cfSDaniel Vetter pci_read_config_dword(intel_private.pcidev, 12652d2430cfSDaniel Vetter I915_PTEADDR, >t_addr); 12662d2430cfSDaniel Vetter intel_private.gtt_bus_addr = gtt_addr; 12672d2430cfSDaniel Vetter } else { 12682d2430cfSDaniel Vetter u32 gtt_offset; 12692d2430cfSDaniel Vetter 12702d2430cfSDaniel Vetter switch (INTEL_GTT_GEN) { 12712d2430cfSDaniel Vetter case 5: 12722d2430cfSDaniel Vetter case 6: 1273e597dad8SJesse Barnes case 7: 12742d2430cfSDaniel Vetter gtt_offset = MB(2); 12752d2430cfSDaniel Vetter break; 12762d2430cfSDaniel Vetter case 4: 12772d2430cfSDaniel Vetter default: 12782d2430cfSDaniel Vetter gtt_offset = KB(512); 12792d2430cfSDaniel Vetter break; 12802d2430cfSDaniel Vetter } 12812d2430cfSDaniel Vetter intel_private.gtt_bus_addr = reg_addr + gtt_offset; 12822d2430cfSDaniel Vetter } 12832d2430cfSDaniel Vetter 128435b09c9bSDan Carpenter if (needs_idle_maps()) 12855c042287SBen Widawsky intel_private.base.do_idle_maps = 1; 12865c042287SBen Widawsky 12872d2430cfSDaniel Vetter intel_i9xx_setup_flush(); 12882d2430cfSDaniel Vetter 12892d2430cfSDaniel Vetter return 0; 12902d2430cfSDaniel Vetter } 12912d2430cfSDaniel Vetter 1292e9b1cc81SDaniel Vetter static const struct agp_bridge_driver intel_fake_agp_driver = { 1293f51b7662SDaniel Vetter .owner = THIS_MODULE, 1294f51b7662SDaniel Vetter .size_type = FIXED_APER_SIZE, 12959e76e7b8SChris Wilson .aperture_sizes = intel_fake_agp_sizes, 12969e76e7b8SChris Wilson .num_aperture_sizes = ARRAY_SIZE(intel_fake_agp_sizes), 1297a6963596SDaniel Vetter .configure = intel_fake_agp_configure, 12983e921f98SDaniel Vetter .fetch_size = intel_fake_agp_fetch_size, 1299fdfb58a9SDaniel Vetter .cleanup = intel_gtt_cleanup, 1300ffdd7510SDaniel Vetter .agp_enable = intel_fake_agp_enable, 1301f51b7662SDaniel Vetter .cache_flush = global_cache_flush, 13023b15a9d7SDaniel Vetter .create_gatt_table = intel_fake_agp_create_gatt_table, 1303ffdd7510SDaniel Vetter .free_gatt_table = intel_fake_agp_free_gatt_table, 1304450f2b3dSDaniel Vetter .insert_memory = intel_fake_agp_insert_entries, 1305450f2b3dSDaniel Vetter .remove_memory = intel_fake_agp_remove_entries, 1306ffdd7510SDaniel Vetter .alloc_by_type = intel_fake_agp_alloc_by_type, 1307f51b7662SDaniel Vetter .free_by_type = intel_i810_free_by_type, 1308f51b7662SDaniel Vetter .agp_alloc_page = agp_generic_alloc_page, 1309f51b7662SDaniel Vetter .agp_alloc_pages = agp_generic_alloc_pages, 1310f51b7662SDaniel Vetter .agp_destroy_page = agp_generic_destroy_page, 1311f51b7662SDaniel Vetter .agp_destroy_pages = agp_generic_destroy_pages, 1312f51b7662SDaniel Vetter }; 131302c026ceSDaniel Vetter 1314bdd30729SDaniel Vetter static const struct intel_gtt_driver i81x_gtt_driver = { 1315bdd30729SDaniel Vetter .gen = 1, 1316820647b9SDaniel Vetter .has_pgtbl_enable = 1, 131722533b49SDaniel Vetter .dma_mask_size = 32, 1318820647b9SDaniel Vetter .setup = i810_setup, 1319820647b9SDaniel Vetter .cleanup = i810_cleanup, 1320625dd9d3SDaniel Vetter .check_flags = i830_check_flags, 1321625dd9d3SDaniel Vetter .write_entry = i810_write_entry, 1322bdd30729SDaniel Vetter }; 13231a997ff2SDaniel Vetter static const struct intel_gtt_driver i8xx_gtt_driver = { 13241a997ff2SDaniel Vetter .gen = 2, 1325100519e2SChris Wilson .has_pgtbl_enable = 1, 132673800422SDaniel Vetter .setup = i830_setup, 1327ae83dd5cSDaniel Vetter .cleanup = i830_cleanup, 1328351bb278SDaniel Vetter .write_entry = i830_write_entry, 132922533b49SDaniel Vetter .dma_mask_size = 32, 13305cbecafcSDaniel Vetter .check_flags = i830_check_flags, 13311b263f24SDaniel Vetter .chipset_flush = i830_chipset_flush, 13321a997ff2SDaniel Vetter }; 13331a997ff2SDaniel Vetter static const struct intel_gtt_driver i915_gtt_driver = { 13341a997ff2SDaniel Vetter .gen = 3, 1335100519e2SChris Wilson .has_pgtbl_enable = 1, 13362d2430cfSDaniel Vetter .setup = i9xx_setup, 1337ae83dd5cSDaniel Vetter .cleanup = i9xx_cleanup, 1338351bb278SDaniel Vetter /* i945 is the last gpu to need phys mem (for overlay and cursors). */ 1339351bb278SDaniel Vetter .write_entry = i830_write_entry, 134022533b49SDaniel Vetter .dma_mask_size = 32, 1341fefaa70fSDaniel Vetter .check_flags = i830_check_flags, 13421b263f24SDaniel Vetter .chipset_flush = i9xx_chipset_flush, 13431a997ff2SDaniel Vetter }; 13441a997ff2SDaniel Vetter static const struct intel_gtt_driver g33_gtt_driver = { 13451a997ff2SDaniel Vetter .gen = 3, 13461a997ff2SDaniel Vetter .is_g33 = 1, 13472d2430cfSDaniel Vetter .setup = i9xx_setup, 1348ae83dd5cSDaniel Vetter .cleanup = i9xx_cleanup, 1349a6963596SDaniel Vetter .write_entry = i965_write_entry, 135022533b49SDaniel Vetter .dma_mask_size = 36, 1351450f2b3dSDaniel Vetter .check_flags = i830_check_flags, 13521b263f24SDaniel Vetter .chipset_flush = i9xx_chipset_flush, 13531a997ff2SDaniel Vetter }; 13541a997ff2SDaniel Vetter static const struct intel_gtt_driver pineview_gtt_driver = { 13551a997ff2SDaniel Vetter .gen = 3, 13561a997ff2SDaniel Vetter .is_pineview = 1, .is_g33 = 1, 13572d2430cfSDaniel Vetter .setup = i9xx_setup, 1358ae83dd5cSDaniel Vetter .cleanup = i9xx_cleanup, 1359a6963596SDaniel Vetter .write_entry = i965_write_entry, 136022533b49SDaniel Vetter .dma_mask_size = 36, 1361450f2b3dSDaniel Vetter .check_flags = i830_check_flags, 13621b263f24SDaniel Vetter .chipset_flush = i9xx_chipset_flush, 13631a997ff2SDaniel Vetter }; 13641a997ff2SDaniel Vetter static const struct intel_gtt_driver i965_gtt_driver = { 13651a997ff2SDaniel Vetter .gen = 4, 1366100519e2SChris Wilson .has_pgtbl_enable = 1, 13672d2430cfSDaniel Vetter .setup = i9xx_setup, 1368ae83dd5cSDaniel Vetter .cleanup = i9xx_cleanup, 1369a6963596SDaniel Vetter .write_entry = i965_write_entry, 137022533b49SDaniel Vetter .dma_mask_size = 36, 1371450f2b3dSDaniel Vetter .check_flags = i830_check_flags, 13721b263f24SDaniel Vetter .chipset_flush = i9xx_chipset_flush, 13731a997ff2SDaniel Vetter }; 13741a997ff2SDaniel Vetter static const struct intel_gtt_driver g4x_gtt_driver = { 13751a997ff2SDaniel Vetter .gen = 5, 13762d2430cfSDaniel Vetter .setup = i9xx_setup, 1377ae83dd5cSDaniel Vetter .cleanup = i9xx_cleanup, 1378a6963596SDaniel Vetter .write_entry = i965_write_entry, 137922533b49SDaniel Vetter .dma_mask_size = 36, 1380450f2b3dSDaniel Vetter .check_flags = i830_check_flags, 13811b263f24SDaniel Vetter .chipset_flush = i9xx_chipset_flush, 13821a997ff2SDaniel Vetter }; 13831a997ff2SDaniel Vetter static const struct intel_gtt_driver ironlake_gtt_driver = { 13841a997ff2SDaniel Vetter .gen = 5, 13851a997ff2SDaniel Vetter .is_ironlake = 1, 13862d2430cfSDaniel Vetter .setup = i9xx_setup, 1387ae83dd5cSDaniel Vetter .cleanup = i9xx_cleanup, 1388a6963596SDaniel Vetter .write_entry = i965_write_entry, 138922533b49SDaniel Vetter .dma_mask_size = 36, 1390450f2b3dSDaniel Vetter .check_flags = i830_check_flags, 13911b263f24SDaniel Vetter .chipset_flush = i9xx_chipset_flush, 13921a997ff2SDaniel Vetter }; 13931a997ff2SDaniel Vetter static const struct intel_gtt_driver sandybridge_gtt_driver = { 13941a997ff2SDaniel Vetter .gen = 6, 13952d2430cfSDaniel Vetter .setup = i9xx_setup, 1396ae83dd5cSDaniel Vetter .cleanup = gen6_cleanup, 139797ef1bddSDaniel Vetter .write_entry = gen6_write_entry, 139822533b49SDaniel Vetter .dma_mask_size = 40, 139990cb149eSDaniel Vetter .check_flags = gen6_check_flags, 14001b263f24SDaniel Vetter .chipset_flush = i9xx_chipset_flush, 14011a997ff2SDaniel Vetter }; 1402a843af18SDaniel Vetter static const struct intel_gtt_driver haswell_gtt_driver = { 1403a843af18SDaniel Vetter .gen = 6, 1404a843af18SDaniel Vetter .setup = i9xx_setup, 1405a843af18SDaniel Vetter .cleanup = gen6_cleanup, 1406a843af18SDaniel Vetter .write_entry = haswell_write_entry, 1407a843af18SDaniel Vetter .dma_mask_size = 40, 1408a843af18SDaniel Vetter .check_flags = gen6_check_flags, 1409a843af18SDaniel Vetter .chipset_flush = i9xx_chipset_flush, 1410a843af18SDaniel Vetter }; 141164757876SJesse Barnes static const struct intel_gtt_driver valleyview_gtt_driver = { 141264757876SJesse Barnes .gen = 7, 141364757876SJesse Barnes .setup = i9xx_setup, 141464757876SJesse Barnes .cleanup = gen6_cleanup, 141564757876SJesse Barnes .write_entry = valleyview_write_entry, 141664757876SJesse Barnes .dma_mask_size = 40, 141764757876SJesse Barnes .check_flags = gen6_check_flags, 141864757876SJesse Barnes }; 14191a997ff2SDaniel Vetter 142002c026ceSDaniel Vetter /* Table to describe Intel GMCH and AGP/PCIE GART drivers. At least one of 142102c026ceSDaniel Vetter * driver and gmch_driver must be non-null, and find_gmch will determine 142202c026ceSDaniel Vetter * which one should be used if a gmch_chip_id is present. 142302c026ceSDaniel Vetter */ 142402c026ceSDaniel Vetter static const struct intel_gtt_driver_description { 142502c026ceSDaniel Vetter unsigned int gmch_chip_id; 142602c026ceSDaniel Vetter char *name; 14271a997ff2SDaniel Vetter const struct intel_gtt_driver *gtt_driver; 142802c026ceSDaniel Vetter } intel_gtt_chipsets[] = { 1429ff26860fSDaniel Vetter { PCI_DEVICE_ID_INTEL_82810_IG1, "i810", 1430bdd30729SDaniel Vetter &i81x_gtt_driver}, 1431ff26860fSDaniel Vetter { PCI_DEVICE_ID_INTEL_82810_IG3, "i810", 1432bdd30729SDaniel Vetter &i81x_gtt_driver}, 1433ff26860fSDaniel Vetter { PCI_DEVICE_ID_INTEL_82810E_IG, "i810", 1434bdd30729SDaniel Vetter &i81x_gtt_driver}, 1435ff26860fSDaniel Vetter { PCI_DEVICE_ID_INTEL_82815_CGC, "i815", 1436bdd30729SDaniel Vetter &i81x_gtt_driver}, 14371a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_82830_CGC, "830M", 1438ff26860fSDaniel Vetter &i8xx_gtt_driver}, 143953371edaSOswald Buddenhagen { PCI_DEVICE_ID_INTEL_82845G_IG, "845G", 1440ff26860fSDaniel Vetter &i8xx_gtt_driver}, 14411a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_82854_IG, "854", 1442ff26860fSDaniel Vetter &i8xx_gtt_driver}, 14431a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_82855GM_IG, "855GM", 1444ff26860fSDaniel Vetter &i8xx_gtt_driver}, 14451a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_82865_IG, "865", 1446ff26860fSDaniel Vetter &i8xx_gtt_driver}, 14471a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_E7221_IG, "E7221 (i915)", 1448ff26860fSDaniel Vetter &i915_gtt_driver }, 14491a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_82915G_IG, "915G", 1450ff26860fSDaniel Vetter &i915_gtt_driver }, 14511a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_82915GM_IG, "915GM", 1452ff26860fSDaniel Vetter &i915_gtt_driver }, 14531a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_82945G_IG, "945G", 1454ff26860fSDaniel Vetter &i915_gtt_driver }, 14551a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_82945GM_IG, "945GM", 1456ff26860fSDaniel Vetter &i915_gtt_driver }, 14571a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_82945GME_IG, "945GME", 1458ff26860fSDaniel Vetter &i915_gtt_driver }, 14591a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_82946GZ_IG, "946GZ", 1460ff26860fSDaniel Vetter &i965_gtt_driver }, 14611a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_82G35_IG, "G35", 1462ff26860fSDaniel Vetter &i965_gtt_driver }, 14631a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_82965Q_IG, "965Q", 1464ff26860fSDaniel Vetter &i965_gtt_driver }, 14651a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_82965G_IG, "965G", 1466ff26860fSDaniel Vetter &i965_gtt_driver }, 14671a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_82965GM_IG, "965GM", 1468ff26860fSDaniel Vetter &i965_gtt_driver }, 14691a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_82965GME_IG, "965GME/GLE", 1470ff26860fSDaniel Vetter &i965_gtt_driver }, 14711a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_G33_IG, "G33", 1472ff26860fSDaniel Vetter &g33_gtt_driver }, 14731a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_Q35_IG, "Q35", 1474ff26860fSDaniel Vetter &g33_gtt_driver }, 14751a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_Q33_IG, "Q33", 1476ff26860fSDaniel Vetter &g33_gtt_driver }, 14771a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_PINEVIEW_M_IG, "GMA3150", 1478ff26860fSDaniel Vetter &pineview_gtt_driver }, 14791a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_PINEVIEW_IG, "GMA3150", 1480ff26860fSDaniel Vetter &pineview_gtt_driver }, 14811a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_GM45_IG, "GM45", 1482ff26860fSDaniel Vetter &g4x_gtt_driver }, 14831a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_EAGLELAKE_IG, "Eaglelake", 1484ff26860fSDaniel Vetter &g4x_gtt_driver }, 14851a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_Q45_IG, "Q45/Q43", 1486ff26860fSDaniel Vetter &g4x_gtt_driver }, 14871a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_G45_IG, "G45/G43", 1488ff26860fSDaniel Vetter &g4x_gtt_driver }, 14891a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_B43_IG, "B43", 1490ff26860fSDaniel Vetter &g4x_gtt_driver }, 1491e9e5f8e8SChris Wilson { PCI_DEVICE_ID_INTEL_B43_1_IG, "B43", 1492ff26860fSDaniel Vetter &g4x_gtt_driver }, 14931a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_G41_IG, "G41", 1494ff26860fSDaniel Vetter &g4x_gtt_driver }, 149502c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_IRONLAKE_D_IG, 1496ff26860fSDaniel Vetter "HD Graphics", &ironlake_gtt_driver }, 149702c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG, 1498ff26860fSDaniel Vetter "HD Graphics", &ironlake_gtt_driver }, 149902c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT1_IG, 1500ff26860fSDaniel Vetter "Sandybridge", &sandybridge_gtt_driver }, 150102c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_IG, 1502ff26860fSDaniel Vetter "Sandybridge", &sandybridge_gtt_driver }, 150302c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_PLUS_IG, 1504ff26860fSDaniel Vetter "Sandybridge", &sandybridge_gtt_driver }, 150502c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT1_IG, 1506ff26860fSDaniel Vetter "Sandybridge", &sandybridge_gtt_driver }, 150702c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_IG, 1508ff26860fSDaniel Vetter "Sandybridge", &sandybridge_gtt_driver }, 150902c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_PLUS_IG, 1510ff26860fSDaniel Vetter "Sandybridge", &sandybridge_gtt_driver }, 151102c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_IG, 1512ff26860fSDaniel Vetter "Sandybridge", &sandybridge_gtt_driver }, 1513246d08b8SJesse Barnes { PCI_DEVICE_ID_INTEL_IVYBRIDGE_GT1_IG, 1514246d08b8SJesse Barnes "Ivybridge", &sandybridge_gtt_driver }, 1515246d08b8SJesse Barnes { PCI_DEVICE_ID_INTEL_IVYBRIDGE_GT2_IG, 1516246d08b8SJesse Barnes "Ivybridge", &sandybridge_gtt_driver }, 1517246d08b8SJesse Barnes { PCI_DEVICE_ID_INTEL_IVYBRIDGE_M_GT1_IG, 1518246d08b8SJesse Barnes "Ivybridge", &sandybridge_gtt_driver }, 1519246d08b8SJesse Barnes { PCI_DEVICE_ID_INTEL_IVYBRIDGE_M_GT2_IG, 1520246d08b8SJesse Barnes "Ivybridge", &sandybridge_gtt_driver }, 1521246d08b8SJesse Barnes { PCI_DEVICE_ID_INTEL_IVYBRIDGE_S_GT1_IG, 1522246d08b8SJesse Barnes "Ivybridge", &sandybridge_gtt_driver }, 1523cc22a938SEugeni Dodonov { PCI_DEVICE_ID_INTEL_IVYBRIDGE_S_GT2_IG, 1524cc22a938SEugeni Dodonov "Ivybridge", &sandybridge_gtt_driver }, 152564757876SJesse Barnes { PCI_DEVICE_ID_INTEL_VALLEYVIEW_IG, 152664757876SJesse Barnes "ValleyView", &valleyview_gtt_driver }, 15274cae9ae0SEugeni Dodonov { PCI_DEVICE_ID_INTEL_HASWELL_D_GT1_IG, 1528a843af18SDaniel Vetter "Haswell", &haswell_gtt_driver }, 15294cae9ae0SEugeni Dodonov { PCI_DEVICE_ID_INTEL_HASWELL_D_GT2_IG, 1530a843af18SDaniel Vetter "Haswell", &haswell_gtt_driver }, 1531da612d88SPaulo Zanoni { PCI_DEVICE_ID_INTEL_HASWELL_D_GT2_PLUS_IG, 1532a843af18SDaniel Vetter "Haswell", &haswell_gtt_driver }, 15334cae9ae0SEugeni Dodonov { PCI_DEVICE_ID_INTEL_HASWELL_M_GT1_IG, 1534a843af18SDaniel Vetter "Haswell", &haswell_gtt_driver }, 15354cae9ae0SEugeni Dodonov { PCI_DEVICE_ID_INTEL_HASWELL_M_GT2_IG, 1536a843af18SDaniel Vetter "Haswell", &haswell_gtt_driver }, 1537da612d88SPaulo Zanoni { PCI_DEVICE_ID_INTEL_HASWELL_M_GT2_PLUS_IG, 1538a843af18SDaniel Vetter "Haswell", &haswell_gtt_driver }, 15394cae9ae0SEugeni Dodonov { PCI_DEVICE_ID_INTEL_HASWELL_S_GT1_IG, 1540a843af18SDaniel Vetter "Haswell", &haswell_gtt_driver }, 15414cae9ae0SEugeni Dodonov { PCI_DEVICE_ID_INTEL_HASWELL_S_GT2_IG, 1542a843af18SDaniel Vetter "Haswell", &haswell_gtt_driver }, 1543da612d88SPaulo Zanoni { PCI_DEVICE_ID_INTEL_HASWELL_S_GT2_PLUS_IG, 1544a843af18SDaniel Vetter "Haswell", &haswell_gtt_driver }, 1545da612d88SPaulo Zanoni { PCI_DEVICE_ID_INTEL_HASWELL_SDV_D_GT1_IG, 1546a843af18SDaniel Vetter "Haswell", &haswell_gtt_driver }, 1547da612d88SPaulo Zanoni { PCI_DEVICE_ID_INTEL_HASWELL_SDV_D_GT2_IG, 1548a843af18SDaniel Vetter "Haswell", &haswell_gtt_driver }, 1549da612d88SPaulo Zanoni { PCI_DEVICE_ID_INTEL_HASWELL_SDV_D_GT2_PLUS_IG, 1550a843af18SDaniel Vetter "Haswell", &haswell_gtt_driver }, 1551da612d88SPaulo Zanoni { PCI_DEVICE_ID_INTEL_HASWELL_SDV_M_GT1_IG, 1552a843af18SDaniel Vetter "Haswell", &haswell_gtt_driver }, 1553da612d88SPaulo Zanoni { PCI_DEVICE_ID_INTEL_HASWELL_SDV_M_GT2_IG, 1554a843af18SDaniel Vetter "Haswell", &haswell_gtt_driver }, 1555da612d88SPaulo Zanoni { PCI_DEVICE_ID_INTEL_HASWELL_SDV_M_GT2_PLUS_IG, 1556a843af18SDaniel Vetter "Haswell", &haswell_gtt_driver }, 1557da612d88SPaulo Zanoni { PCI_DEVICE_ID_INTEL_HASWELL_SDV_S_GT1_IG, 1558a843af18SDaniel Vetter "Haswell", &haswell_gtt_driver }, 1559da612d88SPaulo Zanoni { PCI_DEVICE_ID_INTEL_HASWELL_SDV_S_GT2_IG, 1560a843af18SDaniel Vetter "Haswell", &haswell_gtt_driver }, 1561da612d88SPaulo Zanoni { PCI_DEVICE_ID_INTEL_HASWELL_SDV_S_GT2_PLUS_IG, 1562a843af18SDaniel Vetter "Haswell", &haswell_gtt_driver }, 1563da612d88SPaulo Zanoni { PCI_DEVICE_ID_INTEL_HASWELL_ULT_D_GT1_IG, 1564a843af18SDaniel Vetter "Haswell", &haswell_gtt_driver }, 1565da612d88SPaulo Zanoni { PCI_DEVICE_ID_INTEL_HASWELL_ULT_D_GT2_IG, 1566a843af18SDaniel Vetter "Haswell", &haswell_gtt_driver }, 1567da612d88SPaulo Zanoni { PCI_DEVICE_ID_INTEL_HASWELL_ULT_D_GT2_PLUS_IG, 1568a843af18SDaniel Vetter "Haswell", &haswell_gtt_driver }, 1569da612d88SPaulo Zanoni { PCI_DEVICE_ID_INTEL_HASWELL_ULT_M_GT1_IG, 1570a843af18SDaniel Vetter "Haswell", &haswell_gtt_driver }, 1571da612d88SPaulo Zanoni { PCI_DEVICE_ID_INTEL_HASWELL_ULT_M_GT2_IG, 1572a843af18SDaniel Vetter "Haswell", &haswell_gtt_driver }, 1573da612d88SPaulo Zanoni { PCI_DEVICE_ID_INTEL_HASWELL_ULT_M_GT2_PLUS_IG, 1574a843af18SDaniel Vetter "Haswell", &haswell_gtt_driver }, 1575da612d88SPaulo Zanoni { PCI_DEVICE_ID_INTEL_HASWELL_ULT_S_GT1_IG, 1576a843af18SDaniel Vetter "Haswell", &haswell_gtt_driver }, 1577da612d88SPaulo Zanoni { PCI_DEVICE_ID_INTEL_HASWELL_ULT_S_GT2_IG, 1578a843af18SDaniel Vetter "Haswell", &haswell_gtt_driver }, 1579da612d88SPaulo Zanoni { PCI_DEVICE_ID_INTEL_HASWELL_ULT_S_GT2_PLUS_IG, 1580a843af18SDaniel Vetter "Haswell", &haswell_gtt_driver }, 1581da612d88SPaulo Zanoni { PCI_DEVICE_ID_INTEL_HASWELL_CRW_D_GT1_IG, 1582a843af18SDaniel Vetter "Haswell", &haswell_gtt_driver }, 1583da612d88SPaulo Zanoni { PCI_DEVICE_ID_INTEL_HASWELL_CRW_D_GT2_IG, 1584a843af18SDaniel Vetter "Haswell", &haswell_gtt_driver }, 1585da612d88SPaulo Zanoni { PCI_DEVICE_ID_INTEL_HASWELL_CRW_D_GT2_PLUS_IG, 1586a843af18SDaniel Vetter "Haswell", &haswell_gtt_driver }, 1587da612d88SPaulo Zanoni { PCI_DEVICE_ID_INTEL_HASWELL_CRW_M_GT1_IG, 1588a843af18SDaniel Vetter "Haswell", &haswell_gtt_driver }, 1589da612d88SPaulo Zanoni { PCI_DEVICE_ID_INTEL_HASWELL_CRW_M_GT2_IG, 1590a843af18SDaniel Vetter "Haswell", &haswell_gtt_driver }, 1591da612d88SPaulo Zanoni { PCI_DEVICE_ID_INTEL_HASWELL_CRW_M_GT2_PLUS_IG, 1592a843af18SDaniel Vetter "Haswell", &haswell_gtt_driver }, 1593da612d88SPaulo Zanoni { PCI_DEVICE_ID_INTEL_HASWELL_CRW_S_GT1_IG, 1594a843af18SDaniel Vetter "Haswell", &haswell_gtt_driver }, 1595da612d88SPaulo Zanoni { PCI_DEVICE_ID_INTEL_HASWELL_CRW_S_GT2_IG, 1596a843af18SDaniel Vetter "Haswell", &haswell_gtt_driver }, 1597da612d88SPaulo Zanoni { PCI_DEVICE_ID_INTEL_HASWELL_CRW_S_GT2_PLUS_IG, 1598a843af18SDaniel Vetter "Haswell", &haswell_gtt_driver }, 159902c026ceSDaniel Vetter { 0, NULL, NULL } 160002c026ceSDaniel Vetter }; 160102c026ceSDaniel Vetter 160202c026ceSDaniel Vetter static int find_gmch(u16 device) 160302c026ceSDaniel Vetter { 160402c026ceSDaniel Vetter struct pci_dev *gmch_device; 160502c026ceSDaniel Vetter 160602c026ceSDaniel Vetter gmch_device = pci_get_device(PCI_VENDOR_ID_INTEL, device, NULL); 160702c026ceSDaniel Vetter if (gmch_device && PCI_FUNC(gmch_device->devfn) != 0) { 160802c026ceSDaniel Vetter gmch_device = pci_get_device(PCI_VENDOR_ID_INTEL, 160902c026ceSDaniel Vetter device, gmch_device); 161002c026ceSDaniel Vetter } 161102c026ceSDaniel Vetter 161202c026ceSDaniel Vetter if (!gmch_device) 161302c026ceSDaniel Vetter return 0; 161402c026ceSDaniel Vetter 161502c026ceSDaniel Vetter intel_private.pcidev = gmch_device; 161602c026ceSDaniel Vetter return 1; 161702c026ceSDaniel Vetter } 161802c026ceSDaniel Vetter 161914be93ddSDaniel Vetter int intel_gmch_probe(struct pci_dev *bridge_pdev, struct pci_dev *gpu_pdev, 162002c026ceSDaniel Vetter struct agp_bridge_data *bridge) 162102c026ceSDaniel Vetter { 162202c026ceSDaniel Vetter int i, mask; 162314be93ddSDaniel Vetter 162414be93ddSDaniel Vetter /* 162514be93ddSDaniel Vetter * Can be called from the fake agp driver but also directly from 162614be93ddSDaniel Vetter * drm/i915.ko. Hence we need to check whether everything is set up 162714be93ddSDaniel Vetter * already. 162814be93ddSDaniel Vetter */ 162914be93ddSDaniel Vetter if (intel_private.driver) { 163014be93ddSDaniel Vetter intel_private.refcount++; 163114be93ddSDaniel Vetter return 1; 163214be93ddSDaniel Vetter } 163302c026ceSDaniel Vetter 163402c026ceSDaniel Vetter for (i = 0; intel_gtt_chipsets[i].name != NULL; i++) { 163514be93ddSDaniel Vetter if (gpu_pdev) { 163614be93ddSDaniel Vetter if (gpu_pdev->device == 163714be93ddSDaniel Vetter intel_gtt_chipsets[i].gmch_chip_id) { 163814be93ddSDaniel Vetter intel_private.pcidev = pci_dev_get(gpu_pdev); 163914be93ddSDaniel Vetter intel_private.driver = 164014be93ddSDaniel Vetter intel_gtt_chipsets[i].gtt_driver; 164114be93ddSDaniel Vetter 164214be93ddSDaniel Vetter break; 164314be93ddSDaniel Vetter } 164414be93ddSDaniel Vetter } else if (find_gmch(intel_gtt_chipsets[i].gmch_chip_id)) { 16451a997ff2SDaniel Vetter intel_private.driver = 16461a997ff2SDaniel Vetter intel_gtt_chipsets[i].gtt_driver; 164702c026ceSDaniel Vetter break; 164802c026ceSDaniel Vetter } 164902c026ceSDaniel Vetter } 165002c026ceSDaniel Vetter 1651ff26860fSDaniel Vetter if (!intel_private.driver) 165202c026ceSDaniel Vetter return 0; 165302c026ceSDaniel Vetter 165414be93ddSDaniel Vetter intel_private.refcount++; 165514be93ddSDaniel Vetter 16567e8f6306SDaniel Vetter if (bridge) { 1657ff26860fSDaniel Vetter bridge->driver = &intel_fake_agp_driver; 165802c026ceSDaniel Vetter bridge->dev_private_data = &intel_private; 165914be93ddSDaniel Vetter bridge->dev = bridge_pdev; 16607e8f6306SDaniel Vetter } 166102c026ceSDaniel Vetter 166214be93ddSDaniel Vetter intel_private.bridge_dev = pci_dev_get(bridge_pdev); 1663d7cca2f7SDaniel Vetter 166414be93ddSDaniel Vetter dev_info(&bridge_pdev->dev, "Intel %s Chipset\n", intel_gtt_chipsets[i].name); 166502c026ceSDaniel Vetter 166622533b49SDaniel Vetter mask = intel_private.driver->dma_mask_size; 166702c026ceSDaniel Vetter if (pci_set_dma_mask(intel_private.pcidev, DMA_BIT_MASK(mask))) 166802c026ceSDaniel Vetter dev_err(&intel_private.pcidev->dev, 166902c026ceSDaniel Vetter "set gfx device dma mask %d-bit failed!\n", mask); 167002c026ceSDaniel Vetter else 167102c026ceSDaniel Vetter pci_set_consistent_dma_mask(intel_private.pcidev, 167202c026ceSDaniel Vetter DMA_BIT_MASK(mask)); 167302c026ceSDaniel Vetter 167414be93ddSDaniel Vetter if (intel_gtt_init() != 0) { 167514be93ddSDaniel Vetter intel_gmch_remove(); 167614be93ddSDaniel Vetter 16773b15a9d7SDaniel Vetter return 0; 167814be93ddSDaniel Vetter } 16791784a5fbSDaniel Vetter 168002c026ceSDaniel Vetter return 1; 168102c026ceSDaniel Vetter } 1682e2404e7cSDaniel Vetter EXPORT_SYMBOL(intel_gmch_probe); 168302c026ceSDaniel Vetter 1684c64f7ba5SChris Wilson const struct intel_gtt *intel_gtt_get(void) 168519966754SDaniel Vetter { 168619966754SDaniel Vetter return &intel_private.base; 168719966754SDaniel Vetter } 168819966754SDaniel Vetter EXPORT_SYMBOL(intel_gtt_get); 168919966754SDaniel Vetter 169040ce6575SDaniel Vetter void intel_gtt_chipset_flush(void) 169140ce6575SDaniel Vetter { 169240ce6575SDaniel Vetter if (intel_private.driver->chipset_flush) 169340ce6575SDaniel Vetter intel_private.driver->chipset_flush(); 169440ce6575SDaniel Vetter } 169540ce6575SDaniel Vetter EXPORT_SYMBOL(intel_gtt_chipset_flush); 169640ce6575SDaniel Vetter 169714be93ddSDaniel Vetter void intel_gmch_remove(void) 169802c026ceSDaniel Vetter { 169914be93ddSDaniel Vetter if (--intel_private.refcount) 170014be93ddSDaniel Vetter return; 170114be93ddSDaniel Vetter 170202c026ceSDaniel Vetter if (intel_private.pcidev) 170302c026ceSDaniel Vetter pci_dev_put(intel_private.pcidev); 1704d7cca2f7SDaniel Vetter if (intel_private.bridge_dev) 1705d7cca2f7SDaniel Vetter pci_dev_put(intel_private.bridge_dev); 170614be93ddSDaniel Vetter intel_private.driver = NULL; 170702c026ceSDaniel Vetter } 1708e2404e7cSDaniel Vetter EXPORT_SYMBOL(intel_gmch_remove); 1709e2404e7cSDaniel Vetter 1710e2404e7cSDaniel Vetter MODULE_AUTHOR("Dave Jones <davej@redhat.com>"); 1711e2404e7cSDaniel Vetter MODULE_LICENSE("GPL and additional rights"); 1712