intel-gtt: consolidate i830 setup
[linux-block.git] / drivers / char / agp / intel-gtt.c
index 79eb106c6f08bc5f765ef234de6ae45c0d13f3fd..fd977aa4a17dc0828b12692cff1bd78622d68a6d 100644 (file)
@@ -81,11 +81,23 @@ static struct gatt_mask intel_gen6_masks[] =
          .type = INTEL_AGP_CACHED_MEMORY_LLC_MLC_GFDT },
 };
 
+struct intel_gtt_driver {
+       unsigned int gen : 8;
+       unsigned int is_g33 : 1;
+       unsigned int is_pineview : 1;
+       unsigned int is_ironlake : 1;
+       /* Chipset specific GTT setup */
+       int (*setup)(void);
+};
+
 static struct _intel_private {
        struct intel_gtt base;
+       const struct intel_gtt_driver *driver;
        struct pci_dev *pcidev; /* device one */
        struct pci_dev *bridge_dev;
        u8 __iomem *registers;
+       phys_addr_t gtt_bus_addr;
+       phys_addr_t gma_bus_addr;
        u32 __iomem *gtt;               /* I915G */
        int num_dcache_entries;
        union {
@@ -97,6 +109,11 @@ static struct _intel_private {
        int resource_valid;
 } intel_private;
 
+#define INTEL_GTT_GEN  intel_private.driver->gen
+#define IS_G33         intel_private.driver->is_g33
+#define IS_PINEVIEW    intel_private.driver->is_pineview
+#define IS_IRONLAKE    intel_private.driver->is_ironlake
+
 #ifdef USE_PCI_DMA_API
 static int intel_agp_map_page(struct page *page, dma_addr_t *ret)
 {
@@ -292,7 +309,7 @@ static void intel_i810_cleanup(void)
        iounmap(intel_private.registers);
 }
 
-static void intel_i810_agp_enable(struct agp_bridge_data *bridge, u32 mode)
+static void intel_fake_agp_enable(struct agp_bridge_data *bridge, u32 mode)
 {
        return;
 }
@@ -522,7 +539,7 @@ static unsigned long intel_i810_mask_memory(struct agp_bridge_data *bridge,
        return addr | bridge->driver->masks[type].mask;
 }
 
-static struct aper_size_info_fixed intel_i830_sizes[] =
+static struct aper_size_info_fixed intel_fake_agp_sizes[] =
 {
        {128, 32768, 5},
        /* The 64M mode still requires a 128k gatt */
@@ -537,76 +554,19 @@ static unsigned int intel_gtt_stolen_entries(void)
        u8 rdct;
        int local = 0;
        static const int ddt[4] = { 0, 16, 32, 64 };
-       int size; /* reserved space (in kb) at the top of stolen memory */
        unsigned int overhead_entries, stolen_entries;
        unsigned int stolen_size = 0;
 
        pci_read_config_word(intel_private.bridge_dev,
                             I830_GMCH_CTRL, &gmch_ctrl);
 
-       if (IS_I965) {
-               u32 pgetbl_ctl;
-               pgetbl_ctl = readl(intel_private.registers+I810_PGETBL_CTL);
-
-               /* The 965 has a field telling us the size of the GTT,
-                * which may be larger than what is necessary to map the
-                * aperture.
-                */
-               switch (pgetbl_ctl & I965_PGETBL_SIZE_MASK) {
-               case I965_PGETBL_SIZE_128KB:
-                       size = 128;
-                       break;
-               case I965_PGETBL_SIZE_256KB:
-                       size = 256;
-                       break;
-               case I965_PGETBL_SIZE_512KB:
-                       size = 512;
-                       break;
-               case I965_PGETBL_SIZE_1MB:
-                       size = 1024;
-                       break;
-               case I965_PGETBL_SIZE_2MB:
-                       size = 2048;
-                       break;
-               case I965_PGETBL_SIZE_1_5MB:
-                       size = 1024 + 512;
-                       break;
-               default:
-                       dev_info(&intel_private.pcidev->dev,
-                                "unknown page table size, assuming 512KB\n");
-                       size = 512;
-               }
-               size += 4; /* add in BIOS popup space */
-       } else if (IS_G33 && !IS_PINEVIEW) {
-       /* G33's GTT size defined in gmch_ctrl */
-               switch (gmch_ctrl & G33_PGETBL_SIZE_MASK) {
-               case G33_PGETBL_SIZE_1M:
-                       size = 1024;
-                       break;
-               case G33_PGETBL_SIZE_2M:
-                       size = 2048;
-                       break;
-               default:
-                       dev_info(&intel_private.bridge_dev->dev,
-                                "unknown page table size 0x%x, assuming 512KB\n",
-                               (gmch_ctrl & G33_PGETBL_SIZE_MASK));
-                       size = 512;
-               }
-               size += 4;
-       } else if (IS_G4X || IS_PINEVIEW) {
-               /* On 4 series hardware, GTT stolen is separate from graphics
-                * stolen, ignore it in stolen gtt entries counting.  However,
-                * 4KB of the stolen memory doesn't get mapped to the GTT.
-                */
-               size = 4;
-       } else {
-               /* On previous hardware, the GTT size was just what was
-                * required to map the aperture.
-                */
-               size = agp_bridge->driver->fetch_size() + 4;
-       }
+       if (INTEL_GTT_GEN > 4 || IS_PINEVIEW)
+               overhead_entries = 0;
+       else
+               overhead_entries = intel_private.base.gtt_mappable_entries
+                       / 1024;
 
-       overhead_entries = size/4;
+       overhead_entries += 1; /* BIOS popup */
 
        if (intel_private.bridge_dev->device == PCI_DEVICE_ID_INTEL_82830_HB ||
            intel_private.bridge_dev->device == PCI_DEVICE_ID_INTEL_82845G_HB) {
@@ -630,7 +590,7 @@ static unsigned int intel_gtt_stolen_entries(void)
                        stolen_size = 0;
                        break;
                }
-       } else if (IS_SNB) {
+       } else if (INTEL_GTT_GEN == 6) {
                /*
                 * SandyBridge has new memory control reg at 0x50.w
                 */
@@ -704,54 +664,28 @@ static unsigned int intel_gtt_stolen_entries(void)
                        stolen_size = MB(32);
                        break;
                case I915_GMCH_GMS_STOLEN_48M:
-                       /* Check it's really I915G */
-                       if (IS_I915 || IS_I965 || IS_G33 || IS_G4X)
-                               stolen_size = MB(48);
-                       else
-                               stolen_size = 0;
+                       stolen_size = MB(48);
                        break;
                case I915_GMCH_GMS_STOLEN_64M:
-                       /* Check it's really I915G */
-                       if (IS_I915 || IS_I965 || IS_G33 || IS_G4X)
-                               stolen_size = MB(64);
-                       else
-                               stolen_size = 0;
+                       stolen_size = MB(64);
                        break;
                case G33_GMCH_GMS_STOLEN_128M:
-                       if (IS_G33 || IS_I965 || IS_G4X)
-                               stolen_size = MB(128);
-                       else
-                               stolen_size = 0;
+                       stolen_size = MB(128);
                        break;
                case G33_GMCH_GMS_STOLEN_256M:
-                       if (IS_G33 || IS_I965 || IS_G4X)
-                               stolen_size = MB(256);
-                       else
-                               stolen_size = 0;
+                       stolen_size = MB(256);
                        break;
                case INTEL_GMCH_GMS_STOLEN_96M:
-                       if (IS_I965 || IS_G4X)
-                               stolen_size = MB(96);
-                       else
-                               stolen_size = 0;
+                       stolen_size = MB(96);
                        break;
                case INTEL_GMCH_GMS_STOLEN_160M:
-                       if (IS_I965 || IS_G4X)
-                               stolen_size = MB(160);
-                       else
-                               stolen_size = 0;
+                       stolen_size = MB(160);
                        break;
                case INTEL_GMCH_GMS_STOLEN_224M:
-                       if (IS_I965 || IS_G4X)
-                               stolen_size = MB(224);
-                       else
-                               stolen_size = 0;
+                       stolen_size = MB(224);
                        break;
                case INTEL_GMCH_GMS_STOLEN_352M:
-                       if (IS_I965 || IS_G4X)
-                               stolen_size = MB(352);
-                       else
-                               stolen_size = 0;
+                       stolen_size = MB(352);
                        break;
                default:
                        stolen_size = 0;
@@ -778,6 +712,66 @@ static unsigned int intel_gtt_stolen_entries(void)
        return stolen_entries;
 }
 
+static unsigned int intel_gtt_total_entries(void)
+{
+       int size;
+
+       if (IS_G33 || INTEL_GTT_GEN == 4 || INTEL_GTT_GEN == 5) {
+               u32 pgetbl_ctl;
+               pgetbl_ctl = readl(intel_private.registers+I810_PGETBL_CTL);
+
+               switch (pgetbl_ctl & I965_PGETBL_SIZE_MASK) {
+               case I965_PGETBL_SIZE_128KB:
+                       size = KB(128);
+                       break;
+               case I965_PGETBL_SIZE_256KB:
+                       size = KB(256);
+                       break;
+               case I965_PGETBL_SIZE_512KB:
+                       size = KB(512);
+                       break;
+               case I965_PGETBL_SIZE_1MB:
+                       size = KB(1024);
+                       break;
+               case I965_PGETBL_SIZE_2MB:
+                       size = KB(2048);
+                       break;
+               case I965_PGETBL_SIZE_1_5MB:
+                       size = KB(1024 + 512);
+                       break;
+               default:
+                       dev_info(&intel_private.pcidev->dev,
+                                "unknown page table size, assuming 512KB\n");
+                       size = KB(512);
+               }
+
+               return size/4;
+       } else if (INTEL_GTT_GEN == 6) {
+               u16 snb_gmch_ctl;
+
+               pci_read_config_word(intel_private.pcidev, SNB_GMCH_CTRL, &snb_gmch_ctl);
+               switch (snb_gmch_ctl & SNB_GTT_SIZE_MASK) {
+               default:
+               case SNB_GTT_SIZE_0M:
+                       printk(KERN_ERR "Bad GTT size mask: 0x%04x.\n", snb_gmch_ctl);
+                       size = MB(0);
+                       break;
+               case SNB_GTT_SIZE_1M:
+                       size = MB(1);
+                       break;
+               case SNB_GTT_SIZE_2M:
+                       size = MB(2);
+                       break;
+               }
+               return size/4;
+       } else {
+               /* On previous hardware, the GTT size was just what was
+                * required to map the aperture.
+                */
+               return intel_private.base.gtt_mappable_entries;
+       }
+}
+
 static unsigned int intel_gtt_mappable_entries(void)
 {
        unsigned int aperture_size;
@@ -809,10 +803,27 @@ static unsigned int intel_gtt_mappable_entries(void)
 
 static int intel_gtt_init(void)
 {
+       u32 gtt_map_size;
+
+       intel_private.base.gtt_mappable_entries = intel_gtt_mappable_entries();
+       intel_private.base.gtt_total_entries = intel_gtt_total_entries();
+
+       gtt_map_size = intel_private.base.gtt_total_entries * 4;
+
+       intel_private.gtt = ioremap(intel_private.gtt_bus_addr,
+                                   gtt_map_size);
+       if (!intel_private.gtt) {
+               iounmap(intel_private.registers);
+               return -ENOMEM;
+       }
+
+       global_cache_flush();   /* FIXME: ? */
+
        /* we have to call this as early as possible after the MMIO base address is known */
        intel_private.base.gtt_stolen_entries = intel_gtt_stolen_entries();
        if (intel_private.base.gtt_stolen_entries == 0) {
                iounmap(intel_private.registers);
+               iounmap(intel_private.gtt);
                return -ENOMEM;
        }
 
@@ -823,14 +834,14 @@ static int intel_fake_agp_fetch_size(void)
 {
        unsigned int aper_size;
        int i;
-       int num_sizes = ARRAY_SIZE(intel_i830_sizes);
+       int num_sizes = ARRAY_SIZE(intel_fake_agp_sizes);
 
        aper_size = (intel_private.base.gtt_mappable_entries << PAGE_SHIFT)
                    / MB(1);
 
        for (i = 0; i < num_sizes; i++) {
-               if (aper_size == intel_i830_sizes[i].size) {
-                       agp_bridge->current_size = intel_i830_sizes + i;
+               if (aper_size == intel_fake_agp_sizes[i].size) {
+                       agp_bridge->current_size = intel_fake_agp_sizes + i;
                        return aper_size;
                }
        }
@@ -885,38 +896,60 @@ static void intel_i830_chipset_flush(struct agp_bridge_data *bridge)
                printk(KERN_ERR "Timed out waiting for cache flush.\n");
 }
 
-/* The intel i830 automatically initializes the agp aperture during POST.
- * Use the memory already set aside for in the GTT.
- */
-static int intel_i830_create_gatt_table(struct agp_bridge_data *bridge)
+static void intel_enable_gtt(void)
 {
-       int page_order, ret;
-       struct aper_size_info_fixed *size;
-       int num_entries;
-       u32 temp;
+       u32 ptetbl_addr, gma_addr;
+       u16 gmch_ctrl;
 
-       size = agp_bridge->current_size;
-       page_order = size->page_order;
-       num_entries = size->num_entries;
-       agp_bridge->gatt_table_real = NULL;
+       ptetbl_addr = readl(intel_private.registers+I810_PGETBL_CTL) & 0xfffff000;
 
-       pci_read_config_dword(intel_private.pcidev, I810_MMADDR, &temp);
-       temp &= 0xfff80000;
+       pci_read_config_dword(intel_private.pcidev, I810_GMADDR, &gma_addr);
+       intel_private.gma_bus_addr = (gma_addr & PCI_BASE_ADDRESS_MEM_MASK);
 
-       intel_private.registers = ioremap(temp, 128 * 4096);
+       pci_read_config_word(intel_private.bridge_dev, I830_GMCH_CTRL, &gmch_ctrl);
+       gmch_ctrl |= I830_GMCH_ENABLED;
+       pci_write_config_word(intel_private.bridge_dev, I830_GMCH_CTRL, gmch_ctrl);
+
+       writel(ptetbl_addr|I810_PGETBL_ENABLED, intel_private.registers+I810_PGETBL_CTL);
+       readl(intel_private.registers+I810_PGETBL_CTL); /* PCI Posting. */
+}
+
+static int i830_setup(void)
+{
+       u32 reg_addr;
+
+       pci_read_config_dword(intel_private.pcidev, I810_MMADDR, &reg_addr);
+       reg_addr &= 0xfff80000;
+
+       intel_private.registers = ioremap(reg_addr, KB(64));
        if (!intel_private.registers)
                return -ENOMEM;
 
-       temp = readl(intel_private.registers+I810_PGETBL_CTL) & 0xfffff000;
-       global_cache_flush();   /* FIXME: ?? */
+       intel_private.gtt_bus_addr = reg_addr + I810_PTE_BASE;
+
+       intel_i830_setup_flush();
+
+       return 0;
+}
+
+/* The intel i830 automatically initializes the agp aperture during POST.
+ * Use the memory already set aside for in the GTT.
+ */
+static int intel_i830_create_gatt_table(struct agp_bridge_data *bridge)
+{
+       int ret;
+
+       ret = intel_private.driver->setup();
+       if (ret != 0)
+               return ret;
 
        ret = intel_gtt_init();
        if (ret != 0)
                return ret;
 
+       agp_bridge->gatt_table_real = NULL;
        agp_bridge->gatt_table = NULL;
-
-       agp_bridge->gatt_bus_addr = temp;
+       agp_bridge->gatt_bus_addr = 0;
 
        return 0;
 }
@@ -924,48 +957,32 @@ static int intel_i830_create_gatt_table(struct agp_bridge_data *bridge)
 /* Return the gatt table to a sane state. Use the top of stolen
  * memory for the GTT.
  */
-static int intel_i830_free_gatt_table(struct agp_bridge_data *bridge)
+static int intel_fake_agp_free_gatt_table(struct agp_bridge_data *bridge)
 {
        return 0;
 }
 
 static int intel_i830_configure(void)
 {
-       struct aper_size_info_fixed *current_size;
-       u32 temp;
-       u16 gmch_ctrl;
        int i;
 
-       current_size = A_SIZE_FIX(agp_bridge->current_size);
+       intel_enable_gtt();
 
-       pci_read_config_dword(intel_private.pcidev, I810_GMADDR, &temp);
-       agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
-
-       pci_read_config_word(intel_private.bridge_dev, I830_GMCH_CTRL, &gmch_ctrl);
-       gmch_ctrl |= I830_GMCH_ENABLED;
-       pci_write_config_word(intel_private.bridge_dev, I830_GMCH_CTRL, gmch_ctrl);
-
-       writel(agp_bridge->gatt_bus_addr|I810_PGETBL_ENABLED, intel_private.registers+I810_PGETBL_CTL);
-       readl(intel_private.registers+I810_PGETBL_CTL); /* PCI Posting. */
+       agp_bridge->gart_bus_addr = intel_private.gma_bus_addr;
 
        if (agp_bridge->driver->needs_scratch_page) {
-               for (i = intel_private.base.gtt_stolen_entries; i < current_size->num_entries; i++) {
-                       writel(agp_bridge->scratch_page, intel_private.registers+I810_PTE_BASE+(i*4));
+               for (i = intel_private.base.gtt_stolen_entries;
+                               i < intel_private.base.gtt_total_entries; i++) {
+                       writel(agp_bridge->scratch_page, intel_private.gtt+i);
                }
-               readl(intel_private.registers+I810_PTE_BASE+((i-1)*4)); /* PCI Posting. */
+               readl(intel_private.gtt+i-1);   /* PCI Posting. */
        }
 
        global_cache_flush();
 
-       intel_i830_setup_flush();
        return 0;
 }
 
-static void intel_i830_cleanup(void)
-{
-       iounmap(intel_private.registers);
-}
-
 static int intel_i830_insert_entries(struct agp_memory *mem, off_t pg_start,
                                     int type)
 {
@@ -1012,9 +1029,9 @@ static int intel_i830_insert_entries(struct agp_memory *mem, off_t pg_start,
        for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
                writel(agp_bridge->driver->mask_memory(agp_bridge,
                                page_to_phys(mem->pages[i]), mask_type),
-                      intel_private.registers+I810_PTE_BASE+(j*4));
+                      intel_private.gtt+j);
        }
-       readl(intel_private.registers+I810_PTE_BASE+((j-1)*4));
+       readl(intel_private.gtt+j-1);
 
 out:
        ret = 0;
@@ -1038,14 +1055,15 @@ static int intel_i830_remove_entries(struct agp_memory *mem, off_t pg_start,
        }
 
        for (i = pg_start; i < (mem->page_count + pg_start); i++) {
-               writel(agp_bridge->scratch_page, intel_private.registers+I810_PTE_BASE+(i*4));
+               writel(agp_bridge->scratch_page, intel_private.gtt+i);
        }
-       readl(intel_private.registers+I810_PTE_BASE+((i-1)*4));
+       readl(intel_private.gtt+i-1);
 
        return 0;
 }
 
-static struct agp_memory *intel_i830_alloc_by_type(size_t pg_count, int type)
+static struct agp_memory *intel_fake_agp_alloc_by_type(size_t pg_count,
+                                                      int type)
 {
        if (type == AGP_PHYS_MEMORY)
                return alloc_agpphysmem_i8xx(pg_count, type);
@@ -1124,7 +1142,7 @@ static void intel_i9xx_setup_flush(void)
        if (intel_private.ifp_resource.start)
                return;
 
-       if (IS_SNB)
+       if (INTEL_GTT_GEN == 6)
                return;
 
        /* setup a resource for this object */
@@ -1132,7 +1150,7 @@ static void intel_i9xx_setup_flush(void)
        intel_private.ifp_resource.flags = IORESOURCE_MEM;
 
        /* Setup chipset flush for 915 */
-       if (IS_I965 || IS_G33 || IS_G4X) {
+       if (IS_G33 || INTEL_GTT_GEN >= 4) {
                intel_i965_g33_setup_chipset_flush();
        } else {
                intel_i915_setup_chipset_flush();
@@ -1180,7 +1198,7 @@ static int intel_i9xx_configure(void)
        return 0;
 }
 
-static void intel_i915_cleanup(void)
+static void intel_gtt_cleanup(void)
 {
        if (intel_private.i9xx_flush_page)
                iounmap(intel_private.i9xx_flush_page);
@@ -1234,7 +1252,8 @@ static int intel_i915_insert_entries(struct agp_memory *mem, off_t pg_start,
 
        mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type);
 
-       if (!IS_SNB && mask_type != 0 && mask_type != AGP_PHYS_MEMORY &&
+       if (INTEL_GTT_GEN != 6 && mask_type != 0 &&
+           mask_type != AGP_PHYS_MEMORY &&
            mask_type != INTEL_AGP_CACHED_MEMORY)
                goto out_err;
 
@@ -1272,45 +1291,6 @@ static int intel_i915_remove_entries(struct agp_memory *mem, off_t pg_start,
        return 0;
 }
 
-/* Return the aperture size by just checking the resource length.  The effect
- * described in the spec of the MSAC registers is just changing of the
- * resource size.
- */
-static int intel_i915_get_gtt_size(void)
-{
-       int size;
-
-       if (IS_G33) {
-               u16 gmch_ctrl;
-
-               /* G33's GTT size defined in gmch_ctrl */
-               pci_read_config_word(intel_private.bridge_dev, I830_GMCH_CTRL, &gmch_ctrl);
-               switch (gmch_ctrl & I830_GMCH_GMS_MASK) {
-               case I830_GMCH_GMS_STOLEN_512:
-                       size = 512;
-                       break;
-               case I830_GMCH_GMS_STOLEN_1024:
-                       size = 1024;
-                       break;
-               case I830_GMCH_GMS_STOLEN_8192:
-                       size = 8*1024;
-                       break;
-               default:
-                       dev_info(&intel_private.bridge_dev->dev,
-                                "unknown page table size 0x%x, assuming 512KB\n",
-                               (gmch_ctrl & I830_GMCH_GMS_MASK));
-                       size = 512;
-               }
-       } else {
-               /* On previous hardware, the GTT size was just what was
-                * required to map the aperture.
-                */
-               size = agp_bridge->driver->fetch_size();
-       }
-
-       return KB(size);
-}
-
 /* The intel i915 automatically initializes the agp aperture during POST.
  * Use the memory already set aside for in the GTT.
  */
@@ -1320,7 +1300,6 @@ static int intel_i915_create_gatt_table(struct agp_bridge_data *bridge)
        struct aper_size_info_fixed *size;
        int num_entries;
        u32 temp, temp2;
-       int gtt_map_size;
 
        size = agp_bridge->current_size;
        page_order = size->page_order;
@@ -1330,30 +1309,18 @@ static int intel_i915_create_gatt_table(struct agp_bridge_data *bridge)
        pci_read_config_dword(intel_private.pcidev, I915_MMADDR, &temp);
        pci_read_config_dword(intel_private.pcidev, I915_PTEADDR, &temp2);
 
-       gtt_map_size = intel_i915_get_gtt_size();
-
-       intel_private.gtt = ioremap(temp2, gtt_map_size);
-       if (!intel_private.gtt)
-               return -ENOMEM;
-
-       intel_private.base.gtt_total_entries = gtt_map_size / 4;
-
        temp &= 0xfff80000;
 
        intel_private.registers = ioremap(temp, 128 * 4096);
-       if (!intel_private.registers) {
-               iounmap(intel_private.gtt);
+       if (!intel_private.registers)
                return -ENOMEM;
-       }
 
+       intel_private.gtt_bus_addr = temp2;
        temp = readl(intel_private.registers+I810_PGETBL_CTL) & 0xfffff000;
-       global_cache_flush();   /* FIXME: ? */
 
        ret = intel_gtt_init();
-       if (ret != 0) {
-               iounmap(intel_private.gtt);
+       if (ret != 0)
                return ret;
-       }
 
        agp_bridge->gatt_table = NULL;
 
@@ -1391,45 +1358,17 @@ static unsigned long intel_gen6_mask_memory(struct agp_bridge_data *bridge,
        return addr | bridge->driver->masks[type].mask;
 }
 
-static void intel_i965_get_gtt_range(int *gtt_offset, int *gtt_size)
+static void intel_i965_get_gtt_range(int *gtt_offset)
 {
-       u16 snb_gmch_ctl;
-
-       switch (intel_private.bridge_dev->device) {
-       case PCI_DEVICE_ID_INTEL_GM45_HB:
-       case PCI_DEVICE_ID_INTEL_EAGLELAKE_HB:
-       case PCI_DEVICE_ID_INTEL_Q45_HB:
-       case PCI_DEVICE_ID_INTEL_G45_HB:
-       case PCI_DEVICE_ID_INTEL_G41_HB:
-       case PCI_DEVICE_ID_INTEL_B43_HB:
-       case PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB:
-       case PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB:
-       case PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB:
-       case PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB:
-               *gtt_offset = *gtt_size = MB(2);
-               break;
-       case PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB:
-       case PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB:
-       case PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_HB:
+       switch (INTEL_GTT_GEN) {
+       case 5:
+       case 6:
                *gtt_offset = MB(2);
-
-               pci_read_config_word(intel_private.pcidev, SNB_GMCH_CTRL, &snb_gmch_ctl);
-               switch (snb_gmch_ctl & SNB_GTT_SIZE_MASK) {
-               default:
-               case SNB_GTT_SIZE_0M:
-                       printk(KERN_ERR "Bad GTT size mask: 0x%04x.\n", snb_gmch_ctl);
-                       *gtt_size = MB(0);
-                       break;
-               case SNB_GTT_SIZE_1M:
-                       *gtt_size = MB(1);
-                       break;
-               case SNB_GTT_SIZE_2M:
-                       *gtt_size = MB(2);
-                       break;
-               }
                break;
+       case 4:
        default:
-               *gtt_offset = *gtt_size = KB(512);
+               *gtt_offset =  KB(512);
+               break;
        }
 }
 
@@ -1442,7 +1381,7 @@ static int intel_i965_create_gatt_table(struct agp_bridge_data *bridge)
        struct aper_size_info_fixed *size;
        int num_entries;
        u32 temp;
-       int gtt_offset, gtt_size;
+       int gtt_offset;
 
        size = agp_bridge->current_size;
        page_order = size->page_order;
@@ -1453,29 +1392,17 @@ static int intel_i965_create_gatt_table(struct agp_bridge_data *bridge)
 
        temp &= 0xfff00000;
 
-       intel_i965_get_gtt_range(&gtt_offset, &gtt_size);
-
-       intel_private.gtt = ioremap((temp + gtt_offset) , gtt_size);
-
-       if (!intel_private.gtt)
-               return -ENOMEM;
-
-       intel_private.base.gtt_total_entries = gtt_size / 4;
-
        intel_private.registers = ioremap(temp, 128 * 4096);
-       if (!intel_private.registers) {
-               iounmap(intel_private.gtt);
+       if (!intel_private.registers) 
                return -ENOMEM;
-       }
 
+       intel_i965_get_gtt_range(&gtt_offset);
+       intel_private.gtt_bus_addr = temp + gtt_offset;
        temp = readl(intel_private.registers+I810_PGETBL_CTL) & 0xfffff000;
-       global_cache_flush();   /* FIXME: ? */
 
        ret = intel_gtt_init();
-       if (ret != 0) {
-               iounmap(intel_private.gtt);
+       if (ret != 0)
                return ret;
-       }
 
        agp_bridge->gatt_table = NULL;
 
@@ -1495,7 +1422,7 @@ static const struct agp_bridge_driver intel_810_driver = {
        .cleanup                = intel_i810_cleanup,
        .mask_memory            = intel_i810_mask_memory,
        .masks                  = intel_i810_masks,
-       .agp_enable             = intel_i810_agp_enable,
+       .agp_enable             = intel_fake_agp_enable,
        .cache_flush            = global_cache_flush,
        .create_gatt_table      = agp_generic_create_gatt_table,
        .free_gatt_table        = agp_generic_free_gatt_table,
@@ -1512,22 +1439,22 @@ static const struct agp_bridge_driver intel_810_driver = {
 
 static const struct agp_bridge_driver intel_830_driver = {
        .owner                  = THIS_MODULE,
-       .aperture_sizes         = intel_i830_sizes,
+       .aperture_sizes         = intel_fake_agp_sizes,
        .size_type              = FIXED_APER_SIZE,
        .num_aperture_sizes     = 4,
        .needs_scratch_page     = true,
        .configure              = intel_i830_configure,
        .fetch_size             = intel_fake_agp_fetch_size,
-       .cleanup                = intel_i830_cleanup,
+       .cleanup                = intel_gtt_cleanup,
        .mask_memory            = intel_i810_mask_memory,
        .masks                  = intel_i810_masks,
-       .agp_enable             = intel_i810_agp_enable,
+       .agp_enable             = intel_fake_agp_enable,
        .cache_flush            = global_cache_flush,
        .create_gatt_table      = intel_i830_create_gatt_table,
-       .free_gatt_table        = intel_i830_free_gatt_table,
+       .free_gatt_table        = intel_fake_agp_free_gatt_table,
        .insert_memory          = intel_i830_insert_entries,
        .remove_memory          = intel_i830_remove_entries,
-       .alloc_by_type          = intel_i830_alloc_by_type,
+       .alloc_by_type          = intel_fake_agp_alloc_by_type,
        .free_by_type           = intel_i810_free_by_type,
        .agp_alloc_page         = agp_generic_alloc_page,
        .agp_alloc_pages        = agp_generic_alloc_pages,
@@ -1539,22 +1466,22 @@ static const struct agp_bridge_driver intel_830_driver = {
 
 static const struct agp_bridge_driver intel_915_driver = {
        .owner                  = THIS_MODULE,
-       .aperture_sizes         = intel_i830_sizes,
+       .aperture_sizes         = intel_fake_agp_sizes,
        .size_type              = FIXED_APER_SIZE,
        .num_aperture_sizes     = 4,
        .needs_scratch_page     = true,
        .configure              = intel_i9xx_configure,
        .fetch_size             = intel_fake_agp_fetch_size,
-       .cleanup                = intel_i915_cleanup,
+       .cleanup                = intel_gtt_cleanup,
        .mask_memory            = intel_i810_mask_memory,
        .masks                  = intel_i810_masks,
-       .agp_enable             = intel_i810_agp_enable,
+       .agp_enable             = intel_fake_agp_enable,
        .cache_flush            = global_cache_flush,
        .create_gatt_table      = intel_i915_create_gatt_table,
-       .free_gatt_table        = intel_i830_free_gatt_table,
+       .free_gatt_table        = intel_fake_agp_free_gatt_table,
        .insert_memory          = intel_i915_insert_entries,
        .remove_memory          = intel_i915_remove_entries,
-       .alloc_by_type          = intel_i830_alloc_by_type,
+       .alloc_by_type          = intel_fake_agp_alloc_by_type,
        .free_by_type           = intel_i810_free_by_type,
        .agp_alloc_page         = agp_generic_alloc_page,
        .agp_alloc_pages        = agp_generic_alloc_pages,
@@ -1572,22 +1499,22 @@ static const struct agp_bridge_driver intel_915_driver = {
 
 static const struct agp_bridge_driver intel_i965_driver = {
        .owner                  = THIS_MODULE,
-       .aperture_sizes         = intel_i830_sizes,
+       .aperture_sizes         = intel_fake_agp_sizes,
        .size_type              = FIXED_APER_SIZE,
        .num_aperture_sizes     = 4,
        .needs_scratch_page     = true,
        .configure              = intel_i9xx_configure,
        .fetch_size             = intel_fake_agp_fetch_size,
-       .cleanup                = intel_i915_cleanup,
+       .cleanup                = intel_gtt_cleanup,
        .mask_memory            = intel_i965_mask_memory,
        .masks                  = intel_i810_masks,
-       .agp_enable             = intel_i810_agp_enable,
+       .agp_enable             = intel_fake_agp_enable,
        .cache_flush            = global_cache_flush,
        .create_gatt_table      = intel_i965_create_gatt_table,
-       .free_gatt_table        = intel_i830_free_gatt_table,
+       .free_gatt_table        = intel_fake_agp_free_gatt_table,
        .insert_memory          = intel_i915_insert_entries,
        .remove_memory          = intel_i915_remove_entries,
-       .alloc_by_type          = intel_i830_alloc_by_type,
+       .alloc_by_type          = intel_fake_agp_alloc_by_type,
        .free_by_type           = intel_i810_free_by_type,
        .agp_alloc_page         = agp_generic_alloc_page,
        .agp_alloc_pages        = agp_generic_alloc_pages,
@@ -1605,22 +1532,22 @@ static const struct agp_bridge_driver intel_i965_driver = {
 
 static const struct agp_bridge_driver intel_gen6_driver = {
        .owner                  = THIS_MODULE,
-       .aperture_sizes         = intel_i830_sizes,
+       .aperture_sizes         = intel_fake_agp_sizes,
        .size_type              = FIXED_APER_SIZE,
        .num_aperture_sizes     = 4,
        .needs_scratch_page     = true,
        .configure              = intel_i9xx_configure,
        .fetch_size             = intel_fake_agp_fetch_size,
-       .cleanup                = intel_i915_cleanup,
+       .cleanup                = intel_gtt_cleanup,
        .mask_memory            = intel_gen6_mask_memory,
        .masks                  = intel_gen6_masks,
-       .agp_enable             = intel_i810_agp_enable,
+       .agp_enable             = intel_fake_agp_enable,
        .cache_flush            = global_cache_flush,
        .create_gatt_table      = intel_i965_create_gatt_table,
-       .free_gatt_table        = intel_i830_free_gatt_table,
+       .free_gatt_table        = intel_fake_agp_free_gatt_table,
        .insert_memory          = intel_i915_insert_entries,
        .remove_memory          = intel_i915_remove_entries,
-       .alloc_by_type          = intel_i830_alloc_by_type,
+       .alloc_by_type          = intel_fake_agp_alloc_by_type,
        .free_by_type           = intel_i810_free_by_type,
        .agp_alloc_page         = agp_generic_alloc_page,
        .agp_alloc_pages        = agp_generic_alloc_pages,
@@ -1638,22 +1565,22 @@ static const struct agp_bridge_driver intel_gen6_driver = {
 
 static const struct agp_bridge_driver intel_g33_driver = {
        .owner                  = THIS_MODULE,
-       .aperture_sizes         = intel_i830_sizes,
+       .aperture_sizes         = intel_fake_agp_sizes,
        .size_type              = FIXED_APER_SIZE,
        .num_aperture_sizes     = 4,
        .needs_scratch_page     = true,
        .configure              = intel_i9xx_configure,
        .fetch_size             = intel_fake_agp_fetch_size,
-       .cleanup                = intel_i915_cleanup,
+       .cleanup                = intel_gtt_cleanup,
        .mask_memory            = intel_i965_mask_memory,
        .masks                  = intel_i810_masks,
-       .agp_enable             = intel_i810_agp_enable,
+       .agp_enable             = intel_fake_agp_enable,
        .cache_flush            = global_cache_flush,
        .create_gatt_table      = intel_i915_create_gatt_table,
-       .free_gatt_table        = intel_i830_free_gatt_table,
+       .free_gatt_table        = intel_fake_agp_free_gatt_table,
        .insert_memory          = intel_i915_insert_entries,
        .remove_memory          = intel_i915_remove_entries,
-       .alloc_by_type          = intel_i830_alloc_by_type,
+       .alloc_by_type          = intel_fake_agp_alloc_by_type,
        .free_by_type           = intel_i810_free_by_type,
        .agp_alloc_page         = agp_generic_alloc_page,
        .agp_alloc_pages        = agp_generic_alloc_pages,
@@ -1669,6 +1596,35 @@ static const struct agp_bridge_driver intel_g33_driver = {
 #endif
 };
 
+static const struct intel_gtt_driver i8xx_gtt_driver = {
+       .gen = 2,
+       .setup = i830_setup,
+};
+static const struct intel_gtt_driver i915_gtt_driver = {
+       .gen = 3,
+};
+static const struct intel_gtt_driver g33_gtt_driver = {
+       .gen = 3,
+       .is_g33 = 1,
+};
+static const struct intel_gtt_driver pineview_gtt_driver = {
+       .gen = 3,
+       .is_pineview = 1, .is_g33 = 1,
+};
+static const struct intel_gtt_driver i965_gtt_driver = {
+       .gen = 4,
+};
+static const struct intel_gtt_driver g4x_gtt_driver = {
+       .gen = 5,
+};
+static const struct intel_gtt_driver ironlake_gtt_driver = {
+       .gen = 5,
+       .is_ironlake = 1,
+};
+static const struct intel_gtt_driver sandybridge_gtt_driver = {
+       .gen = 6,
+};
+
 /* Table to describe Intel GMCH and AGP/PCIE GART drivers.  At least one of
  * driver and gmch_driver must be non-null, and find_gmch will determine
  * which one should be used if a gmch_chip_id is present.
@@ -1677,57 +1633,86 @@ static const struct intel_gtt_driver_description {
        unsigned int gmch_chip_id;
        char *name;
        const struct agp_bridge_driver *gmch_driver;
+       const struct intel_gtt_driver *gtt_driver;
 } intel_gtt_chipsets[] = {
-       { PCI_DEVICE_ID_INTEL_82810_IG1, "i810", &intel_810_driver },
-       { PCI_DEVICE_ID_INTEL_82810_IG3, "i810", &intel_810_driver },
-       { PCI_DEVICE_ID_INTEL_82810E_IG, "i810", &intel_810_driver },
-       { PCI_DEVICE_ID_INTEL_82815_CGC, "i815", &intel_810_driver },
-       { PCI_DEVICE_ID_INTEL_82830_CGC, "830M", &intel_830_driver },
-       { PCI_DEVICE_ID_INTEL_82845G_IG, "830M", &intel_830_driver },
-       { PCI_DEVICE_ID_INTEL_82854_IG, "854", &intel_830_driver },
-       { PCI_DEVICE_ID_INTEL_82855GM_IG, "855GM", &intel_830_driver },
-       { PCI_DEVICE_ID_INTEL_82865_IG, "865", &intel_830_driver },
-       { PCI_DEVICE_ID_INTEL_E7221_IG, "E7221 (i915)", &intel_915_driver },
-       { PCI_DEVICE_ID_INTEL_82915G_IG, "915G", &intel_915_driver },
-       { PCI_DEVICE_ID_INTEL_82915GM_IG, "915GM", &intel_915_driver },
-       { PCI_DEVICE_ID_INTEL_82945G_IG, "945G", &intel_915_driver },
-       { PCI_DEVICE_ID_INTEL_82945GM_IG, "945GM", &intel_915_driver },
-       { PCI_DEVICE_ID_INTEL_82945GME_IG, "945GME", &intel_915_driver },
-       { PCI_DEVICE_ID_INTEL_82946GZ_IG, "946GZ", &intel_i965_driver },
-       { PCI_DEVICE_ID_INTEL_82G35_IG, "G35", &intel_i965_driver },
-       { PCI_DEVICE_ID_INTEL_82965Q_IG, "965Q", &intel_i965_driver },
-       { PCI_DEVICE_ID_INTEL_82965G_IG, "965G", &intel_i965_driver },
-       { PCI_DEVICE_ID_INTEL_82965GM_IG, "965GM", &intel_i965_driver },
-       { PCI_DEVICE_ID_INTEL_82965GME_IG, "965GME/GLE", &intel_i965_driver },
-       { PCI_DEVICE_ID_INTEL_G33_IG, "G33", &intel_g33_driver },
-       { PCI_DEVICE_ID_INTEL_Q35_IG, "Q35", &intel_g33_driver },
-       { PCI_DEVICE_ID_INTEL_Q33_IG, "Q33", &intel_g33_driver },
-       { PCI_DEVICE_ID_INTEL_PINEVIEW_M_IG, "GMA3150", &intel_g33_driver },
-       { PCI_DEVICE_ID_INTEL_PINEVIEW_IG, "GMA3150", &intel_g33_driver },
-       { PCI_DEVICE_ID_INTEL_GM45_IG, "GM45", &intel_i965_driver },
-       { PCI_DEVICE_ID_INTEL_EAGLELAKE_IG, "Eaglelake", &intel_i965_driver },
-       { PCI_DEVICE_ID_INTEL_Q45_IG, "Q45/Q43", &intel_i965_driver },
-       { PCI_DEVICE_ID_INTEL_G45_IG, "G45/G43", &intel_i965_driver },
-       { PCI_DEVICE_ID_INTEL_B43_IG, "B43", &intel_i965_driver },
-       { PCI_DEVICE_ID_INTEL_G41_IG, "G41", &intel_i965_driver },
+       { PCI_DEVICE_ID_INTEL_82810_IG1, "i810", &intel_810_driver , NULL},
+       { PCI_DEVICE_ID_INTEL_82810_IG3, "i810", &intel_810_driver , NULL},
+       { PCI_DEVICE_ID_INTEL_82810E_IG, "i810", &intel_810_driver , NULL},
+       { PCI_DEVICE_ID_INTEL_82815_CGC, "i815", &intel_810_driver , NULL},
+       { PCI_DEVICE_ID_INTEL_82830_CGC, "830M",
+               &intel_830_driver , &i8xx_gtt_driver},
+       { PCI_DEVICE_ID_INTEL_82845G_IG, "830M",
+               &intel_830_driver , &i8xx_gtt_driver},
+       { PCI_DEVICE_ID_INTEL_82854_IG, "854",
+               &intel_830_driver , &i8xx_gtt_driver},
+       { PCI_DEVICE_ID_INTEL_82855GM_IG, "855GM",
+               &intel_830_driver , &i8xx_gtt_driver},
+       { PCI_DEVICE_ID_INTEL_82865_IG, "865",
+               &intel_830_driver , &i8xx_gtt_driver},
+       { PCI_DEVICE_ID_INTEL_E7221_IG, "E7221 (i915)",
+               &intel_915_driver , &i915_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_82915G_IG, "915G",
+               &intel_915_driver , &i915_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_82915GM_IG, "915GM",
+               &intel_915_driver , &i915_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_82945G_IG, "945G",
+               &intel_915_driver , &i915_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_82945GM_IG, "945GM",
+               &intel_915_driver , &i915_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_82945GME_IG, "945GME",
+               &intel_915_driver , &i915_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_82946GZ_IG, "946GZ",
+               &intel_i965_driver , &i965_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_82G35_IG, "G35",
+               &intel_i965_driver , &i965_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_82965Q_IG, "965Q",
+               &intel_i965_driver , &i965_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_82965G_IG, "965G",
+               &intel_i965_driver , &i965_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_82965GM_IG, "965GM",
+               &intel_i965_driver , &i965_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_82965GME_IG, "965GME/GLE",
+               &intel_i965_driver , &i965_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_G33_IG, "G33",
+               &intel_g33_driver , &g33_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_Q35_IG, "Q35",
+               &intel_g33_driver , &g33_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_Q33_IG, "Q33",
+               &intel_g33_driver , &g33_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_PINEVIEW_M_IG, "GMA3150",
+               &intel_g33_driver , &pineview_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_PINEVIEW_IG, "GMA3150",
+               &intel_g33_driver , &pineview_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_GM45_IG, "GM45",
+               &intel_i965_driver , &g4x_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_EAGLELAKE_IG, "Eaglelake",
+               &intel_i965_driver , &g4x_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_Q45_IG, "Q45/Q43",
+               &intel_i965_driver , &g4x_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_G45_IG, "G45/G43",
+               &intel_i965_driver , &g4x_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_B43_IG, "B43",
+               &intel_i965_driver , &g4x_gtt_driver },
+       { PCI_DEVICE_ID_INTEL_G41_IG, "G41",
+               &intel_i965_driver , &g4x_gtt_driver },
        { PCI_DEVICE_ID_INTEL_IRONLAKE_D_IG,
-           "HD Graphics", &intel_i965_driver },
+           "HD Graphics", &intel_i965_driver , &ironlake_gtt_driver },
        { PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG,
-           "HD Graphics", &intel_i965_driver },
+           "HD Graphics", &intel_i965_driver , &ironlake_gtt_driver },
        { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT1_IG,
-           "Sandybridge", &intel_gen6_driver },
+           "Sandybridge", &intel_gen6_driver , &sandybridge_gtt_driver },
        { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_IG,
-           "Sandybridge", &intel_gen6_driver },
+           "Sandybridge", &intel_gen6_driver , &sandybridge_gtt_driver },
        { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_PLUS_IG,
-           "Sandybridge", &intel_gen6_driver },
+           "Sandybridge", &intel_gen6_driver , &sandybridge_gtt_driver },
        { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT1_IG,
-           "Sandybridge", &intel_gen6_driver },
+           "Sandybridge", &intel_gen6_driver , &sandybridge_gtt_driver },
        { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_IG,
-           "Sandybridge", &intel_gen6_driver },
+           "Sandybridge", &intel_gen6_driver , &sandybridge_gtt_driver },
        { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_PLUS_IG,
-           "Sandybridge", &intel_gen6_driver },
+           "Sandybridge", &intel_gen6_driver , &sandybridge_gtt_driver },
        { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_IG,
-           "Sandybridge", &intel_gen6_driver },
+           "Sandybridge", &intel_gen6_driver , &sandybridge_gtt_driver },
        { 0, NULL, NULL }
 };
 
@@ -1758,6 +1743,8 @@ int intel_gmch_probe(struct pci_dev *pdev,
                if (find_gmch(intel_gtt_chipsets[i].gmch_chip_id)) {
                        bridge->driver =
                                intel_gtt_chipsets[i].gmch_driver;
+                       intel_private.driver = 
+                               intel_gtt_chipsets[i].gtt_driver;
                        break;
                }
        }