1f51b7662SDaniel Vetter /* 2f51b7662SDaniel Vetter * Intel GTT (Graphics Translation Table) routines 3f51b7662SDaniel Vetter * 4f51b7662SDaniel Vetter * Caveat: This driver implements the linux agp interface, but this is far from 5f51b7662SDaniel Vetter * a agp driver! GTT support ended up here for purely historical reasons: The 6f51b7662SDaniel Vetter * old userspace intel graphics drivers needed an interface to map memory into 7f51b7662SDaniel Vetter * the GTT. And the drm provides a default interface for graphic devices sitting 8f51b7662SDaniel Vetter * on an agp port. So it made sense to fake the GTT support as an agp port to 9f51b7662SDaniel Vetter * avoid having to create a new api. 10f51b7662SDaniel Vetter * 11f51b7662SDaniel Vetter * With gem this does not make much sense anymore, just needlessly complicates 12f51b7662SDaniel Vetter * the code. But as long as the old graphics stack is still support, it's stuck 13f51b7662SDaniel Vetter * here. 14f51b7662SDaniel Vetter * 15f51b7662SDaniel Vetter * /fairy-tale-mode off 16f51b7662SDaniel Vetter */ 17f51b7662SDaniel Vetter 18e2404e7cSDaniel Vetter #include <linux/module.h> 19e2404e7cSDaniel Vetter #include <linux/pci.h> 20e2404e7cSDaniel Vetter #include <linux/init.h> 21e2404e7cSDaniel Vetter #include <linux/kernel.h> 22e2404e7cSDaniel Vetter #include <linux/pagemap.h> 23e2404e7cSDaniel Vetter #include <linux/agp_backend.h> 24e2404e7cSDaniel Vetter #include <asm/smp.h> 25e2404e7cSDaniel Vetter #include "agp.h" 26e2404e7cSDaniel Vetter #include "intel-agp.h" 27e2404e7cSDaniel Vetter #include <linux/intel-gtt.h> 280ade6386SDaniel Vetter #include <drm/intel-gtt.h> 29e2404e7cSDaniel Vetter 30f51b7662SDaniel Vetter /* 31f51b7662SDaniel Vetter * If we have Intel graphics, we're not going to have anything other than 32f51b7662SDaniel Vetter * an Intel IOMMU. So make the correct use of the PCI DMA API contingent 33f51b7662SDaniel Vetter * on the Intel IOMMU support (CONFIG_DMAR). 34f51b7662SDaniel Vetter * Only newer chipsets need to bother with this, of course. 35f51b7662SDaniel Vetter */ 36f51b7662SDaniel Vetter #ifdef CONFIG_DMAR 37f51b7662SDaniel Vetter #define USE_PCI_DMA_API 1 380e87d2b0SDaniel Vetter #else 390e87d2b0SDaniel Vetter #define USE_PCI_DMA_API 0 40f51b7662SDaniel Vetter #endif 41f51b7662SDaniel Vetter 42d1d6ca73SJesse Barnes /* Max amount of stolen space, anything above will be returned to Linux */ 43d1d6ca73SJesse Barnes int intel_max_stolen = 32 * 1024 * 1024; 44d1d6ca73SJesse Barnes EXPORT_SYMBOL(intel_max_stolen); 45d1d6ca73SJesse Barnes 46f51b7662SDaniel Vetter static const struct aper_size_info_fixed intel_i810_sizes[] = 47f51b7662SDaniel Vetter { 48f51b7662SDaniel Vetter {64, 16384, 4}, 49f51b7662SDaniel Vetter /* The 32M mode still requires a 64k gatt */ 50f51b7662SDaniel Vetter {32, 8192, 4} 51f51b7662SDaniel Vetter }; 52f51b7662SDaniel Vetter 53f51b7662SDaniel Vetter #define AGP_DCACHE_MEMORY 1 54f51b7662SDaniel Vetter #define AGP_PHYS_MEMORY 2 55f51b7662SDaniel Vetter #define INTEL_AGP_CACHED_MEMORY 3 56f51b7662SDaniel Vetter 57f51b7662SDaniel Vetter static struct gatt_mask intel_i810_masks[] = 58f51b7662SDaniel Vetter { 59f51b7662SDaniel Vetter {.mask = I810_PTE_VALID, .type = 0}, 60f51b7662SDaniel Vetter {.mask = (I810_PTE_VALID | I810_PTE_LOCAL), .type = AGP_DCACHE_MEMORY}, 61f51b7662SDaniel Vetter {.mask = I810_PTE_VALID, .type = 0}, 62f51b7662SDaniel Vetter {.mask = I810_PTE_VALID | I830_PTE_SYSTEM_CACHED, 63f51b7662SDaniel Vetter .type = INTEL_AGP_CACHED_MEMORY} 64f51b7662SDaniel Vetter }; 65f51b7662SDaniel Vetter 66f8f235e5SZhenyu Wang #define INTEL_AGP_UNCACHED_MEMORY 0 67f8f235e5SZhenyu Wang #define INTEL_AGP_CACHED_MEMORY_LLC 1 68f8f235e5SZhenyu Wang #define INTEL_AGP_CACHED_MEMORY_LLC_GFDT 2 69f8f235e5SZhenyu Wang #define INTEL_AGP_CACHED_MEMORY_LLC_MLC 3 70f8f235e5SZhenyu Wang #define INTEL_AGP_CACHED_MEMORY_LLC_MLC_GFDT 4 71f8f235e5SZhenyu Wang 72f8f235e5SZhenyu Wang static struct gatt_mask intel_gen6_masks[] = 73f8f235e5SZhenyu Wang { 74f8f235e5SZhenyu Wang {.mask = I810_PTE_VALID | GEN6_PTE_UNCACHED, 75f8f235e5SZhenyu Wang .type = INTEL_AGP_UNCACHED_MEMORY }, 76f8f235e5SZhenyu Wang {.mask = I810_PTE_VALID | GEN6_PTE_LLC, 77f8f235e5SZhenyu Wang .type = INTEL_AGP_CACHED_MEMORY_LLC }, 78f8f235e5SZhenyu Wang {.mask = I810_PTE_VALID | GEN6_PTE_LLC | GEN6_PTE_GFDT, 79f8f235e5SZhenyu Wang .type = INTEL_AGP_CACHED_MEMORY_LLC_GFDT }, 80f8f235e5SZhenyu Wang {.mask = I810_PTE_VALID | GEN6_PTE_LLC_MLC, 81f8f235e5SZhenyu Wang .type = INTEL_AGP_CACHED_MEMORY_LLC_MLC }, 82f8f235e5SZhenyu Wang {.mask = I810_PTE_VALID | GEN6_PTE_LLC_MLC | GEN6_PTE_GFDT, 83f8f235e5SZhenyu Wang .type = INTEL_AGP_CACHED_MEMORY_LLC_MLC_GFDT }, 84f8f235e5SZhenyu Wang }; 85f8f235e5SZhenyu Wang 861a997ff2SDaniel Vetter struct intel_gtt_driver { 871a997ff2SDaniel Vetter unsigned int gen : 8; 881a997ff2SDaniel Vetter unsigned int is_g33 : 1; 891a997ff2SDaniel Vetter unsigned int is_pineview : 1; 901a997ff2SDaniel Vetter unsigned int is_ironlake : 1; 9173800422SDaniel Vetter /* Chipset specific GTT setup */ 9273800422SDaniel Vetter int (*setup)(void); 93351bb278SDaniel Vetter void (*write_entry)(dma_addr_t addr, unsigned int entry, unsigned int flags); 94351bb278SDaniel Vetter /* Flags is a more or less chipset specific opaque value. 95351bb278SDaniel Vetter * For chipsets that need to support old ums (non-gem) code, this 96351bb278SDaniel Vetter * needs to be identical to the various supported agp memory types! */ 975cbecafcSDaniel Vetter bool (*check_flags)(unsigned int flags); 981a997ff2SDaniel Vetter }; 991a997ff2SDaniel Vetter 100f51b7662SDaniel Vetter static struct _intel_private { 1010ade6386SDaniel Vetter struct intel_gtt base; 1021a997ff2SDaniel Vetter const struct intel_gtt_driver *driver; 103f51b7662SDaniel Vetter struct pci_dev *pcidev; /* device one */ 104d7cca2f7SDaniel Vetter struct pci_dev *bridge_dev; 105f51b7662SDaniel Vetter u8 __iomem *registers; 106f67eab66SDaniel Vetter phys_addr_t gtt_bus_addr; 10773800422SDaniel Vetter phys_addr_t gma_bus_addr; 1083f08e4efSChris Wilson phys_addr_t pte_bus_addr; 109f51b7662SDaniel Vetter u32 __iomem *gtt; /* I915G */ 110f51b7662SDaniel Vetter int num_dcache_entries; 111f51b7662SDaniel Vetter union { 112f51b7662SDaniel Vetter void __iomem *i9xx_flush_page; 113f51b7662SDaniel Vetter void *i8xx_flush_page; 114f51b7662SDaniel Vetter }; 115f51b7662SDaniel Vetter struct page *i8xx_page; 116f51b7662SDaniel Vetter struct resource ifp_resource; 117f51b7662SDaniel Vetter int resource_valid; 1180e87d2b0SDaniel Vetter struct page *scratch_page; 1190e87d2b0SDaniel Vetter dma_addr_t scratch_page_dma; 120f51b7662SDaniel Vetter } intel_private; 121f51b7662SDaniel Vetter 1221a997ff2SDaniel Vetter #define INTEL_GTT_GEN intel_private.driver->gen 1231a997ff2SDaniel Vetter #define IS_G33 intel_private.driver->is_g33 1241a997ff2SDaniel Vetter #define IS_PINEVIEW intel_private.driver->is_pineview 1251a997ff2SDaniel Vetter #define IS_IRONLAKE intel_private.driver->is_ironlake 1261a997ff2SDaniel Vetter 127f51b7662SDaniel Vetter static void intel_agp_free_sglist(struct agp_memory *mem) 128f51b7662SDaniel Vetter { 129f51b7662SDaniel Vetter struct sg_table st; 130f51b7662SDaniel Vetter 131f51b7662SDaniel Vetter st.sgl = mem->sg_list; 132f51b7662SDaniel Vetter st.orig_nents = st.nents = mem->page_count; 133f51b7662SDaniel Vetter 134f51b7662SDaniel Vetter sg_free_table(&st); 135f51b7662SDaniel Vetter 136f51b7662SDaniel Vetter mem->sg_list = NULL; 137f51b7662SDaniel Vetter mem->num_sg = 0; 138f51b7662SDaniel Vetter } 139f51b7662SDaniel Vetter 140f51b7662SDaniel Vetter static int intel_agp_map_memory(struct agp_memory *mem) 141f51b7662SDaniel Vetter { 142f51b7662SDaniel Vetter struct sg_table st; 143f51b7662SDaniel Vetter struct scatterlist *sg; 144f51b7662SDaniel Vetter int i; 145f51b7662SDaniel Vetter 146fefaa70fSDaniel Vetter if (mem->sg_list) 147fefaa70fSDaniel Vetter return 0; /* already mapped (for e.g. resume */ 148fefaa70fSDaniel Vetter 149f51b7662SDaniel Vetter DBG("try mapping %lu pages\n", (unsigned long)mem->page_count); 150f51b7662SDaniel Vetter 151f51b7662SDaniel Vetter if (sg_alloc_table(&st, mem->page_count, GFP_KERNEL)) 152831cd445SChris Wilson goto err; 153f51b7662SDaniel Vetter 154f51b7662SDaniel Vetter mem->sg_list = sg = st.sgl; 155f51b7662SDaniel Vetter 156f51b7662SDaniel Vetter for (i = 0 ; i < mem->page_count; i++, sg = sg_next(sg)) 157f51b7662SDaniel Vetter sg_set_page(sg, mem->pages[i], PAGE_SIZE, 0); 158f51b7662SDaniel Vetter 159f51b7662SDaniel Vetter mem->num_sg = pci_map_sg(intel_private.pcidev, mem->sg_list, 160f51b7662SDaniel Vetter mem->page_count, PCI_DMA_BIDIRECTIONAL); 161831cd445SChris Wilson if (unlikely(!mem->num_sg)) 162831cd445SChris Wilson goto err; 163831cd445SChris Wilson 164f51b7662SDaniel Vetter return 0; 165831cd445SChris Wilson 166831cd445SChris Wilson err: 167831cd445SChris Wilson sg_free_table(&st); 168831cd445SChris Wilson return -ENOMEM; 169f51b7662SDaniel Vetter } 170f51b7662SDaniel Vetter 171f51b7662SDaniel Vetter static void intel_agp_unmap_memory(struct agp_memory *mem) 172f51b7662SDaniel Vetter { 173f51b7662SDaniel Vetter DBG("try unmapping %lu pages\n", (unsigned long)mem->page_count); 174f51b7662SDaniel Vetter 175f51b7662SDaniel Vetter pci_unmap_sg(intel_private.pcidev, mem->sg_list, 176f51b7662SDaniel Vetter mem->page_count, PCI_DMA_BIDIRECTIONAL); 177f51b7662SDaniel Vetter intel_agp_free_sglist(mem); 178f51b7662SDaniel Vetter } 179f51b7662SDaniel Vetter 180fefaa70fSDaniel Vetter #if USE_PCI_DMA_API 181f51b7662SDaniel Vetter static void intel_agp_insert_sg_entries(struct agp_memory *mem, 182f51b7662SDaniel Vetter off_t pg_start, int mask_type) 183f51b7662SDaniel Vetter { 184f51b7662SDaniel Vetter struct scatterlist *sg; 185f51b7662SDaniel Vetter int i, j; 186f51b7662SDaniel Vetter 187f51b7662SDaniel Vetter j = pg_start; 188f51b7662SDaniel Vetter 189f51b7662SDaniel Vetter WARN_ON(!mem->num_sg); 190f51b7662SDaniel Vetter 191f51b7662SDaniel Vetter if (mem->num_sg == mem->page_count) { 192f51b7662SDaniel Vetter for_each_sg(mem->sg_list, sg, mem->page_count, i) { 193f51b7662SDaniel Vetter writel(agp_bridge->driver->mask_memory(agp_bridge, 194f51b7662SDaniel Vetter sg_dma_address(sg), mask_type), 195f51b7662SDaniel Vetter intel_private.gtt+j); 196f51b7662SDaniel Vetter j++; 197f51b7662SDaniel Vetter } 198f51b7662SDaniel Vetter } else { 199f51b7662SDaniel Vetter /* sg may merge pages, but we have to separate 200f51b7662SDaniel Vetter * per-page addr for GTT */ 201f51b7662SDaniel Vetter unsigned int len, m; 202f51b7662SDaniel Vetter 203f51b7662SDaniel Vetter for_each_sg(mem->sg_list, sg, mem->num_sg, i) { 204f51b7662SDaniel Vetter len = sg_dma_len(sg) / PAGE_SIZE; 205f51b7662SDaniel Vetter for (m = 0; m < len; m++) { 206f51b7662SDaniel Vetter writel(agp_bridge->driver->mask_memory(agp_bridge, 207f51b7662SDaniel Vetter sg_dma_address(sg) + m * PAGE_SIZE, 208f51b7662SDaniel Vetter mask_type), 209f51b7662SDaniel Vetter intel_private.gtt+j); 210f51b7662SDaniel Vetter j++; 211f51b7662SDaniel Vetter } 212f51b7662SDaniel Vetter } 213f51b7662SDaniel Vetter } 214f51b7662SDaniel Vetter readl(intel_private.gtt+j-1); 215f51b7662SDaniel Vetter } 216f51b7662SDaniel Vetter 217f51b7662SDaniel Vetter #else 218f51b7662SDaniel Vetter 219f51b7662SDaniel Vetter static void intel_agp_insert_sg_entries(struct agp_memory *mem, 220f51b7662SDaniel Vetter off_t pg_start, int mask_type) 221f51b7662SDaniel Vetter { 222f51b7662SDaniel Vetter int i, j; 223f51b7662SDaniel Vetter 224f51b7662SDaniel Vetter for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { 225f51b7662SDaniel Vetter writel(agp_bridge->driver->mask_memory(agp_bridge, 226f51b7662SDaniel Vetter page_to_phys(mem->pages[i]), mask_type), 227f51b7662SDaniel Vetter intel_private.gtt+j); 228f51b7662SDaniel Vetter } 229f51b7662SDaniel Vetter 230f51b7662SDaniel Vetter readl(intel_private.gtt+j-1); 231f51b7662SDaniel Vetter } 232f51b7662SDaniel Vetter 233f51b7662SDaniel Vetter #endif 234f51b7662SDaniel Vetter 235f51b7662SDaniel Vetter static int intel_i810_fetch_size(void) 236f51b7662SDaniel Vetter { 237f51b7662SDaniel Vetter u32 smram_miscc; 238f51b7662SDaniel Vetter struct aper_size_info_fixed *values; 239f51b7662SDaniel Vetter 240d7cca2f7SDaniel Vetter pci_read_config_dword(intel_private.bridge_dev, 241d7cca2f7SDaniel Vetter I810_SMRAM_MISCC, &smram_miscc); 242f51b7662SDaniel Vetter values = A_SIZE_FIX(agp_bridge->driver->aperture_sizes); 243f51b7662SDaniel Vetter 244f51b7662SDaniel Vetter if ((smram_miscc & I810_GMS) == I810_GMS_DISABLE) { 245d7cca2f7SDaniel Vetter dev_warn(&intel_private.bridge_dev->dev, "i810 is disabled\n"); 246f51b7662SDaniel Vetter return 0; 247f51b7662SDaniel Vetter } 248f51b7662SDaniel Vetter if ((smram_miscc & I810_GFX_MEM_WIN_SIZE) == I810_GFX_MEM_WIN_32M) { 249f51b7662SDaniel Vetter agp_bridge->current_size = (void *) (values + 1); 250f51b7662SDaniel Vetter agp_bridge->aperture_size_idx = 1; 251f51b7662SDaniel Vetter return values[1].size; 252f51b7662SDaniel Vetter } else { 253f51b7662SDaniel Vetter agp_bridge->current_size = (void *) (values); 254f51b7662SDaniel Vetter agp_bridge->aperture_size_idx = 0; 255f51b7662SDaniel Vetter return values[0].size; 256f51b7662SDaniel Vetter } 257f51b7662SDaniel Vetter 258f51b7662SDaniel Vetter return 0; 259f51b7662SDaniel Vetter } 260f51b7662SDaniel Vetter 261f51b7662SDaniel Vetter static int intel_i810_configure(void) 262f51b7662SDaniel Vetter { 263f51b7662SDaniel Vetter struct aper_size_info_fixed *current_size; 264f51b7662SDaniel Vetter u32 temp; 265f51b7662SDaniel Vetter int i; 266f51b7662SDaniel Vetter 267f51b7662SDaniel Vetter current_size = A_SIZE_FIX(agp_bridge->current_size); 268f51b7662SDaniel Vetter 269f51b7662SDaniel Vetter if (!intel_private.registers) { 270f51b7662SDaniel Vetter pci_read_config_dword(intel_private.pcidev, I810_MMADDR, &temp); 271f51b7662SDaniel Vetter temp &= 0xfff80000; 272f51b7662SDaniel Vetter 273f51b7662SDaniel Vetter intel_private.registers = ioremap(temp, 128 * 4096); 274f51b7662SDaniel Vetter if (!intel_private.registers) { 275f51b7662SDaniel Vetter dev_err(&intel_private.pcidev->dev, 276f51b7662SDaniel Vetter "can't remap memory\n"); 277f51b7662SDaniel Vetter return -ENOMEM; 278f51b7662SDaniel Vetter } 279f51b7662SDaniel Vetter } 280f51b7662SDaniel Vetter 281f51b7662SDaniel Vetter if ((readl(intel_private.registers+I810_DRAM_CTL) 282f51b7662SDaniel Vetter & I810_DRAM_ROW_0) == I810_DRAM_ROW_0_SDRAM) { 283f51b7662SDaniel Vetter /* This will need to be dynamically assigned */ 284f51b7662SDaniel Vetter dev_info(&intel_private.pcidev->dev, 285f51b7662SDaniel Vetter "detected 4MB dedicated video ram\n"); 286f51b7662SDaniel Vetter intel_private.num_dcache_entries = 1024; 287f51b7662SDaniel Vetter } 288f51b7662SDaniel Vetter pci_read_config_dword(intel_private.pcidev, I810_GMADDR, &temp); 289f51b7662SDaniel Vetter agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); 290f51b7662SDaniel Vetter writel(agp_bridge->gatt_bus_addr | I810_PGETBL_ENABLED, intel_private.registers+I810_PGETBL_CTL); 291f51b7662SDaniel Vetter readl(intel_private.registers+I810_PGETBL_CTL); /* PCI Posting. */ 292f51b7662SDaniel Vetter 293f51b7662SDaniel Vetter if (agp_bridge->driver->needs_scratch_page) { 294f51b7662SDaniel Vetter for (i = 0; i < current_size->num_entries; i++) { 295f51b7662SDaniel Vetter writel(agp_bridge->scratch_page, intel_private.registers+I810_PTE_BASE+(i*4)); 296f51b7662SDaniel Vetter } 297f51b7662SDaniel Vetter readl(intel_private.registers+I810_PTE_BASE+((i-1)*4)); /* PCI posting. */ 298f51b7662SDaniel Vetter } 299f51b7662SDaniel Vetter global_cache_flush(); 300f51b7662SDaniel Vetter return 0; 301f51b7662SDaniel Vetter } 302f51b7662SDaniel Vetter 303f51b7662SDaniel Vetter static void intel_i810_cleanup(void) 304f51b7662SDaniel Vetter { 305f51b7662SDaniel Vetter writel(0, intel_private.registers+I810_PGETBL_CTL); 306f51b7662SDaniel Vetter readl(intel_private.registers); /* PCI Posting. */ 307f51b7662SDaniel Vetter iounmap(intel_private.registers); 308f51b7662SDaniel Vetter } 309f51b7662SDaniel Vetter 310ffdd7510SDaniel Vetter static void intel_fake_agp_enable(struct agp_bridge_data *bridge, u32 mode) 311f51b7662SDaniel Vetter { 312f51b7662SDaniel Vetter return; 313f51b7662SDaniel Vetter } 314f51b7662SDaniel Vetter 315f51b7662SDaniel Vetter /* Exists to support ARGB cursors */ 316f51b7662SDaniel Vetter static struct page *i8xx_alloc_pages(void) 317f51b7662SDaniel Vetter { 318f51b7662SDaniel Vetter struct page *page; 319f51b7662SDaniel Vetter 320f51b7662SDaniel Vetter page = alloc_pages(GFP_KERNEL | GFP_DMA32, 2); 321f51b7662SDaniel Vetter if (page == NULL) 322f51b7662SDaniel Vetter return NULL; 323f51b7662SDaniel Vetter 324f51b7662SDaniel Vetter if (set_pages_uc(page, 4) < 0) { 325f51b7662SDaniel Vetter set_pages_wb(page, 4); 326f51b7662SDaniel Vetter __free_pages(page, 2); 327f51b7662SDaniel Vetter return NULL; 328f51b7662SDaniel Vetter } 329f51b7662SDaniel Vetter get_page(page); 330f51b7662SDaniel Vetter atomic_inc(&agp_bridge->current_memory_agp); 331f51b7662SDaniel Vetter return page; 332f51b7662SDaniel Vetter } 333f51b7662SDaniel Vetter 334f51b7662SDaniel Vetter static void i8xx_destroy_pages(struct page *page) 335f51b7662SDaniel Vetter { 336f51b7662SDaniel Vetter if (page == NULL) 337f51b7662SDaniel Vetter return; 338f51b7662SDaniel Vetter 339f51b7662SDaniel Vetter set_pages_wb(page, 4); 340f51b7662SDaniel Vetter put_page(page); 341f51b7662SDaniel Vetter __free_pages(page, 2); 342f51b7662SDaniel Vetter atomic_dec(&agp_bridge->current_memory_agp); 343f51b7662SDaniel Vetter } 344f51b7662SDaniel Vetter 345f51b7662SDaniel Vetter static int intel_i830_type_to_mask_type(struct agp_bridge_data *bridge, 346f51b7662SDaniel Vetter int type) 347f51b7662SDaniel Vetter { 348f51b7662SDaniel Vetter if (type < AGP_USER_TYPES) 349f51b7662SDaniel Vetter return type; 350f51b7662SDaniel Vetter else if (type == AGP_USER_CACHED_MEMORY) 351f51b7662SDaniel Vetter return INTEL_AGP_CACHED_MEMORY; 352f51b7662SDaniel Vetter else 353f51b7662SDaniel Vetter return 0; 354f51b7662SDaniel Vetter } 355f51b7662SDaniel Vetter 356f8f235e5SZhenyu Wang static int intel_gen6_type_to_mask_type(struct agp_bridge_data *bridge, 357f8f235e5SZhenyu Wang int type) 358f8f235e5SZhenyu Wang { 359f8f235e5SZhenyu Wang unsigned int type_mask = type & ~AGP_USER_CACHED_MEMORY_GFDT; 360f8f235e5SZhenyu Wang unsigned int gfdt = type & AGP_USER_CACHED_MEMORY_GFDT; 361f8f235e5SZhenyu Wang 362f8f235e5SZhenyu Wang if (type_mask == AGP_USER_UNCACHED_MEMORY) 363f8f235e5SZhenyu Wang return INTEL_AGP_UNCACHED_MEMORY; 364f8f235e5SZhenyu Wang else if (type_mask == AGP_USER_CACHED_MEMORY_LLC_MLC) 365f8f235e5SZhenyu Wang return gfdt ? INTEL_AGP_CACHED_MEMORY_LLC_MLC_GFDT : 366f8f235e5SZhenyu Wang INTEL_AGP_CACHED_MEMORY_LLC_MLC; 367f8f235e5SZhenyu Wang else /* set 'normal'/'cached' to LLC by default */ 368f8f235e5SZhenyu Wang return gfdt ? INTEL_AGP_CACHED_MEMORY_LLC_GFDT : 369f8f235e5SZhenyu Wang INTEL_AGP_CACHED_MEMORY_LLC; 370f8f235e5SZhenyu Wang } 371f8f235e5SZhenyu Wang 372f8f235e5SZhenyu Wang 373f51b7662SDaniel Vetter static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start, 374f51b7662SDaniel Vetter int type) 375f51b7662SDaniel Vetter { 376f51b7662SDaniel Vetter int i, j, num_entries; 377f51b7662SDaniel Vetter void *temp; 378f51b7662SDaniel Vetter int ret = -EINVAL; 379f51b7662SDaniel Vetter int mask_type; 380f51b7662SDaniel Vetter 381f51b7662SDaniel Vetter if (mem->page_count == 0) 382f51b7662SDaniel Vetter goto out; 383f51b7662SDaniel Vetter 384f51b7662SDaniel Vetter temp = agp_bridge->current_size; 385f51b7662SDaniel Vetter num_entries = A_SIZE_FIX(temp)->num_entries; 386f51b7662SDaniel Vetter 387f51b7662SDaniel Vetter if ((pg_start + mem->page_count) > num_entries) 388f51b7662SDaniel Vetter goto out_err; 389f51b7662SDaniel Vetter 390f51b7662SDaniel Vetter 391f51b7662SDaniel Vetter for (j = pg_start; j < (pg_start + mem->page_count); j++) { 392f51b7662SDaniel Vetter if (!PGE_EMPTY(agp_bridge, readl(agp_bridge->gatt_table+j))) { 393f51b7662SDaniel Vetter ret = -EBUSY; 394f51b7662SDaniel Vetter goto out_err; 395f51b7662SDaniel Vetter } 396f51b7662SDaniel Vetter } 397f51b7662SDaniel Vetter 398f51b7662SDaniel Vetter if (type != mem->type) 399f51b7662SDaniel Vetter goto out_err; 400f51b7662SDaniel Vetter 401f51b7662SDaniel Vetter mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type); 402f51b7662SDaniel Vetter 403f51b7662SDaniel Vetter switch (mask_type) { 404f51b7662SDaniel Vetter case AGP_DCACHE_MEMORY: 405f51b7662SDaniel Vetter if (!mem->is_flushed) 406f51b7662SDaniel Vetter global_cache_flush(); 407f51b7662SDaniel Vetter for (i = pg_start; i < (pg_start + mem->page_count); i++) { 408f51b7662SDaniel Vetter writel((i*4096)|I810_PTE_LOCAL|I810_PTE_VALID, 409f51b7662SDaniel Vetter intel_private.registers+I810_PTE_BASE+(i*4)); 410f51b7662SDaniel Vetter } 411f51b7662SDaniel Vetter readl(intel_private.registers+I810_PTE_BASE+((i-1)*4)); 412f51b7662SDaniel Vetter break; 413f51b7662SDaniel Vetter case AGP_PHYS_MEMORY: 414f51b7662SDaniel Vetter case AGP_NORMAL_MEMORY: 415f51b7662SDaniel Vetter if (!mem->is_flushed) 416f51b7662SDaniel Vetter global_cache_flush(); 417f51b7662SDaniel Vetter for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { 418f51b7662SDaniel Vetter writel(agp_bridge->driver->mask_memory(agp_bridge, 419f51b7662SDaniel Vetter page_to_phys(mem->pages[i]), mask_type), 420f51b7662SDaniel Vetter intel_private.registers+I810_PTE_BASE+(j*4)); 421f51b7662SDaniel Vetter } 422f51b7662SDaniel Vetter readl(intel_private.registers+I810_PTE_BASE+((j-1)*4)); 423f51b7662SDaniel Vetter break; 424f51b7662SDaniel Vetter default: 425f51b7662SDaniel Vetter goto out_err; 426f51b7662SDaniel Vetter } 427f51b7662SDaniel Vetter 428f51b7662SDaniel Vetter out: 429f51b7662SDaniel Vetter ret = 0; 430f51b7662SDaniel Vetter out_err: 431f51b7662SDaniel Vetter mem->is_flushed = true; 432f51b7662SDaniel Vetter return ret; 433f51b7662SDaniel Vetter } 434f51b7662SDaniel Vetter 435f51b7662SDaniel Vetter static int intel_i810_remove_entries(struct agp_memory *mem, off_t pg_start, 436f51b7662SDaniel Vetter int type) 437f51b7662SDaniel Vetter { 438f51b7662SDaniel Vetter int i; 439f51b7662SDaniel Vetter 440f51b7662SDaniel Vetter if (mem->page_count == 0) 441f51b7662SDaniel Vetter return 0; 442f51b7662SDaniel Vetter 443f51b7662SDaniel Vetter for (i = pg_start; i < (mem->page_count + pg_start); i++) { 444f51b7662SDaniel Vetter writel(agp_bridge->scratch_page, intel_private.registers+I810_PTE_BASE+(i*4)); 445f51b7662SDaniel Vetter } 446f51b7662SDaniel Vetter readl(intel_private.registers+I810_PTE_BASE+((i-1)*4)); 447f51b7662SDaniel Vetter 448f51b7662SDaniel Vetter return 0; 449f51b7662SDaniel Vetter } 450f51b7662SDaniel Vetter 451f51b7662SDaniel Vetter /* 452f51b7662SDaniel Vetter * The i810/i830 requires a physical address to program its mouse 453f51b7662SDaniel Vetter * pointer into hardware. 454f51b7662SDaniel Vetter * However the Xserver still writes to it through the agp aperture. 455f51b7662SDaniel Vetter */ 456f51b7662SDaniel Vetter static struct agp_memory *alloc_agpphysmem_i8xx(size_t pg_count, int type) 457f51b7662SDaniel Vetter { 458f51b7662SDaniel Vetter struct agp_memory *new; 459f51b7662SDaniel Vetter struct page *page; 460f51b7662SDaniel Vetter 461f51b7662SDaniel Vetter switch (pg_count) { 462f51b7662SDaniel Vetter case 1: page = agp_bridge->driver->agp_alloc_page(agp_bridge); 463f51b7662SDaniel Vetter break; 464f51b7662SDaniel Vetter case 4: 465f51b7662SDaniel Vetter /* kludge to get 4 physical pages for ARGB cursor */ 466f51b7662SDaniel Vetter page = i8xx_alloc_pages(); 467f51b7662SDaniel Vetter break; 468f51b7662SDaniel Vetter default: 469f51b7662SDaniel Vetter return NULL; 470f51b7662SDaniel Vetter } 471f51b7662SDaniel Vetter 472f51b7662SDaniel Vetter if (page == NULL) 473f51b7662SDaniel Vetter return NULL; 474f51b7662SDaniel Vetter 475f51b7662SDaniel Vetter new = agp_create_memory(pg_count); 476f51b7662SDaniel Vetter if (new == NULL) 477f51b7662SDaniel Vetter return NULL; 478f51b7662SDaniel Vetter 479f51b7662SDaniel Vetter new->pages[0] = page; 480f51b7662SDaniel Vetter if (pg_count == 4) { 481f51b7662SDaniel Vetter /* kludge to get 4 physical pages for ARGB cursor */ 482f51b7662SDaniel Vetter new->pages[1] = new->pages[0] + 1; 483f51b7662SDaniel Vetter new->pages[2] = new->pages[1] + 1; 484f51b7662SDaniel Vetter new->pages[3] = new->pages[2] + 1; 485f51b7662SDaniel Vetter } 486f51b7662SDaniel Vetter new->page_count = pg_count; 487f51b7662SDaniel Vetter new->num_scratch_pages = pg_count; 488f51b7662SDaniel Vetter new->type = AGP_PHYS_MEMORY; 489f51b7662SDaniel Vetter new->physical = page_to_phys(new->pages[0]); 490f51b7662SDaniel Vetter return new; 491f51b7662SDaniel Vetter } 492f51b7662SDaniel Vetter 493f51b7662SDaniel Vetter static struct agp_memory *intel_i810_alloc_by_type(size_t pg_count, int type) 494f51b7662SDaniel Vetter { 495f51b7662SDaniel Vetter struct agp_memory *new; 496f51b7662SDaniel Vetter 497f51b7662SDaniel Vetter if (type == AGP_DCACHE_MEMORY) { 498f51b7662SDaniel Vetter if (pg_count != intel_private.num_dcache_entries) 499f51b7662SDaniel Vetter return NULL; 500f51b7662SDaniel Vetter 501f51b7662SDaniel Vetter new = agp_create_memory(1); 502f51b7662SDaniel Vetter if (new == NULL) 503f51b7662SDaniel Vetter return NULL; 504f51b7662SDaniel Vetter 505f51b7662SDaniel Vetter new->type = AGP_DCACHE_MEMORY; 506f51b7662SDaniel Vetter new->page_count = pg_count; 507f51b7662SDaniel Vetter new->num_scratch_pages = 0; 508f51b7662SDaniel Vetter agp_free_page_array(new); 509f51b7662SDaniel Vetter return new; 510f51b7662SDaniel Vetter } 511f51b7662SDaniel Vetter if (type == AGP_PHYS_MEMORY) 512f51b7662SDaniel Vetter return alloc_agpphysmem_i8xx(pg_count, type); 513f51b7662SDaniel Vetter return NULL; 514f51b7662SDaniel Vetter } 515f51b7662SDaniel Vetter 516f51b7662SDaniel Vetter static void intel_i810_free_by_type(struct agp_memory *curr) 517f51b7662SDaniel Vetter { 518f51b7662SDaniel Vetter agp_free_key(curr->key); 519f51b7662SDaniel Vetter if (curr->type == AGP_PHYS_MEMORY) { 520f51b7662SDaniel Vetter if (curr->page_count == 4) 521f51b7662SDaniel Vetter i8xx_destroy_pages(curr->pages[0]); 522f51b7662SDaniel Vetter else { 523f51b7662SDaniel Vetter agp_bridge->driver->agp_destroy_page(curr->pages[0], 524f51b7662SDaniel Vetter AGP_PAGE_DESTROY_UNMAP); 525f51b7662SDaniel Vetter agp_bridge->driver->agp_destroy_page(curr->pages[0], 526f51b7662SDaniel Vetter AGP_PAGE_DESTROY_FREE); 527f51b7662SDaniel Vetter } 528f51b7662SDaniel Vetter agp_free_page_array(curr); 529f51b7662SDaniel Vetter } 530f51b7662SDaniel Vetter kfree(curr); 531f51b7662SDaniel Vetter } 532f51b7662SDaniel Vetter 533f51b7662SDaniel Vetter static unsigned long intel_i810_mask_memory(struct agp_bridge_data *bridge, 534f51b7662SDaniel Vetter dma_addr_t addr, int type) 535f51b7662SDaniel Vetter { 536f51b7662SDaniel Vetter /* Type checking must be done elsewhere */ 537f51b7662SDaniel Vetter return addr | bridge->driver->masks[type].mask; 538f51b7662SDaniel Vetter } 539f51b7662SDaniel Vetter 5400e87d2b0SDaniel Vetter static int intel_gtt_setup_scratch_page(void) 5410e87d2b0SDaniel Vetter { 5420e87d2b0SDaniel Vetter struct page *page; 5430e87d2b0SDaniel Vetter dma_addr_t dma_addr; 5440e87d2b0SDaniel Vetter 5450e87d2b0SDaniel Vetter page = alloc_page(GFP_KERNEL | GFP_DMA32 | __GFP_ZERO); 5460e87d2b0SDaniel Vetter if (page == NULL) 5470e87d2b0SDaniel Vetter return -ENOMEM; 5480e87d2b0SDaniel Vetter get_page(page); 5490e87d2b0SDaniel Vetter set_pages_uc(page, 1); 5500e87d2b0SDaniel Vetter 5510e87d2b0SDaniel Vetter if (USE_PCI_DMA_API && INTEL_GTT_GEN > 2) { 5520e87d2b0SDaniel Vetter dma_addr = pci_map_page(intel_private.pcidev, page, 0, 5530e87d2b0SDaniel Vetter PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); 5540e87d2b0SDaniel Vetter if (pci_dma_mapping_error(intel_private.pcidev, dma_addr)) 5550e87d2b0SDaniel Vetter return -EINVAL; 5560e87d2b0SDaniel Vetter 5570e87d2b0SDaniel Vetter intel_private.scratch_page_dma = dma_addr; 5580e87d2b0SDaniel Vetter } else 5590e87d2b0SDaniel Vetter intel_private.scratch_page_dma = page_to_phys(page); 5600e87d2b0SDaniel Vetter 5610e87d2b0SDaniel Vetter intel_private.scratch_page = page; 5620e87d2b0SDaniel Vetter 5630e87d2b0SDaniel Vetter return 0; 5640e87d2b0SDaniel Vetter } 5650e87d2b0SDaniel Vetter 5669e76e7b8SChris Wilson static const struct aper_size_info_fixed const intel_fake_agp_sizes[] = { 567f51b7662SDaniel Vetter {128, 32768, 5}, 568f51b7662SDaniel Vetter /* The 64M mode still requires a 128k gatt */ 569f51b7662SDaniel Vetter {64, 16384, 5}, 570f51b7662SDaniel Vetter {256, 65536, 6}, 571f51b7662SDaniel Vetter {512, 131072, 7}, 572f51b7662SDaniel Vetter }; 573f51b7662SDaniel Vetter 574bfde067bSDaniel Vetter static unsigned int intel_gtt_stolen_entries(void) 575f51b7662SDaniel Vetter { 576f51b7662SDaniel Vetter u16 gmch_ctrl; 577f51b7662SDaniel Vetter u8 rdct; 578f51b7662SDaniel Vetter int local = 0; 579f51b7662SDaniel Vetter static const int ddt[4] = { 0, 16, 32, 64 }; 580d8d9abcdSDaniel Vetter unsigned int overhead_entries, stolen_entries; 581d8d9abcdSDaniel Vetter unsigned int stolen_size = 0; 582f51b7662SDaniel Vetter 583d7cca2f7SDaniel Vetter pci_read_config_word(intel_private.bridge_dev, 584d7cca2f7SDaniel Vetter I830_GMCH_CTRL, &gmch_ctrl); 585f51b7662SDaniel Vetter 5861a997ff2SDaniel Vetter if (INTEL_GTT_GEN > 4 || IS_PINEVIEW) 587fbe40783SDaniel Vetter overhead_entries = 0; 588fbe40783SDaniel Vetter else 589fbe40783SDaniel Vetter overhead_entries = intel_private.base.gtt_mappable_entries 590fbe40783SDaniel Vetter / 1024; 591f51b7662SDaniel Vetter 592fbe40783SDaniel Vetter overhead_entries += 1; /* BIOS popup */ 593d8d9abcdSDaniel Vetter 594d7cca2f7SDaniel Vetter if (intel_private.bridge_dev->device == PCI_DEVICE_ID_INTEL_82830_HB || 595d7cca2f7SDaniel Vetter intel_private.bridge_dev->device == PCI_DEVICE_ID_INTEL_82845G_HB) { 596f51b7662SDaniel Vetter switch (gmch_ctrl & I830_GMCH_GMS_MASK) { 597f51b7662SDaniel Vetter case I830_GMCH_GMS_STOLEN_512: 598d8d9abcdSDaniel Vetter stolen_size = KB(512); 599f51b7662SDaniel Vetter break; 600f51b7662SDaniel Vetter case I830_GMCH_GMS_STOLEN_1024: 601d8d9abcdSDaniel Vetter stolen_size = MB(1); 602f51b7662SDaniel Vetter break; 603f51b7662SDaniel Vetter case I830_GMCH_GMS_STOLEN_8192: 604d8d9abcdSDaniel Vetter stolen_size = MB(8); 605f51b7662SDaniel Vetter break; 606f51b7662SDaniel Vetter case I830_GMCH_GMS_LOCAL: 607f51b7662SDaniel Vetter rdct = readb(intel_private.registers+I830_RDRAM_CHANNEL_TYPE); 608d8d9abcdSDaniel Vetter stolen_size = (I830_RDRAM_ND(rdct) + 1) * 609f51b7662SDaniel Vetter MB(ddt[I830_RDRAM_DDT(rdct)]); 610f51b7662SDaniel Vetter local = 1; 611f51b7662SDaniel Vetter break; 612f51b7662SDaniel Vetter default: 613d8d9abcdSDaniel Vetter stolen_size = 0; 614f51b7662SDaniel Vetter break; 615f51b7662SDaniel Vetter } 6161a997ff2SDaniel Vetter } else if (INTEL_GTT_GEN == 6) { 617f51b7662SDaniel Vetter /* 618f51b7662SDaniel Vetter * SandyBridge has new memory control reg at 0x50.w 619f51b7662SDaniel Vetter */ 620f51b7662SDaniel Vetter u16 snb_gmch_ctl; 621f51b7662SDaniel Vetter pci_read_config_word(intel_private.pcidev, SNB_GMCH_CTRL, &snb_gmch_ctl); 622f51b7662SDaniel Vetter switch (snb_gmch_ctl & SNB_GMCH_GMS_STOLEN_MASK) { 623f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_32M: 624d8d9abcdSDaniel Vetter stolen_size = MB(32); 625f51b7662SDaniel Vetter break; 626f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_64M: 627d8d9abcdSDaniel Vetter stolen_size = MB(64); 628f51b7662SDaniel Vetter break; 629f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_96M: 630d8d9abcdSDaniel Vetter stolen_size = MB(96); 631f51b7662SDaniel Vetter break; 632f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_128M: 633d8d9abcdSDaniel Vetter stolen_size = MB(128); 634f51b7662SDaniel Vetter break; 635f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_160M: 636d8d9abcdSDaniel Vetter stolen_size = MB(160); 637f51b7662SDaniel Vetter break; 638f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_192M: 639d8d9abcdSDaniel Vetter stolen_size = MB(192); 640f51b7662SDaniel Vetter break; 641f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_224M: 642d8d9abcdSDaniel Vetter stolen_size = MB(224); 643f51b7662SDaniel Vetter break; 644f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_256M: 645d8d9abcdSDaniel Vetter stolen_size = MB(256); 646f51b7662SDaniel Vetter break; 647f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_288M: 648d8d9abcdSDaniel Vetter stolen_size = MB(288); 649f51b7662SDaniel Vetter break; 650f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_320M: 651d8d9abcdSDaniel Vetter stolen_size = MB(320); 652f51b7662SDaniel Vetter break; 653f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_352M: 654d8d9abcdSDaniel Vetter stolen_size = MB(352); 655f51b7662SDaniel Vetter break; 656f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_384M: 657d8d9abcdSDaniel Vetter stolen_size = MB(384); 658f51b7662SDaniel Vetter break; 659f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_416M: 660d8d9abcdSDaniel Vetter stolen_size = MB(416); 661f51b7662SDaniel Vetter break; 662f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_448M: 663d8d9abcdSDaniel Vetter stolen_size = MB(448); 664f51b7662SDaniel Vetter break; 665f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_480M: 666d8d9abcdSDaniel Vetter stolen_size = MB(480); 667f51b7662SDaniel Vetter break; 668f51b7662SDaniel Vetter case SNB_GMCH_GMS_STOLEN_512M: 669d8d9abcdSDaniel Vetter stolen_size = MB(512); 670f51b7662SDaniel Vetter break; 671f51b7662SDaniel Vetter } 672f51b7662SDaniel Vetter } else { 673f51b7662SDaniel Vetter switch (gmch_ctrl & I855_GMCH_GMS_MASK) { 674f51b7662SDaniel Vetter case I855_GMCH_GMS_STOLEN_1M: 675d8d9abcdSDaniel Vetter stolen_size = MB(1); 676f51b7662SDaniel Vetter break; 677f51b7662SDaniel Vetter case I855_GMCH_GMS_STOLEN_4M: 678d8d9abcdSDaniel Vetter stolen_size = MB(4); 679f51b7662SDaniel Vetter break; 680f51b7662SDaniel Vetter case I855_GMCH_GMS_STOLEN_8M: 681d8d9abcdSDaniel Vetter stolen_size = MB(8); 682f51b7662SDaniel Vetter break; 683f51b7662SDaniel Vetter case I855_GMCH_GMS_STOLEN_16M: 684d8d9abcdSDaniel Vetter stolen_size = MB(16); 685f51b7662SDaniel Vetter break; 686f51b7662SDaniel Vetter case I855_GMCH_GMS_STOLEN_32M: 687d8d9abcdSDaniel Vetter stolen_size = MB(32); 688f51b7662SDaniel Vetter break; 689f51b7662SDaniel Vetter case I915_GMCH_GMS_STOLEN_48M: 690d8d9abcdSDaniel Vetter stolen_size = MB(48); 691f51b7662SDaniel Vetter break; 692f51b7662SDaniel Vetter case I915_GMCH_GMS_STOLEN_64M: 693d8d9abcdSDaniel Vetter stolen_size = MB(64); 694f51b7662SDaniel Vetter break; 695f51b7662SDaniel Vetter case G33_GMCH_GMS_STOLEN_128M: 696d8d9abcdSDaniel Vetter stolen_size = MB(128); 697f51b7662SDaniel Vetter break; 698f51b7662SDaniel Vetter case G33_GMCH_GMS_STOLEN_256M: 699d8d9abcdSDaniel Vetter stolen_size = MB(256); 700f51b7662SDaniel Vetter break; 701f51b7662SDaniel Vetter case INTEL_GMCH_GMS_STOLEN_96M: 702d8d9abcdSDaniel Vetter stolen_size = MB(96); 703f51b7662SDaniel Vetter break; 704f51b7662SDaniel Vetter case INTEL_GMCH_GMS_STOLEN_160M: 705d8d9abcdSDaniel Vetter stolen_size = MB(160); 706f51b7662SDaniel Vetter break; 707f51b7662SDaniel Vetter case INTEL_GMCH_GMS_STOLEN_224M: 708d8d9abcdSDaniel Vetter stolen_size = MB(224); 709f51b7662SDaniel Vetter break; 710f51b7662SDaniel Vetter case INTEL_GMCH_GMS_STOLEN_352M: 711d8d9abcdSDaniel Vetter stolen_size = MB(352); 712f51b7662SDaniel Vetter break; 713f51b7662SDaniel Vetter default: 714d8d9abcdSDaniel Vetter stolen_size = 0; 715f51b7662SDaniel Vetter break; 716f51b7662SDaniel Vetter } 717f51b7662SDaniel Vetter } 7181784a5fbSDaniel Vetter 719d8d9abcdSDaniel Vetter if (!local && stolen_size > intel_max_stolen) { 720d7cca2f7SDaniel Vetter dev_info(&intel_private.bridge_dev->dev, 721d1d6ca73SJesse Barnes "detected %dK stolen memory, trimming to %dK\n", 722d8d9abcdSDaniel Vetter stolen_size / KB(1), intel_max_stolen / KB(1)); 723d8d9abcdSDaniel Vetter stolen_size = intel_max_stolen; 724d8d9abcdSDaniel Vetter } else if (stolen_size > 0) { 725d7cca2f7SDaniel Vetter dev_info(&intel_private.bridge_dev->dev, "detected %dK %s memory\n", 726d8d9abcdSDaniel Vetter stolen_size / KB(1), local ? "local" : "stolen"); 727f51b7662SDaniel Vetter } else { 728d7cca2f7SDaniel Vetter dev_info(&intel_private.bridge_dev->dev, 729f51b7662SDaniel Vetter "no pre-allocated video memory detected\n"); 730d8d9abcdSDaniel Vetter stolen_size = 0; 731f51b7662SDaniel Vetter } 732f51b7662SDaniel Vetter 733d8d9abcdSDaniel Vetter stolen_entries = stolen_size/KB(4) - overhead_entries; 734d8d9abcdSDaniel Vetter 735d8d9abcdSDaniel Vetter return stolen_entries; 736f51b7662SDaniel Vetter } 737f51b7662SDaniel Vetter 738fbe40783SDaniel Vetter static unsigned int intel_gtt_total_entries(void) 739fbe40783SDaniel Vetter { 740fbe40783SDaniel Vetter int size; 741fbe40783SDaniel Vetter 742210b23c2SDaniel Vetter if (IS_G33 || INTEL_GTT_GEN == 4 || INTEL_GTT_GEN == 5) { 743fbe40783SDaniel Vetter u32 pgetbl_ctl; 744fbe40783SDaniel Vetter pgetbl_ctl = readl(intel_private.registers+I810_PGETBL_CTL); 745fbe40783SDaniel Vetter 746fbe40783SDaniel Vetter switch (pgetbl_ctl & I965_PGETBL_SIZE_MASK) { 747fbe40783SDaniel Vetter case I965_PGETBL_SIZE_128KB: 748e5e408fcSDaniel Vetter size = KB(128); 749fbe40783SDaniel Vetter break; 750fbe40783SDaniel Vetter case I965_PGETBL_SIZE_256KB: 751e5e408fcSDaniel Vetter size = KB(256); 752fbe40783SDaniel Vetter break; 753fbe40783SDaniel Vetter case I965_PGETBL_SIZE_512KB: 754e5e408fcSDaniel Vetter size = KB(512); 755fbe40783SDaniel Vetter break; 756fbe40783SDaniel Vetter case I965_PGETBL_SIZE_1MB: 757e5e408fcSDaniel Vetter size = KB(1024); 758fbe40783SDaniel Vetter break; 759fbe40783SDaniel Vetter case I965_PGETBL_SIZE_2MB: 760e5e408fcSDaniel Vetter size = KB(2048); 761fbe40783SDaniel Vetter break; 762fbe40783SDaniel Vetter case I965_PGETBL_SIZE_1_5MB: 763e5e408fcSDaniel Vetter size = KB(1024 + 512); 764fbe40783SDaniel Vetter break; 765fbe40783SDaniel Vetter default: 766fbe40783SDaniel Vetter dev_info(&intel_private.pcidev->dev, 767fbe40783SDaniel Vetter "unknown page table size, assuming 512KB\n"); 768e5e408fcSDaniel Vetter size = KB(512); 769fbe40783SDaniel Vetter } 770e5e408fcSDaniel Vetter 771e5e408fcSDaniel Vetter return size/4; 772210b23c2SDaniel Vetter } else if (INTEL_GTT_GEN == 6) { 773210b23c2SDaniel Vetter u16 snb_gmch_ctl; 774210b23c2SDaniel Vetter 775210b23c2SDaniel Vetter pci_read_config_word(intel_private.pcidev, SNB_GMCH_CTRL, &snb_gmch_ctl); 776210b23c2SDaniel Vetter switch (snb_gmch_ctl & SNB_GTT_SIZE_MASK) { 777210b23c2SDaniel Vetter default: 778210b23c2SDaniel Vetter case SNB_GTT_SIZE_0M: 779210b23c2SDaniel Vetter printk(KERN_ERR "Bad GTT size mask: 0x%04x.\n", snb_gmch_ctl); 780210b23c2SDaniel Vetter size = MB(0); 781210b23c2SDaniel Vetter break; 782210b23c2SDaniel Vetter case SNB_GTT_SIZE_1M: 783210b23c2SDaniel Vetter size = MB(1); 784210b23c2SDaniel Vetter break; 785210b23c2SDaniel Vetter case SNB_GTT_SIZE_2M: 786210b23c2SDaniel Vetter size = MB(2); 787210b23c2SDaniel Vetter break; 788210b23c2SDaniel Vetter } 789210b23c2SDaniel Vetter return size/4; 790fbe40783SDaniel Vetter } else { 791fbe40783SDaniel Vetter /* On previous hardware, the GTT size was just what was 792fbe40783SDaniel Vetter * required to map the aperture. 793fbe40783SDaniel Vetter */ 794e5e408fcSDaniel Vetter return intel_private.base.gtt_mappable_entries; 795fbe40783SDaniel Vetter } 796fbe40783SDaniel Vetter } 797fbe40783SDaniel Vetter 7981784a5fbSDaniel Vetter static unsigned int intel_gtt_mappable_entries(void) 7991784a5fbSDaniel Vetter { 8001784a5fbSDaniel Vetter unsigned int aperture_size; 8011784a5fbSDaniel Vetter 802b1c5b0f8SChris Wilson if (INTEL_GTT_GEN == 2) { 803b1c5b0f8SChris Wilson u16 gmch_ctrl; 8041784a5fbSDaniel Vetter 8051784a5fbSDaniel Vetter pci_read_config_word(intel_private.bridge_dev, 8061784a5fbSDaniel Vetter I830_GMCH_CTRL, &gmch_ctrl); 8071784a5fbSDaniel Vetter 8081784a5fbSDaniel Vetter if ((gmch_ctrl & I830_GMCH_MEM_MASK) == I830_GMCH_MEM_64M) 809b1c5b0f8SChris Wilson aperture_size = MB(64); 8101784a5fbSDaniel Vetter else 811b1c5b0f8SChris Wilson aperture_size = MB(128); 812239918f7SDaniel Vetter } else { 8131784a5fbSDaniel Vetter /* 9xx supports large sizes, just look at the length */ 8141784a5fbSDaniel Vetter aperture_size = pci_resource_len(intel_private.pcidev, 2); 8151784a5fbSDaniel Vetter } 8161784a5fbSDaniel Vetter 8171784a5fbSDaniel Vetter return aperture_size >> PAGE_SHIFT; 8181784a5fbSDaniel Vetter } 8191784a5fbSDaniel Vetter 8200e87d2b0SDaniel Vetter static void intel_gtt_teardown_scratch_page(void) 8210e87d2b0SDaniel Vetter { 8220e87d2b0SDaniel Vetter set_pages_wb(intel_private.scratch_page, 1); 8230e87d2b0SDaniel Vetter pci_unmap_page(intel_private.pcidev, intel_private.scratch_page_dma, 8240e87d2b0SDaniel Vetter PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); 8250e87d2b0SDaniel Vetter put_page(intel_private.scratch_page); 8260e87d2b0SDaniel Vetter __free_page(intel_private.scratch_page); 8270e87d2b0SDaniel Vetter } 8280e87d2b0SDaniel Vetter 8290e87d2b0SDaniel Vetter static void intel_gtt_cleanup(void) 8300e87d2b0SDaniel Vetter { 8310e87d2b0SDaniel Vetter if (intel_private.i9xx_flush_page) 8320e87d2b0SDaniel Vetter iounmap(intel_private.i9xx_flush_page); 8330e87d2b0SDaniel Vetter if (intel_private.resource_valid) 8340e87d2b0SDaniel Vetter release_resource(&intel_private.ifp_resource); 8350e87d2b0SDaniel Vetter intel_private.ifp_resource.start = 0; 8360e87d2b0SDaniel Vetter intel_private.resource_valid = 0; 8370e87d2b0SDaniel Vetter iounmap(intel_private.gtt); 8380e87d2b0SDaniel Vetter iounmap(intel_private.registers); 8390e87d2b0SDaniel Vetter 8400e87d2b0SDaniel Vetter intel_gtt_teardown_scratch_page(); 8410e87d2b0SDaniel Vetter } 8420e87d2b0SDaniel Vetter 8431784a5fbSDaniel Vetter static int intel_gtt_init(void) 8441784a5fbSDaniel Vetter { 845f67eab66SDaniel Vetter u32 gtt_map_size; 8463b15a9d7SDaniel Vetter int ret; 8473b15a9d7SDaniel Vetter 8483b15a9d7SDaniel Vetter ret = intel_private.driver->setup(); 8493b15a9d7SDaniel Vetter if (ret != 0) 8503b15a9d7SDaniel Vetter return ret; 851f67eab66SDaniel Vetter 852f67eab66SDaniel Vetter intel_private.base.gtt_mappable_entries = intel_gtt_mappable_entries(); 853f67eab66SDaniel Vetter intel_private.base.gtt_total_entries = intel_gtt_total_entries(); 854f67eab66SDaniel Vetter 855f67eab66SDaniel Vetter gtt_map_size = intel_private.base.gtt_total_entries * 4; 856f67eab66SDaniel Vetter 857f67eab66SDaniel Vetter intel_private.gtt = ioremap(intel_private.gtt_bus_addr, 858f67eab66SDaniel Vetter gtt_map_size); 859f67eab66SDaniel Vetter if (!intel_private.gtt) { 860f67eab66SDaniel Vetter iounmap(intel_private.registers); 861f67eab66SDaniel Vetter return -ENOMEM; 862f67eab66SDaniel Vetter } 863f67eab66SDaniel Vetter 864f67eab66SDaniel Vetter global_cache_flush(); /* FIXME: ? */ 865f67eab66SDaniel Vetter 8661784a5fbSDaniel Vetter /* we have to call this as early as possible after the MMIO base address is known */ 8671784a5fbSDaniel Vetter intel_private.base.gtt_stolen_entries = intel_gtt_stolen_entries(); 8681784a5fbSDaniel Vetter if (intel_private.base.gtt_stolen_entries == 0) { 8691784a5fbSDaniel Vetter iounmap(intel_private.registers); 870f67eab66SDaniel Vetter iounmap(intel_private.gtt); 8711784a5fbSDaniel Vetter return -ENOMEM; 8721784a5fbSDaniel Vetter } 8731784a5fbSDaniel Vetter 8740e87d2b0SDaniel Vetter ret = intel_gtt_setup_scratch_page(); 8750e87d2b0SDaniel Vetter if (ret != 0) { 8760e87d2b0SDaniel Vetter intel_gtt_cleanup(); 8770e87d2b0SDaniel Vetter return ret; 8780e87d2b0SDaniel Vetter } 8790e87d2b0SDaniel Vetter 8801784a5fbSDaniel Vetter return 0; 8811784a5fbSDaniel Vetter } 8821784a5fbSDaniel Vetter 8833e921f98SDaniel Vetter static int intel_fake_agp_fetch_size(void) 8843e921f98SDaniel Vetter { 8859e76e7b8SChris Wilson int num_sizes = ARRAY_SIZE(intel_fake_agp_sizes); 8863e921f98SDaniel Vetter unsigned int aper_size; 8873e921f98SDaniel Vetter int i; 8883e921f98SDaniel Vetter 8893e921f98SDaniel Vetter aper_size = (intel_private.base.gtt_mappable_entries << PAGE_SHIFT) 8903e921f98SDaniel Vetter / MB(1); 8913e921f98SDaniel Vetter 8923e921f98SDaniel Vetter for (i = 0; i < num_sizes; i++) { 893ffdd7510SDaniel Vetter if (aper_size == intel_fake_agp_sizes[i].size) { 8949e76e7b8SChris Wilson agp_bridge->current_size = 8959e76e7b8SChris Wilson (void *) (intel_fake_agp_sizes + i); 8963e921f98SDaniel Vetter return aper_size; 8973e921f98SDaniel Vetter } 8983e921f98SDaniel Vetter } 8993e921f98SDaniel Vetter 9003e921f98SDaniel Vetter return 0; 9013e921f98SDaniel Vetter } 9023e921f98SDaniel Vetter 903f51b7662SDaniel Vetter static void intel_i830_fini_flush(void) 904f51b7662SDaniel Vetter { 905f51b7662SDaniel Vetter kunmap(intel_private.i8xx_page); 906f51b7662SDaniel Vetter intel_private.i8xx_flush_page = NULL; 907f51b7662SDaniel Vetter unmap_page_from_agp(intel_private.i8xx_page); 908f51b7662SDaniel Vetter 909f51b7662SDaniel Vetter __free_page(intel_private.i8xx_page); 910f51b7662SDaniel Vetter intel_private.i8xx_page = NULL; 911f51b7662SDaniel Vetter } 912f51b7662SDaniel Vetter 913f51b7662SDaniel Vetter static void intel_i830_setup_flush(void) 914f51b7662SDaniel Vetter { 915f51b7662SDaniel Vetter /* return if we've already set the flush mechanism up */ 916f51b7662SDaniel Vetter if (intel_private.i8xx_page) 917f51b7662SDaniel Vetter return; 918f51b7662SDaniel Vetter 919f51b7662SDaniel Vetter intel_private.i8xx_page = alloc_page(GFP_KERNEL | __GFP_ZERO | GFP_DMA32); 920f51b7662SDaniel Vetter if (!intel_private.i8xx_page) 921f51b7662SDaniel Vetter return; 922f51b7662SDaniel Vetter 923f51b7662SDaniel Vetter intel_private.i8xx_flush_page = kmap(intel_private.i8xx_page); 924f51b7662SDaniel Vetter if (!intel_private.i8xx_flush_page) 925f51b7662SDaniel Vetter intel_i830_fini_flush(); 926f51b7662SDaniel Vetter } 927f51b7662SDaniel Vetter 928f51b7662SDaniel Vetter /* The chipset_flush interface needs to get data that has already been 929f51b7662SDaniel Vetter * flushed out of the CPU all the way out to main memory, because the GPU 930f51b7662SDaniel Vetter * doesn't snoop those buffers. 931f51b7662SDaniel Vetter * 932f51b7662SDaniel Vetter * The 8xx series doesn't have the same lovely interface for flushing the 933f51b7662SDaniel Vetter * chipset write buffers that the later chips do. According to the 865 934f51b7662SDaniel Vetter * specs, it's 64 octwords, or 1KB. So, to get those previous things in 935f51b7662SDaniel Vetter * that buffer out, we just fill 1KB and clflush it out, on the assumption 936f51b7662SDaniel Vetter * that it'll push whatever was in there out. It appears to work. 937f51b7662SDaniel Vetter */ 938f51b7662SDaniel Vetter static void intel_i830_chipset_flush(struct agp_bridge_data *bridge) 939f51b7662SDaniel Vetter { 940f51b7662SDaniel Vetter unsigned int *pg = intel_private.i8xx_flush_page; 941f51b7662SDaniel Vetter 942f51b7662SDaniel Vetter memset(pg, 0, 1024); 943f51b7662SDaniel Vetter 944f51b7662SDaniel Vetter if (cpu_has_clflush) 945f51b7662SDaniel Vetter clflush_cache_range(pg, 1024); 946f51b7662SDaniel Vetter else if (wbinvd_on_all_cpus() != 0) 947f51b7662SDaniel Vetter printk(KERN_ERR "Timed out waiting for cache flush.\n"); 948f51b7662SDaniel Vetter } 949f51b7662SDaniel Vetter 950351bb278SDaniel Vetter static void i830_write_entry(dma_addr_t addr, unsigned int entry, 951351bb278SDaniel Vetter unsigned int flags) 952351bb278SDaniel Vetter { 953351bb278SDaniel Vetter u32 pte_flags = I810_PTE_VALID; 954351bb278SDaniel Vetter 955351bb278SDaniel Vetter switch (flags) { 956351bb278SDaniel Vetter case AGP_DCACHE_MEMORY: 957351bb278SDaniel Vetter pte_flags |= I810_PTE_LOCAL; 958351bb278SDaniel Vetter break; 959351bb278SDaniel Vetter case AGP_USER_CACHED_MEMORY: 960351bb278SDaniel Vetter pte_flags |= I830_PTE_SYSTEM_CACHED; 961351bb278SDaniel Vetter break; 962351bb278SDaniel Vetter } 963351bb278SDaniel Vetter 964351bb278SDaniel Vetter writel(addr | pte_flags, intel_private.gtt + entry); 965351bb278SDaniel Vetter } 966351bb278SDaniel Vetter 96773800422SDaniel Vetter static void intel_enable_gtt(void) 96873800422SDaniel Vetter { 9693f08e4efSChris Wilson u32 gma_addr; 97073800422SDaniel Vetter u16 gmch_ctrl; 97173800422SDaniel Vetter 9722d2430cfSDaniel Vetter if (INTEL_GTT_GEN == 2) 9732d2430cfSDaniel Vetter pci_read_config_dword(intel_private.pcidev, I810_GMADDR, 9742d2430cfSDaniel Vetter &gma_addr); 9752d2430cfSDaniel Vetter else 9762d2430cfSDaniel Vetter pci_read_config_dword(intel_private.pcidev, I915_GMADDR, 9772d2430cfSDaniel Vetter &gma_addr); 9782d2430cfSDaniel Vetter 97973800422SDaniel Vetter intel_private.gma_bus_addr = (gma_addr & PCI_BASE_ADDRESS_MEM_MASK); 98073800422SDaniel Vetter 98173800422SDaniel Vetter pci_read_config_word(intel_private.bridge_dev, I830_GMCH_CTRL, &gmch_ctrl); 98273800422SDaniel Vetter gmch_ctrl |= I830_GMCH_ENABLED; 98373800422SDaniel Vetter pci_write_config_word(intel_private.bridge_dev, I830_GMCH_CTRL, gmch_ctrl); 98473800422SDaniel Vetter 9853f08e4efSChris Wilson writel(intel_private.pte_bus_addr|I810_PGETBL_ENABLED, 9863f08e4efSChris Wilson intel_private.registers+I810_PGETBL_CTL); 98773800422SDaniel Vetter readl(intel_private.registers+I810_PGETBL_CTL); /* PCI Posting. */ 98873800422SDaniel Vetter } 98973800422SDaniel Vetter 99073800422SDaniel Vetter static int i830_setup(void) 99173800422SDaniel Vetter { 99273800422SDaniel Vetter u32 reg_addr; 99373800422SDaniel Vetter 99473800422SDaniel Vetter pci_read_config_dword(intel_private.pcidev, I810_MMADDR, ®_addr); 99573800422SDaniel Vetter reg_addr &= 0xfff80000; 99673800422SDaniel Vetter 99773800422SDaniel Vetter intel_private.registers = ioremap(reg_addr, KB(64)); 99873800422SDaniel Vetter if (!intel_private.registers) 99973800422SDaniel Vetter return -ENOMEM; 100073800422SDaniel Vetter 100173800422SDaniel Vetter intel_private.gtt_bus_addr = reg_addr + I810_PTE_BASE; 10023f08e4efSChris Wilson intel_private.pte_bus_addr = 10033f08e4efSChris Wilson readl(intel_private.registers+I810_PGETBL_CTL) & 0xfffff000; 100473800422SDaniel Vetter 100573800422SDaniel Vetter intel_i830_setup_flush(); 100673800422SDaniel Vetter 100773800422SDaniel Vetter return 0; 100873800422SDaniel Vetter } 100973800422SDaniel Vetter 10103b15a9d7SDaniel Vetter static int intel_fake_agp_create_gatt_table(struct agp_bridge_data *bridge) 1011f51b7662SDaniel Vetter { 101273800422SDaniel Vetter agp_bridge->gatt_table_real = NULL; 1013f51b7662SDaniel Vetter agp_bridge->gatt_table = NULL; 101473800422SDaniel Vetter agp_bridge->gatt_bus_addr = 0; 1015f51b7662SDaniel Vetter 1016f51b7662SDaniel Vetter return 0; 1017f51b7662SDaniel Vetter } 1018f51b7662SDaniel Vetter 1019ffdd7510SDaniel Vetter static int intel_fake_agp_free_gatt_table(struct agp_bridge_data *bridge) 1020f51b7662SDaniel Vetter { 1021f51b7662SDaniel Vetter return 0; 1022f51b7662SDaniel Vetter } 1023f51b7662SDaniel Vetter 1024351bb278SDaniel Vetter static int intel_fake_agp_configure(void) 1025f51b7662SDaniel Vetter { 1026f51b7662SDaniel Vetter int i; 1027f51b7662SDaniel Vetter 102873800422SDaniel Vetter intel_enable_gtt(); 1029f51b7662SDaniel Vetter 103073800422SDaniel Vetter agp_bridge->gart_bus_addr = intel_private.gma_bus_addr; 1031f51b7662SDaniel Vetter 103273800422SDaniel Vetter for (i = intel_private.base.gtt_stolen_entries; 103373800422SDaniel Vetter i < intel_private.base.gtt_total_entries; i++) { 1034351bb278SDaniel Vetter intel_private.driver->write_entry(intel_private.scratch_page_dma, 1035351bb278SDaniel Vetter i, 0); 1036f51b7662SDaniel Vetter } 1037fdfb58a9SDaniel Vetter readl(intel_private.gtt+i-1); /* PCI Posting. */ 1038f51b7662SDaniel Vetter 1039f51b7662SDaniel Vetter global_cache_flush(); 1040f51b7662SDaniel Vetter 1041f51b7662SDaniel Vetter return 0; 1042f51b7662SDaniel Vetter } 1043f51b7662SDaniel Vetter 10445cbecafcSDaniel Vetter static bool i830_check_flags(unsigned int flags) 1045f51b7662SDaniel Vetter { 10465cbecafcSDaniel Vetter switch (flags) { 10475cbecafcSDaniel Vetter case 0: 10485cbecafcSDaniel Vetter case AGP_PHYS_MEMORY: 10495cbecafcSDaniel Vetter case AGP_USER_CACHED_MEMORY: 10505cbecafcSDaniel Vetter case AGP_USER_MEMORY: 10515cbecafcSDaniel Vetter return true; 10525cbecafcSDaniel Vetter } 10535cbecafcSDaniel Vetter 10545cbecafcSDaniel Vetter return false; 10555cbecafcSDaniel Vetter } 10565cbecafcSDaniel Vetter 1057fefaa70fSDaniel Vetter static void intel_gtt_insert_sg_entries(struct scatterlist *sg_list, 1058fefaa70fSDaniel Vetter unsigned int sg_len, 1059fefaa70fSDaniel Vetter unsigned int pg_start, 1060fefaa70fSDaniel Vetter unsigned int flags) 1061fefaa70fSDaniel Vetter { 1062fefaa70fSDaniel Vetter struct scatterlist *sg; 1063fefaa70fSDaniel Vetter unsigned int len, m; 1064fefaa70fSDaniel Vetter int i, j; 1065fefaa70fSDaniel Vetter 1066fefaa70fSDaniel Vetter j = pg_start; 1067fefaa70fSDaniel Vetter 1068fefaa70fSDaniel Vetter /* sg may merge pages, but we have to separate 1069fefaa70fSDaniel Vetter * per-page addr for GTT */ 1070fefaa70fSDaniel Vetter for_each_sg(sg_list, sg, sg_len, i) { 1071fefaa70fSDaniel Vetter len = sg_dma_len(sg) >> PAGE_SHIFT; 1072fefaa70fSDaniel Vetter for (m = 0; m < len; m++) { 1073fefaa70fSDaniel Vetter dma_addr_t addr = sg_dma_address(sg) + (m << PAGE_SHIFT); 1074fefaa70fSDaniel Vetter intel_private.driver->write_entry(addr, 1075fefaa70fSDaniel Vetter j, flags); 1076fefaa70fSDaniel Vetter j++; 1077fefaa70fSDaniel Vetter } 1078fefaa70fSDaniel Vetter } 1079fefaa70fSDaniel Vetter readl(intel_private.gtt+j-1); 1080fefaa70fSDaniel Vetter } 1081fefaa70fSDaniel Vetter 10825cbecafcSDaniel Vetter static int intel_fake_agp_insert_entries(struct agp_memory *mem, 10835cbecafcSDaniel Vetter off_t pg_start, int type) 10845cbecafcSDaniel Vetter { 10855cbecafcSDaniel Vetter int i, j; 1086f51b7662SDaniel Vetter int ret = -EINVAL; 1087f51b7662SDaniel Vetter 1088f51b7662SDaniel Vetter if (mem->page_count == 0) 1089f51b7662SDaniel Vetter goto out; 1090f51b7662SDaniel Vetter 10910ade6386SDaniel Vetter if (pg_start < intel_private.base.gtt_stolen_entries) { 1092f51b7662SDaniel Vetter dev_printk(KERN_DEBUG, &intel_private.pcidev->dev, 10930ade6386SDaniel Vetter "pg_start == 0x%.8lx, gtt_stolen_entries == 0x%.8x\n", 10940ade6386SDaniel Vetter pg_start, intel_private.base.gtt_stolen_entries); 1095f51b7662SDaniel Vetter 1096f51b7662SDaniel Vetter dev_info(&intel_private.pcidev->dev, 1097f51b7662SDaniel Vetter "trying to insert into local/stolen memory\n"); 1098f51b7662SDaniel Vetter goto out_err; 1099f51b7662SDaniel Vetter } 1100f51b7662SDaniel Vetter 11015cbecafcSDaniel Vetter if ((pg_start + mem->page_count) > intel_private.base.gtt_total_entries) 1102f51b7662SDaniel Vetter goto out_err; 1103f51b7662SDaniel Vetter 1104f51b7662SDaniel Vetter if (type != mem->type) 1105f51b7662SDaniel Vetter goto out_err; 1106f51b7662SDaniel Vetter 11075cbecafcSDaniel Vetter if (!intel_private.driver->check_flags(type)) 1108f51b7662SDaniel Vetter goto out_err; 1109f51b7662SDaniel Vetter 1110f51b7662SDaniel Vetter if (!mem->is_flushed) 1111f51b7662SDaniel Vetter global_cache_flush(); 1112f51b7662SDaniel Vetter 1113fefaa70fSDaniel Vetter if (USE_PCI_DMA_API && INTEL_GTT_GEN > 2) { 1114fefaa70fSDaniel Vetter ret = intel_agp_map_memory(mem); 1115fefaa70fSDaniel Vetter if (ret != 0) 1116fefaa70fSDaniel Vetter return ret; 1117fefaa70fSDaniel Vetter 1118fefaa70fSDaniel Vetter intel_gtt_insert_sg_entries(mem->sg_list, mem->num_sg, 1119fefaa70fSDaniel Vetter pg_start, type); 1120fefaa70fSDaniel Vetter } else { 1121f51b7662SDaniel Vetter for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { 1122fefaa70fSDaniel Vetter dma_addr_t addr = page_to_phys(mem->pages[i]); 1123fefaa70fSDaniel Vetter intel_private.driver->write_entry(addr, 11245cbecafcSDaniel Vetter j, type); 1125f51b7662SDaniel Vetter } 1126fdfb58a9SDaniel Vetter readl(intel_private.gtt+j-1); 1127fefaa70fSDaniel Vetter } 1128f51b7662SDaniel Vetter 1129f51b7662SDaniel Vetter out: 1130f51b7662SDaniel Vetter ret = 0; 1131f51b7662SDaniel Vetter out_err: 1132f51b7662SDaniel Vetter mem->is_flushed = true; 1133f51b7662SDaniel Vetter return ret; 1134f51b7662SDaniel Vetter } 1135f51b7662SDaniel Vetter 11365cbecafcSDaniel Vetter static int intel_fake_agp_remove_entries(struct agp_memory *mem, 11375cbecafcSDaniel Vetter off_t pg_start, int type) 1138f51b7662SDaniel Vetter { 1139f51b7662SDaniel Vetter int i; 1140f51b7662SDaniel Vetter 1141f51b7662SDaniel Vetter if (mem->page_count == 0) 1142f51b7662SDaniel Vetter return 0; 1143f51b7662SDaniel Vetter 11440ade6386SDaniel Vetter if (pg_start < intel_private.base.gtt_stolen_entries) { 1145f51b7662SDaniel Vetter dev_info(&intel_private.pcidev->dev, 1146f51b7662SDaniel Vetter "trying to disable local/stolen memory\n"); 1147f51b7662SDaniel Vetter return -EINVAL; 1148f51b7662SDaniel Vetter } 1149f51b7662SDaniel Vetter 1150fefaa70fSDaniel Vetter if (USE_PCI_DMA_API && INTEL_GTT_GEN > 2) 1151fefaa70fSDaniel Vetter intel_agp_unmap_memory(mem); 1152fefaa70fSDaniel Vetter 1153f51b7662SDaniel Vetter for (i = pg_start; i < (mem->page_count + pg_start); i++) { 11545cbecafcSDaniel Vetter intel_private.driver->write_entry(intel_private.scratch_page_dma, 11555cbecafcSDaniel Vetter i, 0); 1156f51b7662SDaniel Vetter } 1157fdfb58a9SDaniel Vetter readl(intel_private.gtt+i-1); 1158f51b7662SDaniel Vetter 1159f51b7662SDaniel Vetter return 0; 1160f51b7662SDaniel Vetter } 1161f51b7662SDaniel Vetter 1162ffdd7510SDaniel Vetter static struct agp_memory *intel_fake_agp_alloc_by_type(size_t pg_count, 1163ffdd7510SDaniel Vetter int type) 1164f51b7662SDaniel Vetter { 1165f51b7662SDaniel Vetter if (type == AGP_PHYS_MEMORY) 1166f51b7662SDaniel Vetter return alloc_agpphysmem_i8xx(pg_count, type); 1167f51b7662SDaniel Vetter /* always return NULL for other allocation types for now */ 1168f51b7662SDaniel Vetter return NULL; 1169f51b7662SDaniel Vetter } 1170f51b7662SDaniel Vetter 1171f51b7662SDaniel Vetter static int intel_alloc_chipset_flush_resource(void) 1172f51b7662SDaniel Vetter { 1173f51b7662SDaniel Vetter int ret; 1174d7cca2f7SDaniel Vetter ret = pci_bus_alloc_resource(intel_private.bridge_dev->bus, &intel_private.ifp_resource, PAGE_SIZE, 1175f51b7662SDaniel Vetter PAGE_SIZE, PCIBIOS_MIN_MEM, 0, 1176d7cca2f7SDaniel Vetter pcibios_align_resource, intel_private.bridge_dev); 1177f51b7662SDaniel Vetter 1178f51b7662SDaniel Vetter return ret; 1179f51b7662SDaniel Vetter } 1180f51b7662SDaniel Vetter 1181f51b7662SDaniel Vetter static void intel_i915_setup_chipset_flush(void) 1182f51b7662SDaniel Vetter { 1183f51b7662SDaniel Vetter int ret; 1184f51b7662SDaniel Vetter u32 temp; 1185f51b7662SDaniel Vetter 1186d7cca2f7SDaniel Vetter pci_read_config_dword(intel_private.bridge_dev, I915_IFPADDR, &temp); 1187f51b7662SDaniel Vetter if (!(temp & 0x1)) { 1188f51b7662SDaniel Vetter intel_alloc_chipset_flush_resource(); 1189f51b7662SDaniel Vetter intel_private.resource_valid = 1; 1190d7cca2f7SDaniel Vetter pci_write_config_dword(intel_private.bridge_dev, I915_IFPADDR, (intel_private.ifp_resource.start & 0xffffffff) | 0x1); 1191f51b7662SDaniel Vetter } else { 1192f51b7662SDaniel Vetter temp &= ~1; 1193f51b7662SDaniel Vetter 1194f51b7662SDaniel Vetter intel_private.resource_valid = 1; 1195f51b7662SDaniel Vetter intel_private.ifp_resource.start = temp; 1196f51b7662SDaniel Vetter intel_private.ifp_resource.end = temp + PAGE_SIZE; 1197f51b7662SDaniel Vetter ret = request_resource(&iomem_resource, &intel_private.ifp_resource); 1198f51b7662SDaniel Vetter /* some BIOSes reserve this area in a pnp some don't */ 1199f51b7662SDaniel Vetter if (ret) 1200f51b7662SDaniel Vetter intel_private.resource_valid = 0; 1201f51b7662SDaniel Vetter } 1202f51b7662SDaniel Vetter } 1203f51b7662SDaniel Vetter 1204f51b7662SDaniel Vetter static void intel_i965_g33_setup_chipset_flush(void) 1205f51b7662SDaniel Vetter { 1206f51b7662SDaniel Vetter u32 temp_hi, temp_lo; 1207f51b7662SDaniel Vetter int ret; 1208f51b7662SDaniel Vetter 1209d7cca2f7SDaniel Vetter pci_read_config_dword(intel_private.bridge_dev, I965_IFPADDR + 4, &temp_hi); 1210d7cca2f7SDaniel Vetter pci_read_config_dword(intel_private.bridge_dev, I965_IFPADDR, &temp_lo); 1211f51b7662SDaniel Vetter 1212f51b7662SDaniel Vetter if (!(temp_lo & 0x1)) { 1213f51b7662SDaniel Vetter 1214f51b7662SDaniel Vetter intel_alloc_chipset_flush_resource(); 1215f51b7662SDaniel Vetter 1216f51b7662SDaniel Vetter intel_private.resource_valid = 1; 1217d7cca2f7SDaniel Vetter pci_write_config_dword(intel_private.bridge_dev, I965_IFPADDR + 4, 1218f51b7662SDaniel Vetter upper_32_bits(intel_private.ifp_resource.start)); 1219d7cca2f7SDaniel Vetter pci_write_config_dword(intel_private.bridge_dev, I965_IFPADDR, (intel_private.ifp_resource.start & 0xffffffff) | 0x1); 1220f51b7662SDaniel Vetter } else { 1221f51b7662SDaniel Vetter u64 l64; 1222f51b7662SDaniel Vetter 1223f51b7662SDaniel Vetter temp_lo &= ~0x1; 1224f51b7662SDaniel Vetter l64 = ((u64)temp_hi << 32) | temp_lo; 1225f51b7662SDaniel Vetter 1226f51b7662SDaniel Vetter intel_private.resource_valid = 1; 1227f51b7662SDaniel Vetter intel_private.ifp_resource.start = l64; 1228f51b7662SDaniel Vetter intel_private.ifp_resource.end = l64 + PAGE_SIZE; 1229f51b7662SDaniel Vetter ret = request_resource(&iomem_resource, &intel_private.ifp_resource); 1230f51b7662SDaniel Vetter /* some BIOSes reserve this area in a pnp some don't */ 1231f51b7662SDaniel Vetter if (ret) 1232f51b7662SDaniel Vetter intel_private.resource_valid = 0; 1233f51b7662SDaniel Vetter } 1234f51b7662SDaniel Vetter } 1235f51b7662SDaniel Vetter 1236f51b7662SDaniel Vetter static void intel_i9xx_setup_flush(void) 1237f51b7662SDaniel Vetter { 1238f51b7662SDaniel Vetter /* return if already configured */ 1239f51b7662SDaniel Vetter if (intel_private.ifp_resource.start) 1240f51b7662SDaniel Vetter return; 1241f51b7662SDaniel Vetter 12421a997ff2SDaniel Vetter if (INTEL_GTT_GEN == 6) 1243f51b7662SDaniel Vetter return; 1244f51b7662SDaniel Vetter 1245f51b7662SDaniel Vetter /* setup a resource for this object */ 1246f51b7662SDaniel Vetter intel_private.ifp_resource.name = "Intel Flush Page"; 1247f51b7662SDaniel Vetter intel_private.ifp_resource.flags = IORESOURCE_MEM; 1248f51b7662SDaniel Vetter 1249f51b7662SDaniel Vetter /* Setup chipset flush for 915 */ 12501a997ff2SDaniel Vetter if (IS_G33 || INTEL_GTT_GEN >= 4) { 1251f51b7662SDaniel Vetter intel_i965_g33_setup_chipset_flush(); 1252f51b7662SDaniel Vetter } else { 1253f51b7662SDaniel Vetter intel_i915_setup_chipset_flush(); 1254f51b7662SDaniel Vetter } 1255f51b7662SDaniel Vetter 1256df51e7aaSChris Wilson if (intel_private.ifp_resource.start) 1257f51b7662SDaniel Vetter intel_private.i9xx_flush_page = ioremap_nocache(intel_private.ifp_resource.start, PAGE_SIZE); 1258f51b7662SDaniel Vetter if (!intel_private.i9xx_flush_page) 1259df51e7aaSChris Wilson dev_err(&intel_private.pcidev->dev, 1260df51e7aaSChris Wilson "can't ioremap flush page - no chipset flushing\n"); 1261f51b7662SDaniel Vetter } 1262f51b7662SDaniel Vetter 1263f51b7662SDaniel Vetter static void intel_i915_chipset_flush(struct agp_bridge_data *bridge) 1264f51b7662SDaniel Vetter { 1265f51b7662SDaniel Vetter if (intel_private.i9xx_flush_page) 1266f51b7662SDaniel Vetter writel(1, intel_private.i9xx_flush_page); 1267f51b7662SDaniel Vetter } 1268f51b7662SDaniel Vetter 1269f51b7662SDaniel Vetter static int intel_i915_insert_entries(struct agp_memory *mem, off_t pg_start, 1270f51b7662SDaniel Vetter int type) 1271f51b7662SDaniel Vetter { 1272f51b7662SDaniel Vetter int num_entries; 1273f51b7662SDaniel Vetter void *temp; 1274f51b7662SDaniel Vetter int ret = -EINVAL; 1275f51b7662SDaniel Vetter int mask_type; 1276f51b7662SDaniel Vetter 1277f51b7662SDaniel Vetter if (mem->page_count == 0) 1278f51b7662SDaniel Vetter goto out; 1279f51b7662SDaniel Vetter 1280f51b7662SDaniel Vetter temp = agp_bridge->current_size; 1281f51b7662SDaniel Vetter num_entries = A_SIZE_FIX(temp)->num_entries; 1282f51b7662SDaniel Vetter 12830ade6386SDaniel Vetter if (pg_start < intel_private.base.gtt_stolen_entries) { 1284f51b7662SDaniel Vetter dev_printk(KERN_DEBUG, &intel_private.pcidev->dev, 12850ade6386SDaniel Vetter "pg_start == 0x%.8lx, gtt_stolen_entries == 0x%.8x\n", 12860ade6386SDaniel Vetter pg_start, intel_private.base.gtt_stolen_entries); 1287f51b7662SDaniel Vetter 1288f51b7662SDaniel Vetter dev_info(&intel_private.pcidev->dev, 1289f51b7662SDaniel Vetter "trying to insert into local/stolen memory\n"); 1290f51b7662SDaniel Vetter goto out_err; 1291f51b7662SDaniel Vetter } 1292f51b7662SDaniel Vetter 1293f51b7662SDaniel Vetter if ((pg_start + mem->page_count) > num_entries) 1294f51b7662SDaniel Vetter goto out_err; 1295f51b7662SDaniel Vetter 1296f51b7662SDaniel Vetter /* The i915 can't check the GTT for entries since it's read only; 1297f51b7662SDaniel Vetter * depend on the caller to make the correct offset decisions. 1298f51b7662SDaniel Vetter */ 1299f51b7662SDaniel Vetter 1300f51b7662SDaniel Vetter if (type != mem->type) 1301f51b7662SDaniel Vetter goto out_err; 1302f51b7662SDaniel Vetter 1303f51b7662SDaniel Vetter mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type); 1304f51b7662SDaniel Vetter 13051a997ff2SDaniel Vetter if (INTEL_GTT_GEN != 6 && mask_type != 0 && 13061a997ff2SDaniel Vetter mask_type != AGP_PHYS_MEMORY && 1307f51b7662SDaniel Vetter mask_type != INTEL_AGP_CACHED_MEMORY) 1308f51b7662SDaniel Vetter goto out_err; 1309f51b7662SDaniel Vetter 1310f51b7662SDaniel Vetter if (!mem->is_flushed) 1311f51b7662SDaniel Vetter global_cache_flush(); 1312f51b7662SDaniel Vetter 1313f51b7662SDaniel Vetter intel_agp_insert_sg_entries(mem, pg_start, mask_type); 1314f51b7662SDaniel Vetter 1315f51b7662SDaniel Vetter out: 1316f51b7662SDaniel Vetter ret = 0; 1317f51b7662SDaniel Vetter out_err: 1318f51b7662SDaniel Vetter mem->is_flushed = true; 1319f51b7662SDaniel Vetter return ret; 1320f51b7662SDaniel Vetter } 1321f51b7662SDaniel Vetter 1322f51b7662SDaniel Vetter static int intel_i915_remove_entries(struct agp_memory *mem, off_t pg_start, 1323f51b7662SDaniel Vetter int type) 1324f51b7662SDaniel Vetter { 1325f51b7662SDaniel Vetter int i; 1326f51b7662SDaniel Vetter 1327f51b7662SDaniel Vetter if (mem->page_count == 0) 1328f51b7662SDaniel Vetter return 0; 1329f51b7662SDaniel Vetter 13300ade6386SDaniel Vetter if (pg_start < intel_private.base.gtt_stolen_entries) { 1331f51b7662SDaniel Vetter dev_info(&intel_private.pcidev->dev, 1332f51b7662SDaniel Vetter "trying to disable local/stolen memory\n"); 1333f51b7662SDaniel Vetter return -EINVAL; 1334f51b7662SDaniel Vetter } 1335f51b7662SDaniel Vetter 1336f51b7662SDaniel Vetter for (i = pg_start; i < (mem->page_count + pg_start); i++) 1337f51b7662SDaniel Vetter writel(agp_bridge->scratch_page, intel_private.gtt+i); 1338f51b7662SDaniel Vetter 1339f51b7662SDaniel Vetter readl(intel_private.gtt+i-1); 1340f51b7662SDaniel Vetter 1341f51b7662SDaniel Vetter return 0; 1342f51b7662SDaniel Vetter } 1343f51b7662SDaniel Vetter 1344a6963596SDaniel Vetter static void i965_write_entry(dma_addr_t addr, unsigned int entry, 1345a6963596SDaniel Vetter unsigned int flags) 1346a6963596SDaniel Vetter { 1347a6963596SDaniel Vetter /* Shift high bits down */ 1348a6963596SDaniel Vetter addr |= (addr >> 28) & 0xf0; 1349a6963596SDaniel Vetter writel(addr | I810_PTE_VALID, intel_private.gtt + entry); 1350a6963596SDaniel Vetter } 1351a6963596SDaniel Vetter 135297ef1bddSDaniel Vetter static void gen6_write_entry(dma_addr_t addr, unsigned int entry, 135397ef1bddSDaniel Vetter unsigned int flags) 135497ef1bddSDaniel Vetter { 135597ef1bddSDaniel Vetter unsigned int type_mask = flags & ~AGP_USER_CACHED_MEMORY_GFDT; 135697ef1bddSDaniel Vetter unsigned int gfdt = flags & AGP_USER_CACHED_MEMORY_GFDT; 135797ef1bddSDaniel Vetter u32 pte_flags; 135897ef1bddSDaniel Vetter 135997ef1bddSDaniel Vetter if (type_mask == AGP_USER_UNCACHED_MEMORY) 136097ef1bddSDaniel Vetter pte_flags = GEN6_PTE_UNCACHED; 136197ef1bddSDaniel Vetter else if (type_mask == AGP_USER_CACHED_MEMORY_LLC_MLC) { 136297ef1bddSDaniel Vetter pte_flags = GEN6_PTE_LLC; 136397ef1bddSDaniel Vetter if (gfdt) 136497ef1bddSDaniel Vetter pte_flags |= GEN6_PTE_GFDT; 136597ef1bddSDaniel Vetter } else { /* set 'normal'/'cached' to LLC by default */ 136697ef1bddSDaniel Vetter pte_flags = GEN6_PTE_LLC_MLC; 136797ef1bddSDaniel Vetter if (gfdt) 136897ef1bddSDaniel Vetter pte_flags |= GEN6_PTE_GFDT; 136997ef1bddSDaniel Vetter } 137097ef1bddSDaniel Vetter 137197ef1bddSDaniel Vetter /* gen6 has bit11-4 for physical addr bit39-32 */ 137297ef1bddSDaniel Vetter addr |= (addr >> 28) & 0xff0; 137397ef1bddSDaniel Vetter writel(addr | pte_flags, intel_private.gtt + entry); 137497ef1bddSDaniel Vetter } 137597ef1bddSDaniel Vetter 13762d2430cfSDaniel Vetter static int i9xx_setup(void) 13772d2430cfSDaniel Vetter { 13782d2430cfSDaniel Vetter u32 reg_addr; 13792d2430cfSDaniel Vetter 13802d2430cfSDaniel Vetter pci_read_config_dword(intel_private.pcidev, I915_MMADDR, ®_addr); 13812d2430cfSDaniel Vetter 13822d2430cfSDaniel Vetter reg_addr &= 0xfff80000; 13832d2430cfSDaniel Vetter 13842d2430cfSDaniel Vetter intel_private.registers = ioremap(reg_addr, 128 * 4096); 13852d2430cfSDaniel Vetter if (!intel_private.registers) 13862d2430cfSDaniel Vetter return -ENOMEM; 13872d2430cfSDaniel Vetter 13882d2430cfSDaniel Vetter if (INTEL_GTT_GEN == 3) { 13892d2430cfSDaniel Vetter u32 gtt_addr; 13903f08e4efSChris Wilson 13912d2430cfSDaniel Vetter pci_read_config_dword(intel_private.pcidev, 13922d2430cfSDaniel Vetter I915_PTEADDR, >t_addr); 13932d2430cfSDaniel Vetter intel_private.gtt_bus_addr = gtt_addr; 13942d2430cfSDaniel Vetter } else { 13952d2430cfSDaniel Vetter u32 gtt_offset; 13962d2430cfSDaniel Vetter 13972d2430cfSDaniel Vetter switch (INTEL_GTT_GEN) { 13982d2430cfSDaniel Vetter case 5: 13992d2430cfSDaniel Vetter case 6: 14002d2430cfSDaniel Vetter gtt_offset = MB(2); 14012d2430cfSDaniel Vetter break; 14022d2430cfSDaniel Vetter case 4: 14032d2430cfSDaniel Vetter default: 14042d2430cfSDaniel Vetter gtt_offset = KB(512); 14052d2430cfSDaniel Vetter break; 14062d2430cfSDaniel Vetter } 14072d2430cfSDaniel Vetter intel_private.gtt_bus_addr = reg_addr + gtt_offset; 14082d2430cfSDaniel Vetter } 14092d2430cfSDaniel Vetter 14103f08e4efSChris Wilson intel_private.pte_bus_addr = 14113f08e4efSChris Wilson readl(intel_private.registers+I810_PGETBL_CTL) & 0xfffff000; 14123f08e4efSChris Wilson 14132d2430cfSDaniel Vetter intel_i9xx_setup_flush(); 14142d2430cfSDaniel Vetter 14152d2430cfSDaniel Vetter return 0; 14162d2430cfSDaniel Vetter } 14172d2430cfSDaniel Vetter 1418f51b7662SDaniel Vetter /* 1419f51b7662SDaniel Vetter * The i965 supports 36-bit physical addresses, but to keep 1420f51b7662SDaniel Vetter * the format of the GTT the same, the bits that don't fit 1421f51b7662SDaniel Vetter * in a 32-bit word are shifted down to bits 4..7. 1422f51b7662SDaniel Vetter * 1423f51b7662SDaniel Vetter * Gcc is smart enough to notice that "(addr >> 28) & 0xf0" 1424f51b7662SDaniel Vetter * is always zero on 32-bit architectures, so no need to make 1425f51b7662SDaniel Vetter * this conditional. 1426f51b7662SDaniel Vetter */ 1427f51b7662SDaniel Vetter static unsigned long intel_i965_mask_memory(struct agp_bridge_data *bridge, 1428f51b7662SDaniel Vetter dma_addr_t addr, int type) 1429f51b7662SDaniel Vetter { 1430f51b7662SDaniel Vetter /* Shift high bits down */ 1431f51b7662SDaniel Vetter addr |= (addr >> 28) & 0xf0; 1432f51b7662SDaniel Vetter 1433f51b7662SDaniel Vetter /* Type checking must be done elsewhere */ 1434f51b7662SDaniel Vetter return addr | bridge->driver->masks[type].mask; 1435f51b7662SDaniel Vetter } 1436f51b7662SDaniel Vetter 14373869d4a8SZhenyu Wang static unsigned long intel_gen6_mask_memory(struct agp_bridge_data *bridge, 14383869d4a8SZhenyu Wang dma_addr_t addr, int type) 14393869d4a8SZhenyu Wang { 14408dfc2b14SZhenyu Wang /* gen6 has bit11-4 for physical addr bit39-32 */ 14418dfc2b14SZhenyu Wang addr |= (addr >> 28) & 0xff0; 14423869d4a8SZhenyu Wang 14433869d4a8SZhenyu Wang /* Type checking must be done elsewhere */ 14443869d4a8SZhenyu Wang return addr | bridge->driver->masks[type].mask; 14453869d4a8SZhenyu Wang } 14463869d4a8SZhenyu Wang 1447f51b7662SDaniel Vetter static const struct agp_bridge_driver intel_810_driver = { 1448f51b7662SDaniel Vetter .owner = THIS_MODULE, 1449f51b7662SDaniel Vetter .aperture_sizes = intel_i810_sizes, 1450f51b7662SDaniel Vetter .size_type = FIXED_APER_SIZE, 1451f51b7662SDaniel Vetter .num_aperture_sizes = 2, 1452f51b7662SDaniel Vetter .needs_scratch_page = true, 1453f51b7662SDaniel Vetter .configure = intel_i810_configure, 1454f51b7662SDaniel Vetter .fetch_size = intel_i810_fetch_size, 1455f51b7662SDaniel Vetter .cleanup = intel_i810_cleanup, 1456f51b7662SDaniel Vetter .mask_memory = intel_i810_mask_memory, 1457f51b7662SDaniel Vetter .masks = intel_i810_masks, 1458ffdd7510SDaniel Vetter .agp_enable = intel_fake_agp_enable, 1459f51b7662SDaniel Vetter .cache_flush = global_cache_flush, 1460f51b7662SDaniel Vetter .create_gatt_table = agp_generic_create_gatt_table, 1461f51b7662SDaniel Vetter .free_gatt_table = agp_generic_free_gatt_table, 1462f51b7662SDaniel Vetter .insert_memory = intel_i810_insert_entries, 1463f51b7662SDaniel Vetter .remove_memory = intel_i810_remove_entries, 1464f51b7662SDaniel Vetter .alloc_by_type = intel_i810_alloc_by_type, 1465f51b7662SDaniel Vetter .free_by_type = intel_i810_free_by_type, 1466f51b7662SDaniel Vetter .agp_alloc_page = agp_generic_alloc_page, 1467f51b7662SDaniel Vetter .agp_alloc_pages = agp_generic_alloc_pages, 1468f51b7662SDaniel Vetter .agp_destroy_page = agp_generic_destroy_page, 1469f51b7662SDaniel Vetter .agp_destroy_pages = agp_generic_destroy_pages, 1470f51b7662SDaniel Vetter .agp_type_to_mask_type = agp_generic_type_to_mask_type, 1471f51b7662SDaniel Vetter }; 1472f51b7662SDaniel Vetter 1473f51b7662SDaniel Vetter static const struct agp_bridge_driver intel_830_driver = { 1474f51b7662SDaniel Vetter .owner = THIS_MODULE, 1475f51b7662SDaniel Vetter .size_type = FIXED_APER_SIZE, 14769e76e7b8SChris Wilson .aperture_sizes = intel_fake_agp_sizes, 14779e76e7b8SChris Wilson .num_aperture_sizes = ARRAY_SIZE(intel_fake_agp_sizes), 1478351bb278SDaniel Vetter .configure = intel_fake_agp_configure, 14793e921f98SDaniel Vetter .fetch_size = intel_fake_agp_fetch_size, 1480fdfb58a9SDaniel Vetter .cleanup = intel_gtt_cleanup, 1481f51b7662SDaniel Vetter .mask_memory = intel_i810_mask_memory, 1482f51b7662SDaniel Vetter .masks = intel_i810_masks, 1483ffdd7510SDaniel Vetter .agp_enable = intel_fake_agp_enable, 1484f51b7662SDaniel Vetter .cache_flush = global_cache_flush, 14853b15a9d7SDaniel Vetter .create_gatt_table = intel_fake_agp_create_gatt_table, 1486ffdd7510SDaniel Vetter .free_gatt_table = intel_fake_agp_free_gatt_table, 14875cbecafcSDaniel Vetter .insert_memory = intel_fake_agp_insert_entries, 14885cbecafcSDaniel Vetter .remove_memory = intel_fake_agp_remove_entries, 1489ffdd7510SDaniel Vetter .alloc_by_type = intel_fake_agp_alloc_by_type, 1490f51b7662SDaniel Vetter .free_by_type = intel_i810_free_by_type, 1491f51b7662SDaniel Vetter .agp_alloc_page = agp_generic_alloc_page, 1492f51b7662SDaniel Vetter .agp_alloc_pages = agp_generic_alloc_pages, 1493f51b7662SDaniel Vetter .agp_destroy_page = agp_generic_destroy_page, 1494f51b7662SDaniel Vetter .agp_destroy_pages = agp_generic_destroy_pages, 1495f51b7662SDaniel Vetter .agp_type_to_mask_type = intel_i830_type_to_mask_type, 1496f51b7662SDaniel Vetter .chipset_flush = intel_i830_chipset_flush, 1497f51b7662SDaniel Vetter }; 1498f51b7662SDaniel Vetter 1499f51b7662SDaniel Vetter static const struct agp_bridge_driver intel_915_driver = { 1500f51b7662SDaniel Vetter .owner = THIS_MODULE, 1501f51b7662SDaniel Vetter .size_type = FIXED_APER_SIZE, 15029e76e7b8SChris Wilson .aperture_sizes = intel_fake_agp_sizes, 15039e76e7b8SChris Wilson .num_aperture_sizes = ARRAY_SIZE(intel_fake_agp_sizes), 1504351bb278SDaniel Vetter .configure = intel_fake_agp_configure, 15053e921f98SDaniel Vetter .fetch_size = intel_fake_agp_fetch_size, 1506fdfb58a9SDaniel Vetter .cleanup = intel_gtt_cleanup, 1507f51b7662SDaniel Vetter .mask_memory = intel_i810_mask_memory, 1508f51b7662SDaniel Vetter .masks = intel_i810_masks, 1509ffdd7510SDaniel Vetter .agp_enable = intel_fake_agp_enable, 1510f51b7662SDaniel Vetter .cache_flush = global_cache_flush, 15113b15a9d7SDaniel Vetter .create_gatt_table = intel_fake_agp_create_gatt_table, 1512ffdd7510SDaniel Vetter .free_gatt_table = intel_fake_agp_free_gatt_table, 1513fefaa70fSDaniel Vetter .insert_memory = intel_fake_agp_insert_entries, 1514fefaa70fSDaniel Vetter .remove_memory = intel_fake_agp_remove_entries, 1515ffdd7510SDaniel Vetter .alloc_by_type = intel_fake_agp_alloc_by_type, 1516f51b7662SDaniel Vetter .free_by_type = intel_i810_free_by_type, 1517f51b7662SDaniel Vetter .agp_alloc_page = agp_generic_alloc_page, 1518f51b7662SDaniel Vetter .agp_alloc_pages = agp_generic_alloc_pages, 1519f51b7662SDaniel Vetter .agp_destroy_page = agp_generic_destroy_page, 1520f51b7662SDaniel Vetter .agp_destroy_pages = agp_generic_destroy_pages, 1521f51b7662SDaniel Vetter .agp_type_to_mask_type = intel_i830_type_to_mask_type, 1522f51b7662SDaniel Vetter .chipset_flush = intel_i915_chipset_flush, 1523f51b7662SDaniel Vetter }; 1524f51b7662SDaniel Vetter 1525f51b7662SDaniel Vetter static const struct agp_bridge_driver intel_i965_driver = { 1526f51b7662SDaniel Vetter .owner = THIS_MODULE, 1527f51b7662SDaniel Vetter .size_type = FIXED_APER_SIZE, 15289e76e7b8SChris Wilson .aperture_sizes = intel_fake_agp_sizes, 15299e76e7b8SChris Wilson .num_aperture_sizes = ARRAY_SIZE(intel_fake_agp_sizes), 1530a6963596SDaniel Vetter .configure = intel_fake_agp_configure, 15313e921f98SDaniel Vetter .fetch_size = intel_fake_agp_fetch_size, 1532fdfb58a9SDaniel Vetter .cleanup = intel_gtt_cleanup, 1533f51b7662SDaniel Vetter .mask_memory = intel_i965_mask_memory, 1534f51b7662SDaniel Vetter .masks = intel_i810_masks, 1535ffdd7510SDaniel Vetter .agp_enable = intel_fake_agp_enable, 1536f51b7662SDaniel Vetter .cache_flush = global_cache_flush, 15373b15a9d7SDaniel Vetter .create_gatt_table = intel_fake_agp_create_gatt_table, 1538ffdd7510SDaniel Vetter .free_gatt_table = intel_fake_agp_free_gatt_table, 1539f51b7662SDaniel Vetter .insert_memory = intel_i915_insert_entries, 1540f51b7662SDaniel Vetter .remove_memory = intel_i915_remove_entries, 1541ffdd7510SDaniel Vetter .alloc_by_type = intel_fake_agp_alloc_by_type, 1542f51b7662SDaniel Vetter .free_by_type = intel_i810_free_by_type, 1543f51b7662SDaniel Vetter .agp_alloc_page = agp_generic_alloc_page, 1544f51b7662SDaniel Vetter .agp_alloc_pages = agp_generic_alloc_pages, 1545f51b7662SDaniel Vetter .agp_destroy_page = agp_generic_destroy_page, 1546f51b7662SDaniel Vetter .agp_destroy_pages = agp_generic_destroy_pages, 1547f51b7662SDaniel Vetter .agp_type_to_mask_type = intel_i830_type_to_mask_type, 1548f51b7662SDaniel Vetter .chipset_flush = intel_i915_chipset_flush, 15490e87d2b0SDaniel Vetter #if USE_PCI_DMA_API 1550f51b7662SDaniel Vetter .agp_map_memory = intel_agp_map_memory, 1551f51b7662SDaniel Vetter .agp_unmap_memory = intel_agp_unmap_memory, 1552f51b7662SDaniel Vetter #endif 1553f51b7662SDaniel Vetter }; 1554f51b7662SDaniel Vetter 15553869d4a8SZhenyu Wang static const struct agp_bridge_driver intel_gen6_driver = { 15563869d4a8SZhenyu Wang .owner = THIS_MODULE, 15573869d4a8SZhenyu Wang .size_type = FIXED_APER_SIZE, 15589e76e7b8SChris Wilson .aperture_sizes = intel_fake_agp_sizes, 15599e76e7b8SChris Wilson .num_aperture_sizes = ARRAY_SIZE(intel_fake_agp_sizes), 156097ef1bddSDaniel Vetter .configure = intel_fake_agp_configure, 15613e921f98SDaniel Vetter .fetch_size = intel_fake_agp_fetch_size, 1562fdfb58a9SDaniel Vetter .cleanup = intel_gtt_cleanup, 15633869d4a8SZhenyu Wang .mask_memory = intel_gen6_mask_memory, 1564f8f235e5SZhenyu Wang .masks = intel_gen6_masks, 1565ffdd7510SDaniel Vetter .agp_enable = intel_fake_agp_enable, 15663869d4a8SZhenyu Wang .cache_flush = global_cache_flush, 15673b15a9d7SDaniel Vetter .create_gatt_table = intel_fake_agp_create_gatt_table, 1568ffdd7510SDaniel Vetter .free_gatt_table = intel_fake_agp_free_gatt_table, 15693869d4a8SZhenyu Wang .insert_memory = intel_i915_insert_entries, 15703869d4a8SZhenyu Wang .remove_memory = intel_i915_remove_entries, 1571ffdd7510SDaniel Vetter .alloc_by_type = intel_fake_agp_alloc_by_type, 15723869d4a8SZhenyu Wang .free_by_type = intel_i810_free_by_type, 15733869d4a8SZhenyu Wang .agp_alloc_page = agp_generic_alloc_page, 15743869d4a8SZhenyu Wang .agp_alloc_pages = agp_generic_alloc_pages, 15753869d4a8SZhenyu Wang .agp_destroy_page = agp_generic_destroy_page, 15763869d4a8SZhenyu Wang .agp_destroy_pages = agp_generic_destroy_pages, 1577f8f235e5SZhenyu Wang .agp_type_to_mask_type = intel_gen6_type_to_mask_type, 15783869d4a8SZhenyu Wang .chipset_flush = intel_i915_chipset_flush, 15790e87d2b0SDaniel Vetter #if USE_PCI_DMA_API 15803869d4a8SZhenyu Wang .agp_map_memory = intel_agp_map_memory, 15813869d4a8SZhenyu Wang .agp_unmap_memory = intel_agp_unmap_memory, 15823869d4a8SZhenyu Wang #endif 15833869d4a8SZhenyu Wang }; 15843869d4a8SZhenyu Wang 1585f51b7662SDaniel Vetter static const struct agp_bridge_driver intel_g33_driver = { 1586f51b7662SDaniel Vetter .owner = THIS_MODULE, 1587f51b7662SDaniel Vetter .size_type = FIXED_APER_SIZE, 15889e76e7b8SChris Wilson .aperture_sizes = intel_fake_agp_sizes, 15899e76e7b8SChris Wilson .num_aperture_sizes = ARRAY_SIZE(intel_fake_agp_sizes), 1590a6963596SDaniel Vetter .configure = intel_fake_agp_configure, 15913e921f98SDaniel Vetter .fetch_size = intel_fake_agp_fetch_size, 1592fdfb58a9SDaniel Vetter .cleanup = intel_gtt_cleanup, 1593f51b7662SDaniel Vetter .mask_memory = intel_i965_mask_memory, 1594f51b7662SDaniel Vetter .masks = intel_i810_masks, 1595ffdd7510SDaniel Vetter .agp_enable = intel_fake_agp_enable, 1596f51b7662SDaniel Vetter .cache_flush = global_cache_flush, 15973b15a9d7SDaniel Vetter .create_gatt_table = intel_fake_agp_create_gatt_table, 1598ffdd7510SDaniel Vetter .free_gatt_table = intel_fake_agp_free_gatt_table, 1599f51b7662SDaniel Vetter .insert_memory = intel_i915_insert_entries, 1600f51b7662SDaniel Vetter .remove_memory = intel_i915_remove_entries, 1601ffdd7510SDaniel Vetter .alloc_by_type = intel_fake_agp_alloc_by_type, 1602f51b7662SDaniel Vetter .free_by_type = intel_i810_free_by_type, 1603f51b7662SDaniel Vetter .agp_alloc_page = agp_generic_alloc_page, 1604f51b7662SDaniel Vetter .agp_alloc_pages = agp_generic_alloc_pages, 1605f51b7662SDaniel Vetter .agp_destroy_page = agp_generic_destroy_page, 1606f51b7662SDaniel Vetter .agp_destroy_pages = agp_generic_destroy_pages, 1607f51b7662SDaniel Vetter .agp_type_to_mask_type = intel_i830_type_to_mask_type, 1608f51b7662SDaniel Vetter .chipset_flush = intel_i915_chipset_flush, 16090e87d2b0SDaniel Vetter #if USE_PCI_DMA_API 1610f51b7662SDaniel Vetter .agp_map_memory = intel_agp_map_memory, 1611f51b7662SDaniel Vetter .agp_unmap_memory = intel_agp_unmap_memory, 1612f51b7662SDaniel Vetter #endif 1613f51b7662SDaniel Vetter }; 161402c026ceSDaniel Vetter 16151a997ff2SDaniel Vetter static const struct intel_gtt_driver i8xx_gtt_driver = { 16161a997ff2SDaniel Vetter .gen = 2, 161773800422SDaniel Vetter .setup = i830_setup, 1618351bb278SDaniel Vetter .write_entry = i830_write_entry, 16195cbecafcSDaniel Vetter .check_flags = i830_check_flags, 16201a997ff2SDaniel Vetter }; 16211a997ff2SDaniel Vetter static const struct intel_gtt_driver i915_gtt_driver = { 16221a997ff2SDaniel Vetter .gen = 3, 16232d2430cfSDaniel Vetter .setup = i9xx_setup, 1624351bb278SDaniel Vetter /* i945 is the last gpu to need phys mem (for overlay and cursors). */ 1625351bb278SDaniel Vetter .write_entry = i830_write_entry, 1626fefaa70fSDaniel Vetter .check_flags = i830_check_flags, 16271a997ff2SDaniel Vetter }; 16281a997ff2SDaniel Vetter static const struct intel_gtt_driver g33_gtt_driver = { 16291a997ff2SDaniel Vetter .gen = 3, 16301a997ff2SDaniel Vetter .is_g33 = 1, 16312d2430cfSDaniel Vetter .setup = i9xx_setup, 1632a6963596SDaniel Vetter .write_entry = i965_write_entry, 16331a997ff2SDaniel Vetter }; 16341a997ff2SDaniel Vetter static const struct intel_gtt_driver pineview_gtt_driver = { 16351a997ff2SDaniel Vetter .gen = 3, 16361a997ff2SDaniel Vetter .is_pineview = 1, .is_g33 = 1, 16372d2430cfSDaniel Vetter .setup = i9xx_setup, 1638a6963596SDaniel Vetter .write_entry = i965_write_entry, 16391a997ff2SDaniel Vetter }; 16401a997ff2SDaniel Vetter static const struct intel_gtt_driver i965_gtt_driver = { 16411a997ff2SDaniel Vetter .gen = 4, 16422d2430cfSDaniel Vetter .setup = i9xx_setup, 1643a6963596SDaniel Vetter .write_entry = i965_write_entry, 16441a997ff2SDaniel Vetter }; 16451a997ff2SDaniel Vetter static const struct intel_gtt_driver g4x_gtt_driver = { 16461a997ff2SDaniel Vetter .gen = 5, 16472d2430cfSDaniel Vetter .setup = i9xx_setup, 1648a6963596SDaniel Vetter .write_entry = i965_write_entry, 16491a997ff2SDaniel Vetter }; 16501a997ff2SDaniel Vetter static const struct intel_gtt_driver ironlake_gtt_driver = { 16511a997ff2SDaniel Vetter .gen = 5, 16521a997ff2SDaniel Vetter .is_ironlake = 1, 16532d2430cfSDaniel Vetter .setup = i9xx_setup, 1654a6963596SDaniel Vetter .write_entry = i965_write_entry, 16551a997ff2SDaniel Vetter }; 16561a997ff2SDaniel Vetter static const struct intel_gtt_driver sandybridge_gtt_driver = { 16571a997ff2SDaniel Vetter .gen = 6, 16582d2430cfSDaniel Vetter .setup = i9xx_setup, 165997ef1bddSDaniel Vetter .write_entry = gen6_write_entry, 16601a997ff2SDaniel Vetter }; 16611a997ff2SDaniel Vetter 166202c026ceSDaniel Vetter /* Table to describe Intel GMCH and AGP/PCIE GART drivers. At least one of 166302c026ceSDaniel Vetter * driver and gmch_driver must be non-null, and find_gmch will determine 166402c026ceSDaniel Vetter * which one should be used if a gmch_chip_id is present. 166502c026ceSDaniel Vetter */ 166602c026ceSDaniel Vetter static const struct intel_gtt_driver_description { 166702c026ceSDaniel Vetter unsigned int gmch_chip_id; 166802c026ceSDaniel Vetter char *name; 166902c026ceSDaniel Vetter const struct agp_bridge_driver *gmch_driver; 16701a997ff2SDaniel Vetter const struct intel_gtt_driver *gtt_driver; 167102c026ceSDaniel Vetter } intel_gtt_chipsets[] = { 16721a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_82810_IG1, "i810", &intel_810_driver , NULL}, 16731a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_82810_IG3, "i810", &intel_810_driver , NULL}, 16741a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_82810E_IG, "i810", &intel_810_driver , NULL}, 16751a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_82815_CGC, "i815", &intel_810_driver , NULL}, 16761a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_82830_CGC, "830M", 16771a997ff2SDaniel Vetter &intel_830_driver , &i8xx_gtt_driver}, 16781a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_82845G_IG, "830M", 16791a997ff2SDaniel Vetter &intel_830_driver , &i8xx_gtt_driver}, 16801a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_82854_IG, "854", 16811a997ff2SDaniel Vetter &intel_830_driver , &i8xx_gtt_driver}, 16821a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_82855GM_IG, "855GM", 16831a997ff2SDaniel Vetter &intel_830_driver , &i8xx_gtt_driver}, 16841a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_82865_IG, "865", 16851a997ff2SDaniel Vetter &intel_830_driver , &i8xx_gtt_driver}, 16861a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_E7221_IG, "E7221 (i915)", 16871a997ff2SDaniel Vetter &intel_915_driver , &i915_gtt_driver }, 16881a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_82915G_IG, "915G", 16891a997ff2SDaniel Vetter &intel_915_driver , &i915_gtt_driver }, 16901a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_82915GM_IG, "915GM", 16911a997ff2SDaniel Vetter &intel_915_driver , &i915_gtt_driver }, 16921a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_82945G_IG, "945G", 16931a997ff2SDaniel Vetter &intel_915_driver , &i915_gtt_driver }, 16941a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_82945GM_IG, "945GM", 16951a997ff2SDaniel Vetter &intel_915_driver , &i915_gtt_driver }, 16961a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_82945GME_IG, "945GME", 16971a997ff2SDaniel Vetter &intel_915_driver , &i915_gtt_driver }, 16981a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_82946GZ_IG, "946GZ", 16991a997ff2SDaniel Vetter &intel_i965_driver , &i965_gtt_driver }, 17001a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_82G35_IG, "G35", 17011a997ff2SDaniel Vetter &intel_i965_driver , &i965_gtt_driver }, 17021a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_82965Q_IG, "965Q", 17031a997ff2SDaniel Vetter &intel_i965_driver , &i965_gtt_driver }, 17041a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_82965G_IG, "965G", 17051a997ff2SDaniel Vetter &intel_i965_driver , &i965_gtt_driver }, 17061a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_82965GM_IG, "965GM", 17071a997ff2SDaniel Vetter &intel_i965_driver , &i965_gtt_driver }, 17081a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_82965GME_IG, "965GME/GLE", 17091a997ff2SDaniel Vetter &intel_i965_driver , &i965_gtt_driver }, 17101a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_G33_IG, "G33", 17111a997ff2SDaniel Vetter &intel_g33_driver , &g33_gtt_driver }, 17121a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_Q35_IG, "Q35", 17131a997ff2SDaniel Vetter &intel_g33_driver , &g33_gtt_driver }, 17141a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_Q33_IG, "Q33", 17151a997ff2SDaniel Vetter &intel_g33_driver , &g33_gtt_driver }, 17161a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_PINEVIEW_M_IG, "GMA3150", 17171a997ff2SDaniel Vetter &intel_g33_driver , &pineview_gtt_driver }, 17181a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_PINEVIEW_IG, "GMA3150", 17191a997ff2SDaniel Vetter &intel_g33_driver , &pineview_gtt_driver }, 17201a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_GM45_IG, "GM45", 17211a997ff2SDaniel Vetter &intel_i965_driver , &g4x_gtt_driver }, 17221a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_EAGLELAKE_IG, "Eaglelake", 17231a997ff2SDaniel Vetter &intel_i965_driver , &g4x_gtt_driver }, 17241a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_Q45_IG, "Q45/Q43", 17251a997ff2SDaniel Vetter &intel_i965_driver , &g4x_gtt_driver }, 17261a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_G45_IG, "G45/G43", 17271a997ff2SDaniel Vetter &intel_i965_driver , &g4x_gtt_driver }, 17281a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_B43_IG, "B43", 17291a997ff2SDaniel Vetter &intel_i965_driver , &g4x_gtt_driver }, 1730e9e5f8e8SChris Wilson { PCI_DEVICE_ID_INTEL_B43_1_IG, "B43", 1731e9e5f8e8SChris Wilson &intel_i965_driver , &g4x_gtt_driver }, 17321a997ff2SDaniel Vetter { PCI_DEVICE_ID_INTEL_G41_IG, "G41", 17331a997ff2SDaniel Vetter &intel_i965_driver , &g4x_gtt_driver }, 173402c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_IRONLAKE_D_IG, 17351a997ff2SDaniel Vetter "HD Graphics", &intel_i965_driver , &ironlake_gtt_driver }, 173602c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG, 17371a997ff2SDaniel Vetter "HD Graphics", &intel_i965_driver , &ironlake_gtt_driver }, 173802c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT1_IG, 17391a997ff2SDaniel Vetter "Sandybridge", &intel_gen6_driver , &sandybridge_gtt_driver }, 174002c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_IG, 17411a997ff2SDaniel Vetter "Sandybridge", &intel_gen6_driver , &sandybridge_gtt_driver }, 174202c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_PLUS_IG, 17431a997ff2SDaniel Vetter "Sandybridge", &intel_gen6_driver , &sandybridge_gtt_driver }, 174402c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT1_IG, 17451a997ff2SDaniel Vetter "Sandybridge", &intel_gen6_driver , &sandybridge_gtt_driver }, 174602c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_IG, 17471a997ff2SDaniel Vetter "Sandybridge", &intel_gen6_driver , &sandybridge_gtt_driver }, 174802c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_PLUS_IG, 17491a997ff2SDaniel Vetter "Sandybridge", &intel_gen6_driver , &sandybridge_gtt_driver }, 175002c026ceSDaniel Vetter { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_IG, 17511a997ff2SDaniel Vetter "Sandybridge", &intel_gen6_driver , &sandybridge_gtt_driver }, 175202c026ceSDaniel Vetter { 0, NULL, NULL } 175302c026ceSDaniel Vetter }; 175402c026ceSDaniel Vetter 175502c026ceSDaniel Vetter static int find_gmch(u16 device) 175602c026ceSDaniel Vetter { 175702c026ceSDaniel Vetter struct pci_dev *gmch_device; 175802c026ceSDaniel Vetter 175902c026ceSDaniel Vetter gmch_device = pci_get_device(PCI_VENDOR_ID_INTEL, device, NULL); 176002c026ceSDaniel Vetter if (gmch_device && PCI_FUNC(gmch_device->devfn) != 0) { 176102c026ceSDaniel Vetter gmch_device = pci_get_device(PCI_VENDOR_ID_INTEL, 176202c026ceSDaniel Vetter device, gmch_device); 176302c026ceSDaniel Vetter } 176402c026ceSDaniel Vetter 176502c026ceSDaniel Vetter if (!gmch_device) 176602c026ceSDaniel Vetter return 0; 176702c026ceSDaniel Vetter 176802c026ceSDaniel Vetter intel_private.pcidev = gmch_device; 176902c026ceSDaniel Vetter return 1; 177002c026ceSDaniel Vetter } 177102c026ceSDaniel Vetter 1772e2404e7cSDaniel Vetter int intel_gmch_probe(struct pci_dev *pdev, 177302c026ceSDaniel Vetter struct agp_bridge_data *bridge) 177402c026ceSDaniel Vetter { 177502c026ceSDaniel Vetter int i, mask; 177602c026ceSDaniel Vetter bridge->driver = NULL; 177702c026ceSDaniel Vetter 177802c026ceSDaniel Vetter for (i = 0; intel_gtt_chipsets[i].name != NULL; i++) { 177902c026ceSDaniel Vetter if (find_gmch(intel_gtt_chipsets[i].gmch_chip_id)) { 178002c026ceSDaniel Vetter bridge->driver = 178102c026ceSDaniel Vetter intel_gtt_chipsets[i].gmch_driver; 17821a997ff2SDaniel Vetter intel_private.driver = 17831a997ff2SDaniel Vetter intel_gtt_chipsets[i].gtt_driver; 178402c026ceSDaniel Vetter break; 178502c026ceSDaniel Vetter } 178602c026ceSDaniel Vetter } 178702c026ceSDaniel Vetter 178802c026ceSDaniel Vetter if (!bridge->driver) 178902c026ceSDaniel Vetter return 0; 179002c026ceSDaniel Vetter 179102c026ceSDaniel Vetter bridge->dev_private_data = &intel_private; 179202c026ceSDaniel Vetter bridge->dev = pdev; 179302c026ceSDaniel Vetter 1794d7cca2f7SDaniel Vetter intel_private.bridge_dev = pci_dev_get(pdev); 1795d7cca2f7SDaniel Vetter 179602c026ceSDaniel Vetter dev_info(&pdev->dev, "Intel %s Chipset\n", intel_gtt_chipsets[i].name); 179702c026ceSDaniel Vetter 179802c026ceSDaniel Vetter if (bridge->driver->mask_memory == intel_gen6_mask_memory) 179902c026ceSDaniel Vetter mask = 40; 180002c026ceSDaniel Vetter else if (bridge->driver->mask_memory == intel_i965_mask_memory) 180102c026ceSDaniel Vetter mask = 36; 180202c026ceSDaniel Vetter else 180302c026ceSDaniel Vetter mask = 32; 180402c026ceSDaniel Vetter 180502c026ceSDaniel Vetter if (pci_set_dma_mask(intel_private.pcidev, DMA_BIT_MASK(mask))) 180602c026ceSDaniel Vetter dev_err(&intel_private.pcidev->dev, 180702c026ceSDaniel Vetter "set gfx device dma mask %d-bit failed!\n", mask); 180802c026ceSDaniel Vetter else 180902c026ceSDaniel Vetter pci_set_consistent_dma_mask(intel_private.pcidev, 181002c026ceSDaniel Vetter DMA_BIT_MASK(mask)); 181102c026ceSDaniel Vetter 18121784a5fbSDaniel Vetter if (bridge->driver == &intel_810_driver) 18131784a5fbSDaniel Vetter return 1; 18141784a5fbSDaniel Vetter 18153b15a9d7SDaniel Vetter if (intel_gtt_init() != 0) 18163b15a9d7SDaniel Vetter return 0; 18171784a5fbSDaniel Vetter 181802c026ceSDaniel Vetter return 1; 181902c026ceSDaniel Vetter } 1820e2404e7cSDaniel Vetter EXPORT_SYMBOL(intel_gmch_probe); 182102c026ceSDaniel Vetter 182219966754SDaniel Vetter struct intel_gtt *intel_gtt_get(void) 182319966754SDaniel Vetter { 182419966754SDaniel Vetter return &intel_private.base; 182519966754SDaniel Vetter } 182619966754SDaniel Vetter EXPORT_SYMBOL(intel_gtt_get); 182719966754SDaniel Vetter 1828e2404e7cSDaniel Vetter void intel_gmch_remove(struct pci_dev *pdev) 182902c026ceSDaniel Vetter { 183002c026ceSDaniel Vetter if (intel_private.pcidev) 183102c026ceSDaniel Vetter pci_dev_put(intel_private.pcidev); 1832d7cca2f7SDaniel Vetter if (intel_private.bridge_dev) 1833d7cca2f7SDaniel Vetter pci_dev_put(intel_private.bridge_dev); 183402c026ceSDaniel Vetter } 1835e2404e7cSDaniel Vetter EXPORT_SYMBOL(intel_gmch_remove); 1836e2404e7cSDaniel Vetter 1837e2404e7cSDaniel Vetter MODULE_AUTHOR("Dave Jones <davej@redhat.com>"); 1838e2404e7cSDaniel Vetter MODULE_LICENSE("GPL and additional rights"); 1839