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 18f51b7662SDaniel Vetter /* 19f51b7662SDaniel Vetter * If we have Intel graphics, we're not going to have anything other than 20f51b7662SDaniel Vetter * an Intel IOMMU. So make the correct use of the PCI DMA API contingent 21f51b7662SDaniel Vetter * on the Intel IOMMU support (CONFIG_DMAR). 22f51b7662SDaniel Vetter * Only newer chipsets need to bother with this, of course. 23f51b7662SDaniel Vetter */ 24f51b7662SDaniel Vetter #ifdef CONFIG_DMAR 25f51b7662SDaniel Vetter #define USE_PCI_DMA_API 1 26f51b7662SDaniel Vetter #endif 27f51b7662SDaniel Vetter 28d1d6ca73SJesse Barnes /* Max amount of stolen space, anything above will be returned to Linux */ 29d1d6ca73SJesse Barnes int intel_max_stolen = 32 * 1024 * 1024; 30d1d6ca73SJesse Barnes EXPORT_SYMBOL(intel_max_stolen); 31d1d6ca73SJesse Barnes 32f51b7662SDaniel Vetter static const struct aper_size_info_fixed intel_i810_sizes[] = 33f51b7662SDaniel Vetter { 34f51b7662SDaniel Vetter {64, 16384, 4}, 35f51b7662SDaniel Vetter /* The 32M mode still requires a 64k gatt */ 36f51b7662SDaniel Vetter {32, 8192, 4} 37f51b7662SDaniel Vetter }; 38f51b7662SDaniel Vetter 39f51b7662SDaniel Vetter #define AGP_DCACHE_MEMORY 1 40f51b7662SDaniel Vetter #define AGP_PHYS_MEMORY 2 41f51b7662SDaniel Vetter #define INTEL_AGP_CACHED_MEMORY 3 42f51b7662SDaniel Vetter 43f51b7662SDaniel Vetter static struct gatt_mask intel_i810_masks[] = 44f51b7662SDaniel Vetter { 45f51b7662SDaniel Vetter {.mask = I810_PTE_VALID, .type = 0}, 46f51b7662SDaniel Vetter {.mask = (I810_PTE_VALID | I810_PTE_LOCAL), .type = AGP_DCACHE_MEMORY}, 47f51b7662SDaniel Vetter {.mask = I810_PTE_VALID, .type = 0}, 48f51b7662SDaniel Vetter {.mask = I810_PTE_VALID | I830_PTE_SYSTEM_CACHED, 49f51b7662SDaniel Vetter .type = INTEL_AGP_CACHED_MEMORY} 50f51b7662SDaniel Vetter }; 51f51b7662SDaniel Vetter 52f8f235e5SZhenyu Wang #define INTEL_AGP_UNCACHED_MEMORY 0 53f8f235e5SZhenyu Wang #define INTEL_AGP_CACHED_MEMORY_LLC 1 54f8f235e5SZhenyu Wang #define INTEL_AGP_CACHED_MEMORY_LLC_GFDT 2 55f8f235e5SZhenyu Wang #define INTEL_AGP_CACHED_MEMORY_LLC_MLC 3 56f8f235e5SZhenyu Wang #define INTEL_AGP_CACHED_MEMORY_LLC_MLC_GFDT 4 57f8f235e5SZhenyu Wang 58f8f235e5SZhenyu Wang static struct gatt_mask intel_gen6_masks[] = 59f8f235e5SZhenyu Wang { 60f8f235e5SZhenyu Wang {.mask = I810_PTE_VALID | GEN6_PTE_UNCACHED, 61f8f235e5SZhenyu Wang .type = INTEL_AGP_UNCACHED_MEMORY }, 62f8f235e5SZhenyu Wang {.mask = I810_PTE_VALID | GEN6_PTE_LLC, 63f8f235e5SZhenyu Wang .type = INTEL_AGP_CACHED_MEMORY_LLC }, 64f8f235e5SZhenyu Wang {.mask = I810_PTE_VALID | GEN6_PTE_LLC | GEN6_PTE_GFDT, 65f8f235e5SZhenyu Wang .type = INTEL_AGP_CACHED_MEMORY_LLC_GFDT }, 66f8f235e5SZhenyu Wang {.mask = I810_PTE_VALID | GEN6_PTE_LLC_MLC, 67f8f235e5SZhenyu Wang .type = INTEL_AGP_CACHED_MEMORY_LLC_MLC }, 68f8f235e5SZhenyu Wang {.mask = I810_PTE_VALID | GEN6_PTE_LLC_MLC | GEN6_PTE_GFDT, 69f8f235e5SZhenyu Wang .type = INTEL_AGP_CACHED_MEMORY_LLC_MLC_GFDT }, 70f8f235e5SZhenyu Wang }; 71f8f235e5SZhenyu Wang 72f51b7662SDaniel Vetter static struct _intel_private { 73f51b7662SDaniel Vetter struct pci_dev *pcidev; /* device one */ 74f51b7662SDaniel Vetter u8 __iomem *registers; 75f51b7662SDaniel Vetter u32 __iomem *gtt; /* I915G */ 76f51b7662SDaniel Vetter int num_dcache_entries; 77f51b7662SDaniel Vetter /* gtt_entries is the number of gtt entries that are already mapped 78f51b7662SDaniel Vetter * to stolen memory. Stolen memory is larger than the memory mapped 79f51b7662SDaniel Vetter * through gtt_entries, as it includes some reserved space for the BIOS 80f51b7662SDaniel Vetter * popup and for the GTT. 81f51b7662SDaniel Vetter */ 82f51b7662SDaniel Vetter int gtt_entries; /* i830+ */ 83f51b7662SDaniel Vetter int gtt_total_size; 84f51b7662SDaniel Vetter union { 85f51b7662SDaniel Vetter void __iomem *i9xx_flush_page; 86f51b7662SDaniel Vetter void *i8xx_flush_page; 87f51b7662SDaniel Vetter }; 88f51b7662SDaniel Vetter struct page *i8xx_page; 89f51b7662SDaniel Vetter struct resource ifp_resource; 90f51b7662SDaniel Vetter int resource_valid; 91f51b7662SDaniel Vetter } intel_private; 92f51b7662SDaniel Vetter 93f51b7662SDaniel Vetter #ifdef USE_PCI_DMA_API 94f51b7662SDaniel Vetter static int intel_agp_map_page(struct page *page, dma_addr_t *ret) 95f51b7662SDaniel Vetter { 96f51b7662SDaniel Vetter *ret = pci_map_page(intel_private.pcidev, page, 0, 97f51b7662SDaniel Vetter PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); 98f51b7662SDaniel Vetter if (pci_dma_mapping_error(intel_private.pcidev, *ret)) 99f51b7662SDaniel Vetter return -EINVAL; 100f51b7662SDaniel Vetter return 0; 101f51b7662SDaniel Vetter } 102f51b7662SDaniel Vetter 103f51b7662SDaniel Vetter static void intel_agp_unmap_page(struct page *page, dma_addr_t dma) 104f51b7662SDaniel Vetter { 105f51b7662SDaniel Vetter pci_unmap_page(intel_private.pcidev, dma, 106f51b7662SDaniel Vetter PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); 107f51b7662SDaniel Vetter } 108f51b7662SDaniel Vetter 109f51b7662SDaniel Vetter static void intel_agp_free_sglist(struct agp_memory *mem) 110f51b7662SDaniel Vetter { 111f51b7662SDaniel Vetter struct sg_table st; 112f51b7662SDaniel Vetter 113f51b7662SDaniel Vetter st.sgl = mem->sg_list; 114f51b7662SDaniel Vetter st.orig_nents = st.nents = mem->page_count; 115f51b7662SDaniel Vetter 116f51b7662SDaniel Vetter sg_free_table(&st); 117f51b7662SDaniel Vetter 118f51b7662SDaniel Vetter mem->sg_list = NULL; 119f51b7662SDaniel Vetter mem->num_sg = 0; 120f51b7662SDaniel Vetter } 121f51b7662SDaniel Vetter 122f51b7662SDaniel Vetter static int intel_agp_map_memory(struct agp_memory *mem) 123f51b7662SDaniel Vetter { 124f51b7662SDaniel Vetter struct sg_table st; 125f51b7662SDaniel Vetter struct scatterlist *sg; 126f51b7662SDaniel Vetter int i; 127f51b7662SDaniel Vetter 128f51b7662SDaniel Vetter DBG("try mapping %lu pages\n", (unsigned long)mem->page_count); 129f51b7662SDaniel Vetter 130f51b7662SDaniel Vetter if (sg_alloc_table(&st, mem->page_count, GFP_KERNEL)) 131831cd445SChris Wilson goto err; 132f51b7662SDaniel Vetter 133f51b7662SDaniel Vetter mem->sg_list = sg = st.sgl; 134f51b7662SDaniel Vetter 135f51b7662SDaniel Vetter for (i = 0 ; i < mem->page_count; i++, sg = sg_next(sg)) 136f51b7662SDaniel Vetter sg_set_page(sg, mem->pages[i], PAGE_SIZE, 0); 137f51b7662SDaniel Vetter 138f51b7662SDaniel Vetter mem->num_sg = pci_map_sg(intel_private.pcidev, mem->sg_list, 139f51b7662SDaniel Vetter mem->page_count, PCI_DMA_BIDIRECTIONAL); 140831cd445SChris Wilson if (unlikely(!mem->num_sg)) 141831cd445SChris Wilson goto err; 142831cd445SChris Wilson 143f51b7662SDaniel Vetter return 0; 144831cd445SChris Wilson 145831cd445SChris Wilson err: 146831cd445SChris Wilson sg_free_table(&st); 147831cd445SChris Wilson return -ENOMEM; 148f51b7662SDaniel Vetter } 149f51b7662SDaniel Vetter 150f51b7662SDaniel Vetter static void intel_agp_unmap_memory(struct agp_memory *mem) 151f51b7662SDaniel Vetter { 152f51b7662SDaniel Vetter DBG("try unmapping %lu pages\n", (unsigned long)mem->page_count); 153f51b7662SDaniel Vetter 154f51b7662SDaniel Vetter pci_unmap_sg(intel_private.pcidev, mem->sg_list, 155f51b7662SDaniel Vetter mem->page_count, PCI_DMA_BIDIRECTIONAL); 156f51b7662SDaniel Vetter intel_agp_free_sglist(mem); 157f51b7662SDaniel Vetter } 158f51b7662SDaniel Vetter 159f51b7662SDaniel Vetter static void intel_agp_insert_sg_entries(struct agp_memory *mem, 160f51b7662SDaniel Vetter off_t pg_start, int mask_type) 161f51b7662SDaniel Vetter { 162f51b7662SDaniel Vetter struct scatterlist *sg; 163f51b7662SDaniel Vetter int i, j; 164f51b7662SDaniel Vetter 165f51b7662SDaniel Vetter j = pg_start; 166f51b7662SDaniel Vetter 167f51b7662SDaniel Vetter WARN_ON(!mem->num_sg); 168f51b7662SDaniel Vetter 169f51b7662SDaniel Vetter if (mem->num_sg == mem->page_count) { 170f51b7662SDaniel Vetter for_each_sg(mem->sg_list, sg, mem->page_count, i) { 171f51b7662SDaniel Vetter writel(agp_bridge->driver->mask_memory(agp_bridge, 172f51b7662SDaniel Vetter sg_dma_address(sg), mask_type), 173f51b7662SDaniel Vetter intel_private.gtt+j); 174f51b7662SDaniel Vetter j++; 175f51b7662SDaniel Vetter } 176f51b7662SDaniel Vetter } else { 177f51b7662SDaniel Vetter /* sg may merge pages, but we have to separate 178f51b7662SDaniel Vetter * per-page addr for GTT */ 179f51b7662SDaniel Vetter unsigned int len, m; 180f51b7662SDaniel Vetter 181f51b7662SDaniel Vetter for_each_sg(mem->sg_list, sg, mem->num_sg, i) { 182f51b7662SDaniel Vetter len = sg_dma_len(sg) / PAGE_SIZE; 183f51b7662SDaniel Vetter for (m = 0; m < len; m++) { 184f51b7662SDaniel Vetter writel(agp_bridge->driver->mask_memory(agp_bridge, 185f51b7662SDaniel Vetter sg_dma_address(sg) + m * PAGE_SIZE, 186f51b7662SDaniel Vetter mask_type), 187f51b7662SDaniel Vetter intel_private.gtt+j); 188f51b7662SDaniel Vetter j++; 189f51b7662SDaniel Vetter } 190f51b7662SDaniel Vetter } 191f51b7662SDaniel Vetter } 192f51b7662SDaniel Vetter readl(intel_private.gtt+j-1); 193f51b7662SDaniel Vetter } 194f51b7662SDaniel Vetter 195f51b7662SDaniel Vetter #else 196f51b7662SDaniel Vetter 197f51b7662SDaniel Vetter static void intel_agp_insert_sg_entries(struct agp_memory *mem, 198f51b7662SDaniel Vetter off_t pg_start, int mask_type) 199f51b7662SDaniel Vetter { 200f51b7662SDaniel Vetter int i, j; 201f51b7662SDaniel Vetter 202f51b7662SDaniel Vetter for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { 203f51b7662SDaniel Vetter writel(agp_bridge->driver->mask_memory(agp_bridge, 204f51b7662SDaniel Vetter page_to_phys(mem->pages[i]), mask_type), 205f51b7662SDaniel Vetter intel_private.gtt+j); 206f51b7662SDaniel Vetter } 207f51b7662SDaniel Vetter 208f51b7662SDaniel Vetter readl(intel_private.gtt+j-1); 209f51b7662SDaniel Vetter } 210f51b7662SDaniel Vetter 211f51b7662SDaniel Vetter #endif 212f51b7662SDaniel Vetter 213f51b7662SDaniel Vetter static int intel_i810_fetch_size(void) 214f51b7662SDaniel Vetter { 215f51b7662SDaniel Vetter u32 smram_miscc; 216f51b7662SDaniel Vetter struct aper_size_info_fixed *values; 217f51b7662SDaniel Vetter 218f51b7662SDaniel Vetter pci_read_config_dword(agp_bridge->dev, I810_SMRAM_MISCC, &smram_miscc); 219f51b7662SDaniel Vetter values = A_SIZE_FIX(agp_bridge->driver->aperture_sizes); 220f51b7662SDaniel Vetter 221f51b7662SDaniel Vetter if ((smram_miscc & I810_GMS) == I810_GMS_DISABLE) { 222f51b7662SDaniel Vetter dev_warn(&agp_bridge->dev->dev, "i810 is disabled\n"); 223f51b7662SDaniel Vetter return 0; 224f51b7662SDaniel Vetter } 225f51b7662SDaniel Vetter if ((smram_miscc & I810_GFX_MEM_WIN_SIZE) == I810_GFX_MEM_WIN_32M) { 226f51b7662SDaniel Vetter agp_bridge->current_size = (void *) (values + 1); 227f51b7662SDaniel Vetter agp_bridge->aperture_size_idx = 1; 228f51b7662SDaniel Vetter return values[1].size; 229f51b7662SDaniel Vetter } else { 230f51b7662SDaniel Vetter agp_bridge->current_size = (void *) (values); 231f51b7662SDaniel Vetter agp_bridge->aperture_size_idx = 0; 232f51b7662SDaniel Vetter return values[0].size; 233f51b7662SDaniel Vetter } 234f51b7662SDaniel Vetter 235f51b7662SDaniel Vetter return 0; 236f51b7662SDaniel Vetter } 237f51b7662SDaniel Vetter 238f51b7662SDaniel Vetter static int intel_i810_configure(void) 239f51b7662SDaniel Vetter { 240f51b7662SDaniel Vetter struct aper_size_info_fixed *current_size; 241f51b7662SDaniel Vetter u32 temp; 242f51b7662SDaniel Vetter int i; 243f51b7662SDaniel Vetter 244f51b7662SDaniel Vetter current_size = A_SIZE_FIX(agp_bridge->current_size); 245f51b7662SDaniel Vetter 246f51b7662SDaniel Vetter if (!intel_private.registers) { 247f51b7662SDaniel Vetter pci_read_config_dword(intel_private.pcidev, I810_MMADDR, &temp); 248f51b7662SDaniel Vetter temp &= 0xfff80000; 249f51b7662SDaniel Vetter 250f51b7662SDaniel Vetter intel_private.registers = ioremap(temp, 128 * 4096); 251f51b7662SDaniel Vetter if (!intel_private.registers) { 252f51b7662SDaniel Vetter dev_err(&intel_private.pcidev->dev, 253f51b7662SDaniel Vetter "can't remap memory\n"); 254f51b7662SDaniel Vetter return -ENOMEM; 255f51b7662SDaniel Vetter } 256f51b7662SDaniel Vetter } 257f51b7662SDaniel Vetter 258f51b7662SDaniel Vetter if ((readl(intel_private.registers+I810_DRAM_CTL) 259f51b7662SDaniel Vetter & I810_DRAM_ROW_0) == I810_DRAM_ROW_0_SDRAM) { 260f51b7662SDaniel Vetter /* This will need to be dynamically assigned */ 261f51b7662SDaniel Vetter dev_info(&intel_private.pcidev->dev, 262f51b7662SDaniel Vetter "detected 4MB dedicated video ram\n"); 263f51b7662SDaniel Vetter intel_private.num_dcache_entries = 1024; 264f51b7662SDaniel Vetter } 265f51b7662SDaniel Vetter pci_read_config_dword(intel_private.pcidev, I810_GMADDR, &temp); 266f51b7662SDaniel Vetter agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); 267f51b7662SDaniel Vetter writel(agp_bridge->gatt_bus_addr | I810_PGETBL_ENABLED, intel_private.registers+I810_PGETBL_CTL); 268f51b7662SDaniel Vetter readl(intel_private.registers+I810_PGETBL_CTL); /* PCI Posting. */ 269f51b7662SDaniel Vetter 270f51b7662SDaniel Vetter if (agp_bridge->driver->needs_scratch_page) { 271f51b7662SDaniel Vetter for (i = 0; i < current_size->num_entries; i++) { 272f51b7662SDaniel Vetter writel(agp_bridge->scratch_page, intel_private.registers+I810_PTE_BASE+(i*4)); 273f51b7662SDaniel Vetter } 274f51b7662SDaniel Vetter readl(intel_private.registers+I810_PTE_BASE+((i-1)*4)); /* PCI posting. */ 275f51b7662SDaniel Vetter } 276f51b7662SDaniel Vetter global_cache_flush(); 277f51b7662SDaniel Vetter return 0; 278f51b7662SDaniel Vetter } 279f51b7662SDaniel Vetter 280f51b7662SDaniel Vetter static void intel_i810_cleanup(void) 281f51b7662SDaniel Vetter { 282f51b7662SDaniel Vetter writel(0, intel_private.registers+I810_PGETBL_CTL); 283f51b7662SDaniel Vetter readl(intel_private.registers); /* PCI Posting. */ 284f51b7662SDaniel Vetter iounmap(intel_private.registers); 285f51b7662SDaniel Vetter } 286f51b7662SDaniel Vetter 287f51b7662SDaniel Vetter static void intel_i810_agp_enable(struct agp_bridge_data *bridge, u32 mode) 288f51b7662SDaniel Vetter { 289f51b7662SDaniel Vetter return; 290f51b7662SDaniel Vetter } 291f51b7662SDaniel Vetter 292f51b7662SDaniel Vetter /* Exists to support ARGB cursors */ 293f51b7662SDaniel Vetter static struct page *i8xx_alloc_pages(void) 294f51b7662SDaniel Vetter { 295f51b7662SDaniel Vetter struct page *page; 296f51b7662SDaniel Vetter 297f51b7662SDaniel Vetter page = alloc_pages(GFP_KERNEL | GFP_DMA32, 2); 298f51b7662SDaniel Vetter if (page == NULL) 299f51b7662SDaniel Vetter return NULL; 300f51b7662SDaniel Vetter 301f51b7662SDaniel Vetter if (set_pages_uc(page, 4) < 0) { 302f51b7662SDaniel Vetter set_pages_wb(page, 4); 303f51b7662SDaniel Vetter __free_pages(page, 2); 304f51b7662SDaniel Vetter return NULL; 305f51b7662SDaniel Vetter } 306f51b7662SDaniel Vetter get_page(page); 307f51b7662SDaniel Vetter atomic_inc(&agp_bridge->current_memory_agp); 308f51b7662SDaniel Vetter return page; 309f51b7662SDaniel Vetter } 310f51b7662SDaniel Vetter 311f51b7662SDaniel Vetter static void i8xx_destroy_pages(struct page *page) 312f51b7662SDaniel Vetter { 313f51b7662SDaniel Vetter if (page == NULL) 314f51b7662SDaniel Vetter return; 315f51b7662SDaniel Vetter 316f51b7662SDaniel Vetter set_pages_wb(page, 4); 317f51b7662SDaniel Vetter put_page(page); 318f51b7662SDaniel Vetter __free_pages(page, 2); 319f51b7662SDaniel Vetter atomic_dec(&agp_bridge->current_memory_agp); 320f51b7662SDaniel Vetter } 321f51b7662SDaniel Vetter 322f51b7662SDaniel Vetter static int intel_i830_type_to_mask_type(struct agp_bridge_data *bridge, 323f51b7662SDaniel Vetter int type) 324f51b7662SDaniel Vetter { 325f51b7662SDaniel Vetter if (type < AGP_USER_TYPES) 326f51b7662SDaniel Vetter return type; 327f51b7662SDaniel Vetter else if (type == AGP_USER_CACHED_MEMORY) 328f51b7662SDaniel Vetter return INTEL_AGP_CACHED_MEMORY; 329f51b7662SDaniel Vetter else 330f51b7662SDaniel Vetter return 0; 331f51b7662SDaniel Vetter } 332f51b7662SDaniel Vetter 333f8f235e5SZhenyu Wang static int intel_gen6_type_to_mask_type(struct agp_bridge_data *bridge, 334f8f235e5SZhenyu Wang int type) 335f8f235e5SZhenyu Wang { 336f8f235e5SZhenyu Wang unsigned int type_mask = type & ~AGP_USER_CACHED_MEMORY_GFDT; 337f8f235e5SZhenyu Wang unsigned int gfdt = type & AGP_USER_CACHED_MEMORY_GFDT; 338f8f235e5SZhenyu Wang 339f8f235e5SZhenyu Wang if (type_mask == AGP_USER_UNCACHED_MEMORY) 340f8f235e5SZhenyu Wang return INTEL_AGP_UNCACHED_MEMORY; 341f8f235e5SZhenyu Wang else if (type_mask == AGP_USER_CACHED_MEMORY_LLC_MLC) 342f8f235e5SZhenyu Wang return gfdt ? INTEL_AGP_CACHED_MEMORY_LLC_MLC_GFDT : 343f8f235e5SZhenyu Wang INTEL_AGP_CACHED_MEMORY_LLC_MLC; 344f8f235e5SZhenyu Wang else /* set 'normal'/'cached' to LLC by default */ 345f8f235e5SZhenyu Wang return gfdt ? INTEL_AGP_CACHED_MEMORY_LLC_GFDT : 346f8f235e5SZhenyu Wang INTEL_AGP_CACHED_MEMORY_LLC; 347f8f235e5SZhenyu Wang } 348f8f235e5SZhenyu Wang 349f8f235e5SZhenyu Wang 350f51b7662SDaniel Vetter static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start, 351f51b7662SDaniel Vetter int type) 352f51b7662SDaniel Vetter { 353f51b7662SDaniel Vetter int i, j, num_entries; 354f51b7662SDaniel Vetter void *temp; 355f51b7662SDaniel Vetter int ret = -EINVAL; 356f51b7662SDaniel Vetter int mask_type; 357f51b7662SDaniel Vetter 358f51b7662SDaniel Vetter if (mem->page_count == 0) 359f51b7662SDaniel Vetter goto out; 360f51b7662SDaniel Vetter 361f51b7662SDaniel Vetter temp = agp_bridge->current_size; 362f51b7662SDaniel Vetter num_entries = A_SIZE_FIX(temp)->num_entries; 363f51b7662SDaniel Vetter 364f51b7662SDaniel Vetter if ((pg_start + mem->page_count) > num_entries) 365f51b7662SDaniel Vetter goto out_err; 366f51b7662SDaniel Vetter 367f51b7662SDaniel Vetter 368f51b7662SDaniel Vetter for (j = pg_start; j < (pg_start + mem->page_count); j++) { 369f51b7662SDaniel Vetter if (!PGE_EMPTY(agp_bridge, readl(agp_bridge->gatt_table+j))) { 370f51b7662SDaniel Vetter ret = -EBUSY; 371f51b7662SDaniel Vetter goto out_err; 372f51b7662SDaniel Vetter } 373f51b7662SDaniel Vetter } 374f51b7662SDaniel Vetter 375f51b7662SDaniel Vetter if (type != mem->type) 376f51b7662SDaniel Vetter goto out_err; 377f51b7662SDaniel Vetter 378f51b7662SDaniel Vetter mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type); 379f51b7662SDaniel Vetter 380f51b7662SDaniel Vetter switch (mask_type) { 381f51b7662SDaniel Vetter case AGP_DCACHE_MEMORY: 382f51b7662SDaniel Vetter if (!mem->is_flushed) 383f51b7662SDaniel Vetter global_cache_flush(); 384f51b7662SDaniel Vetter for (i = pg_start; i < (pg_start + mem->page_count); i++) { 385f51b7662SDaniel Vetter writel((i*4096)|I810_PTE_LOCAL|I810_PTE_VALID, 386f51b7662SDaniel Vetter intel_private.registers+I810_PTE_BASE+(i*4)); 387f51b7662SDaniel Vetter } 388f51b7662SDaniel Vetter readl(intel_private.registers+I810_PTE_BASE+((i-1)*4)); 389f51b7662SDaniel Vetter break; 390f51b7662SDaniel Vetter case AGP_PHYS_MEMORY: 391f51b7662SDaniel Vetter case AGP_NORMAL_MEMORY: 392f51b7662SDaniel Vetter if (!mem->is_flushed) 393f51b7662SDaniel Vetter global_cache_flush(); 394f51b7662SDaniel Vetter for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { 395f51b7662SDaniel Vetter writel(agp_bridge->driver->mask_memory(agp_bridge, 396f51b7662SDaniel Vetter page_to_phys(mem->pages[i]), mask_type), 397f51b7662SDaniel Vetter intel_private.registers+I810_PTE_BASE+(j*4)); 398f51b7662SDaniel Vetter } 399f51b7662SDaniel Vetter readl(intel_private.registers+I810_PTE_BASE+((j-1)*4)); 400f51b7662SDaniel Vetter break; 401f51b7662SDaniel Vetter default: 402f51b7662SDaniel Vetter goto out_err; 403f51b7662SDaniel Vetter } 404f51b7662SDaniel Vetter 405f51b7662SDaniel Vetter out: 406f51b7662SDaniel Vetter ret = 0; 407f51b7662SDaniel Vetter out_err: 408f51b7662SDaniel Vetter mem->is_flushed = true; 409f51b7662SDaniel Vetter return ret; 410f51b7662SDaniel Vetter } 411f51b7662SDaniel Vetter 412f51b7662SDaniel Vetter static int intel_i810_remove_entries(struct agp_memory *mem, off_t pg_start, 413f51b7662SDaniel Vetter int type) 414f51b7662SDaniel Vetter { 415f51b7662SDaniel Vetter int i; 416f51b7662SDaniel Vetter 417f51b7662SDaniel Vetter if (mem->page_count == 0) 418f51b7662SDaniel Vetter return 0; 419f51b7662SDaniel Vetter 420f51b7662SDaniel Vetter for (i = pg_start; i < (mem->page_count + pg_start); i++) { 421f51b7662SDaniel Vetter writel(agp_bridge->scratch_page, intel_private.registers+I810_PTE_BASE+(i*4)); 422f51b7662SDaniel Vetter } 423f51b7662SDaniel Vetter readl(intel_private.registers+I810_PTE_BASE+((i-1)*4)); 424f51b7662SDaniel Vetter 425f51b7662SDaniel Vetter return 0; 426f51b7662SDaniel Vetter } 427f51b7662SDaniel Vetter 428f51b7662SDaniel Vetter /* 429f51b7662SDaniel Vetter * The i810/i830 requires a physical address to program its mouse 430f51b7662SDaniel Vetter * pointer into hardware. 431f51b7662SDaniel Vetter * However the Xserver still writes to it through the agp aperture. 432f51b7662SDaniel Vetter */ 433f51b7662SDaniel Vetter static struct agp_memory *alloc_agpphysmem_i8xx(size_t pg_count, int type) 434f51b7662SDaniel Vetter { 435f51b7662SDaniel Vetter struct agp_memory *new; 436f51b7662SDaniel Vetter struct page *page; 437f51b7662SDaniel Vetter 438f51b7662SDaniel Vetter switch (pg_count) { 439f51b7662SDaniel Vetter case 1: page = agp_bridge->driver->agp_alloc_page(agp_bridge); 440f51b7662SDaniel Vetter break; 441f51b7662SDaniel Vetter case 4: 442f51b7662SDaniel Vetter /* kludge to get 4 physical pages for ARGB cursor */ 443f51b7662SDaniel Vetter page = i8xx_alloc_pages(); 444f51b7662SDaniel Vetter break; 445f51b7662SDaniel Vetter default: 446f51b7662SDaniel Vetter return NULL; 447f51b7662SDaniel Vetter } 448f51b7662SDaniel Vetter 449f51b7662SDaniel Vetter if (page == NULL) 450f51b7662SDaniel Vetter return NULL; 451f51b7662SDaniel Vetter 452f51b7662SDaniel Vetter new = agp_create_memory(pg_count); 453f51b7662SDaniel Vetter if (new == NULL) 454f51b7662SDaniel Vetter return NULL; 455f51b7662SDaniel Vetter 456f51b7662SDaniel Vetter new->pages[0] = page; 457f51b7662SDaniel Vetter if (pg_count == 4) { 458f51b7662SDaniel Vetter /* kludge to get 4 physical pages for ARGB cursor */ 459f51b7662SDaniel Vetter new->pages[1] = new->pages[0] + 1; 460f51b7662SDaniel Vetter new->pages[2] = new->pages[1] + 1; 461f51b7662SDaniel Vetter new->pages[3] = new->pages[2] + 1; 462f51b7662SDaniel Vetter } 463f51b7662SDaniel Vetter new->page_count = pg_count; 464f51b7662SDaniel Vetter new->num_scratch_pages = pg_count; 465f51b7662SDaniel Vetter new->type = AGP_PHYS_MEMORY; 466f51b7662SDaniel Vetter new->physical = page_to_phys(new->pages[0]); 467f51b7662SDaniel Vetter return new; 468f51b7662SDaniel Vetter } 469f51b7662SDaniel Vetter 470f51b7662SDaniel Vetter static struct agp_memory *intel_i810_alloc_by_type(size_t pg_count, int type) 471f51b7662SDaniel Vetter { 472f51b7662SDaniel Vetter struct agp_memory *new; 473f51b7662SDaniel Vetter 474f51b7662SDaniel Vetter if (type == AGP_DCACHE_MEMORY) { 475f51b7662SDaniel Vetter if (pg_count != intel_private.num_dcache_entries) 476f51b7662SDaniel Vetter return NULL; 477f51b7662SDaniel Vetter 478f51b7662SDaniel Vetter new = agp_create_memory(1); 479f51b7662SDaniel Vetter if (new == NULL) 480f51b7662SDaniel Vetter return NULL; 481f51b7662SDaniel Vetter 482f51b7662SDaniel Vetter new->type = AGP_DCACHE_MEMORY; 483f51b7662SDaniel Vetter new->page_count = pg_count; 484f51b7662SDaniel Vetter new->num_scratch_pages = 0; 485f51b7662SDaniel Vetter agp_free_page_array(new); 486f51b7662SDaniel Vetter return new; 487f51b7662SDaniel Vetter } 488f51b7662SDaniel Vetter if (type == AGP_PHYS_MEMORY) 489f51b7662SDaniel Vetter return alloc_agpphysmem_i8xx(pg_count, type); 490f51b7662SDaniel Vetter return NULL; 491f51b7662SDaniel Vetter } 492f51b7662SDaniel Vetter 493f51b7662SDaniel Vetter static void intel_i810_free_by_type(struct agp_memory *curr) 494f51b7662SDaniel Vetter { 495f51b7662SDaniel Vetter agp_free_key(curr->key); 496f51b7662SDaniel Vetter if (curr->type == AGP_PHYS_MEMORY) { 497f51b7662SDaniel Vetter if (curr->page_count == 4) 498f51b7662SDaniel Vetter i8xx_destroy_pages(curr->pages[0]); 499f51b7662SDaniel Vetter else { 500f51b7662SDaniel Vetter agp_bridge->driver->agp_destroy_page(curr->pages[0], 501f51b7662SDaniel Vetter AGP_PAGE_DESTROY_UNMAP); 502f51b7662SDaniel Vetter agp_bridge->driver->agp_destroy_page(curr->pages[0], 503f51b7662SDaniel Vetter AGP_PAGE_DESTROY_FREE); 504f51b7662SDaniel Vetter } 505f51b7662SDaniel Vetter agp_free_page_array(curr); 506f51b7662SDaniel Vetter } 507f51b7662SDaniel Vetter kfree(curr); 508f51b7662SDaniel Vetter } 509f51b7662SDaniel Vetter 510f51b7662SDaniel Vetter static unsigned long intel_i810_mask_memory(struct agp_bridge_data *bridge, 511f51b7662SDaniel Vetter dma_addr_t addr, int type) 512f51b7662SDaniel Vetter { 513f51b7662SDaniel Vetter /* Type checking must be done elsewhere */ 514f51b7662SDaniel Vetter return addr | bridge->driver->masks[type].mask; 515f51b7662SDaniel Vetter } 516f51b7662SDaniel Vetter 517f51b7662SDaniel Vetter static struct aper_size_info_fixed intel_i830_sizes[] = 518f51b7662SDaniel Vetter { 519f51b7662SDaniel Vetter {128, 32768, 5}, 520f51b7662SDaniel Vetter /* The 64M mode still requires a 128k gatt */ 521f51b7662SDaniel Vetter {64, 16384, 5}, 522f51b7662SDaniel Vetter {256, 65536, 6}, 523f51b7662SDaniel Vetter {512, 131072, 7}, 524f51b7662SDaniel Vetter }; 525f51b7662SDaniel Vetter 526f51b7662SDaniel Vetter static void intel_i830_init_gtt_entries(void) 527f51b7662SDaniel Vetter { 528f51b7662SDaniel Vetter u16 gmch_ctrl; 529f51b7662SDaniel Vetter int gtt_entries = 0; 530f51b7662SDaniel Vetter u8 rdct; 531f51b7662SDaniel Vetter int local = 0; 532f51b7662SDaniel Vetter static const int ddt[4] = { 0, 16, 32, 64 }; 533f51b7662SDaniel Vetter int size; /* reserved space (in kb) at the top of stolen memory */ 534f51b7662SDaniel Vetter 535f51b7662SDaniel Vetter pci_read_config_word(agp_bridge->dev, I830_GMCH_CTRL, &gmch_ctrl); 536f51b7662SDaniel Vetter 537f51b7662SDaniel Vetter if (IS_I965) { 538f51b7662SDaniel Vetter u32 pgetbl_ctl; 539f51b7662SDaniel Vetter pgetbl_ctl = readl(intel_private.registers+I810_PGETBL_CTL); 540f51b7662SDaniel Vetter 541f51b7662SDaniel Vetter /* The 965 has a field telling us the size of the GTT, 542f51b7662SDaniel Vetter * which may be larger than what is necessary to map the 543f51b7662SDaniel Vetter * aperture. 544f51b7662SDaniel Vetter */ 545f51b7662SDaniel Vetter switch (pgetbl_ctl & I965_PGETBL_SIZE_MASK) { 546f51b7662SDaniel Vetter case I965_PGETBL_SIZE_128KB: 547f51b7662SDaniel Vetter size = 128; 548f51b7662SDaniel Vetter break; 549f51b7662SDaniel Vetter case I965_PGETBL_SIZE_256KB: 550f51b7662SDaniel Vetter size = 256; 551f51b7662SDaniel Vetter break; 552f51b7662SDaniel Vetter case I965_PGETBL_SIZE_512KB: 553f51b7662SDaniel Vetter size = 512; 554f51b7662SDaniel Vetter break; 555f51b7662SDaniel Vetter case I965_PGETBL_SIZE_1MB: 556f51b7662SDaniel Vetter size = 1024; 557f51b7662SDaniel Vetter break; 558f51b7662SDaniel Vetter case I965_PGETBL_SIZE_2MB: 559f51b7662SDaniel Vetter size = 2048; 560f51b7662SDaniel Vetter break; 561f51b7662SDaniel Vetter case I965_PGETBL_SIZE_1_5MB: 562f51b7662SDaniel Vetter size = 1024 + 512; 563f51b7662SDaniel Vetter break; 564f51b7662SDaniel Vetter default: 565f51b7662SDaniel Vetter dev_info(&intel_private.pcidev->dev, 566f51b7662SDaniel Vetter "unknown page table size, assuming 512KB\n"); 567f51b7662SDaniel Vetter size = 512; 568f51b7662SDaniel Vetter } 569f51b7662SDaniel Vetter size += 4; /* add in BIOS popup space */ 570f51b7662SDaniel Vetter } else if (IS_G33 && !IS_PINEVIEW) { 571f51b7662SDaniel Vetter /* G33's GTT size defined in gmch_ctrl */ 572f51b7662SDaniel Vetter switch (gmch_ctrl & G33_PGETBL_SIZE_MASK) { 573f51b7662SDaniel Vetter case G33_PGETBL_SIZE_1M: 574f51b7662SDaniel Vetter size = 1024; 575f51b7662SDaniel Vetter break; 576f51b7662SDaniel Vetter case G33_PGETBL_SIZE_2M: 577f51b7662SDaniel Vetter size = 2048; 578f51b7662SDaniel Vetter break; 579f51b7662SDaniel Vetter default: 580f51b7662SDaniel Vetter dev_info(&agp_bridge->dev->dev, 581f51b7662SDaniel Vetter "unknown page table size 0x%x, assuming 512KB\n", 582f51b7662SDaniel Vetter (gmch_ctrl & G33_PGETBL_SIZE_MASK)); 583f51b7662SDaniel Vetter size = 512; 584f51b7662SDaniel Vetter } 585f51b7662SDaniel Vetter size += 4; 586f51b7662SDaniel Vetter } else if (IS_G4X || IS_PINEVIEW) { 587f51b7662SDaniel Vetter /* On 4 series hardware, GTT stolen is separate from graphics 588f51b7662SDaniel Vetter * stolen, ignore it in stolen gtt entries counting. However, 589f51b7662SDaniel Vetter * 4KB of the stolen memory doesn't get mapped to the GTT. 590f51b7662SDaniel Vetter */ 591f51b7662SDaniel Vetter size = 4; 592f51b7662SDaniel Vetter } else { 593f51b7662SDaniel Vetter /* On previous hardware, the GTT size was just what was 594f51b7662SDaniel Vetter * required to map the aperture. 595f51b7662SDaniel Vetter */ 596f51b7662SDaniel Vetter size = agp_bridge->driver->fetch_size() + 4; 597f51b7662SDaniel Vetter } 598f51b7662SDaniel Vetter 599f51b7662SDaniel Vetter if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82830_HB || 600f51b7662SDaniel Vetter agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82845G_HB) { 601f51b7662SDaniel Vetter switch (gmch_ctrl & I830_GMCH_GMS_MASK) { 602f51b7662SDaniel Vetter case I830_GMCH_GMS_STOLEN_512: 603f51b7662SDaniel Vetter gtt_entries = KB(512) - KB(size); 604f51b7662SDaniel Vetter break; 605f51b7662SDaniel Vetter case I830_GMCH_GMS_STOLEN_1024: 606f51b7662SDaniel Vetter gtt_entries = MB(1) - KB(size); 607f51b7662SDaniel Vetter break; 608f51b7662SDaniel Vetter case I830_GMCH_GMS_STOLEN_8192: 609f51b7662SDaniel Vetter gtt_entries = MB(8) - KB(size); 610f51b7662SDaniel Vetter break; 611f51b7662SDaniel Vetter case I830_GMCH_GMS_LOCAL: 612f51b7662SDaniel Vetter rdct = readb(intel_private.registers+I830_RDRAM_CHANNEL_TYPE); 613f51b7662SDaniel Vetter gtt_entries = (I830_RDRAM_ND(rdct) + 1) * 614f51b7662SDaniel Vetter MB(ddt[I830_RDRAM_DDT(rdct)]); 615f51b7662SDaniel Vetter local = 1; 616f51b7662SDaniel Vetter break; 617f51b7662SDaniel Vetter default: 618f51b7662SDaniel Vetter gtt_entries = 0; 619f51b7662SDaniel Vetter break; 620f51b7662SDaniel Vetter } 62185540480SZhenyu Wang } else if (IS_SNB) { 622f51b7662SDaniel Vetter /* 623f51b7662SDaniel Vetter * SandyBridge has new memory control reg at 0x50.w 624f51b7662SDaniel Vetter */ 625f51b7662SDaniel Vetter u16 snb_gmch_ctl; 626f51b7662SDaniel Vetter pci_read_config_word(intel_private.pcidev, SNB_GMCH_CTRL, &snb_gmch_ctl); 627f51b7662SDaniel Vetter switch (snb_gmch_ctl & SNB_GMCH_GMS_STOLEN_MASK) { 628f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_32M: 629f51b7662SDaniel Vetter gtt_entries = MB(32) - KB(size); 630f51b7662SDaniel Vetter break; 631f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_64M: 632f51b7662SDaniel Vetter gtt_entries = MB(64) - KB(size); 633f51b7662SDaniel Vetter break; 634f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_96M: 635f51b7662SDaniel Vetter gtt_entries = MB(96) - KB(size); 636f51b7662SDaniel Vetter break; 637f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_128M: 638f51b7662SDaniel Vetter gtt_entries = MB(128) - KB(size); 639f51b7662SDaniel Vetter break; 640f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_160M: 641f51b7662SDaniel Vetter gtt_entries = MB(160) - KB(size); 642f51b7662SDaniel Vetter break; 643f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_192M: 644f51b7662SDaniel Vetter gtt_entries = MB(192) - KB(size); 645f51b7662SDaniel Vetter break; 646f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_224M: 647f51b7662SDaniel Vetter gtt_entries = MB(224) - KB(size); 648f51b7662SDaniel Vetter break; 649f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_256M: 650f51b7662SDaniel Vetter gtt_entries = MB(256) - KB(size); 651f51b7662SDaniel Vetter break; 652f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_288M: 653f51b7662SDaniel Vetter gtt_entries = MB(288) - KB(size); 654f51b7662SDaniel Vetter break; 655f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_320M: 656f51b7662SDaniel Vetter gtt_entries = MB(320) - KB(size); 657f51b7662SDaniel Vetter break; 658f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_352M: 659f51b7662SDaniel Vetter gtt_entries = MB(352) - KB(size); 660f51b7662SDaniel Vetter break; 661f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_384M: 662f51b7662SDaniel Vetter gtt_entries = MB(384) - KB(size); 663f51b7662SDaniel Vetter break; 664f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_416M: 665f51b7662SDaniel Vetter gtt_entries = MB(416) - KB(size); 666f51b7662SDaniel Vetter break; 667f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_448M: 668f51b7662SDaniel Vetter gtt_entries = MB(448) - KB(size); 669f51b7662SDaniel Vetter break; 670f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_480M: 671f51b7662SDaniel Vetter gtt_entries = MB(480) - KB(size); 672f51b7662SDaniel Vetter break; 673f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_512M: 674f51b7662SDaniel Vetter gtt_entries = MB(512) - KB(size); 675f51b7662SDaniel Vetter break; 676f51b7662SDaniel Vetter } 677f51b7662SDaniel Vetter } else { 678f51b7662SDaniel Vetter switch (gmch_ctrl & I855_GMCH_GMS_MASK) { 679f51b7662SDaniel Vetter case I855_GMCH_GMS_STOLEN_1M: 680f51b7662SDaniel Vetter gtt_entries = MB(1) - KB(size); 681f51b7662SDaniel Vetter break; 682f51b7662SDaniel Vetter case I855_GMCH_GMS_STOLEN_4M: 683f51b7662SDaniel Vetter gtt_entries = MB(4) - KB(size); 684f51b7662SDaniel Vetter break; 685f51b7662SDaniel Vetter case I855_GMCH_GMS_STOLEN_8M: 686f51b7662SDaniel Vetter gtt_entries = MB(8) - KB(size); 687f51b7662SDaniel Vetter break; 688f51b7662SDaniel Vetter case I855_GMCH_GMS_STOLEN_16M: 689f51b7662SDaniel Vetter gtt_entries = MB(16) - KB(size); 690f51b7662SDaniel Vetter break; 691f51b7662SDaniel Vetter case I855_GMCH_GMS_STOLEN_32M: 692f51b7662SDaniel Vetter gtt_entries = MB(32) - KB(size); 693f51b7662SDaniel Vetter break; 694f51b7662SDaniel Vetter case I915_GMCH_GMS_STOLEN_48M: 695f51b7662SDaniel Vetter /* Check it's really I915G */ 696f51b7662SDaniel Vetter if (IS_I915 || IS_I965 || IS_G33 || IS_G4X) 697f51b7662SDaniel Vetter gtt_entries = MB(48) - KB(size); 698f51b7662SDaniel Vetter else 699f51b7662SDaniel Vetter gtt_entries = 0; 700f51b7662SDaniel Vetter break; 701f51b7662SDaniel Vetter case I915_GMCH_GMS_STOLEN_64M: 702f51b7662SDaniel Vetter /* Check it's really I915G */ 703f51b7662SDaniel Vetter if (IS_I915 || IS_I965 || IS_G33 || IS_G4X) 704f51b7662SDaniel Vetter gtt_entries = MB(64) - KB(size); 705f51b7662SDaniel Vetter else 706f51b7662SDaniel Vetter gtt_entries = 0; 707f51b7662SDaniel Vetter break; 708f51b7662SDaniel Vetter case G33_GMCH_GMS_STOLEN_128M: 709f51b7662SDaniel Vetter if (IS_G33 || IS_I965 || IS_G4X) 710f51b7662SDaniel Vetter gtt_entries = MB(128) - KB(size); 711f51b7662SDaniel Vetter else 712f51b7662SDaniel Vetter gtt_entries = 0; 713f51b7662SDaniel Vetter break; 714f51b7662SDaniel Vetter case G33_GMCH_GMS_STOLEN_256M: 715f51b7662SDaniel Vetter if (IS_G33 || IS_I965 || IS_G4X) 716f51b7662SDaniel Vetter gtt_entries = MB(256) - KB(size); 717f51b7662SDaniel Vetter else 718f51b7662SDaniel Vetter gtt_entries = 0; 719f51b7662SDaniel Vetter break; 720f51b7662SDaniel Vetter case INTEL_GMCH_GMS_STOLEN_96M: 721f51b7662SDaniel Vetter if (IS_I965 || IS_G4X) 722f51b7662SDaniel Vetter gtt_entries = MB(96) - KB(size); 723f51b7662SDaniel Vetter else 724f51b7662SDaniel Vetter gtt_entries = 0; 725f51b7662SDaniel Vetter break; 726f51b7662SDaniel Vetter case INTEL_GMCH_GMS_STOLEN_160M: 727f51b7662SDaniel Vetter if (IS_I965 || IS_G4X) 728f51b7662SDaniel Vetter gtt_entries = MB(160) - KB(size); 729f51b7662SDaniel Vetter else 730f51b7662SDaniel Vetter gtt_entries = 0; 731f51b7662SDaniel Vetter break; 732f51b7662SDaniel Vetter case INTEL_GMCH_GMS_STOLEN_224M: 733f51b7662SDaniel Vetter if (IS_I965 || IS_G4X) 734f51b7662SDaniel Vetter gtt_entries = MB(224) - KB(size); 735f51b7662SDaniel Vetter else 736f51b7662SDaniel Vetter gtt_entries = 0; 737f51b7662SDaniel Vetter break; 738f51b7662SDaniel Vetter case INTEL_GMCH_GMS_STOLEN_352M: 739f51b7662SDaniel Vetter if (IS_I965 || IS_G4X) 740f51b7662SDaniel Vetter gtt_entries = MB(352) - KB(size); 741f51b7662SDaniel Vetter else 742f51b7662SDaniel Vetter gtt_entries = 0; 743f51b7662SDaniel Vetter break; 744f51b7662SDaniel Vetter default: 745f51b7662SDaniel Vetter gtt_entries = 0; 746f51b7662SDaniel Vetter break; 747f51b7662SDaniel Vetter } 748f51b7662SDaniel Vetter } 749d1d6ca73SJesse Barnes if (!local && gtt_entries > intel_max_stolen) { 750d1d6ca73SJesse Barnes dev_info(&agp_bridge->dev->dev, 751d1d6ca73SJesse Barnes "detected %dK stolen memory, trimming to %dK\n", 752d1d6ca73SJesse Barnes gtt_entries / KB(1), intel_max_stolen / KB(1)); 753d1d6ca73SJesse Barnes gtt_entries = intel_max_stolen / KB(4); 754d1d6ca73SJesse Barnes } else if (gtt_entries > 0) { 755f51b7662SDaniel Vetter dev_info(&agp_bridge->dev->dev, "detected %dK %s memory\n", 756f51b7662SDaniel Vetter gtt_entries / KB(1), local ? "local" : "stolen"); 757f51b7662SDaniel Vetter gtt_entries /= KB(4); 758f51b7662SDaniel Vetter } else { 759f51b7662SDaniel Vetter dev_info(&agp_bridge->dev->dev, 760f51b7662SDaniel Vetter "no pre-allocated video memory detected\n"); 761f51b7662SDaniel Vetter gtt_entries = 0; 762f51b7662SDaniel Vetter } 763f51b7662SDaniel Vetter 764f51b7662SDaniel Vetter intel_private.gtt_entries = gtt_entries; 765f51b7662SDaniel Vetter } 766f51b7662SDaniel Vetter 767f51b7662SDaniel Vetter static void intel_i830_fini_flush(void) 768f51b7662SDaniel Vetter { 769f51b7662SDaniel Vetter kunmap(intel_private.i8xx_page); 770f51b7662SDaniel Vetter intel_private.i8xx_flush_page = NULL; 771f51b7662SDaniel Vetter unmap_page_from_agp(intel_private.i8xx_page); 772f51b7662SDaniel Vetter 773f51b7662SDaniel Vetter __free_page(intel_private.i8xx_page); 774f51b7662SDaniel Vetter intel_private.i8xx_page = NULL; 775f51b7662SDaniel Vetter } 776f51b7662SDaniel Vetter 777f51b7662SDaniel Vetter static void intel_i830_setup_flush(void) 778f51b7662SDaniel Vetter { 779f51b7662SDaniel Vetter /* return if we've already set the flush mechanism up */ 780f51b7662SDaniel Vetter if (intel_private.i8xx_page) 781f51b7662SDaniel Vetter return; 782f51b7662SDaniel Vetter 783f51b7662SDaniel Vetter intel_private.i8xx_page = alloc_page(GFP_KERNEL | __GFP_ZERO | GFP_DMA32); 784f51b7662SDaniel Vetter if (!intel_private.i8xx_page) 785f51b7662SDaniel Vetter return; 786f51b7662SDaniel Vetter 787f51b7662SDaniel Vetter intel_private.i8xx_flush_page = kmap(intel_private.i8xx_page); 788f51b7662SDaniel Vetter if (!intel_private.i8xx_flush_page) 789f51b7662SDaniel Vetter intel_i830_fini_flush(); 790f51b7662SDaniel Vetter } 791f51b7662SDaniel Vetter 792f51b7662SDaniel Vetter /* The chipset_flush interface needs to get data that has already been 793f51b7662SDaniel Vetter * flushed out of the CPU all the way out to main memory, because the GPU 794f51b7662SDaniel Vetter * doesn't snoop those buffers. 795f51b7662SDaniel Vetter * 796f51b7662SDaniel Vetter * The 8xx series doesn't have the same lovely interface for flushing the 797f51b7662SDaniel Vetter * chipset write buffers that the later chips do. According to the 865 798f51b7662SDaniel Vetter * specs, it's 64 octwords, or 1KB. So, to get those previous things in 799f51b7662SDaniel Vetter * that buffer out, we just fill 1KB and clflush it out, on the assumption 800f51b7662SDaniel Vetter * that it'll push whatever was in there out. It appears to work. 801f51b7662SDaniel Vetter */ 802f51b7662SDaniel Vetter static void intel_i830_chipset_flush(struct agp_bridge_data *bridge) 803f51b7662SDaniel Vetter { 804f51b7662SDaniel Vetter unsigned int *pg = intel_private.i8xx_flush_page; 805f51b7662SDaniel Vetter 806f51b7662SDaniel Vetter memset(pg, 0, 1024); 807f51b7662SDaniel Vetter 808f51b7662SDaniel Vetter if (cpu_has_clflush) 809f51b7662SDaniel Vetter clflush_cache_range(pg, 1024); 810f51b7662SDaniel Vetter else if (wbinvd_on_all_cpus() != 0) 811f51b7662SDaniel Vetter printk(KERN_ERR "Timed out waiting for cache flush.\n"); 812f51b7662SDaniel Vetter } 813f51b7662SDaniel Vetter 814f51b7662SDaniel Vetter /* The intel i830 automatically initializes the agp aperture during POST. 815f51b7662SDaniel Vetter * Use the memory already set aside for in the GTT. 816f51b7662SDaniel Vetter */ 817f51b7662SDaniel Vetter static int intel_i830_create_gatt_table(struct agp_bridge_data *bridge) 818f51b7662SDaniel Vetter { 819f51b7662SDaniel Vetter int page_order; 820f51b7662SDaniel Vetter struct aper_size_info_fixed *size; 821f51b7662SDaniel Vetter int num_entries; 822f51b7662SDaniel Vetter u32 temp; 823f51b7662SDaniel Vetter 824f51b7662SDaniel Vetter size = agp_bridge->current_size; 825f51b7662SDaniel Vetter page_order = size->page_order; 826f51b7662SDaniel Vetter num_entries = size->num_entries; 827f51b7662SDaniel Vetter agp_bridge->gatt_table_real = NULL; 828f51b7662SDaniel Vetter 829f51b7662SDaniel Vetter pci_read_config_dword(intel_private.pcidev, I810_MMADDR, &temp); 830f51b7662SDaniel Vetter temp &= 0xfff80000; 831f51b7662SDaniel Vetter 832f51b7662SDaniel Vetter intel_private.registers = ioremap(temp, 128 * 4096); 833f51b7662SDaniel Vetter if (!intel_private.registers) 834f51b7662SDaniel Vetter return -ENOMEM; 835f51b7662SDaniel Vetter 836f51b7662SDaniel Vetter temp = readl(intel_private.registers+I810_PGETBL_CTL) & 0xfffff000; 837f51b7662SDaniel Vetter global_cache_flush(); /* FIXME: ?? */ 838f51b7662SDaniel Vetter 839f51b7662SDaniel Vetter /* we have to call this as early as possible after the MMIO base address is known */ 840f51b7662SDaniel Vetter intel_i830_init_gtt_entries(); 8418699be3eSOndrej Zary if (intel_private.gtt_entries == 0) { 8428699be3eSOndrej Zary iounmap(intel_private.registers); 8438699be3eSOndrej Zary return -ENOMEM; 8448699be3eSOndrej Zary } 845f51b7662SDaniel Vetter 846f51b7662SDaniel Vetter agp_bridge->gatt_table = NULL; 847f51b7662SDaniel Vetter 848f51b7662SDaniel Vetter agp_bridge->gatt_bus_addr = temp; 849f51b7662SDaniel Vetter 850f51b7662SDaniel Vetter return 0; 851f51b7662SDaniel Vetter } 852f51b7662SDaniel Vetter 853f51b7662SDaniel Vetter /* Return the gatt table to a sane state. Use the top of stolen 854f51b7662SDaniel Vetter * memory for the GTT. 855f51b7662SDaniel Vetter */ 856f51b7662SDaniel Vetter static int intel_i830_free_gatt_table(struct agp_bridge_data *bridge) 857f51b7662SDaniel Vetter { 858f51b7662SDaniel Vetter return 0; 859f51b7662SDaniel Vetter } 860f51b7662SDaniel Vetter 861f51b7662SDaniel Vetter static int intel_i830_fetch_size(void) 862f51b7662SDaniel Vetter { 863f51b7662SDaniel Vetter u16 gmch_ctrl; 864f51b7662SDaniel Vetter struct aper_size_info_fixed *values; 865f51b7662SDaniel Vetter 866f51b7662SDaniel Vetter values = A_SIZE_FIX(agp_bridge->driver->aperture_sizes); 867f51b7662SDaniel Vetter 868f51b7662SDaniel Vetter if (agp_bridge->dev->device != PCI_DEVICE_ID_INTEL_82830_HB && 869f51b7662SDaniel Vetter agp_bridge->dev->device != PCI_DEVICE_ID_INTEL_82845G_HB) { 870f51b7662SDaniel Vetter /* 855GM/852GM/865G has 128MB aperture size */ 871e1583165SDaniel Vetter agp_bridge->current_size = (void *) values; 872f51b7662SDaniel Vetter agp_bridge->aperture_size_idx = 0; 873f51b7662SDaniel Vetter return values[0].size; 874f51b7662SDaniel Vetter } 875f51b7662SDaniel Vetter 876f51b7662SDaniel Vetter pci_read_config_word(agp_bridge->dev, I830_GMCH_CTRL, &gmch_ctrl); 877f51b7662SDaniel Vetter 878f51b7662SDaniel Vetter if ((gmch_ctrl & I830_GMCH_MEM_MASK) == I830_GMCH_MEM_128M) { 879e1583165SDaniel Vetter agp_bridge->current_size = (void *) values; 880f51b7662SDaniel Vetter agp_bridge->aperture_size_idx = 0; 881f51b7662SDaniel Vetter return values[0].size; 882f51b7662SDaniel Vetter } else { 883e1583165SDaniel Vetter agp_bridge->current_size = (void *) (values + 1); 884f51b7662SDaniel Vetter agp_bridge->aperture_size_idx = 1; 885f51b7662SDaniel Vetter return values[1].size; 886f51b7662SDaniel Vetter } 887f51b7662SDaniel Vetter 888f51b7662SDaniel Vetter return 0; 889f51b7662SDaniel Vetter } 890f51b7662SDaniel Vetter 891f51b7662SDaniel Vetter static int intel_i830_configure(void) 892f51b7662SDaniel Vetter { 893f51b7662SDaniel Vetter struct aper_size_info_fixed *current_size; 894f51b7662SDaniel Vetter u32 temp; 895f51b7662SDaniel Vetter u16 gmch_ctrl; 896f51b7662SDaniel Vetter int i; 897f51b7662SDaniel Vetter 898f51b7662SDaniel Vetter current_size = A_SIZE_FIX(agp_bridge->current_size); 899f51b7662SDaniel Vetter 900f51b7662SDaniel Vetter pci_read_config_dword(intel_private.pcidev, I810_GMADDR, &temp); 901f51b7662SDaniel Vetter agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); 902f51b7662SDaniel Vetter 903f51b7662SDaniel Vetter pci_read_config_word(agp_bridge->dev, I830_GMCH_CTRL, &gmch_ctrl); 904f51b7662SDaniel Vetter gmch_ctrl |= I830_GMCH_ENABLED; 905f51b7662SDaniel Vetter pci_write_config_word(agp_bridge->dev, I830_GMCH_CTRL, gmch_ctrl); 906f51b7662SDaniel Vetter 907f51b7662SDaniel Vetter writel(agp_bridge->gatt_bus_addr|I810_PGETBL_ENABLED, intel_private.registers+I810_PGETBL_CTL); 908f51b7662SDaniel Vetter readl(intel_private.registers+I810_PGETBL_CTL); /* PCI Posting. */ 909f51b7662SDaniel Vetter 910f51b7662SDaniel Vetter if (agp_bridge->driver->needs_scratch_page) { 911f51b7662SDaniel Vetter for (i = intel_private.gtt_entries; i < current_size->num_entries; i++) { 912f51b7662SDaniel Vetter writel(agp_bridge->scratch_page, intel_private.registers+I810_PTE_BASE+(i*4)); 913f51b7662SDaniel Vetter } 914f51b7662SDaniel Vetter readl(intel_private.registers+I810_PTE_BASE+((i-1)*4)); /* PCI Posting. */ 915f51b7662SDaniel Vetter } 916f51b7662SDaniel Vetter 917f51b7662SDaniel Vetter global_cache_flush(); 918f51b7662SDaniel Vetter 919f51b7662SDaniel Vetter intel_i830_setup_flush(); 920f51b7662SDaniel Vetter return 0; 921f51b7662SDaniel Vetter } 922f51b7662SDaniel Vetter 923f51b7662SDaniel Vetter static void intel_i830_cleanup(void) 924f51b7662SDaniel Vetter { 925f51b7662SDaniel Vetter iounmap(intel_private.registers); 926f51b7662SDaniel Vetter } 927f51b7662SDaniel Vetter 928f51b7662SDaniel Vetter static int intel_i830_insert_entries(struct agp_memory *mem, off_t pg_start, 929f51b7662SDaniel Vetter int type) 930f51b7662SDaniel Vetter { 931f51b7662SDaniel Vetter int i, j, num_entries; 932f51b7662SDaniel Vetter void *temp; 933f51b7662SDaniel Vetter int ret = -EINVAL; 934f51b7662SDaniel Vetter int mask_type; 935f51b7662SDaniel Vetter 936f51b7662SDaniel Vetter if (mem->page_count == 0) 937f51b7662SDaniel Vetter goto out; 938f51b7662SDaniel Vetter 939f51b7662SDaniel Vetter temp = agp_bridge->current_size; 940f51b7662SDaniel Vetter num_entries = A_SIZE_FIX(temp)->num_entries; 941f51b7662SDaniel Vetter 942f51b7662SDaniel Vetter if (pg_start < intel_private.gtt_entries) { 943f51b7662SDaniel Vetter dev_printk(KERN_DEBUG, &intel_private.pcidev->dev, 944f51b7662SDaniel Vetter "pg_start == 0x%.8lx, intel_private.gtt_entries == 0x%.8x\n", 945f51b7662SDaniel Vetter pg_start, intel_private.gtt_entries); 946f51b7662SDaniel Vetter 947f51b7662SDaniel Vetter dev_info(&intel_private.pcidev->dev, 948f51b7662SDaniel Vetter "trying to insert into local/stolen memory\n"); 949f51b7662SDaniel Vetter goto out_err; 950f51b7662SDaniel Vetter } 951f51b7662SDaniel Vetter 952f51b7662SDaniel Vetter if ((pg_start + mem->page_count) > num_entries) 953f51b7662SDaniel Vetter goto out_err; 954f51b7662SDaniel Vetter 955f51b7662SDaniel Vetter /* The i830 can't check the GTT for entries since its read only, 956f51b7662SDaniel Vetter * depend on the caller to make the correct offset decisions. 957f51b7662SDaniel Vetter */ 958f51b7662SDaniel Vetter 959f51b7662SDaniel Vetter if (type != mem->type) 960f51b7662SDaniel Vetter goto out_err; 961f51b7662SDaniel Vetter 962f51b7662SDaniel Vetter mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type); 963f51b7662SDaniel Vetter 964f51b7662SDaniel Vetter if (mask_type != 0 && mask_type != AGP_PHYS_MEMORY && 965f51b7662SDaniel Vetter mask_type != INTEL_AGP_CACHED_MEMORY) 966f51b7662SDaniel Vetter goto out_err; 967f51b7662SDaniel Vetter 968f51b7662SDaniel Vetter if (!mem->is_flushed) 969f51b7662SDaniel Vetter global_cache_flush(); 970f51b7662SDaniel Vetter 971f51b7662SDaniel Vetter for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { 972f51b7662SDaniel Vetter writel(agp_bridge->driver->mask_memory(agp_bridge, 973f51b7662SDaniel Vetter page_to_phys(mem->pages[i]), mask_type), 974f51b7662SDaniel Vetter intel_private.registers+I810_PTE_BASE+(j*4)); 975f51b7662SDaniel Vetter } 976f51b7662SDaniel Vetter readl(intel_private.registers+I810_PTE_BASE+((j-1)*4)); 977f51b7662SDaniel Vetter 978f51b7662SDaniel Vetter out: 979f51b7662SDaniel Vetter ret = 0; 980f51b7662SDaniel Vetter out_err: 981f51b7662SDaniel Vetter mem->is_flushed = true; 982f51b7662SDaniel Vetter return ret; 983f51b7662SDaniel Vetter } 984f51b7662SDaniel Vetter 985f51b7662SDaniel Vetter static int intel_i830_remove_entries(struct agp_memory *mem, off_t pg_start, 986f51b7662SDaniel Vetter int type) 987f51b7662SDaniel Vetter { 988f51b7662SDaniel Vetter int i; 989f51b7662SDaniel Vetter 990f51b7662SDaniel Vetter if (mem->page_count == 0) 991f51b7662SDaniel Vetter return 0; 992f51b7662SDaniel Vetter 993f51b7662SDaniel Vetter if (pg_start < intel_private.gtt_entries) { 994f51b7662SDaniel Vetter dev_info(&intel_private.pcidev->dev, 995f51b7662SDaniel Vetter "trying to disable local/stolen memory\n"); 996f51b7662SDaniel Vetter return -EINVAL; 997f51b7662SDaniel Vetter } 998f51b7662SDaniel Vetter 999f51b7662SDaniel Vetter for (i = pg_start; i < (mem->page_count + pg_start); i++) { 1000f51b7662SDaniel Vetter writel(agp_bridge->scratch_page, intel_private.registers+I810_PTE_BASE+(i*4)); 1001f51b7662SDaniel Vetter } 1002f51b7662SDaniel Vetter readl(intel_private.registers+I810_PTE_BASE+((i-1)*4)); 1003f51b7662SDaniel Vetter 1004f51b7662SDaniel Vetter return 0; 1005f51b7662SDaniel Vetter } 1006f51b7662SDaniel Vetter 1007f51b7662SDaniel Vetter static struct agp_memory *intel_i830_alloc_by_type(size_t pg_count, int type) 1008f51b7662SDaniel Vetter { 1009f51b7662SDaniel Vetter if (type == AGP_PHYS_MEMORY) 1010f51b7662SDaniel Vetter return alloc_agpphysmem_i8xx(pg_count, type); 1011f51b7662SDaniel Vetter /* always return NULL for other allocation types for now */ 1012f51b7662SDaniel Vetter return NULL; 1013f51b7662SDaniel Vetter } 1014f51b7662SDaniel Vetter 1015f51b7662SDaniel Vetter static int intel_alloc_chipset_flush_resource(void) 1016f51b7662SDaniel Vetter { 1017f51b7662SDaniel Vetter int ret; 1018f51b7662SDaniel Vetter ret = pci_bus_alloc_resource(agp_bridge->dev->bus, &intel_private.ifp_resource, PAGE_SIZE, 1019f51b7662SDaniel Vetter PAGE_SIZE, PCIBIOS_MIN_MEM, 0, 1020f51b7662SDaniel Vetter pcibios_align_resource, agp_bridge->dev); 1021f51b7662SDaniel Vetter 1022f51b7662SDaniel Vetter return ret; 1023f51b7662SDaniel Vetter } 1024f51b7662SDaniel Vetter 1025f51b7662SDaniel Vetter static void intel_i915_setup_chipset_flush(void) 1026f51b7662SDaniel Vetter { 1027f51b7662SDaniel Vetter int ret; 1028f51b7662SDaniel Vetter u32 temp; 1029f51b7662SDaniel Vetter 1030f51b7662SDaniel Vetter pci_read_config_dword(agp_bridge->dev, I915_IFPADDR, &temp); 1031f51b7662SDaniel Vetter if (!(temp & 0x1)) { 1032f51b7662SDaniel Vetter intel_alloc_chipset_flush_resource(); 1033f51b7662SDaniel Vetter intel_private.resource_valid = 1; 1034f51b7662SDaniel Vetter pci_write_config_dword(agp_bridge->dev, I915_IFPADDR, (intel_private.ifp_resource.start & 0xffffffff) | 0x1); 1035f51b7662SDaniel Vetter } else { 1036f51b7662SDaniel Vetter temp &= ~1; 1037f51b7662SDaniel Vetter 1038f51b7662SDaniel Vetter intel_private.resource_valid = 1; 1039f51b7662SDaniel Vetter intel_private.ifp_resource.start = temp; 1040f51b7662SDaniel Vetter intel_private.ifp_resource.end = temp + PAGE_SIZE; 1041f51b7662SDaniel Vetter ret = request_resource(&iomem_resource, &intel_private.ifp_resource); 1042f51b7662SDaniel Vetter /* some BIOSes reserve this area in a pnp some don't */ 1043f51b7662SDaniel Vetter if (ret) 1044f51b7662SDaniel Vetter intel_private.resource_valid = 0; 1045f51b7662SDaniel Vetter } 1046f51b7662SDaniel Vetter } 1047f51b7662SDaniel Vetter 1048f51b7662SDaniel Vetter static void intel_i965_g33_setup_chipset_flush(void) 1049f51b7662SDaniel Vetter { 1050f51b7662SDaniel Vetter u32 temp_hi, temp_lo; 1051f51b7662SDaniel Vetter int ret; 1052f51b7662SDaniel Vetter 1053f51b7662SDaniel Vetter pci_read_config_dword(agp_bridge->dev, I965_IFPADDR + 4, &temp_hi); 1054f51b7662SDaniel Vetter pci_read_config_dword(agp_bridge->dev, I965_IFPADDR, &temp_lo); 1055f51b7662SDaniel Vetter 1056f51b7662SDaniel Vetter if (!(temp_lo & 0x1)) { 1057f51b7662SDaniel Vetter 1058f51b7662SDaniel Vetter intel_alloc_chipset_flush_resource(); 1059f51b7662SDaniel Vetter 1060f51b7662SDaniel Vetter intel_private.resource_valid = 1; 1061f51b7662SDaniel Vetter pci_write_config_dword(agp_bridge->dev, I965_IFPADDR + 4, 1062f51b7662SDaniel Vetter upper_32_bits(intel_private.ifp_resource.start)); 1063f51b7662SDaniel Vetter pci_write_config_dword(agp_bridge->dev, I965_IFPADDR, (intel_private.ifp_resource.start & 0xffffffff) | 0x1); 1064f51b7662SDaniel Vetter } else { 1065f51b7662SDaniel Vetter u64 l64; 1066f51b7662SDaniel Vetter 1067f51b7662SDaniel Vetter temp_lo &= ~0x1; 1068f51b7662SDaniel Vetter l64 = ((u64)temp_hi << 32) | temp_lo; 1069f51b7662SDaniel Vetter 1070f51b7662SDaniel Vetter intel_private.resource_valid = 1; 1071f51b7662SDaniel Vetter intel_private.ifp_resource.start = l64; 1072f51b7662SDaniel Vetter intel_private.ifp_resource.end = l64 + PAGE_SIZE; 1073f51b7662SDaniel Vetter ret = request_resource(&iomem_resource, &intel_private.ifp_resource); 1074f51b7662SDaniel Vetter /* some BIOSes reserve this area in a pnp some don't */ 1075f51b7662SDaniel Vetter if (ret) 1076f51b7662SDaniel Vetter intel_private.resource_valid = 0; 1077f51b7662SDaniel Vetter } 1078f51b7662SDaniel Vetter } 1079f51b7662SDaniel Vetter 1080f51b7662SDaniel Vetter static void intel_i9xx_setup_flush(void) 1081f51b7662SDaniel Vetter { 1082f51b7662SDaniel Vetter /* return if already configured */ 1083f51b7662SDaniel Vetter if (intel_private.ifp_resource.start) 1084f51b7662SDaniel Vetter return; 1085f51b7662SDaniel Vetter 1086f51b7662SDaniel Vetter if (IS_SNB) 1087f51b7662SDaniel Vetter return; 1088f51b7662SDaniel Vetter 1089f51b7662SDaniel Vetter /* setup a resource for this object */ 1090f51b7662SDaniel Vetter intel_private.ifp_resource.name = "Intel Flush Page"; 1091f51b7662SDaniel Vetter intel_private.ifp_resource.flags = IORESOURCE_MEM; 1092f51b7662SDaniel Vetter 1093f51b7662SDaniel Vetter /* Setup chipset flush for 915 */ 1094f51b7662SDaniel Vetter if (IS_I965 || IS_G33 || IS_G4X) { 1095f51b7662SDaniel Vetter intel_i965_g33_setup_chipset_flush(); 1096f51b7662SDaniel Vetter } else { 1097f51b7662SDaniel Vetter intel_i915_setup_chipset_flush(); 1098f51b7662SDaniel Vetter } 1099f51b7662SDaniel Vetter 1100df51e7aaSChris Wilson if (intel_private.ifp_resource.start) 1101f51b7662SDaniel Vetter intel_private.i9xx_flush_page = ioremap_nocache(intel_private.ifp_resource.start, PAGE_SIZE); 1102f51b7662SDaniel Vetter if (!intel_private.i9xx_flush_page) 1103df51e7aaSChris Wilson dev_err(&intel_private.pcidev->dev, 1104df51e7aaSChris Wilson "can't ioremap flush page - no chipset flushing\n"); 1105f51b7662SDaniel Vetter } 1106f51b7662SDaniel Vetter 1107f1befe71SChris Wilson static int intel_i9xx_configure(void) 1108f51b7662SDaniel Vetter { 1109f51b7662SDaniel Vetter struct aper_size_info_fixed *current_size; 1110f51b7662SDaniel Vetter u32 temp; 1111f51b7662SDaniel Vetter u16 gmch_ctrl; 1112f51b7662SDaniel Vetter int i; 1113f51b7662SDaniel Vetter 1114f51b7662SDaniel Vetter current_size = A_SIZE_FIX(agp_bridge->current_size); 1115f51b7662SDaniel Vetter 1116f51b7662SDaniel Vetter pci_read_config_dword(intel_private.pcidev, I915_GMADDR, &temp); 1117f51b7662SDaniel Vetter 1118f51b7662SDaniel Vetter agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); 1119f51b7662SDaniel Vetter 1120f51b7662SDaniel Vetter pci_read_config_word(agp_bridge->dev, I830_GMCH_CTRL, &gmch_ctrl); 1121f51b7662SDaniel Vetter gmch_ctrl |= I830_GMCH_ENABLED; 1122f51b7662SDaniel Vetter pci_write_config_word(agp_bridge->dev, I830_GMCH_CTRL, gmch_ctrl); 1123f51b7662SDaniel Vetter 1124f51b7662SDaniel Vetter writel(agp_bridge->gatt_bus_addr|I810_PGETBL_ENABLED, intel_private.registers+I810_PGETBL_CTL); 1125f51b7662SDaniel Vetter readl(intel_private.registers+I810_PGETBL_CTL); /* PCI Posting. */ 1126f51b7662SDaniel Vetter 1127f51b7662SDaniel Vetter if (agp_bridge->driver->needs_scratch_page) { 1128f51b7662SDaniel Vetter for (i = intel_private.gtt_entries; i < intel_private.gtt_total_size; i++) { 1129f51b7662SDaniel Vetter writel(agp_bridge->scratch_page, intel_private.gtt+i); 1130f51b7662SDaniel Vetter } 1131f51b7662SDaniel Vetter readl(intel_private.gtt+i-1); /* PCI Posting. */ 1132f51b7662SDaniel Vetter } 1133f51b7662SDaniel Vetter 1134f51b7662SDaniel Vetter global_cache_flush(); 1135f51b7662SDaniel Vetter 1136f51b7662SDaniel Vetter intel_i9xx_setup_flush(); 1137f51b7662SDaniel Vetter 1138f51b7662SDaniel Vetter return 0; 1139f51b7662SDaniel Vetter } 1140f51b7662SDaniel Vetter 1141f51b7662SDaniel Vetter static void intel_i915_cleanup(void) 1142f51b7662SDaniel Vetter { 1143f51b7662SDaniel Vetter if (intel_private.i9xx_flush_page) 1144f51b7662SDaniel Vetter iounmap(intel_private.i9xx_flush_page); 1145f51b7662SDaniel Vetter if (intel_private.resource_valid) 1146f51b7662SDaniel Vetter release_resource(&intel_private.ifp_resource); 1147f51b7662SDaniel Vetter intel_private.ifp_resource.start = 0; 1148f51b7662SDaniel Vetter intel_private.resource_valid = 0; 1149f51b7662SDaniel Vetter iounmap(intel_private.gtt); 1150f51b7662SDaniel Vetter iounmap(intel_private.registers); 1151f51b7662SDaniel Vetter } 1152f51b7662SDaniel Vetter 1153f51b7662SDaniel Vetter static void intel_i915_chipset_flush(struct agp_bridge_data *bridge) 1154f51b7662SDaniel Vetter { 1155f51b7662SDaniel Vetter if (intel_private.i9xx_flush_page) 1156f51b7662SDaniel Vetter writel(1, intel_private.i9xx_flush_page); 1157f51b7662SDaniel Vetter } 1158f51b7662SDaniel Vetter 1159f51b7662SDaniel Vetter static int intel_i915_insert_entries(struct agp_memory *mem, off_t pg_start, 1160f51b7662SDaniel Vetter int type) 1161f51b7662SDaniel Vetter { 1162f51b7662SDaniel Vetter int num_entries; 1163f51b7662SDaniel Vetter void *temp; 1164f51b7662SDaniel Vetter int ret = -EINVAL; 1165f51b7662SDaniel Vetter int mask_type; 1166f51b7662SDaniel Vetter 1167f51b7662SDaniel Vetter if (mem->page_count == 0) 1168f51b7662SDaniel Vetter goto out; 1169f51b7662SDaniel Vetter 1170f51b7662SDaniel Vetter temp = agp_bridge->current_size; 1171f51b7662SDaniel Vetter num_entries = A_SIZE_FIX(temp)->num_entries; 1172f51b7662SDaniel Vetter 1173f51b7662SDaniel Vetter if (pg_start < intel_private.gtt_entries) { 1174f51b7662SDaniel Vetter dev_printk(KERN_DEBUG, &intel_private.pcidev->dev, 1175f51b7662SDaniel Vetter "pg_start == 0x%.8lx, intel_private.gtt_entries == 0x%.8x\n", 1176f51b7662SDaniel Vetter pg_start, intel_private.gtt_entries); 1177f51b7662SDaniel Vetter 1178f51b7662SDaniel Vetter dev_info(&intel_private.pcidev->dev, 1179f51b7662SDaniel Vetter "trying to insert into local/stolen memory\n"); 1180f51b7662SDaniel Vetter goto out_err; 1181f51b7662SDaniel Vetter } 1182f51b7662SDaniel Vetter 1183f51b7662SDaniel Vetter if ((pg_start + mem->page_count) > num_entries) 1184f51b7662SDaniel Vetter goto out_err; 1185f51b7662SDaniel Vetter 1186f51b7662SDaniel Vetter /* The i915 can't check the GTT for entries since it's read only; 1187f51b7662SDaniel Vetter * depend on the caller to make the correct offset decisions. 1188f51b7662SDaniel Vetter */ 1189f51b7662SDaniel Vetter 1190f51b7662SDaniel Vetter if (type != mem->type) 1191f51b7662SDaniel Vetter goto out_err; 1192f51b7662SDaniel Vetter 1193f51b7662SDaniel Vetter mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type); 1194f51b7662SDaniel Vetter 1195f8f235e5SZhenyu Wang if (!IS_SNB && mask_type != 0 && mask_type != AGP_PHYS_MEMORY && 1196f51b7662SDaniel Vetter mask_type != INTEL_AGP_CACHED_MEMORY) 1197f51b7662SDaniel Vetter goto out_err; 1198f51b7662SDaniel Vetter 1199f51b7662SDaniel Vetter if (!mem->is_flushed) 1200f51b7662SDaniel Vetter global_cache_flush(); 1201f51b7662SDaniel Vetter 1202f51b7662SDaniel Vetter intel_agp_insert_sg_entries(mem, pg_start, mask_type); 1203f51b7662SDaniel Vetter 1204f51b7662SDaniel Vetter out: 1205f51b7662SDaniel Vetter ret = 0; 1206f51b7662SDaniel Vetter out_err: 1207f51b7662SDaniel Vetter mem->is_flushed = true; 1208f51b7662SDaniel Vetter return ret; 1209f51b7662SDaniel Vetter } 1210f51b7662SDaniel Vetter 1211f51b7662SDaniel Vetter static int intel_i915_remove_entries(struct agp_memory *mem, off_t pg_start, 1212f51b7662SDaniel Vetter int type) 1213f51b7662SDaniel Vetter { 1214f51b7662SDaniel Vetter int i; 1215f51b7662SDaniel Vetter 1216f51b7662SDaniel Vetter if (mem->page_count == 0) 1217f51b7662SDaniel Vetter return 0; 1218f51b7662SDaniel Vetter 1219f51b7662SDaniel Vetter if (pg_start < intel_private.gtt_entries) { 1220f51b7662SDaniel Vetter dev_info(&intel_private.pcidev->dev, 1221f51b7662SDaniel Vetter "trying to disable local/stolen memory\n"); 1222f51b7662SDaniel Vetter return -EINVAL; 1223f51b7662SDaniel Vetter } 1224f51b7662SDaniel Vetter 1225f51b7662SDaniel Vetter for (i = pg_start; i < (mem->page_count + pg_start); i++) 1226f51b7662SDaniel Vetter writel(agp_bridge->scratch_page, intel_private.gtt+i); 1227f51b7662SDaniel Vetter 1228f51b7662SDaniel Vetter readl(intel_private.gtt+i-1); 1229f51b7662SDaniel Vetter 1230f51b7662SDaniel Vetter return 0; 1231f51b7662SDaniel Vetter } 1232f51b7662SDaniel Vetter 1233f51b7662SDaniel Vetter /* Return the aperture size by just checking the resource length. The effect 1234f51b7662SDaniel Vetter * described in the spec of the MSAC registers is just changing of the 1235f51b7662SDaniel Vetter * resource size. 1236f51b7662SDaniel Vetter */ 1237f51b7662SDaniel Vetter static int intel_i9xx_fetch_size(void) 1238f51b7662SDaniel Vetter { 1239f51b7662SDaniel Vetter int num_sizes = ARRAY_SIZE(intel_i830_sizes); 1240f51b7662SDaniel Vetter int aper_size; /* size in megabytes */ 1241f51b7662SDaniel Vetter int i; 1242f51b7662SDaniel Vetter 1243f51b7662SDaniel Vetter aper_size = pci_resource_len(intel_private.pcidev, 2) / MB(1); 1244f51b7662SDaniel Vetter 1245f51b7662SDaniel Vetter for (i = 0; i < num_sizes; i++) { 1246f51b7662SDaniel Vetter if (aper_size == intel_i830_sizes[i].size) { 1247f51b7662SDaniel Vetter agp_bridge->current_size = intel_i830_sizes + i; 1248f51b7662SDaniel Vetter return aper_size; 1249f51b7662SDaniel Vetter } 1250f51b7662SDaniel Vetter } 1251f51b7662SDaniel Vetter 1252f51b7662SDaniel Vetter return 0; 1253f51b7662SDaniel Vetter } 1254f51b7662SDaniel Vetter 1255f1befe71SChris Wilson static int intel_i915_get_gtt_size(void) 1256f1befe71SChris Wilson { 1257f1befe71SChris Wilson int size; 1258f1befe71SChris Wilson 1259f1befe71SChris Wilson if (IS_G33) { 1260f1befe71SChris Wilson u16 gmch_ctrl; 1261f1befe71SChris Wilson 1262f1befe71SChris Wilson /* G33's GTT size defined in gmch_ctrl */ 1263f1befe71SChris Wilson pci_read_config_word(agp_bridge->dev, I830_GMCH_CTRL, &gmch_ctrl); 1264e7b96f28STim Gardner switch (gmch_ctrl & I830_GMCH_GMS_MASK) { 1265e7b96f28STim Gardner case I830_GMCH_GMS_STOLEN_512: 1266e7b96f28STim Gardner size = 512; 1267e7b96f28STim Gardner break; 1268e7b96f28STim Gardner case I830_GMCH_GMS_STOLEN_1024: 1269f1befe71SChris Wilson size = 1024; 1270f1befe71SChris Wilson break; 1271e7b96f28STim Gardner case I830_GMCH_GMS_STOLEN_8192: 1272e7b96f28STim Gardner size = 8*1024; 1273f1befe71SChris Wilson break; 1274f1befe71SChris Wilson default: 1275f1befe71SChris Wilson dev_info(&agp_bridge->dev->dev, 1276f1befe71SChris Wilson "unknown page table size 0x%x, assuming 512KB\n", 1277e7b96f28STim Gardner (gmch_ctrl & I830_GMCH_GMS_MASK)); 1278f1befe71SChris Wilson size = 512; 1279f1befe71SChris Wilson } 1280f1befe71SChris Wilson } else { 1281f1befe71SChris Wilson /* On previous hardware, the GTT size was just what was 1282f1befe71SChris Wilson * required to map the aperture. 1283f1befe71SChris Wilson */ 1284f1befe71SChris Wilson size = agp_bridge->driver->fetch_size(); 1285f1befe71SChris Wilson } 1286f1befe71SChris Wilson 1287f1befe71SChris Wilson return KB(size); 1288f1befe71SChris Wilson } 1289f1befe71SChris Wilson 1290f51b7662SDaniel Vetter /* The intel i915 automatically initializes the agp aperture during POST. 1291f51b7662SDaniel Vetter * Use the memory already set aside for in the GTT. 1292f51b7662SDaniel Vetter */ 1293f51b7662SDaniel Vetter static int intel_i915_create_gatt_table(struct agp_bridge_data *bridge) 1294f51b7662SDaniel Vetter { 1295f51b7662SDaniel Vetter int page_order; 1296f51b7662SDaniel Vetter struct aper_size_info_fixed *size; 1297f51b7662SDaniel Vetter int num_entries; 1298f51b7662SDaniel Vetter u32 temp, temp2; 1299f1befe71SChris Wilson int gtt_map_size; 1300f51b7662SDaniel Vetter 1301f51b7662SDaniel Vetter size = agp_bridge->current_size; 1302f51b7662SDaniel Vetter page_order = size->page_order; 1303f51b7662SDaniel Vetter num_entries = size->num_entries; 1304f51b7662SDaniel Vetter agp_bridge->gatt_table_real = NULL; 1305f51b7662SDaniel Vetter 1306f51b7662SDaniel Vetter pci_read_config_dword(intel_private.pcidev, I915_MMADDR, &temp); 1307f51b7662SDaniel Vetter pci_read_config_dword(intel_private.pcidev, I915_PTEADDR, &temp2); 1308f51b7662SDaniel Vetter 1309f1befe71SChris Wilson gtt_map_size = intel_i915_get_gtt_size(); 1310f1befe71SChris Wilson 1311f51b7662SDaniel Vetter intel_private.gtt = ioremap(temp2, gtt_map_size); 1312f51b7662SDaniel Vetter if (!intel_private.gtt) 1313f51b7662SDaniel Vetter return -ENOMEM; 1314f51b7662SDaniel Vetter 1315f51b7662SDaniel Vetter intel_private.gtt_total_size = gtt_map_size / 4; 1316f51b7662SDaniel Vetter 1317f51b7662SDaniel Vetter temp &= 0xfff80000; 1318f51b7662SDaniel Vetter 1319f51b7662SDaniel Vetter intel_private.registers = ioremap(temp, 128 * 4096); 1320f51b7662SDaniel Vetter if (!intel_private.registers) { 1321f51b7662SDaniel Vetter iounmap(intel_private.gtt); 1322f51b7662SDaniel Vetter return -ENOMEM; 1323f51b7662SDaniel Vetter } 1324f51b7662SDaniel Vetter 1325f51b7662SDaniel Vetter temp = readl(intel_private.registers+I810_PGETBL_CTL) & 0xfffff000; 1326f51b7662SDaniel Vetter global_cache_flush(); /* FIXME: ? */ 1327f51b7662SDaniel Vetter 1328f51b7662SDaniel Vetter /* we have to call this as early as possible after the MMIO base address is known */ 1329f51b7662SDaniel Vetter intel_i830_init_gtt_entries(); 13308699be3eSOndrej Zary if (intel_private.gtt_entries == 0) { 13318699be3eSOndrej Zary iounmap(intel_private.gtt); 13328699be3eSOndrej Zary iounmap(intel_private.registers); 13338699be3eSOndrej Zary return -ENOMEM; 13348699be3eSOndrej Zary } 1335f51b7662SDaniel Vetter 1336f51b7662SDaniel Vetter agp_bridge->gatt_table = NULL; 1337f51b7662SDaniel Vetter 1338f51b7662SDaniel Vetter agp_bridge->gatt_bus_addr = temp; 1339f51b7662SDaniel Vetter 1340f51b7662SDaniel Vetter return 0; 1341f51b7662SDaniel Vetter } 1342f51b7662SDaniel Vetter 1343f51b7662SDaniel Vetter /* 1344f51b7662SDaniel Vetter * The i965 supports 36-bit physical addresses, but to keep 1345f51b7662SDaniel Vetter * the format of the GTT the same, the bits that don't fit 1346f51b7662SDaniel Vetter * in a 32-bit word are shifted down to bits 4..7. 1347f51b7662SDaniel Vetter * 1348f51b7662SDaniel Vetter * Gcc is smart enough to notice that "(addr >> 28) & 0xf0" 1349f51b7662SDaniel Vetter * is always zero on 32-bit architectures, so no need to make 1350f51b7662SDaniel Vetter * this conditional. 1351f51b7662SDaniel Vetter */ 1352f51b7662SDaniel Vetter static unsigned long intel_i965_mask_memory(struct agp_bridge_data *bridge, 1353f51b7662SDaniel Vetter dma_addr_t addr, int type) 1354f51b7662SDaniel Vetter { 1355f51b7662SDaniel Vetter /* Shift high bits down */ 1356f51b7662SDaniel Vetter addr |= (addr >> 28) & 0xf0; 1357f51b7662SDaniel Vetter 1358f51b7662SDaniel Vetter /* Type checking must be done elsewhere */ 1359f51b7662SDaniel Vetter return addr | bridge->driver->masks[type].mask; 1360f51b7662SDaniel Vetter } 1361f51b7662SDaniel Vetter 13623869d4a8SZhenyu Wang static unsigned long intel_gen6_mask_memory(struct agp_bridge_data *bridge, 13633869d4a8SZhenyu Wang dma_addr_t addr, int type) 13643869d4a8SZhenyu Wang { 13658dfc2b14SZhenyu Wang /* gen6 has bit11-4 for physical addr bit39-32 */ 13668dfc2b14SZhenyu Wang addr |= (addr >> 28) & 0xff0; 13673869d4a8SZhenyu Wang 13683869d4a8SZhenyu Wang /* Type checking must be done elsewhere */ 13693869d4a8SZhenyu Wang return addr | bridge->driver->masks[type].mask; 13703869d4a8SZhenyu Wang } 13713869d4a8SZhenyu Wang 1372f51b7662SDaniel Vetter static void intel_i965_get_gtt_range(int *gtt_offset, int *gtt_size) 1373f51b7662SDaniel Vetter { 1374f51b7662SDaniel Vetter u16 snb_gmch_ctl; 1375f51b7662SDaniel Vetter 1376f51b7662SDaniel Vetter switch (agp_bridge->dev->device) { 1377f51b7662SDaniel Vetter case PCI_DEVICE_ID_INTEL_GM45_HB: 1378f51b7662SDaniel Vetter case PCI_DEVICE_ID_INTEL_EAGLELAKE_HB: 1379f51b7662SDaniel Vetter case PCI_DEVICE_ID_INTEL_Q45_HB: 1380f51b7662SDaniel Vetter case PCI_DEVICE_ID_INTEL_G45_HB: 1381f51b7662SDaniel Vetter case PCI_DEVICE_ID_INTEL_G41_HB: 1382f51b7662SDaniel Vetter case PCI_DEVICE_ID_INTEL_B43_HB: 1383f51b7662SDaniel Vetter case PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB: 1384f51b7662SDaniel Vetter case PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB: 1385f51b7662SDaniel Vetter case PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB: 1386f51b7662SDaniel Vetter case PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB: 1387f51b7662SDaniel Vetter *gtt_offset = *gtt_size = MB(2); 1388f51b7662SDaniel Vetter break; 1389f51b7662SDaniel Vetter case PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB: 1390f51b7662SDaniel Vetter case PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB: 139185540480SZhenyu Wang case PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_HB: 1392f51b7662SDaniel Vetter *gtt_offset = MB(2); 1393f51b7662SDaniel Vetter 1394f51b7662SDaniel Vetter pci_read_config_word(intel_private.pcidev, SNB_GMCH_CTRL, &snb_gmch_ctl); 1395f51b7662SDaniel Vetter switch (snb_gmch_ctl & SNB_GTT_SIZE_MASK) { 1396f51b7662SDaniel Vetter default: 1397f51b7662SDaniel Vetter case SNB_GTT_SIZE_0M: 1398f51b7662SDaniel Vetter printk(KERN_ERR "Bad GTT size mask: 0x%04x.\n", snb_gmch_ctl); 1399f51b7662SDaniel Vetter *gtt_size = MB(0); 1400f51b7662SDaniel Vetter break; 1401f51b7662SDaniel Vetter case SNB_GTT_SIZE_1M: 1402f51b7662SDaniel Vetter *gtt_size = MB(1); 1403f51b7662SDaniel Vetter break; 1404f51b7662SDaniel Vetter case SNB_GTT_SIZE_2M: 1405f51b7662SDaniel Vetter *gtt_size = MB(2); 1406f51b7662SDaniel Vetter break; 1407f51b7662SDaniel Vetter } 1408f51b7662SDaniel Vetter break; 1409f51b7662SDaniel Vetter default: 1410f51b7662SDaniel Vetter *gtt_offset = *gtt_size = KB(512); 1411f51b7662SDaniel Vetter } 1412f51b7662SDaniel Vetter } 1413f51b7662SDaniel Vetter 1414f51b7662SDaniel Vetter /* The intel i965 automatically initializes the agp aperture during POST. 1415f51b7662SDaniel Vetter * Use the memory already set aside for in the GTT. 1416f51b7662SDaniel Vetter */ 1417f51b7662SDaniel Vetter static int intel_i965_create_gatt_table(struct agp_bridge_data *bridge) 1418f51b7662SDaniel Vetter { 1419f51b7662SDaniel Vetter int page_order; 1420f51b7662SDaniel Vetter struct aper_size_info_fixed *size; 1421f51b7662SDaniel Vetter int num_entries; 1422f51b7662SDaniel Vetter u32 temp; 1423f51b7662SDaniel Vetter int gtt_offset, gtt_size; 1424f51b7662SDaniel Vetter 1425f51b7662SDaniel Vetter size = agp_bridge->current_size; 1426f51b7662SDaniel Vetter page_order = size->page_order; 1427f51b7662SDaniel Vetter num_entries = size->num_entries; 1428f51b7662SDaniel Vetter agp_bridge->gatt_table_real = NULL; 1429f51b7662SDaniel Vetter 1430f51b7662SDaniel Vetter pci_read_config_dword(intel_private.pcidev, I915_MMADDR, &temp); 1431f51b7662SDaniel Vetter 1432f51b7662SDaniel Vetter temp &= 0xfff00000; 1433f51b7662SDaniel Vetter 1434f51b7662SDaniel Vetter intel_i965_get_gtt_range(>t_offset, >t_size); 1435f51b7662SDaniel Vetter 1436f51b7662SDaniel Vetter intel_private.gtt = ioremap((temp + gtt_offset) , gtt_size); 1437f51b7662SDaniel Vetter 1438f51b7662SDaniel Vetter if (!intel_private.gtt) 1439f51b7662SDaniel Vetter return -ENOMEM; 1440f51b7662SDaniel Vetter 1441f51b7662SDaniel Vetter intel_private.gtt_total_size = gtt_size / 4; 1442f51b7662SDaniel Vetter 1443f51b7662SDaniel Vetter intel_private.registers = ioremap(temp, 128 * 4096); 1444f51b7662SDaniel Vetter if (!intel_private.registers) { 1445f51b7662SDaniel Vetter iounmap(intel_private.gtt); 1446f51b7662SDaniel Vetter return -ENOMEM; 1447f51b7662SDaniel Vetter } 1448f51b7662SDaniel Vetter 1449f51b7662SDaniel Vetter temp = readl(intel_private.registers+I810_PGETBL_CTL) & 0xfffff000; 1450f51b7662SDaniel Vetter global_cache_flush(); /* FIXME: ? */ 1451f51b7662SDaniel Vetter 1452f51b7662SDaniel Vetter /* we have to call this as early as possible after the MMIO base address is known */ 1453f51b7662SDaniel Vetter intel_i830_init_gtt_entries(); 14548699be3eSOndrej Zary if (intel_private.gtt_entries == 0) { 14558699be3eSOndrej Zary iounmap(intel_private.gtt); 14568699be3eSOndrej Zary iounmap(intel_private.registers); 14578699be3eSOndrej Zary return -ENOMEM; 14588699be3eSOndrej Zary } 1459f51b7662SDaniel Vetter 1460f51b7662SDaniel Vetter agp_bridge->gatt_table = NULL; 1461f51b7662SDaniel Vetter 1462f51b7662SDaniel Vetter agp_bridge->gatt_bus_addr = temp; 1463f51b7662SDaniel Vetter 1464f51b7662SDaniel Vetter return 0; 1465f51b7662SDaniel Vetter } 1466f51b7662SDaniel Vetter 1467f51b7662SDaniel Vetter static const struct agp_bridge_driver intel_810_driver = { 1468f51b7662SDaniel Vetter .owner = THIS_MODULE, 1469f51b7662SDaniel Vetter .aperture_sizes = intel_i810_sizes, 1470f51b7662SDaniel Vetter .size_type = FIXED_APER_SIZE, 1471f51b7662SDaniel Vetter .num_aperture_sizes = 2, 1472f51b7662SDaniel Vetter .needs_scratch_page = true, 1473f51b7662SDaniel Vetter .configure = intel_i810_configure, 1474f51b7662SDaniel Vetter .fetch_size = intel_i810_fetch_size, 1475f51b7662SDaniel Vetter .cleanup = intel_i810_cleanup, 1476f51b7662SDaniel Vetter .mask_memory = intel_i810_mask_memory, 1477f51b7662SDaniel Vetter .masks = intel_i810_masks, 1478f51b7662SDaniel Vetter .agp_enable = intel_i810_agp_enable, 1479f51b7662SDaniel Vetter .cache_flush = global_cache_flush, 1480f51b7662SDaniel Vetter .create_gatt_table = agp_generic_create_gatt_table, 1481f51b7662SDaniel Vetter .free_gatt_table = agp_generic_free_gatt_table, 1482f51b7662SDaniel Vetter .insert_memory = intel_i810_insert_entries, 1483f51b7662SDaniel Vetter .remove_memory = intel_i810_remove_entries, 1484f51b7662SDaniel Vetter .alloc_by_type = intel_i810_alloc_by_type, 1485f51b7662SDaniel Vetter .free_by_type = intel_i810_free_by_type, 1486f51b7662SDaniel Vetter .agp_alloc_page = agp_generic_alloc_page, 1487f51b7662SDaniel Vetter .agp_alloc_pages = agp_generic_alloc_pages, 1488f51b7662SDaniel Vetter .agp_destroy_page = agp_generic_destroy_page, 1489f51b7662SDaniel Vetter .agp_destroy_pages = agp_generic_destroy_pages, 1490f51b7662SDaniel Vetter .agp_type_to_mask_type = agp_generic_type_to_mask_type, 1491f51b7662SDaniel Vetter }; 1492f51b7662SDaniel Vetter 1493f51b7662SDaniel Vetter static const struct agp_bridge_driver intel_830_driver = { 1494f51b7662SDaniel Vetter .owner = THIS_MODULE, 1495f51b7662SDaniel Vetter .aperture_sizes = intel_i830_sizes, 1496f51b7662SDaniel Vetter .size_type = FIXED_APER_SIZE, 1497f51b7662SDaniel Vetter .num_aperture_sizes = 4, 1498f51b7662SDaniel Vetter .needs_scratch_page = true, 1499f51b7662SDaniel Vetter .configure = intel_i830_configure, 1500f51b7662SDaniel Vetter .fetch_size = intel_i830_fetch_size, 1501f51b7662SDaniel Vetter .cleanup = intel_i830_cleanup, 1502f51b7662SDaniel Vetter .mask_memory = intel_i810_mask_memory, 1503f51b7662SDaniel Vetter .masks = intel_i810_masks, 1504f51b7662SDaniel Vetter .agp_enable = intel_i810_agp_enable, 1505f51b7662SDaniel Vetter .cache_flush = global_cache_flush, 1506f51b7662SDaniel Vetter .create_gatt_table = intel_i830_create_gatt_table, 1507f51b7662SDaniel Vetter .free_gatt_table = intel_i830_free_gatt_table, 1508f51b7662SDaniel Vetter .insert_memory = intel_i830_insert_entries, 1509f51b7662SDaniel Vetter .remove_memory = intel_i830_remove_entries, 1510f51b7662SDaniel Vetter .alloc_by_type = intel_i830_alloc_by_type, 1511f51b7662SDaniel Vetter .free_by_type = intel_i810_free_by_type, 1512f51b7662SDaniel Vetter .agp_alloc_page = agp_generic_alloc_page, 1513f51b7662SDaniel Vetter .agp_alloc_pages = agp_generic_alloc_pages, 1514f51b7662SDaniel Vetter .agp_destroy_page = agp_generic_destroy_page, 1515f51b7662SDaniel Vetter .agp_destroy_pages = agp_generic_destroy_pages, 1516f51b7662SDaniel Vetter .agp_type_to_mask_type = intel_i830_type_to_mask_type, 1517f51b7662SDaniel Vetter .chipset_flush = intel_i830_chipset_flush, 1518f51b7662SDaniel Vetter }; 1519f51b7662SDaniel Vetter 1520f51b7662SDaniel Vetter static const struct agp_bridge_driver intel_915_driver = { 1521f51b7662SDaniel Vetter .owner = THIS_MODULE, 1522f51b7662SDaniel Vetter .aperture_sizes = intel_i830_sizes, 1523f51b7662SDaniel Vetter .size_type = FIXED_APER_SIZE, 1524f51b7662SDaniel Vetter .num_aperture_sizes = 4, 1525f51b7662SDaniel Vetter .needs_scratch_page = true, 1526f1befe71SChris Wilson .configure = intel_i9xx_configure, 1527f51b7662SDaniel Vetter .fetch_size = intel_i9xx_fetch_size, 1528f51b7662SDaniel Vetter .cleanup = intel_i915_cleanup, 1529f51b7662SDaniel Vetter .mask_memory = intel_i810_mask_memory, 1530f51b7662SDaniel Vetter .masks = intel_i810_masks, 1531f51b7662SDaniel Vetter .agp_enable = intel_i810_agp_enable, 1532f51b7662SDaniel Vetter .cache_flush = global_cache_flush, 1533f51b7662SDaniel Vetter .create_gatt_table = intel_i915_create_gatt_table, 1534f51b7662SDaniel Vetter .free_gatt_table = intel_i830_free_gatt_table, 1535f51b7662SDaniel Vetter .insert_memory = intel_i915_insert_entries, 1536f51b7662SDaniel Vetter .remove_memory = intel_i915_remove_entries, 1537f51b7662SDaniel Vetter .alloc_by_type = intel_i830_alloc_by_type, 1538f51b7662SDaniel Vetter .free_by_type = intel_i810_free_by_type, 1539f51b7662SDaniel Vetter .agp_alloc_page = agp_generic_alloc_page, 1540f51b7662SDaniel Vetter .agp_alloc_pages = agp_generic_alloc_pages, 1541f51b7662SDaniel Vetter .agp_destroy_page = agp_generic_destroy_page, 1542f51b7662SDaniel Vetter .agp_destroy_pages = agp_generic_destroy_pages, 1543f51b7662SDaniel Vetter .agp_type_to_mask_type = intel_i830_type_to_mask_type, 1544f51b7662SDaniel Vetter .chipset_flush = intel_i915_chipset_flush, 1545f51b7662SDaniel Vetter #ifdef USE_PCI_DMA_API 1546f51b7662SDaniel Vetter .agp_map_page = intel_agp_map_page, 1547f51b7662SDaniel Vetter .agp_unmap_page = intel_agp_unmap_page, 1548f51b7662SDaniel Vetter .agp_map_memory = intel_agp_map_memory, 1549f51b7662SDaniel Vetter .agp_unmap_memory = intel_agp_unmap_memory, 1550f51b7662SDaniel Vetter #endif 1551f51b7662SDaniel Vetter }; 1552f51b7662SDaniel Vetter 1553f51b7662SDaniel Vetter static const struct agp_bridge_driver intel_i965_driver = { 1554f51b7662SDaniel Vetter .owner = THIS_MODULE, 1555f51b7662SDaniel Vetter .aperture_sizes = intel_i830_sizes, 1556f51b7662SDaniel Vetter .size_type = FIXED_APER_SIZE, 1557f51b7662SDaniel Vetter .num_aperture_sizes = 4, 1558f51b7662SDaniel Vetter .needs_scratch_page = true, 1559f1befe71SChris Wilson .configure = intel_i9xx_configure, 1560f51b7662SDaniel Vetter .fetch_size = intel_i9xx_fetch_size, 1561f51b7662SDaniel Vetter .cleanup = intel_i915_cleanup, 1562f51b7662SDaniel Vetter .mask_memory = intel_i965_mask_memory, 1563f51b7662SDaniel Vetter .masks = intel_i810_masks, 1564f51b7662SDaniel Vetter .agp_enable = intel_i810_agp_enable, 1565f51b7662SDaniel Vetter .cache_flush = global_cache_flush, 1566f51b7662SDaniel Vetter .create_gatt_table = intel_i965_create_gatt_table, 1567f51b7662SDaniel Vetter .free_gatt_table = intel_i830_free_gatt_table, 1568f51b7662SDaniel Vetter .insert_memory = intel_i915_insert_entries, 1569f51b7662SDaniel Vetter .remove_memory = intel_i915_remove_entries, 1570f51b7662SDaniel Vetter .alloc_by_type = intel_i830_alloc_by_type, 1571f51b7662SDaniel Vetter .free_by_type = intel_i810_free_by_type, 1572f51b7662SDaniel Vetter .agp_alloc_page = agp_generic_alloc_page, 1573f51b7662SDaniel Vetter .agp_alloc_pages = agp_generic_alloc_pages, 1574f51b7662SDaniel Vetter .agp_destroy_page = agp_generic_destroy_page, 1575f51b7662SDaniel Vetter .agp_destroy_pages = agp_generic_destroy_pages, 1576f51b7662SDaniel Vetter .agp_type_to_mask_type = intel_i830_type_to_mask_type, 1577f51b7662SDaniel Vetter .chipset_flush = intel_i915_chipset_flush, 1578f51b7662SDaniel Vetter #ifdef USE_PCI_DMA_API 1579f51b7662SDaniel Vetter .agp_map_page = intel_agp_map_page, 1580f51b7662SDaniel Vetter .agp_unmap_page = intel_agp_unmap_page, 1581f51b7662SDaniel Vetter .agp_map_memory = intel_agp_map_memory, 1582f51b7662SDaniel Vetter .agp_unmap_memory = intel_agp_unmap_memory, 1583f51b7662SDaniel Vetter #endif 1584f51b7662SDaniel Vetter }; 1585f51b7662SDaniel Vetter 15863869d4a8SZhenyu Wang static const struct agp_bridge_driver intel_gen6_driver = { 15873869d4a8SZhenyu Wang .owner = THIS_MODULE, 15883869d4a8SZhenyu Wang .aperture_sizes = intel_i830_sizes, 15893869d4a8SZhenyu Wang .size_type = FIXED_APER_SIZE, 15903869d4a8SZhenyu Wang .num_aperture_sizes = 4, 15913869d4a8SZhenyu Wang .needs_scratch_page = true, 15923869d4a8SZhenyu Wang .configure = intel_i9xx_configure, 15933869d4a8SZhenyu Wang .fetch_size = intel_i9xx_fetch_size, 15943869d4a8SZhenyu Wang .cleanup = intel_i915_cleanup, 15953869d4a8SZhenyu Wang .mask_memory = intel_gen6_mask_memory, 1596f8f235e5SZhenyu Wang .masks = intel_gen6_masks, 15973869d4a8SZhenyu Wang .agp_enable = intel_i810_agp_enable, 15983869d4a8SZhenyu Wang .cache_flush = global_cache_flush, 15993869d4a8SZhenyu Wang .create_gatt_table = intel_i965_create_gatt_table, 16003869d4a8SZhenyu Wang .free_gatt_table = intel_i830_free_gatt_table, 16013869d4a8SZhenyu Wang .insert_memory = intel_i915_insert_entries, 16023869d4a8SZhenyu Wang .remove_memory = intel_i915_remove_entries, 16033869d4a8SZhenyu Wang .alloc_by_type = intel_i830_alloc_by_type, 16043869d4a8SZhenyu Wang .free_by_type = intel_i810_free_by_type, 16053869d4a8SZhenyu Wang .agp_alloc_page = agp_generic_alloc_page, 16063869d4a8SZhenyu Wang .agp_alloc_pages = agp_generic_alloc_pages, 16073869d4a8SZhenyu Wang .agp_destroy_page = agp_generic_destroy_page, 16083869d4a8SZhenyu Wang .agp_destroy_pages = agp_generic_destroy_pages, 1609f8f235e5SZhenyu Wang .agp_type_to_mask_type = intel_gen6_type_to_mask_type, 16103869d4a8SZhenyu Wang .chipset_flush = intel_i915_chipset_flush, 16113869d4a8SZhenyu Wang #ifdef USE_PCI_DMA_API 16123869d4a8SZhenyu Wang .agp_map_page = intel_agp_map_page, 16133869d4a8SZhenyu Wang .agp_unmap_page = intel_agp_unmap_page, 16143869d4a8SZhenyu Wang .agp_map_memory = intel_agp_map_memory, 16153869d4a8SZhenyu Wang .agp_unmap_memory = intel_agp_unmap_memory, 16163869d4a8SZhenyu Wang #endif 16173869d4a8SZhenyu Wang }; 16183869d4a8SZhenyu Wang 1619f51b7662SDaniel Vetter static const struct agp_bridge_driver intel_g33_driver = { 1620f51b7662SDaniel Vetter .owner = THIS_MODULE, 1621f51b7662SDaniel Vetter .aperture_sizes = intel_i830_sizes, 1622f51b7662SDaniel Vetter .size_type = FIXED_APER_SIZE, 1623f51b7662SDaniel Vetter .num_aperture_sizes = 4, 1624f51b7662SDaniel Vetter .needs_scratch_page = true, 1625f1befe71SChris Wilson .configure = intel_i9xx_configure, 1626f51b7662SDaniel Vetter .fetch_size = intel_i9xx_fetch_size, 1627f51b7662SDaniel Vetter .cleanup = intel_i915_cleanup, 1628f51b7662SDaniel Vetter .mask_memory = intel_i965_mask_memory, 1629f51b7662SDaniel Vetter .masks = intel_i810_masks, 1630f51b7662SDaniel Vetter .agp_enable = intel_i810_agp_enable, 1631f51b7662SDaniel Vetter .cache_flush = global_cache_flush, 1632f51b7662SDaniel Vetter .create_gatt_table = intel_i915_create_gatt_table, 1633f51b7662SDaniel Vetter .free_gatt_table = intel_i830_free_gatt_table, 1634f51b7662SDaniel Vetter .insert_memory = intel_i915_insert_entries, 1635f51b7662SDaniel Vetter .remove_memory = intel_i915_remove_entries, 1636f51b7662SDaniel Vetter .alloc_by_type = intel_i830_alloc_by_type, 1637f51b7662SDaniel Vetter .free_by_type = intel_i810_free_by_type, 1638f51b7662SDaniel Vetter .agp_alloc_page = agp_generic_alloc_page, 1639f51b7662SDaniel Vetter .agp_alloc_pages = agp_generic_alloc_pages, 1640f51b7662SDaniel Vetter .agp_destroy_page = agp_generic_destroy_page, 1641f51b7662SDaniel Vetter .agp_destroy_pages = agp_generic_destroy_pages, 1642f51b7662SDaniel Vetter .agp_type_to_mask_type = intel_i830_type_to_mask_type, 1643f51b7662SDaniel Vetter .chipset_flush = intel_i915_chipset_flush, 1644f51b7662SDaniel Vetter #ifdef USE_PCI_DMA_API 1645f51b7662SDaniel Vetter .agp_map_page = intel_agp_map_page, 1646f51b7662SDaniel Vetter .agp_unmap_page = intel_agp_unmap_page, 1647f51b7662SDaniel Vetter .agp_map_memory = intel_agp_map_memory, 1648f51b7662SDaniel Vetter .agp_unmap_memory = intel_agp_unmap_memory, 1649f51b7662SDaniel Vetter #endif 1650f51b7662SDaniel Vetter }; 165102c026ceSDaniel Vetter 165202c026ceSDaniel Vetter /* Table to describe Intel GMCH and AGP/PCIE GART drivers. At least one of 165302c026ceSDaniel Vetter * driver and gmch_driver must be non-null, and find_gmch will determine 165402c026ceSDaniel Vetter * which one should be used if a gmch_chip_id is present. 165502c026ceSDaniel Vetter */ 165602c026ceSDaniel Vetter static const struct intel_gtt_driver_description { 165702c026ceSDaniel Vetter unsigned int gmch_chip_id; 165802c026ceSDaniel Vetter char *name; 165902c026ceSDaniel Vetter const struct agp_bridge_driver *gmch_driver; 166002c026ceSDaniel Vetter } intel_gtt_chipsets[] = { 166102c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_82810_IG1, "i810", &intel_810_driver }, 166202c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_82810_IG3, "i810", &intel_810_driver }, 166302c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_82810E_IG, "i810", &intel_810_driver }, 166402c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_82815_CGC, "i815", &intel_810_driver }, 166502c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_82830_CGC, "830M", &intel_830_driver }, 166602c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_82845G_IG, "830M", &intel_830_driver }, 166702c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_82854_IG, "854", &intel_830_driver }, 166802c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_82855GM_IG, "855GM", &intel_830_driver }, 166902c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_82865_IG, "865", &intel_830_driver }, 167002c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_E7221_IG, "E7221 (i915)", &intel_915_driver }, 167102c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_82915G_IG, "915G", &intel_915_driver }, 167202c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_82915GM_IG, "915GM", &intel_915_driver }, 167302c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_82945G_IG, "945G", &intel_915_driver }, 167402c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_82945GM_IG, "945GM", &intel_915_driver }, 167502c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_82945GME_IG, "945GME", &intel_915_driver }, 167602c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_82946GZ_IG, "946GZ", &intel_i965_driver }, 167702c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_82G35_IG, "G35", &intel_i965_driver }, 167802c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_82965Q_IG, "965Q", &intel_i965_driver }, 167902c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_82965G_IG, "965G", &intel_i965_driver }, 168002c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_82965GM_IG, "965GM", &intel_i965_driver }, 168102c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_82965GME_IG, "965GME/GLE", &intel_i965_driver }, 168202c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_G33_IG, "G33", &intel_g33_driver }, 168302c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_Q35_IG, "Q35", &intel_g33_driver }, 168402c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_Q33_IG, "Q33", &intel_g33_driver }, 168502c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_PINEVIEW_M_IG, "GMA3150", &intel_g33_driver }, 168602c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_PINEVIEW_IG, "GMA3150", &intel_g33_driver }, 168702c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_GM45_IG, "GM45", &intel_i965_driver }, 168802c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_EAGLELAKE_IG, "Eaglelake", &intel_i965_driver }, 168902c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_Q45_IG, "Q45/Q43", &intel_i965_driver }, 169002c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_G45_IG, "G45/G43", &intel_i965_driver }, 169102c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_B43_IG, "B43", &intel_i965_driver }, 169202c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_G41_IG, "G41", &intel_i965_driver }, 169302c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_IRONLAKE_D_IG, 169402c026ceSDaniel Vetter "HD Graphics", &intel_i965_driver }, 169502c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG, 169602c026ceSDaniel Vetter "HD Graphics", &intel_i965_driver }, 169702c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT1_IG, 169802c026ceSDaniel Vetter "Sandybridge", &intel_gen6_driver }, 169902c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_IG, 170002c026ceSDaniel Vetter "Sandybridge", &intel_gen6_driver }, 170102c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_PLUS_IG, 170202c026ceSDaniel Vetter "Sandybridge", &intel_gen6_driver }, 170302c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT1_IG, 170402c026ceSDaniel Vetter "Sandybridge", &intel_gen6_driver }, 170502c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_IG, 170602c026ceSDaniel Vetter "Sandybridge", &intel_gen6_driver }, 170702c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_PLUS_IG, 170802c026ceSDaniel Vetter "Sandybridge", &intel_gen6_driver }, 170902c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_IG, 171002c026ceSDaniel Vetter "Sandybridge", &intel_gen6_driver }, 171102c026ceSDaniel Vetter { 0, NULL, NULL } 171202c026ceSDaniel Vetter }; 171302c026ceSDaniel Vetter 171402c026ceSDaniel Vetter static int find_gmch(u16 device) 171502c026ceSDaniel Vetter { 171602c026ceSDaniel Vetter struct pci_dev *gmch_device; 171702c026ceSDaniel Vetter 171802c026ceSDaniel Vetter gmch_device = pci_get_device(PCI_VENDOR_ID_INTEL, device, NULL); 171902c026ceSDaniel Vetter if (gmch_device && PCI_FUNC(gmch_device->devfn) != 0) { 172002c026ceSDaniel Vetter gmch_device = pci_get_device(PCI_VENDOR_ID_INTEL, 172102c026ceSDaniel Vetter device, gmch_device); 172202c026ceSDaniel Vetter } 172302c026ceSDaniel Vetter 172402c026ceSDaniel Vetter if (!gmch_device) 172502c026ceSDaniel Vetter return 0; 172602c026ceSDaniel Vetter 172702c026ceSDaniel Vetter intel_private.pcidev = gmch_device; 172802c026ceSDaniel Vetter return 1; 172902c026ceSDaniel Vetter } 173002c026ceSDaniel Vetter 173102c026ceSDaniel Vetter int __devinit intel_gmch_probe(struct pci_dev *pdev, 173202c026ceSDaniel Vetter struct agp_bridge_data *bridge) 173302c026ceSDaniel Vetter { 173402c026ceSDaniel Vetter int i, mask; 173502c026ceSDaniel Vetter bridge->driver = NULL; 173602c026ceSDaniel Vetter 173702c026ceSDaniel Vetter for (i = 0; intel_gtt_chipsets[i].name != NULL; i++) { 173802c026ceSDaniel Vetter if (find_gmch(intel_gtt_chipsets[i].gmch_chip_id)) { 173902c026ceSDaniel Vetter bridge->driver = 174002c026ceSDaniel Vetter intel_gtt_chipsets[i].gmch_driver; 174102c026ceSDaniel Vetter break; 174202c026ceSDaniel Vetter } 174302c026ceSDaniel Vetter } 174402c026ceSDaniel Vetter 174502c026ceSDaniel Vetter if (!bridge->driver) 174602c026ceSDaniel Vetter return 0; 174702c026ceSDaniel Vetter 174802c026ceSDaniel Vetter bridge->dev_private_data = &intel_private; 174902c026ceSDaniel Vetter bridge->dev = pdev; 175002c026ceSDaniel Vetter 175102c026ceSDaniel Vetter dev_info(&pdev->dev, "Intel %s Chipset\n", intel_gtt_chipsets[i].name); 175202c026ceSDaniel Vetter 175302c026ceSDaniel Vetter if (bridge->driver->mask_memory == intel_gen6_mask_memory) 175402c026ceSDaniel Vetter mask = 40; 175502c026ceSDaniel Vetter else if (bridge->driver->mask_memory == intel_i965_mask_memory) 175602c026ceSDaniel Vetter mask = 36; 175702c026ceSDaniel Vetter else 175802c026ceSDaniel Vetter mask = 32; 175902c026ceSDaniel Vetter 176002c026ceSDaniel Vetter if (pci_set_dma_mask(intel_private.pcidev, DMA_BIT_MASK(mask))) 176102c026ceSDaniel Vetter dev_err(&intel_private.pcidev->dev, 176202c026ceSDaniel Vetter "set gfx device dma mask %d-bit failed!\n", mask); 176302c026ceSDaniel Vetter else 176402c026ceSDaniel Vetter pci_set_consistent_dma_mask(intel_private.pcidev, 176502c026ceSDaniel Vetter DMA_BIT_MASK(mask)); 176602c026ceSDaniel Vetter 176702c026ceSDaniel Vetter return 1; 176802c026ceSDaniel Vetter } 176902c026ceSDaniel Vetter 177002c026ceSDaniel Vetter void __devexit intel_gmch_remove(struct pci_dev *pdev) 177102c026ceSDaniel Vetter { 177202c026ceSDaniel Vetter if (intel_private.pcidev) 177302c026ceSDaniel Vetter pci_dev_put(intel_private.pcidev); 177402c026ceSDaniel Vetter } 1775