blob: c1c07a2ccb11c0c8fb5241daba93f98cc425ac23 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Intel AGPGART routines.
3 */
4
Linus Torvalds1da177e2005-04-16 15:20:36 -07005#include <linux/module.h>
6#include <linux/pci.h>
7#include <linux/init.h>
Ahmed S. Darwish1eaf1222007-02-06 18:08:28 +02008#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -07009#include <linux/pagemap.h>
10#include <linux/agp_backend.h>
11#include "agp.h"
12
Zhenyu Wang1f7a6e32010-02-23 14:05:24 +080013int intel_agp_enabled;
14EXPORT_SYMBOL(intel_agp_enabled);
15
Zhenyu Wang17661682009-07-27 12:59:57 +010016/*
17 * If we have Intel graphics, we're not going to have anything other than
18 * an Intel IOMMU. So make the correct use of the PCI DMA API contingent
19 * on the Intel IOMMU support (CONFIG_DMAR).
20 * Only newer chipsets need to bother with this, of course.
21 */
22#ifdef CONFIG_DMAR
23#define USE_PCI_DMA_API 1
24#endif
25
Carlos Martíne914a362008-01-24 10:34:09 +100026#define PCI_DEVICE_ID_INTEL_E7221_HB 0x2588
27#define PCI_DEVICE_ID_INTEL_E7221_IG 0x258a
Eric Anholt65c25aa2006-09-06 11:57:18 -040028#define PCI_DEVICE_ID_INTEL_82946GZ_HB 0x2970
29#define PCI_DEVICE_ID_INTEL_82946GZ_IG 0x2972
Zhenyu Wang9119f852008-01-23 15:49:26 +100030#define PCI_DEVICE_ID_INTEL_82G35_HB 0x2980
31#define PCI_DEVICE_ID_INTEL_82G35_IG 0x2982
Eric Anholt65c25aa2006-09-06 11:57:18 -040032#define PCI_DEVICE_ID_INTEL_82965Q_HB 0x2990
33#define PCI_DEVICE_ID_INTEL_82965Q_IG 0x2992
34#define PCI_DEVICE_ID_INTEL_82965G_HB 0x29A0
35#define PCI_DEVICE_ID_INTEL_82965G_IG 0x29A2
Wang Zhenyu4598af32007-04-09 08:51:36 +080036#define PCI_DEVICE_ID_INTEL_82965GM_HB 0x2A00
37#define PCI_DEVICE_ID_INTEL_82965GM_IG 0x2A02
Zhenyu Wangdde47872007-07-26 09:18:09 +080038#define PCI_DEVICE_ID_INTEL_82965GME_HB 0x2A10
Wang Zhenyuc8eebfd2007-05-31 11:34:06 +080039#define PCI_DEVICE_ID_INTEL_82965GME_IG 0x2A12
Zhenyu Wangdde47872007-07-26 09:18:09 +080040#define PCI_DEVICE_ID_INTEL_82945GME_HB 0x27AC
Wang Zhenyudf80b142007-05-31 11:51:12 +080041#define PCI_DEVICE_ID_INTEL_82945GME_IG 0x27AE
Adam Jackson107f5172009-12-03 17:14:41 -050042#define PCI_DEVICE_ID_INTEL_PINEVIEW_M_HB 0xA010
43#define PCI_DEVICE_ID_INTEL_PINEVIEW_M_IG 0xA011
44#define PCI_DEVICE_ID_INTEL_PINEVIEW_HB 0xA000
45#define PCI_DEVICE_ID_INTEL_PINEVIEW_IG 0xA001
Wang Zhenyu874808c62007-06-06 11:16:25 +080046#define PCI_DEVICE_ID_INTEL_G33_HB 0x29C0
47#define PCI_DEVICE_ID_INTEL_G33_IG 0x29C2
48#define PCI_DEVICE_ID_INTEL_Q35_HB 0x29B0
49#define PCI_DEVICE_ID_INTEL_Q35_IG 0x29B2
50#define PCI_DEVICE_ID_INTEL_Q33_HB 0x29D0
51#define PCI_DEVICE_ID_INTEL_Q33_IG 0x29D2
Fabian Henze38d8a952009-09-08 00:59:58 +080052#define PCI_DEVICE_ID_INTEL_B43_HB 0x2E40
53#define PCI_DEVICE_ID_INTEL_B43_IG 0x2E42
Zhenyu Wang99d32bd2008-07-30 12:26:50 -070054#define PCI_DEVICE_ID_INTEL_GM45_HB 0x2A40
55#define PCI_DEVICE_ID_INTEL_GM45_IG 0x2A42
Adam Jackson107f5172009-12-03 17:14:41 -050056#define PCI_DEVICE_ID_INTEL_EAGLELAKE_HB 0x2E00
57#define PCI_DEVICE_ID_INTEL_EAGLELAKE_IG 0x2E02
Zhenyu Wang25ce77a2008-06-19 14:17:58 +100058#define PCI_DEVICE_ID_INTEL_Q45_HB 0x2E10
59#define PCI_DEVICE_ID_INTEL_Q45_IG 0x2E12
60#define PCI_DEVICE_ID_INTEL_G45_HB 0x2E20
61#define PCI_DEVICE_ID_INTEL_G45_IG 0x2E22
Zhenyu Wanga50ccc62008-11-17 14:39:00 +080062#define PCI_DEVICE_ID_INTEL_G41_HB 0x2E30
63#define PCI_DEVICE_ID_INTEL_G41_IG 0x2E32
Adam Jackson107f5172009-12-03 17:14:41 -050064#define PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB 0x0040
65#define PCI_DEVICE_ID_INTEL_IRONLAKE_D_IG 0x0042
66#define PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB 0x0044
67#define PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB 0x0062
Dave Airlie3ff99162009-12-08 14:03:47 +100068#define PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB 0x006a
Adam Jackson107f5172009-12-03 17:14:41 -050069#define PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG 0x0046
Eric Anholt1089e302009-10-22 16:10:52 -070070#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB 0x0100
71#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_IG 0x0102
Eric Anholt954bce52010-01-07 16:21:46 -080072#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB 0x0104
73#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_IG 0x0106
Eric Anholt65c25aa2006-09-06 11:57:18 -040074
Dave Airlief011ae72008-01-25 11:23:04 +100075/* cover 915 and 945 variants */
76#define IS_I915 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_E7221_HB || \
77 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB || \
78 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB || \
79 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB || \
80 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB || \
81 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GME_HB)
82
Eric Anholt65c25aa2006-09-06 11:57:18 -040083#define IS_I965 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82946GZ_HB || \
Dave Airlief011ae72008-01-25 11:23:04 +100084 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82G35_HB || \
85 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965Q_HB || \
86 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965G_HB || \
87 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965GM_HB || \
Eric Anholt82e14a62008-10-14 11:28:58 -070088 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965GME_HB)
Eric Anholt65c25aa2006-09-06 11:57:18 -040089
Wang Zhenyu874808c62007-06-06 11:16:25 +080090#define IS_G33 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G33_HB || \
91 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q35_HB || \
Shaohua Li21778322009-02-23 15:19:16 +080092 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q33_HB || \
Adam Jackson107f5172009-12-03 17:14:41 -050093 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_PINEVIEW_M_HB || \
94 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_PINEVIEW_HB)
Shaohua Li21778322009-02-23 15:19:16 +080095
Adam Jackson107f5172009-12-03 17:14:41 -050096#define IS_PINEVIEW (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_PINEVIEW_M_HB || \
97 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_PINEVIEW_HB)
Eric Anholt65c25aa2006-09-06 11:57:18 -040098
Adam Jackson107f5172009-12-03 17:14:41 -050099#define IS_G4X (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_EAGLELAKE_HB || \
Zhenyu Wang25ce77a2008-06-19 14:17:58 +1000100 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q45_HB || \
Eric Anholt82e14a62008-10-14 11:28:58 -0700101 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G45_HB || \
Zhenyu Wanga50ccc62008-11-17 14:39:00 +0800102 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_GM45_HB || \
Zhenyu Wang32cb0552009-06-05 15:38:36 +0800103 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G41_HB || \
Fabian Henze38d8a952009-09-08 00:59:58 +0800104 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_B43_HB || \
Adam Jackson107f5172009-12-03 17:14:41 -0500105 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB || \
106 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB || \
Dave Airlie3ff99162009-12-08 14:03:47 +1000107 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB || \
Eric Anholt1089e302009-10-22 16:10:52 -0700108 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB || \
Eric Anholt954bce52010-01-07 16:21:46 -0800109 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB || \
110 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB)
Zhenyu Wang25ce77a2008-06-19 14:17:58 +1000111
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100112extern int agp_memory_reserved;
113
114
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115/* Intel 815 register */
116#define INTEL_815_APCONT 0x51
117#define INTEL_815_ATTBASE_MASK ~0x1FFFFFFF
118
119/* Intel i820 registers */
120#define INTEL_I820_RDCR 0x51
121#define INTEL_I820_ERRSTS 0xc8
122
123/* Intel i840 registers */
124#define INTEL_I840_MCHCFG 0x50
125#define INTEL_I840_ERRSTS 0xc8
126
127/* Intel i850 registers */
128#define INTEL_I850_MCHCFG 0x50
129#define INTEL_I850_ERRSTS 0xc8
130
131/* intel 915G registers */
132#define I915_GMADDR 0x18
133#define I915_MMADDR 0x10
134#define I915_PTEADDR 0x1C
135#define I915_GMCH_GMS_STOLEN_48M (0x6 << 4)
136#define I915_GMCH_GMS_STOLEN_64M (0x7 << 4)
Zhenyu Wang25ce77a2008-06-19 14:17:58 +1000137#define G33_GMCH_GMS_STOLEN_128M (0x8 << 4)
138#define G33_GMCH_GMS_STOLEN_256M (0x9 << 4)
139#define INTEL_GMCH_GMS_STOLEN_96M (0xa << 4)
140#define INTEL_GMCH_GMS_STOLEN_160M (0xb << 4)
141#define INTEL_GMCH_GMS_STOLEN_224M (0xc << 4)
142#define INTEL_GMCH_GMS_STOLEN_352M (0xd << 4)
143
Dave Airlie6c00a612007-10-29 18:06:10 +1000144#define I915_IFPADDR 0x60
Linus Torvalds1da177e2005-04-16 15:20:36 -0700145
Eric Anholt65c25aa2006-09-06 11:57:18 -0400146/* Intel 965G registers */
147#define I965_MSAC 0x62
Dave Airlie6c00a612007-10-29 18:06:10 +1000148#define I965_IFPADDR 0x70
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149
150/* Intel 7505 registers */
151#define INTEL_I7505_APSIZE 0x74
152#define INTEL_I7505_NCAPID 0x60
153#define INTEL_I7505_NISTAT 0x6c
154#define INTEL_I7505_ATTBASE 0x78
155#define INTEL_I7505_ERRSTS 0x42
156#define INTEL_I7505_AGPCTRL 0x70
157#define INTEL_I7505_MCHCFG 0x50
158
Zhenyu Wang14bc4902009-11-11 01:25:25 +0800159#define SNB_GMCH_CTRL 0x50
160#define SNB_GMCH_GMS_STOLEN_MASK 0xF8
161#define SNB_GMCH_GMS_STOLEN_32M (1 << 3)
162#define SNB_GMCH_GMS_STOLEN_64M (2 << 3)
163#define SNB_GMCH_GMS_STOLEN_96M (3 << 3)
164#define SNB_GMCH_GMS_STOLEN_128M (4 << 3)
165#define SNB_GMCH_GMS_STOLEN_160M (5 << 3)
166#define SNB_GMCH_GMS_STOLEN_192M (6 << 3)
167#define SNB_GMCH_GMS_STOLEN_224M (7 << 3)
168#define SNB_GMCH_GMS_STOLEN_256M (8 << 3)
169#define SNB_GMCH_GMS_STOLEN_288M (9 << 3)
170#define SNB_GMCH_GMS_STOLEN_320M (0xa << 3)
171#define SNB_GMCH_GMS_STOLEN_352M (0xb << 3)
172#define SNB_GMCH_GMS_STOLEN_384M (0xc << 3)
173#define SNB_GMCH_GMS_STOLEN_416M (0xd << 3)
174#define SNB_GMCH_GMS_STOLEN_448M (0xe << 3)
175#define SNB_GMCH_GMS_STOLEN_480M (0xf << 3)
176#define SNB_GMCH_GMS_STOLEN_512M (0x10 << 3)
177
Dave Jonese5524f32007-02-22 18:41:28 -0500178static const struct aper_size_info_fixed intel_i810_sizes[] =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179{
180 {64, 16384, 4},
181 /* The 32M mode still requires a 64k gatt */
182 {32, 8192, 4}
183};
184
185#define AGP_DCACHE_MEMORY 1
186#define AGP_PHYS_MEMORY 2
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100187#define INTEL_AGP_CACHED_MEMORY 3
Linus Torvalds1da177e2005-04-16 15:20:36 -0700188
189static struct gatt_mask intel_i810_masks[] =
190{
191 {.mask = I810_PTE_VALID, .type = 0},
192 {.mask = (I810_PTE_VALID | I810_PTE_LOCAL), .type = AGP_DCACHE_MEMORY},
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100193 {.mask = I810_PTE_VALID, .type = 0},
194 {.mask = I810_PTE_VALID | I830_PTE_SYSTEM_CACHED,
195 .type = INTEL_AGP_CACHED_MEMORY}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700196};
197
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800198static struct _intel_private {
199 struct pci_dev *pcidev; /* device one */
200 u8 __iomem *registers;
201 u32 __iomem *gtt; /* I915G */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202 int num_dcache_entries;
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800203 /* gtt_entries is the number of gtt entries that are already mapped
204 * to stolen memory. Stolen memory is larger than the memory mapped
205 * through gtt_entries, as it includes some reserved space for the BIOS
206 * popup and for the GTT.
207 */
208 int gtt_entries; /* i830+ */
David Woodhousefc619012009-12-02 11:00:05 +0000209 int gtt_total_size;
Dave Airlie2162e6a2007-11-21 16:36:31 +1000210 union {
211 void __iomem *i9xx_flush_page;
212 void *i8xx_flush_page;
213 };
214 struct page *i8xx_page;
Dave Airlie6c00a612007-10-29 18:06:10 +1000215 struct resource ifp_resource;
Dave Airlie4d64dd92008-01-23 15:34:29 +1000216 int resource_valid;
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800217} intel_private;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218
Zhenyu Wang17661682009-07-27 12:59:57 +0100219#ifdef USE_PCI_DMA_API
David Woodhousec2980d82009-07-29 08:39:26 +0100220static int intel_agp_map_page(struct page *page, dma_addr_t *ret)
Zhenyu Wang17661682009-07-27 12:59:57 +0100221{
David Woodhousec2980d82009-07-29 08:39:26 +0100222 *ret = pci_map_page(intel_private.pcidev, page, 0,
223 PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
Zhenyu Wang17661682009-07-27 12:59:57 +0100224 if (pci_dma_mapping_error(intel_private.pcidev, *ret))
225 return -EINVAL;
226 return 0;
227}
228
David Woodhousec2980d82009-07-29 08:39:26 +0100229static void intel_agp_unmap_page(struct page *page, dma_addr_t dma)
Zhenyu Wang17661682009-07-27 12:59:57 +0100230{
David Woodhousec2980d82009-07-29 08:39:26 +0100231 pci_unmap_page(intel_private.pcidev, dma,
232 PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
Zhenyu Wang17661682009-07-27 12:59:57 +0100233}
234
David Woodhouse91b8e302009-07-29 08:49:12 +0100235static void intel_agp_free_sglist(struct agp_memory *mem)
236{
David Woodhousef6927752009-07-29 09:28:45 +0100237 struct sg_table st;
David Woodhouse91b8e302009-07-29 08:49:12 +0100238
David Woodhousef6927752009-07-29 09:28:45 +0100239 st.sgl = mem->sg_list;
240 st.orig_nents = st.nents = mem->page_count;
241
242 sg_free_table(&st);
243
David Woodhouse91b8e302009-07-29 08:49:12 +0100244 mem->sg_list = NULL;
245 mem->num_sg = 0;
246}
247
Zhenyu Wang17661682009-07-27 12:59:57 +0100248static int intel_agp_map_memory(struct agp_memory *mem)
249{
David Woodhousef6927752009-07-29 09:28:45 +0100250 struct sg_table st;
Zhenyu Wang17661682009-07-27 12:59:57 +0100251 struct scatterlist *sg;
252 int i;
253
254 DBG("try mapping %lu pages\n", (unsigned long)mem->page_count);
255
David Woodhousef6927752009-07-29 09:28:45 +0100256 if (sg_alloc_table(&st, mem->page_count, GFP_KERNEL))
Zhenyu Wang17661682009-07-27 12:59:57 +0100257 return -ENOMEM;
Zhenyu Wang17661682009-07-27 12:59:57 +0100258
David Woodhousef6927752009-07-29 09:28:45 +0100259 mem->sg_list = sg = st.sgl;
260
Zhenyu Wang17661682009-07-27 12:59:57 +0100261 for (i = 0 ; i < mem->page_count; i++, sg = sg_next(sg))
262 sg_set_page(sg, mem->pages[i], PAGE_SIZE, 0);
263
264 mem->num_sg = pci_map_sg(intel_private.pcidev, mem->sg_list,
265 mem->page_count, PCI_DMA_BIDIRECTIONAL);
David Woodhouse91b8e302009-07-29 08:49:12 +0100266 if (unlikely(!mem->num_sg)) {
267 intel_agp_free_sglist(mem);
Zhenyu Wang17661682009-07-27 12:59:57 +0100268 return -ENOMEM;
269 }
270 return 0;
271}
272
273static void intel_agp_unmap_memory(struct agp_memory *mem)
274{
275 DBG("try unmapping %lu pages\n", (unsigned long)mem->page_count);
276
277 pci_unmap_sg(intel_private.pcidev, mem->sg_list,
278 mem->page_count, PCI_DMA_BIDIRECTIONAL);
David Woodhouse91b8e302009-07-29 08:49:12 +0100279 intel_agp_free_sglist(mem);
Zhenyu Wang17661682009-07-27 12:59:57 +0100280}
281
282static void intel_agp_insert_sg_entries(struct agp_memory *mem,
283 off_t pg_start, int mask_type)
284{
285 struct scatterlist *sg;
286 int i, j;
287
288 j = pg_start;
289
290 WARN_ON(!mem->num_sg);
291
292 if (mem->num_sg == mem->page_count) {
293 for_each_sg(mem->sg_list, sg, mem->page_count, i) {
294 writel(agp_bridge->driver->mask_memory(agp_bridge,
295 sg_dma_address(sg), mask_type),
296 intel_private.gtt+j);
297 j++;
298 }
299 } else {
300 /* sg may merge pages, but we have to seperate
301 * per-page addr for GTT */
302 unsigned int len, m;
303
304 for_each_sg(mem->sg_list, sg, mem->num_sg, i) {
305 len = sg_dma_len(sg) / PAGE_SIZE;
306 for (m = 0; m < len; m++) {
307 writel(agp_bridge->driver->mask_memory(agp_bridge,
308 sg_dma_address(sg) + m * PAGE_SIZE,
309 mask_type),
310 intel_private.gtt+j);
311 j++;
312 }
313 }
314 }
315 readl(intel_private.gtt+j-1);
316}
317
318#else
319
320static void intel_agp_insert_sg_entries(struct agp_memory *mem,
321 off_t pg_start, int mask_type)
322{
323 int i, j;
Eric Anholte3deb202009-11-02 15:33:05 -0800324 u32 cache_bits = 0;
325
Eric Anholt954bce52010-01-07 16:21:46 -0800326 if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB ||
327 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB)
328 {
Eric Anholte3deb202009-11-02 15:33:05 -0800329 cache_bits = I830_PTE_SYSTEM_CACHED;
330 }
Zhenyu Wang17661682009-07-27 12:59:57 +0100331
332 for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
333 writel(agp_bridge->driver->mask_memory(agp_bridge,
David Woodhouse6a122352009-07-29 10:25:58 +0100334 page_to_phys(mem->pages[i]), mask_type),
Zhenyu Wang17661682009-07-27 12:59:57 +0100335 intel_private.gtt+j);
336 }
337
338 readl(intel_private.gtt+j-1);
339}
340
341#endif
342
Linus Torvalds1da177e2005-04-16 15:20:36 -0700343static int intel_i810_fetch_size(void)
344{
345 u32 smram_miscc;
346 struct aper_size_info_fixed *values;
347
348 pci_read_config_dword(agp_bridge->dev, I810_SMRAM_MISCC, &smram_miscc);
349 values = A_SIZE_FIX(agp_bridge->driver->aperture_sizes);
350
351 if ((smram_miscc & I810_GMS) == I810_GMS_DISABLE) {
Bjorn Helgaase3cf6952008-07-30 12:26:51 -0700352 dev_warn(&agp_bridge->dev->dev, "i810 is disabled\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353 return 0;
354 }
355 if ((smram_miscc & I810_GFX_MEM_WIN_SIZE) == I810_GFX_MEM_WIN_32M) {
356 agp_bridge->previous_size =
357 agp_bridge->current_size = (void *) (values + 1);
358 agp_bridge->aperture_size_idx = 1;
359 return values[1].size;
360 } else {
361 agp_bridge->previous_size =
362 agp_bridge->current_size = (void *) (values);
363 agp_bridge->aperture_size_idx = 0;
364 return values[0].size;
365 }
366
367 return 0;
368}
369
370static int intel_i810_configure(void)
371{
372 struct aper_size_info_fixed *current_size;
373 u32 temp;
374 int i;
375
376 current_size = A_SIZE_FIX(agp_bridge->current_size);
377
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800378 if (!intel_private.registers) {
379 pci_read_config_dword(intel_private.pcidev, I810_MMADDR, &temp);
Dave Jonese4ac5e42007-02-04 17:37:42 -0500380 temp &= 0xfff80000;
381
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800382 intel_private.registers = ioremap(temp, 128 * 4096);
383 if (!intel_private.registers) {
Bjorn Helgaase3cf6952008-07-30 12:26:51 -0700384 dev_err(&intel_private.pcidev->dev,
385 "can't remap memory\n");
Dave Jonese4ac5e42007-02-04 17:37:42 -0500386 return -ENOMEM;
387 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388 }
389
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800390 if ((readl(intel_private.registers+I810_DRAM_CTL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391 & I810_DRAM_ROW_0) == I810_DRAM_ROW_0_SDRAM) {
392 /* This will need to be dynamically assigned */
Bjorn Helgaase3cf6952008-07-30 12:26:51 -0700393 dev_info(&intel_private.pcidev->dev,
394 "detected 4MB dedicated video ram\n");
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800395 intel_private.num_dcache_entries = 1024;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396 }
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800397 pci_read_config_dword(intel_private.pcidev, I810_GMADDR, &temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800399 writel(agp_bridge->gatt_bus_addr | I810_PGETBL_ENABLED, intel_private.registers+I810_PGETBL_CTL);
400 readl(intel_private.registers+I810_PGETBL_CTL); /* PCI Posting. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401
402 if (agp_bridge->driver->needs_scratch_page) {
403 for (i = 0; i < current_size->num_entries; i++) {
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800404 writel(agp_bridge->scratch_page, intel_private.registers+I810_PTE_BASE+(i*4));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405 }
Keith Packard44d49442008-10-14 17:18:45 -0700406 readl(intel_private.registers+I810_PTE_BASE+((i-1)*4)); /* PCI posting. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407 }
408 global_cache_flush();
409 return 0;
410}
411
412static void intel_i810_cleanup(void)
413{
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800414 writel(0, intel_private.registers+I810_PGETBL_CTL);
415 readl(intel_private.registers); /* PCI Posting. */
416 iounmap(intel_private.registers);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417}
418
419static void intel_i810_tlbflush(struct agp_memory *mem)
420{
421 return;
422}
423
424static void intel_i810_agp_enable(struct agp_bridge_data *bridge, u32 mode)
425{
426 return;
427}
428
429/* Exists to support ARGB cursors */
Dave Airlie07613ba2009-06-12 14:11:41 +1000430static struct page *i8xx_alloc_pages(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431{
Dave Airlief011ae72008-01-25 11:23:04 +1000432 struct page *page;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433
Linus Torvalds66c669b2006-11-22 14:55:29 -0800434 page = alloc_pages(GFP_KERNEL | GFP_DMA32, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435 if (page == NULL)
436 return NULL;
437
Arjan van de Ven6d238cc2008-01-30 13:34:06 +0100438 if (set_pages_uc(page, 4) < 0) {
439 set_pages_wb(page, 4);
Jan Beulich89cf7cc2007-04-02 14:50:14 +0100440 __free_pages(page, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441 return NULL;
442 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443 get_page(page);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444 atomic_inc(&agp_bridge->current_memory_agp);
Dave Airlie07613ba2009-06-12 14:11:41 +1000445 return page;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446}
447
Dave Airlie07613ba2009-06-12 14:11:41 +1000448static void i8xx_destroy_pages(struct page *page)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449{
Dave Airlie07613ba2009-06-12 14:11:41 +1000450 if (page == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451 return;
452
Arjan van de Ven6d238cc2008-01-30 13:34:06 +0100453 set_pages_wb(page, 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454 put_page(page);
Jan Beulich89cf7cc2007-04-02 14:50:14 +0100455 __free_pages(page, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456 atomic_dec(&agp_bridge->current_memory_agp);
457}
458
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100459static int intel_i830_type_to_mask_type(struct agp_bridge_data *bridge,
460 int type)
461{
462 if (type < AGP_USER_TYPES)
463 return type;
464 else if (type == AGP_USER_CACHED_MEMORY)
465 return INTEL_AGP_CACHED_MEMORY;
466 else
467 return 0;
468}
469
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start,
471 int type)
472{
473 int i, j, num_entries;
474 void *temp;
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100475 int ret = -EINVAL;
476 int mask_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +0100478 if (mem->page_count == 0)
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100479 goto out;
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +0100480
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481 temp = agp_bridge->current_size;
482 num_entries = A_SIZE_FIX(temp)->num_entries;
483
Dave Jones6a92a4e2006-02-28 00:54:25 -0500484 if ((pg_start + mem->page_count) > num_entries)
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100485 goto out_err;
486
Dave Jones6a92a4e2006-02-28 00:54:25 -0500487
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488 for (j = pg_start; j < (pg_start + mem->page_count); j++) {
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100489 if (!PGE_EMPTY(agp_bridge, readl(agp_bridge->gatt_table+j))) {
490 ret = -EBUSY;
491 goto out_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493 }
494
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100495 if (type != mem->type)
496 goto out_err;
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +0100497
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100498 mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type);
499
500 switch (mask_type) {
501 case AGP_DCACHE_MEMORY:
502 if (!mem->is_flushed)
503 global_cache_flush();
504 for (i = pg_start; i < (pg_start + mem->page_count); i++) {
505 writel((i*4096)|I810_PTE_LOCAL|I810_PTE_VALID,
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800506 intel_private.registers+I810_PTE_BASE+(i*4));
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100507 }
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800508 readl(intel_private.registers+I810_PTE_BASE+((i-1)*4));
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100509 break;
510 case AGP_PHYS_MEMORY:
511 case AGP_NORMAL_MEMORY:
512 if (!mem->is_flushed)
513 global_cache_flush();
514 for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
515 writel(agp_bridge->driver->mask_memory(agp_bridge,
David Woodhouse6a122352009-07-29 10:25:58 +0100516 page_to_phys(mem->pages[i]), mask_type),
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800517 intel_private.registers+I810_PTE_BASE+(j*4));
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100518 }
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800519 readl(intel_private.registers+I810_PTE_BASE+((j-1)*4));
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100520 break;
521 default:
522 goto out_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700523 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524
525 agp_bridge->driver->tlb_flush(mem);
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100526out:
527 ret = 0;
528out_err:
Dave Airlie9516b032008-06-19 10:42:17 +1000529 mem->is_flushed = true;
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100530 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531}
532
533static int intel_i810_remove_entries(struct agp_memory *mem, off_t pg_start,
534 int type)
535{
536 int i;
537
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +0100538 if (mem->page_count == 0)
539 return 0;
540
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541 for (i = pg_start; i < (mem->page_count + pg_start); i++) {
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800542 writel(agp_bridge->scratch_page, intel_private.registers+I810_PTE_BASE+(i*4));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543 }
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800544 readl(intel_private.registers+I810_PTE_BASE+((i-1)*4));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546 agp_bridge->driver->tlb_flush(mem);
547 return 0;
548}
549
550/*
551 * The i810/i830 requires a physical address to program its mouse
552 * pointer into hardware.
553 * However the Xserver still writes to it through the agp aperture.
554 */
555static struct agp_memory *alloc_agpphysmem_i8xx(size_t pg_count, int type)
556{
557 struct agp_memory *new;
Dave Airlie07613ba2009-06-12 14:11:41 +1000558 struct page *page;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560 switch (pg_count) {
Dave Airlie07613ba2009-06-12 14:11:41 +1000561 case 1: page = agp_bridge->driver->agp_alloc_page(agp_bridge);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562 break;
563 case 4:
564 /* kludge to get 4 physical pages for ARGB cursor */
Dave Airlie07613ba2009-06-12 14:11:41 +1000565 page = i8xx_alloc_pages();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566 break;
567 default:
568 return NULL;
569 }
570
Dave Airlie07613ba2009-06-12 14:11:41 +1000571 if (page == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700572 return NULL;
573
574 new = agp_create_memory(pg_count);
575 if (new == NULL)
576 return NULL;
577
Dave Airlie07613ba2009-06-12 14:11:41 +1000578 new->pages[0] = page;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700579 if (pg_count == 4) {
580 /* kludge to get 4 physical pages for ARGB cursor */
Dave Airlie07613ba2009-06-12 14:11:41 +1000581 new->pages[1] = new->pages[0] + 1;
582 new->pages[2] = new->pages[1] + 1;
583 new->pages[3] = new->pages[2] + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584 }
585 new->page_count = pg_count;
586 new->num_scratch_pages = pg_count;
587 new->type = AGP_PHYS_MEMORY;
Dave Airlie07613ba2009-06-12 14:11:41 +1000588 new->physical = page_to_phys(new->pages[0]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589 return new;
590}
591
592static struct agp_memory *intel_i810_alloc_by_type(size_t pg_count, int type)
593{
594 struct agp_memory *new;
595
596 if (type == AGP_DCACHE_MEMORY) {
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800597 if (pg_count != intel_private.num_dcache_entries)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598 return NULL;
599
600 new = agp_create_memory(1);
601 if (new == NULL)
602 return NULL;
603
604 new->type = AGP_DCACHE_MEMORY;
605 new->page_count = pg_count;
606 new->num_scratch_pages = 0;
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100607 agp_free_page_array(new);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700608 return new;
609 }
610 if (type == AGP_PHYS_MEMORY)
611 return alloc_agpphysmem_i8xx(pg_count, type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612 return NULL;
613}
614
615static void intel_i810_free_by_type(struct agp_memory *curr)
616{
617 agp_free_key(curr->key);
Dave Jones6a92a4e2006-02-28 00:54:25 -0500618 if (curr->type == AGP_PHYS_MEMORY) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619 if (curr->page_count == 4)
Dave Airlie07613ba2009-06-12 14:11:41 +1000620 i8xx_destroy_pages(curr->pages[0]);
Alan Hourihane88d51962005-11-06 23:35:34 -0800621 else {
Dave Airlie07613ba2009-06-12 14:11:41 +1000622 agp_bridge->driver->agp_destroy_page(curr->pages[0],
Dave Airliea2721e92007-10-15 10:19:16 +1000623 AGP_PAGE_DESTROY_UNMAP);
Dave Airlie07613ba2009-06-12 14:11:41 +1000624 agp_bridge->driver->agp_destroy_page(curr->pages[0],
Dave Airliea2721e92007-10-15 10:19:16 +1000625 AGP_PAGE_DESTROY_FREE);
Alan Hourihane88d51962005-11-06 23:35:34 -0800626 }
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100627 agp_free_page_array(curr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628 }
629 kfree(curr);
630}
631
632static unsigned long intel_i810_mask_memory(struct agp_bridge_data *bridge,
David Woodhouse2a4ceb62009-07-27 10:27:29 +0100633 dma_addr_t addr, int type)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634{
635 /* Type checking must be done elsewhere */
636 return addr | bridge->driver->masks[type].mask;
637}
638
639static struct aper_size_info_fixed intel_i830_sizes[] =
640{
641 {128, 32768, 5},
642 /* The 64M mode still requires a 128k gatt */
643 {64, 16384, 5},
644 {256, 65536, 6},
Eric Anholt65c25aa2006-09-06 11:57:18 -0400645 {512, 131072, 7},
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646};
647
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648static void intel_i830_init_gtt_entries(void)
649{
650 u16 gmch_ctrl;
Zhenyu Wang14bc4902009-11-11 01:25:25 +0800651 int gtt_entries = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652 u8 rdct;
653 int local = 0;
654 static const int ddt[4] = { 0, 16, 32, 64 };
Eric Anholtc41e0de2006-12-19 12:57:24 -0800655 int size; /* reserved space (in kb) at the top of stolen memory */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656
Dave Airlief011ae72008-01-25 11:23:04 +1000657 pci_read_config_word(agp_bridge->dev, I830_GMCH_CTRL, &gmch_ctrl);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658
Eric Anholtc41e0de2006-12-19 12:57:24 -0800659 if (IS_I965) {
660 u32 pgetbl_ctl;
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800661 pgetbl_ctl = readl(intel_private.registers+I810_PGETBL_CTL);
Eric Anholtc41e0de2006-12-19 12:57:24 -0800662
Eric Anholtc41e0de2006-12-19 12:57:24 -0800663 /* The 965 has a field telling us the size of the GTT,
664 * which may be larger than what is necessary to map the
665 * aperture.
666 */
667 switch (pgetbl_ctl & I965_PGETBL_SIZE_MASK) {
668 case I965_PGETBL_SIZE_128KB:
669 size = 128;
670 break;
671 case I965_PGETBL_SIZE_256KB:
672 size = 256;
673 break;
674 case I965_PGETBL_SIZE_512KB:
675 size = 512;
676 break;
Zhenyu Wang4e8b6e22008-01-23 14:54:37 +1000677 case I965_PGETBL_SIZE_1MB:
678 size = 1024;
679 break;
680 case I965_PGETBL_SIZE_2MB:
681 size = 2048;
682 break;
683 case I965_PGETBL_SIZE_1_5MB:
684 size = 1024 + 512;
685 break;
Eric Anholtc41e0de2006-12-19 12:57:24 -0800686 default:
Bjorn Helgaase3cf6952008-07-30 12:26:51 -0700687 dev_info(&intel_private.pcidev->dev,
688 "unknown page table size, assuming 512KB\n");
Eric Anholtc41e0de2006-12-19 12:57:24 -0800689 size = 512;
690 }
691 size += 4; /* add in BIOS popup space */
Adam Jackson107f5172009-12-03 17:14:41 -0500692 } else if (IS_G33 && !IS_PINEVIEW) {
Wang Zhenyu874808c62007-06-06 11:16:25 +0800693 /* G33's GTT size defined in gmch_ctrl */
694 switch (gmch_ctrl & G33_PGETBL_SIZE_MASK) {
695 case G33_PGETBL_SIZE_1M:
696 size = 1024;
697 break;
698 case G33_PGETBL_SIZE_2M:
699 size = 2048;
700 break;
701 default:
Bjorn Helgaase3cf6952008-07-30 12:26:51 -0700702 dev_info(&agp_bridge->dev->dev,
703 "unknown page table size 0x%x, assuming 512KB\n",
Wang Zhenyu874808c62007-06-06 11:16:25 +0800704 (gmch_ctrl & G33_PGETBL_SIZE_MASK));
705 size = 512;
706 }
707 size += 4;
Adam Jackson107f5172009-12-03 17:14:41 -0500708 } else if (IS_G4X || IS_PINEVIEW) {
Zhenyu Wang25ce77a2008-06-19 14:17:58 +1000709 /* On 4 series hardware, GTT stolen is separate from graphics
Eric Anholt82e14a62008-10-14 11:28:58 -0700710 * stolen, ignore it in stolen gtt entries counting. However,
711 * 4KB of the stolen memory doesn't get mapped to the GTT.
712 */
713 size = 4;
Eric Anholtc41e0de2006-12-19 12:57:24 -0800714 } else {
715 /* On previous hardware, the GTT size was just what was
716 * required to map the aperture.
717 */
718 size = agp_bridge->driver->fetch_size() + 4;
719 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720
721 if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82830_HB ||
722 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82845G_HB) {
723 switch (gmch_ctrl & I830_GMCH_GMS_MASK) {
724 case I830_GMCH_GMS_STOLEN_512:
725 gtt_entries = KB(512) - KB(size);
726 break;
727 case I830_GMCH_GMS_STOLEN_1024:
728 gtt_entries = MB(1) - KB(size);
729 break;
730 case I830_GMCH_GMS_STOLEN_8192:
731 gtt_entries = MB(8) - KB(size);
732 break;
733 case I830_GMCH_GMS_LOCAL:
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800734 rdct = readb(intel_private.registers+I830_RDRAM_CHANNEL_TYPE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700735 gtt_entries = (I830_RDRAM_ND(rdct) + 1) *
736 MB(ddt[I830_RDRAM_DDT(rdct)]);
737 local = 1;
738 break;
739 default:
740 gtt_entries = 0;
741 break;
742 }
Eric Anholt954bce52010-01-07 16:21:46 -0800743 } else if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB ||
744 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB) {
Zhenyu Wang14bc4902009-11-11 01:25:25 +0800745 /*
746 * SandyBridge has new memory control reg at 0x50.w
Eric Anholt1089e302009-10-22 16:10:52 -0700747 */
Zhenyu Wang14bc4902009-11-11 01:25:25 +0800748 u16 snb_gmch_ctl;
749 pci_read_config_word(intel_private.pcidev, SNB_GMCH_CTRL, &snb_gmch_ctl);
750 switch (snb_gmch_ctl & SNB_GMCH_GMS_STOLEN_MASK) {
751 case SNB_GMCH_GMS_STOLEN_32M:
752 gtt_entries = MB(32) - KB(size);
753 break;
754 case SNB_GMCH_GMS_STOLEN_64M:
755 gtt_entries = MB(64) - KB(size);
756 break;
757 case SNB_GMCH_GMS_STOLEN_96M:
758 gtt_entries = MB(96) - KB(size);
759 break;
760 case SNB_GMCH_GMS_STOLEN_128M:
761 gtt_entries = MB(128) - KB(size);
762 break;
763 case SNB_GMCH_GMS_STOLEN_160M:
764 gtt_entries = MB(160) - KB(size);
765 break;
766 case SNB_GMCH_GMS_STOLEN_192M:
767 gtt_entries = MB(192) - KB(size);
768 break;
769 case SNB_GMCH_GMS_STOLEN_224M:
770 gtt_entries = MB(224) - KB(size);
771 break;
772 case SNB_GMCH_GMS_STOLEN_256M:
773 gtt_entries = MB(256) - KB(size);
774 break;
775 case SNB_GMCH_GMS_STOLEN_288M:
776 gtt_entries = MB(288) - KB(size);
777 break;
778 case SNB_GMCH_GMS_STOLEN_320M:
779 gtt_entries = MB(320) - KB(size);
780 break;
781 case SNB_GMCH_GMS_STOLEN_352M:
782 gtt_entries = MB(352) - KB(size);
783 break;
784 case SNB_GMCH_GMS_STOLEN_384M:
785 gtt_entries = MB(384) - KB(size);
786 break;
787 case SNB_GMCH_GMS_STOLEN_416M:
788 gtt_entries = MB(416) - KB(size);
789 break;
790 case SNB_GMCH_GMS_STOLEN_448M:
791 gtt_entries = MB(448) - KB(size);
792 break;
793 case SNB_GMCH_GMS_STOLEN_480M:
794 gtt_entries = MB(480) - KB(size);
795 break;
796 case SNB_GMCH_GMS_STOLEN_512M:
797 gtt_entries = MB(512) - KB(size);
798 break;
799 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800 } else {
Dave Airliee67aa272007-09-18 22:46:35 -0700801 switch (gmch_ctrl & I855_GMCH_GMS_MASK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700802 case I855_GMCH_GMS_STOLEN_1M:
803 gtt_entries = MB(1) - KB(size);
804 break;
805 case I855_GMCH_GMS_STOLEN_4M:
806 gtt_entries = MB(4) - KB(size);
807 break;
808 case I855_GMCH_GMS_STOLEN_8M:
809 gtt_entries = MB(8) - KB(size);
810 break;
811 case I855_GMCH_GMS_STOLEN_16M:
812 gtt_entries = MB(16) - KB(size);
813 break;
814 case I855_GMCH_GMS_STOLEN_32M:
815 gtt_entries = MB(32) - KB(size);
816 break;
817 case I915_GMCH_GMS_STOLEN_48M:
818 /* Check it's really I915G */
Zhenyu Wang25ce77a2008-06-19 14:17:58 +1000819 if (IS_I915 || IS_I965 || IS_G33 || IS_G4X)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820 gtt_entries = MB(48) - KB(size);
821 else
822 gtt_entries = 0;
823 break;
824 case I915_GMCH_GMS_STOLEN_64M:
825 /* Check it's really I915G */
Zhenyu Wang25ce77a2008-06-19 14:17:58 +1000826 if (IS_I915 || IS_I965 || IS_G33 || IS_G4X)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827 gtt_entries = MB(64) - KB(size);
828 else
829 gtt_entries = 0;
Wang Zhenyu874808c62007-06-06 11:16:25 +0800830 break;
831 case G33_GMCH_GMS_STOLEN_128M:
Zhenyu Wang25ce77a2008-06-19 14:17:58 +1000832 if (IS_G33 || IS_I965 || IS_G4X)
Wang Zhenyu874808c62007-06-06 11:16:25 +0800833 gtt_entries = MB(128) - KB(size);
834 else
835 gtt_entries = 0;
836 break;
837 case G33_GMCH_GMS_STOLEN_256M:
Zhenyu Wang25ce77a2008-06-19 14:17:58 +1000838 if (IS_G33 || IS_I965 || IS_G4X)
Wang Zhenyu874808c62007-06-06 11:16:25 +0800839 gtt_entries = MB(256) - KB(size);
840 else
841 gtt_entries = 0;
842 break;
Zhenyu Wang25ce77a2008-06-19 14:17:58 +1000843 case INTEL_GMCH_GMS_STOLEN_96M:
844 if (IS_I965 || IS_G4X)
845 gtt_entries = MB(96) - KB(size);
846 else
847 gtt_entries = 0;
848 break;
849 case INTEL_GMCH_GMS_STOLEN_160M:
850 if (IS_I965 || IS_G4X)
851 gtt_entries = MB(160) - KB(size);
852 else
853 gtt_entries = 0;
854 break;
855 case INTEL_GMCH_GMS_STOLEN_224M:
856 if (IS_I965 || IS_G4X)
857 gtt_entries = MB(224) - KB(size);
858 else
859 gtt_entries = 0;
860 break;
861 case INTEL_GMCH_GMS_STOLEN_352M:
862 if (IS_I965 || IS_G4X)
863 gtt_entries = MB(352) - KB(size);
864 else
865 gtt_entries = 0;
866 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700867 default:
868 gtt_entries = 0;
869 break;
870 }
871 }
Lubomir Rintel9c1e8a42009-03-10 12:55:54 -0700872 if (gtt_entries > 0) {
Bjorn Helgaase3cf6952008-07-30 12:26:51 -0700873 dev_info(&agp_bridge->dev->dev, "detected %dK %s memory\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700874 gtt_entries / KB(1), local ? "local" : "stolen");
Lubomir Rintel9c1e8a42009-03-10 12:55:54 -0700875 gtt_entries /= KB(4);
876 } else {
Bjorn Helgaase3cf6952008-07-30 12:26:51 -0700877 dev_info(&agp_bridge->dev->dev,
878 "no pre-allocated video memory detected\n");
Lubomir Rintel9c1e8a42009-03-10 12:55:54 -0700879 gtt_entries = 0;
880 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800882 intel_private.gtt_entries = gtt_entries;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883}
884
Dave Airlie2162e6a2007-11-21 16:36:31 +1000885static void intel_i830_fini_flush(void)
886{
887 kunmap(intel_private.i8xx_page);
888 intel_private.i8xx_flush_page = NULL;
889 unmap_page_from_agp(intel_private.i8xx_page);
Dave Airlie2162e6a2007-11-21 16:36:31 +1000890
891 __free_page(intel_private.i8xx_page);
Dave Airlie4d64dd92008-01-23 15:34:29 +1000892 intel_private.i8xx_page = NULL;
Dave Airlie2162e6a2007-11-21 16:36:31 +1000893}
894
895static void intel_i830_setup_flush(void)
896{
Dave Airlie4d64dd92008-01-23 15:34:29 +1000897 /* return if we've already set the flush mechanism up */
898 if (intel_private.i8xx_page)
899 return;
Dave Airlie2162e6a2007-11-21 16:36:31 +1000900
901 intel_private.i8xx_page = alloc_page(GFP_KERNEL | __GFP_ZERO | GFP_DMA32);
Dave Airlief011ae72008-01-25 11:23:04 +1000902 if (!intel_private.i8xx_page)
Dave Airlie2162e6a2007-11-21 16:36:31 +1000903 return;
Dave Airlie2162e6a2007-11-21 16:36:31 +1000904
Dave Airlie2162e6a2007-11-21 16:36:31 +1000905 intel_private.i8xx_flush_page = kmap(intel_private.i8xx_page);
906 if (!intel_private.i8xx_flush_page)
907 intel_i830_fini_flush();
908}
909
Eric Anholte517a5e2009-09-10 17:48:48 -0700910static void
911do_wbinvd(void *null)
912{
913 wbinvd();
914}
915
916/* The chipset_flush interface needs to get data that has already been
917 * flushed out of the CPU all the way out to main memory, because the GPU
918 * doesn't snoop those buffers.
919 *
920 * The 8xx series doesn't have the same lovely interface for flushing the
921 * chipset write buffers that the later chips do. According to the 865
922 * specs, it's 64 octwords, or 1KB. So, to get those previous things in
923 * that buffer out, we just fill 1KB and clflush it out, on the assumption
924 * that it'll push whatever was in there out. It appears to work.
925 */
Dave Airlie2162e6a2007-11-21 16:36:31 +1000926static void intel_i830_chipset_flush(struct agp_bridge_data *bridge)
927{
928 unsigned int *pg = intel_private.i8xx_flush_page;
Dave Airlie2162e6a2007-11-21 16:36:31 +1000929
Eric Anholte517a5e2009-09-10 17:48:48 -0700930 memset(pg, 0, 1024);
Dave Airlief011ae72008-01-25 11:23:04 +1000931
Eric Anholte517a5e2009-09-10 17:48:48 -0700932 if (cpu_has_clflush) {
933 clflush_cache_range(pg, 1024);
934 } else {
935 if (on_each_cpu(do_wbinvd, NULL, 1) != 0)
936 printk(KERN_ERR "Timed out waiting for cache flush.\n");
937 }
Dave Airlie2162e6a2007-11-21 16:36:31 +1000938}
939
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940/* The intel i830 automatically initializes the agp aperture during POST.
941 * Use the memory already set aside for in the GTT.
942 */
943static int intel_i830_create_gatt_table(struct agp_bridge_data *bridge)
944{
945 int page_order;
946 struct aper_size_info_fixed *size;
947 int num_entries;
948 u32 temp;
949
950 size = agp_bridge->current_size;
951 page_order = size->page_order;
952 num_entries = size->num_entries;
953 agp_bridge->gatt_table_real = NULL;
954
Dave Airlief011ae72008-01-25 11:23:04 +1000955 pci_read_config_dword(intel_private.pcidev, I810_MMADDR, &temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700956 temp &= 0xfff80000;
957
Dave Airlief011ae72008-01-25 11:23:04 +1000958 intel_private.registers = ioremap(temp, 128 * 4096);
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800959 if (!intel_private.registers)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700960 return -ENOMEM;
961
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800962 temp = readl(intel_private.registers+I810_PGETBL_CTL) & 0xfffff000;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963 global_cache_flush(); /* FIXME: ?? */
964
965 /* we have to call this as early as possible after the MMIO base address is known */
966 intel_i830_init_gtt_entries();
967
968 agp_bridge->gatt_table = NULL;
969
970 agp_bridge->gatt_bus_addr = temp;
971
972 return 0;
973}
974
975/* Return the gatt table to a sane state. Use the top of stolen
976 * memory for the GTT.
977 */
978static int intel_i830_free_gatt_table(struct agp_bridge_data *bridge)
979{
980 return 0;
981}
982
983static int intel_i830_fetch_size(void)
984{
985 u16 gmch_ctrl;
986 struct aper_size_info_fixed *values;
987
988 values = A_SIZE_FIX(agp_bridge->driver->aperture_sizes);
989
990 if (agp_bridge->dev->device != PCI_DEVICE_ID_INTEL_82830_HB &&
991 agp_bridge->dev->device != PCI_DEVICE_ID_INTEL_82845G_HB) {
992 /* 855GM/852GM/865G has 128MB aperture size */
993 agp_bridge->previous_size = agp_bridge->current_size = (void *) values;
994 agp_bridge->aperture_size_idx = 0;
995 return values[0].size;
996 }
997
Dave Airlief011ae72008-01-25 11:23:04 +1000998 pci_read_config_word(agp_bridge->dev, I830_GMCH_CTRL, &gmch_ctrl);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700999
1000 if ((gmch_ctrl & I830_GMCH_MEM_MASK) == I830_GMCH_MEM_128M) {
1001 agp_bridge->previous_size = agp_bridge->current_size = (void *) values;
1002 agp_bridge->aperture_size_idx = 0;
1003 return values[0].size;
1004 } else {
1005 agp_bridge->previous_size = agp_bridge->current_size = (void *) (values + 1);
1006 agp_bridge->aperture_size_idx = 1;
1007 return values[1].size;
1008 }
1009
1010 return 0;
1011}
1012
1013static int intel_i830_configure(void)
1014{
1015 struct aper_size_info_fixed *current_size;
1016 u32 temp;
1017 u16 gmch_ctrl;
1018 int i;
1019
1020 current_size = A_SIZE_FIX(agp_bridge->current_size);
1021
Dave Airlief011ae72008-01-25 11:23:04 +10001022 pci_read_config_dword(intel_private.pcidev, I810_GMADDR, &temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
1024
Dave Airlief011ae72008-01-25 11:23:04 +10001025 pci_read_config_word(agp_bridge->dev, I830_GMCH_CTRL, &gmch_ctrl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026 gmch_ctrl |= I830_GMCH_ENABLED;
Dave Airlief011ae72008-01-25 11:23:04 +10001027 pci_write_config_word(agp_bridge->dev, I830_GMCH_CTRL, gmch_ctrl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001029 writel(agp_bridge->gatt_bus_addr|I810_PGETBL_ENABLED, intel_private.registers+I810_PGETBL_CTL);
1030 readl(intel_private.registers+I810_PGETBL_CTL); /* PCI Posting. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031
1032 if (agp_bridge->driver->needs_scratch_page) {
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001033 for (i = intel_private.gtt_entries; i < current_size->num_entries; i++) {
1034 writel(agp_bridge->scratch_page, intel_private.registers+I810_PTE_BASE+(i*4));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035 }
Keith Packard44d49442008-10-14 17:18:45 -07001036 readl(intel_private.registers+I810_PTE_BASE+((i-1)*4)); /* PCI Posting. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037 }
1038
1039 global_cache_flush();
Dave Airlie2162e6a2007-11-21 16:36:31 +10001040
1041 intel_i830_setup_flush();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042 return 0;
1043}
1044
1045static void intel_i830_cleanup(void)
1046{
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001047 iounmap(intel_private.registers);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048}
1049
Dave Airlief011ae72008-01-25 11:23:04 +10001050static int intel_i830_insert_entries(struct agp_memory *mem, off_t pg_start,
1051 int type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052{
Dave Airlief011ae72008-01-25 11:23:04 +10001053 int i, j, num_entries;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054 void *temp;
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001055 int ret = -EINVAL;
1056 int mask_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +01001058 if (mem->page_count == 0)
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001059 goto out;
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +01001060
Linus Torvalds1da177e2005-04-16 15:20:36 -07001061 temp = agp_bridge->current_size;
1062 num_entries = A_SIZE_FIX(temp)->num_entries;
1063
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001064 if (pg_start < intel_private.gtt_entries) {
Bjorn Helgaase3cf6952008-07-30 12:26:51 -07001065 dev_printk(KERN_DEBUG, &intel_private.pcidev->dev,
1066 "pg_start == 0x%.8lx, intel_private.gtt_entries == 0x%.8x\n",
1067 pg_start, intel_private.gtt_entries);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068
Bjorn Helgaase3cf6952008-07-30 12:26:51 -07001069 dev_info(&intel_private.pcidev->dev,
1070 "trying to insert into local/stolen memory\n");
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001071 goto out_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072 }
1073
1074 if ((pg_start + mem->page_count) > num_entries)
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001075 goto out_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076
1077 /* The i830 can't check the GTT for entries since its read only,
1078 * depend on the caller to make the correct offset decisions.
1079 */
1080
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001081 if (type != mem->type)
1082 goto out_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001083
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001084 mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type);
1085
1086 if (mask_type != 0 && mask_type != AGP_PHYS_MEMORY &&
1087 mask_type != INTEL_AGP_CACHED_MEMORY)
1088 goto out_err;
1089
1090 if (!mem->is_flushed)
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +01001091 global_cache_flush();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092
1093 for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
1094 writel(agp_bridge->driver->mask_memory(agp_bridge,
David Woodhouse6a122352009-07-29 10:25:58 +01001095 page_to_phys(mem->pages[i]), mask_type),
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001096 intel_private.registers+I810_PTE_BASE+(j*4));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097 }
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001098 readl(intel_private.registers+I810_PTE_BASE+((j-1)*4));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099 agp_bridge->driver->tlb_flush(mem);
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001100
1101out:
1102 ret = 0;
1103out_err:
Dave Airlie9516b032008-06-19 10:42:17 +10001104 mem->is_flushed = true;
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001105 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001106}
1107
Dave Airlief011ae72008-01-25 11:23:04 +10001108static int intel_i830_remove_entries(struct agp_memory *mem, off_t pg_start,
1109 int type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110{
1111 int i;
1112
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +01001113 if (mem->page_count == 0)
1114 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001116 if (pg_start < intel_private.gtt_entries) {
Bjorn Helgaase3cf6952008-07-30 12:26:51 -07001117 dev_info(&intel_private.pcidev->dev,
1118 "trying to disable local/stolen memory\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119 return -EINVAL;
1120 }
1121
1122 for (i = pg_start; i < (mem->page_count + pg_start); i++) {
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001123 writel(agp_bridge->scratch_page, intel_private.registers+I810_PTE_BASE+(i*4));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124 }
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001125 readl(intel_private.registers+I810_PTE_BASE+((i-1)*4));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127 agp_bridge->driver->tlb_flush(mem);
1128 return 0;
1129}
1130
Dave Airlief011ae72008-01-25 11:23:04 +10001131static struct agp_memory *intel_i830_alloc_by_type(size_t pg_count, int type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132{
1133 if (type == AGP_PHYS_MEMORY)
1134 return alloc_agpphysmem_i8xx(pg_count, type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135 /* always return NULL for other allocation types for now */
1136 return NULL;
1137}
1138
Dave Airlie6c00a612007-10-29 18:06:10 +10001139static int intel_alloc_chipset_flush_resource(void)
1140{
1141 int ret;
1142 ret = pci_bus_alloc_resource(agp_bridge->dev->bus, &intel_private.ifp_resource, PAGE_SIZE,
1143 PAGE_SIZE, PCIBIOS_MIN_MEM, 0,
1144 pcibios_align_resource, agp_bridge->dev);
Dave Airlie6c00a612007-10-29 18:06:10 +10001145
Dave Airlie2162e6a2007-11-21 16:36:31 +10001146 return ret;
Dave Airlie6c00a612007-10-29 18:06:10 +10001147}
1148
1149static void intel_i915_setup_chipset_flush(void)
1150{
1151 int ret;
1152 u32 temp;
1153
1154 pci_read_config_dword(agp_bridge->dev, I915_IFPADDR, &temp);
1155 if (!(temp & 0x1)) {
1156 intel_alloc_chipset_flush_resource();
Dave Airlie4d64dd92008-01-23 15:34:29 +10001157 intel_private.resource_valid = 1;
Dave Airlie6c00a612007-10-29 18:06:10 +10001158 pci_write_config_dword(agp_bridge->dev, I915_IFPADDR, (intel_private.ifp_resource.start & 0xffffffff) | 0x1);
1159 } else {
1160 temp &= ~1;
1161
Dave Airlie4d64dd92008-01-23 15:34:29 +10001162 intel_private.resource_valid = 1;
Dave Airlie6c00a612007-10-29 18:06:10 +10001163 intel_private.ifp_resource.start = temp;
1164 intel_private.ifp_resource.end = temp + PAGE_SIZE;
1165 ret = request_resource(&iomem_resource, &intel_private.ifp_resource);
Dave Airlie4d64dd92008-01-23 15:34:29 +10001166 /* some BIOSes reserve this area in a pnp some don't */
1167 if (ret)
1168 intel_private.resource_valid = 0;
Dave Airlie6c00a612007-10-29 18:06:10 +10001169 }
1170}
1171
1172static void intel_i965_g33_setup_chipset_flush(void)
1173{
1174 u32 temp_hi, temp_lo;
1175 int ret;
1176
1177 pci_read_config_dword(agp_bridge->dev, I965_IFPADDR + 4, &temp_hi);
1178 pci_read_config_dword(agp_bridge->dev, I965_IFPADDR, &temp_lo);
1179
1180 if (!(temp_lo & 0x1)) {
1181
1182 intel_alloc_chipset_flush_resource();
1183
Dave Airlie4d64dd92008-01-23 15:34:29 +10001184 intel_private.resource_valid = 1;
Andrew Morton1fa4db72007-11-29 10:00:48 +10001185 pci_write_config_dword(agp_bridge->dev, I965_IFPADDR + 4,
1186 upper_32_bits(intel_private.ifp_resource.start));
Dave Airlie6c00a612007-10-29 18:06:10 +10001187 pci_write_config_dword(agp_bridge->dev, I965_IFPADDR, (intel_private.ifp_resource.start & 0xffffffff) | 0x1);
Dave Airlie6c00a612007-10-29 18:06:10 +10001188 } else {
1189 u64 l64;
Dave Airlief011ae72008-01-25 11:23:04 +10001190
Dave Airlie6c00a612007-10-29 18:06:10 +10001191 temp_lo &= ~0x1;
1192 l64 = ((u64)temp_hi << 32) | temp_lo;
1193
Dave Airlie4d64dd92008-01-23 15:34:29 +10001194 intel_private.resource_valid = 1;
Dave Airlie6c00a612007-10-29 18:06:10 +10001195 intel_private.ifp_resource.start = l64;
1196 intel_private.ifp_resource.end = l64 + PAGE_SIZE;
1197 ret = request_resource(&iomem_resource, &intel_private.ifp_resource);
Dave Airlie4d64dd92008-01-23 15:34:29 +10001198 /* some BIOSes reserve this area in a pnp some don't */
1199 if (ret)
1200 intel_private.resource_valid = 0;
Dave Airlie6c00a612007-10-29 18:06:10 +10001201 }
1202}
1203
Dave Airlie2162e6a2007-11-21 16:36:31 +10001204static void intel_i9xx_setup_flush(void)
1205{
Dave Airlie4d64dd92008-01-23 15:34:29 +10001206 /* return if already configured */
1207 if (intel_private.ifp_resource.start)
1208 return;
Dave Airlie2162e6a2007-11-21 16:36:31 +10001209
Dave Airlie4d64dd92008-01-23 15:34:29 +10001210 /* setup a resource for this object */
Dave Airlie2162e6a2007-11-21 16:36:31 +10001211 intel_private.ifp_resource.name = "Intel Flush Page";
1212 intel_private.ifp_resource.flags = IORESOURCE_MEM;
1213
1214 /* Setup chipset flush for 915 */
Zhenyu Wang7d15ddf2008-06-20 11:48:06 +10001215 if (IS_I965 || IS_G33 || IS_G4X) {
Dave Airlie2162e6a2007-11-21 16:36:31 +10001216 intel_i965_g33_setup_chipset_flush();
1217 } else {
1218 intel_i915_setup_chipset_flush();
1219 }
1220
1221 if (intel_private.ifp_resource.start) {
1222 intel_private.i9xx_flush_page = ioremap_nocache(intel_private.ifp_resource.start, PAGE_SIZE);
1223 if (!intel_private.i9xx_flush_page)
Bjorn Helgaase3cf6952008-07-30 12:26:51 -07001224 dev_info(&intel_private.pcidev->dev, "can't ioremap flush page - no chipset flushing");
Dave Airlie2162e6a2007-11-21 16:36:31 +10001225 }
1226}
1227
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228static int intel_i915_configure(void)
1229{
1230 struct aper_size_info_fixed *current_size;
1231 u32 temp;
1232 u16 gmch_ctrl;
1233 int i;
1234
1235 current_size = A_SIZE_FIX(agp_bridge->current_size);
1236
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001237 pci_read_config_dword(intel_private.pcidev, I915_GMADDR, &temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238
1239 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
1240
Dave Airlief011ae72008-01-25 11:23:04 +10001241 pci_read_config_word(agp_bridge->dev, I830_GMCH_CTRL, &gmch_ctrl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242 gmch_ctrl |= I830_GMCH_ENABLED;
Dave Airlief011ae72008-01-25 11:23:04 +10001243 pci_write_config_word(agp_bridge->dev, I830_GMCH_CTRL, gmch_ctrl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001244
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001245 writel(agp_bridge->gatt_bus_addr|I810_PGETBL_ENABLED, intel_private.registers+I810_PGETBL_CTL);
1246 readl(intel_private.registers+I810_PGETBL_CTL); /* PCI Posting. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001247
1248 if (agp_bridge->driver->needs_scratch_page) {
David Woodhousefc619012009-12-02 11:00:05 +00001249 for (i = intel_private.gtt_entries; i < intel_private.gtt_total_size; i++) {
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001250 writel(agp_bridge->scratch_page, intel_private.gtt+i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001251 }
Keith Packard44d49442008-10-14 17:18:45 -07001252 readl(intel_private.gtt+i-1); /* PCI Posting. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001253 }
1254
1255 global_cache_flush();
Dave Airlie6c00a612007-10-29 18:06:10 +10001256
Dave Airlie2162e6a2007-11-21 16:36:31 +10001257 intel_i9xx_setup_flush();
Dave Airlief011ae72008-01-25 11:23:04 +10001258
Linus Torvalds1da177e2005-04-16 15:20:36 -07001259 return 0;
1260}
1261
1262static void intel_i915_cleanup(void)
1263{
Dave Airlie2162e6a2007-11-21 16:36:31 +10001264 if (intel_private.i9xx_flush_page)
1265 iounmap(intel_private.i9xx_flush_page);
Dave Airlie4d64dd92008-01-23 15:34:29 +10001266 if (intel_private.resource_valid)
1267 release_resource(&intel_private.ifp_resource);
1268 intel_private.ifp_resource.start = 0;
1269 intel_private.resource_valid = 0;
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001270 iounmap(intel_private.gtt);
1271 iounmap(intel_private.registers);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001272}
1273
Dave Airlie6c00a612007-10-29 18:06:10 +10001274static void intel_i915_chipset_flush(struct agp_bridge_data *bridge)
1275{
Dave Airlie2162e6a2007-11-21 16:36:31 +10001276 if (intel_private.i9xx_flush_page)
1277 writel(1, intel_private.i9xx_flush_page);
Dave Airlie6c00a612007-10-29 18:06:10 +10001278}
1279
Dave Airlief011ae72008-01-25 11:23:04 +10001280static int intel_i915_insert_entries(struct agp_memory *mem, off_t pg_start,
1281 int type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001282{
Zhenyu Wang17661682009-07-27 12:59:57 +01001283 int num_entries;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001284 void *temp;
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001285 int ret = -EINVAL;
1286 int mask_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +01001288 if (mem->page_count == 0)
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001289 goto out;
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +01001290
Linus Torvalds1da177e2005-04-16 15:20:36 -07001291 temp = agp_bridge->current_size;
1292 num_entries = A_SIZE_FIX(temp)->num_entries;
1293
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001294 if (pg_start < intel_private.gtt_entries) {
Bjorn Helgaase3cf6952008-07-30 12:26:51 -07001295 dev_printk(KERN_DEBUG, &intel_private.pcidev->dev,
1296 "pg_start == 0x%.8lx, intel_private.gtt_entries == 0x%.8x\n",
1297 pg_start, intel_private.gtt_entries);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298
Bjorn Helgaase3cf6952008-07-30 12:26:51 -07001299 dev_info(&intel_private.pcidev->dev,
1300 "trying to insert into local/stolen memory\n");
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001301 goto out_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001302 }
1303
1304 if ((pg_start + mem->page_count) > num_entries)
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001305 goto out_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306
Zhenyu Wang17661682009-07-27 12:59:57 +01001307 /* The i915 can't check the GTT for entries since it's read only;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001308 * depend on the caller to make the correct offset decisions.
1309 */
1310
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001311 if (type != mem->type)
1312 goto out_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001313
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001314 mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type);
1315
1316 if (mask_type != 0 && mask_type != AGP_PHYS_MEMORY &&
1317 mask_type != INTEL_AGP_CACHED_MEMORY)
1318 goto out_err;
1319
1320 if (!mem->is_flushed)
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +01001321 global_cache_flush();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322
Zhenyu Wang17661682009-07-27 12:59:57 +01001323 intel_agp_insert_sg_entries(mem, pg_start, mask_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001324 agp_bridge->driver->tlb_flush(mem);
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001325
1326 out:
1327 ret = 0;
1328 out_err:
Dave Airlie9516b032008-06-19 10:42:17 +10001329 mem->is_flushed = true;
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001330 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001331}
1332
Dave Airlief011ae72008-01-25 11:23:04 +10001333static int intel_i915_remove_entries(struct agp_memory *mem, off_t pg_start,
1334 int type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001335{
1336 int i;
1337
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +01001338 if (mem->page_count == 0)
1339 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001341 if (pg_start < intel_private.gtt_entries) {
Bjorn Helgaase3cf6952008-07-30 12:26:51 -07001342 dev_info(&intel_private.pcidev->dev,
1343 "trying to disable local/stolen memory\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001344 return -EINVAL;
1345 }
1346
Dave Airlief011ae72008-01-25 11:23:04 +10001347 for (i = pg_start; i < (mem->page_count + pg_start); i++)
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001348 writel(agp_bridge->scratch_page, intel_private.gtt+i);
Dave Airlief011ae72008-01-25 11:23:04 +10001349
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001350 readl(intel_private.gtt+i-1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352 agp_bridge->driver->tlb_flush(mem);
1353 return 0;
1354}
1355
Eric Anholtc41e0de2006-12-19 12:57:24 -08001356/* Return the aperture size by just checking the resource length. The effect
1357 * described in the spec of the MSAC registers is just changing of the
1358 * resource size.
1359 */
1360static int intel_i9xx_fetch_size(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361{
Ahmed S. Darwish1eaf1222007-02-06 18:08:28 +02001362 int num_sizes = ARRAY_SIZE(intel_i830_sizes);
Eric Anholtc41e0de2006-12-19 12:57:24 -08001363 int aper_size; /* size in megabytes */
1364 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001365
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001366 aper_size = pci_resource_len(intel_private.pcidev, 2) / MB(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001367
Eric Anholtc41e0de2006-12-19 12:57:24 -08001368 for (i = 0; i < num_sizes; i++) {
1369 if (aper_size == intel_i830_sizes[i].size) {
1370 agp_bridge->current_size = intel_i830_sizes + i;
1371 agp_bridge->previous_size = agp_bridge->current_size;
1372 return aper_size;
1373 }
1374 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375
Eric Anholtc41e0de2006-12-19 12:57:24 -08001376 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377}
1378
1379/* The intel i915 automatically initializes the agp aperture during POST.
1380 * Use the memory already set aside for in the GTT.
1381 */
1382static int intel_i915_create_gatt_table(struct agp_bridge_data *bridge)
1383{
1384 int page_order;
1385 struct aper_size_info_fixed *size;
1386 int num_entries;
1387 u32 temp, temp2;
Zhenyu Wang47406222007-09-11 15:23:58 -07001388 int gtt_map_size = 256 * 1024;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389
1390 size = agp_bridge->current_size;
1391 page_order = size->page_order;
1392 num_entries = size->num_entries;
1393 agp_bridge->gatt_table_real = NULL;
1394
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001395 pci_read_config_dword(intel_private.pcidev, I915_MMADDR, &temp);
Dave Airlief011ae72008-01-25 11:23:04 +10001396 pci_read_config_dword(intel_private.pcidev, I915_PTEADDR, &temp2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001397
Zhenyu Wang47406222007-09-11 15:23:58 -07001398 if (IS_G33)
1399 gtt_map_size = 1024 * 1024; /* 1M on G33 */
1400 intel_private.gtt = ioremap(temp2, gtt_map_size);
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001401 if (!intel_private.gtt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001402 return -ENOMEM;
1403
David Woodhousefc619012009-12-02 11:00:05 +00001404 intel_private.gtt_total_size = gtt_map_size / 4;
1405
Linus Torvalds1da177e2005-04-16 15:20:36 -07001406 temp &= 0xfff80000;
1407
Dave Airlief011ae72008-01-25 11:23:04 +10001408 intel_private.registers = ioremap(temp, 128 * 4096);
Scott Thompson5bdbc7d2007-08-25 18:14:00 +10001409 if (!intel_private.registers) {
1410 iounmap(intel_private.gtt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001411 return -ENOMEM;
Scott Thompson5bdbc7d2007-08-25 18:14:00 +10001412 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001413
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001414 temp = readl(intel_private.registers+I810_PGETBL_CTL) & 0xfffff000;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001415 global_cache_flush(); /* FIXME: ? */
1416
1417 /* we have to call this as early as possible after the MMIO base address is known */
1418 intel_i830_init_gtt_entries();
1419
1420 agp_bridge->gatt_table = NULL;
1421
1422 agp_bridge->gatt_bus_addr = temp;
1423
1424 return 0;
1425}
Linus Torvalds7d915a32006-11-22 09:37:54 -08001426
1427/*
1428 * The i965 supports 36-bit physical addresses, but to keep
1429 * the format of the GTT the same, the bits that don't fit
1430 * in a 32-bit word are shifted down to bits 4..7.
1431 *
1432 * Gcc is smart enough to notice that "(addr >> 28) & 0xf0"
1433 * is always zero on 32-bit architectures, so no need to make
1434 * this conditional.
1435 */
1436static unsigned long intel_i965_mask_memory(struct agp_bridge_data *bridge,
David Woodhouse2a4ceb62009-07-27 10:27:29 +01001437 dma_addr_t addr, int type)
Linus Torvalds7d915a32006-11-22 09:37:54 -08001438{
1439 /* Shift high bits down */
1440 addr |= (addr >> 28) & 0xf0;
1441
1442 /* Type checking must be done elsewhere */
1443 return addr | bridge->driver->masks[type].mask;
1444}
1445
Zhenyu Wang25ce77a2008-06-19 14:17:58 +10001446static void intel_i965_get_gtt_range(int *gtt_offset, int *gtt_size)
1447{
1448 switch (agp_bridge->dev->device) {
Zhenyu Wang99d32bd2008-07-30 12:26:50 -07001449 case PCI_DEVICE_ID_INTEL_GM45_HB:
Adam Jackson107f5172009-12-03 17:14:41 -05001450 case PCI_DEVICE_ID_INTEL_EAGLELAKE_HB:
Zhenyu Wang25ce77a2008-06-19 14:17:58 +10001451 case PCI_DEVICE_ID_INTEL_Q45_HB:
1452 case PCI_DEVICE_ID_INTEL_G45_HB:
Zhenyu Wanga50ccc62008-11-17 14:39:00 +08001453 case PCI_DEVICE_ID_INTEL_G41_HB:
Fabian Henze38d8a952009-09-08 00:59:58 +08001454 case PCI_DEVICE_ID_INTEL_B43_HB:
Adam Jackson107f5172009-12-03 17:14:41 -05001455 case PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB:
1456 case PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB:
1457 case PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB:
Dave Airlie3ff99162009-12-08 14:03:47 +10001458 case PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB:
Eric Anholt1089e302009-10-22 16:10:52 -07001459 case PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB:
Eric Anholt954bce52010-01-07 16:21:46 -08001460 case PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB:
Zhenyu Wang25ce77a2008-06-19 14:17:58 +10001461 *gtt_offset = *gtt_size = MB(2);
1462 break;
1463 default:
1464 *gtt_offset = *gtt_size = KB(512);
1465 }
1466}
1467
Eric Anholt65c25aa2006-09-06 11:57:18 -04001468/* The intel i965 automatically initializes the agp aperture during POST.
Eric Anholtc41e0de2006-12-19 12:57:24 -08001469 * Use the memory already set aside for in the GTT.
1470 */
Eric Anholt65c25aa2006-09-06 11:57:18 -04001471static int intel_i965_create_gatt_table(struct agp_bridge_data *bridge)
1472{
Dave Airlie62c96b92008-06-19 14:27:53 +10001473 int page_order;
1474 struct aper_size_info_fixed *size;
1475 int num_entries;
1476 u32 temp;
1477 int gtt_offset, gtt_size;
Eric Anholt65c25aa2006-09-06 11:57:18 -04001478
Dave Airlie62c96b92008-06-19 14:27:53 +10001479 size = agp_bridge->current_size;
1480 page_order = size->page_order;
1481 num_entries = size->num_entries;
1482 agp_bridge->gatt_table_real = NULL;
Eric Anholt65c25aa2006-09-06 11:57:18 -04001483
Dave Airlie62c96b92008-06-19 14:27:53 +10001484 pci_read_config_dword(intel_private.pcidev, I915_MMADDR, &temp);
Eric Anholt65c25aa2006-09-06 11:57:18 -04001485
Dave Airlie62c96b92008-06-19 14:27:53 +10001486 temp &= 0xfff00000;
Eric Anholt65c25aa2006-09-06 11:57:18 -04001487
Zhenyu Wang25ce77a2008-06-19 14:17:58 +10001488 intel_i965_get_gtt_range(&gtt_offset, &gtt_size);
Eric Anholt65c25aa2006-09-06 11:57:18 -04001489
Dave Airlie62c96b92008-06-19 14:27:53 +10001490 intel_private.gtt = ioremap((temp + gtt_offset) , gtt_size);
Eric Anholt65c25aa2006-09-06 11:57:18 -04001491
Dave Airlie62c96b92008-06-19 14:27:53 +10001492 if (!intel_private.gtt)
1493 return -ENOMEM;
Zhenyu Wang4e8b6e22008-01-23 14:54:37 +10001494
David Woodhousefc619012009-12-02 11:00:05 +00001495 intel_private.gtt_total_size = gtt_size / 4;
1496
Dave Airlie62c96b92008-06-19 14:27:53 +10001497 intel_private.registers = ioremap(temp, 128 * 4096);
1498 if (!intel_private.registers) {
Scott Thompson5bdbc7d2007-08-25 18:14:00 +10001499 iounmap(intel_private.gtt);
1500 return -ENOMEM;
1501 }
Eric Anholt65c25aa2006-09-06 11:57:18 -04001502
Dave Airlie62c96b92008-06-19 14:27:53 +10001503 temp = readl(intel_private.registers+I810_PGETBL_CTL) & 0xfffff000;
1504 global_cache_flush(); /* FIXME: ? */
Eric Anholt65c25aa2006-09-06 11:57:18 -04001505
Dave Airlie62c96b92008-06-19 14:27:53 +10001506 /* we have to call this as early as possible after the MMIO base address is known */
1507 intel_i830_init_gtt_entries();
Eric Anholt65c25aa2006-09-06 11:57:18 -04001508
Dave Airlie62c96b92008-06-19 14:27:53 +10001509 agp_bridge->gatt_table = NULL;
Eric Anholt65c25aa2006-09-06 11:57:18 -04001510
Dave Airlie62c96b92008-06-19 14:27:53 +10001511 agp_bridge->gatt_bus_addr = temp;
Eric Anholt65c25aa2006-09-06 11:57:18 -04001512
Dave Airlie62c96b92008-06-19 14:27:53 +10001513 return 0;
Eric Anholt65c25aa2006-09-06 11:57:18 -04001514}
1515
Linus Torvalds1da177e2005-04-16 15:20:36 -07001516
1517static int intel_fetch_size(void)
1518{
1519 int i;
1520 u16 temp;
1521 struct aper_size_info_16 *values;
1522
1523 pci_read_config_word(agp_bridge->dev, INTEL_APSIZE, &temp);
1524 values = A_SIZE_16(agp_bridge->driver->aperture_sizes);
1525
1526 for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) {
1527 if (temp == values[i].size_value) {
1528 agp_bridge->previous_size = agp_bridge->current_size = (void *) (values + i);
1529 agp_bridge->aperture_size_idx = i;
1530 return values[i].size;
1531 }
1532 }
1533
1534 return 0;
1535}
1536
1537static int __intel_8xx_fetch_size(u8 temp)
1538{
1539 int i;
1540 struct aper_size_info_8 *values;
1541
1542 values = A_SIZE_8(agp_bridge->driver->aperture_sizes);
1543
1544 for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) {
1545 if (temp == values[i].size_value) {
1546 agp_bridge->previous_size =
1547 agp_bridge->current_size = (void *) (values + i);
1548 agp_bridge->aperture_size_idx = i;
1549 return values[i].size;
1550 }
1551 }
1552 return 0;
1553}
1554
1555static int intel_8xx_fetch_size(void)
1556{
1557 u8 temp;
1558
1559 pci_read_config_byte(agp_bridge->dev, INTEL_APSIZE, &temp);
1560 return __intel_8xx_fetch_size(temp);
1561}
1562
1563static int intel_815_fetch_size(void)
1564{
1565 u8 temp;
1566
1567 /* Intel 815 chipsets have a _weird_ APSIZE register with only
1568 * one non-reserved bit, so mask the others out ... */
1569 pci_read_config_byte(agp_bridge->dev, INTEL_APSIZE, &temp);
1570 temp &= (1 << 3);
1571
1572 return __intel_8xx_fetch_size(temp);
1573}
1574
1575static void intel_tlbflush(struct agp_memory *mem)
1576{
1577 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x2200);
1578 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x2280);
1579}
1580
1581
1582static void intel_8xx_tlbflush(struct agp_memory *mem)
1583{
1584 u32 temp;
1585 pci_read_config_dword(agp_bridge->dev, INTEL_AGPCTRL, &temp);
1586 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, temp & ~(1 << 7));
1587 pci_read_config_dword(agp_bridge->dev, INTEL_AGPCTRL, &temp);
1588 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, temp | (1 << 7));
1589}
1590
1591
1592static void intel_cleanup(void)
1593{
1594 u16 temp;
1595 struct aper_size_info_16 *previous_size;
1596
1597 previous_size = A_SIZE_16(agp_bridge->previous_size);
1598 pci_read_config_word(agp_bridge->dev, INTEL_NBXCFG, &temp);
1599 pci_write_config_word(agp_bridge->dev, INTEL_NBXCFG, temp & ~(1 << 9));
1600 pci_write_config_word(agp_bridge->dev, INTEL_APSIZE, previous_size->size_value);
1601}
1602
1603
1604static void intel_8xx_cleanup(void)
1605{
1606 u16 temp;
1607 struct aper_size_info_8 *previous_size;
1608
1609 previous_size = A_SIZE_8(agp_bridge->previous_size);
1610 pci_read_config_word(agp_bridge->dev, INTEL_NBXCFG, &temp);
1611 pci_write_config_word(agp_bridge->dev, INTEL_NBXCFG, temp & ~(1 << 9));
1612 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, previous_size->size_value);
1613}
1614
1615
1616static int intel_configure(void)
1617{
1618 u32 temp;
1619 u16 temp2;
1620 struct aper_size_info_16 *current_size;
1621
1622 current_size = A_SIZE_16(agp_bridge->current_size);
1623
1624 /* aperture size */
1625 pci_write_config_word(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
1626
1627 /* address to map to */
1628 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
1629 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
1630
1631 /* attbase - aperture base */
1632 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
1633
1634 /* agpctrl */
1635 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x2280);
1636
1637 /* paccfg/nbxcfg */
1638 pci_read_config_word(agp_bridge->dev, INTEL_NBXCFG, &temp2);
1639 pci_write_config_word(agp_bridge->dev, INTEL_NBXCFG,
1640 (temp2 & ~(1 << 10)) | (1 << 9));
1641 /* clear any possible error conditions */
1642 pci_write_config_byte(agp_bridge->dev, INTEL_ERRSTS + 1, 7);
1643 return 0;
1644}
1645
1646static int intel_815_configure(void)
1647{
1648 u32 temp, addr;
1649 u8 temp2;
1650 struct aper_size_info_8 *current_size;
1651
1652 /* attbase - aperture base */
1653 /* the Intel 815 chipset spec. says that bits 29-31 in the
1654 * ATTBASE register are reserved -> try not to write them */
1655 if (agp_bridge->gatt_bus_addr & INTEL_815_ATTBASE_MASK) {
Bjorn Helgaase3cf6952008-07-30 12:26:51 -07001656 dev_emerg(&agp_bridge->dev->dev, "gatt bus addr too high");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001657 return -EINVAL;
1658 }
1659
1660 current_size = A_SIZE_8(agp_bridge->current_size);
1661
1662 /* aperture size */
1663 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE,
1664 current_size->size_value);
1665
1666 /* address to map to */
1667 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
1668 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
1669
1670 pci_read_config_dword(agp_bridge->dev, INTEL_ATTBASE, &addr);
1671 addr &= INTEL_815_ATTBASE_MASK;
1672 addr |= agp_bridge->gatt_bus_addr;
1673 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, addr);
1674
1675 /* agpctrl */
1676 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
1677
1678 /* apcont */
1679 pci_read_config_byte(agp_bridge->dev, INTEL_815_APCONT, &temp2);
1680 pci_write_config_byte(agp_bridge->dev, INTEL_815_APCONT, temp2 | (1 << 1));
1681
1682 /* clear any possible error conditions */
1683 /* Oddness : this chipset seems to have no ERRSTS register ! */
1684 return 0;
1685}
1686
1687static void intel_820_tlbflush(struct agp_memory *mem)
1688{
1689 return;
1690}
1691
1692static void intel_820_cleanup(void)
1693{
1694 u8 temp;
1695 struct aper_size_info_8 *previous_size;
1696
1697 previous_size = A_SIZE_8(agp_bridge->previous_size);
1698 pci_read_config_byte(agp_bridge->dev, INTEL_I820_RDCR, &temp);
1699 pci_write_config_byte(agp_bridge->dev, INTEL_I820_RDCR,
1700 temp & ~(1 << 1));
1701 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE,
1702 previous_size->size_value);
1703}
1704
1705
1706static int intel_820_configure(void)
1707{
1708 u32 temp;
1709 u8 temp2;
1710 struct aper_size_info_8 *current_size;
1711
1712 current_size = A_SIZE_8(agp_bridge->current_size);
1713
1714 /* aperture size */
1715 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
1716
1717 /* address to map to */
1718 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
1719 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
1720
1721 /* attbase - aperture base */
1722 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
1723
1724 /* agpctrl */
1725 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
1726
1727 /* global enable aperture access */
1728 /* This flag is not accessed through MCHCFG register as in */
1729 /* i850 chipset. */
1730 pci_read_config_byte(agp_bridge->dev, INTEL_I820_RDCR, &temp2);
1731 pci_write_config_byte(agp_bridge->dev, INTEL_I820_RDCR, temp2 | (1 << 1));
1732 /* clear any possible AGP-related error conditions */
1733 pci_write_config_word(agp_bridge->dev, INTEL_I820_ERRSTS, 0x001c);
1734 return 0;
1735}
1736
1737static int intel_840_configure(void)
1738{
1739 u32 temp;
1740 u16 temp2;
1741 struct aper_size_info_8 *current_size;
1742
1743 current_size = A_SIZE_8(agp_bridge->current_size);
1744
1745 /* aperture size */
1746 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
1747
1748 /* address to map to */
1749 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
1750 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
1751
1752 /* attbase - aperture base */
1753 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
1754
1755 /* agpctrl */
1756 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
1757
1758 /* mcgcfg */
1759 pci_read_config_word(agp_bridge->dev, INTEL_I840_MCHCFG, &temp2);
1760 pci_write_config_word(agp_bridge->dev, INTEL_I840_MCHCFG, temp2 | (1 << 9));
1761 /* clear any possible error conditions */
1762 pci_write_config_word(agp_bridge->dev, INTEL_I840_ERRSTS, 0xc000);
1763 return 0;
1764}
1765
1766static int intel_845_configure(void)
1767{
1768 u32 temp;
1769 u8 temp2;
1770 struct aper_size_info_8 *current_size;
1771
1772 current_size = A_SIZE_8(agp_bridge->current_size);
1773
1774 /* aperture size */
1775 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
1776
Matthew Garrettb0825482005-07-29 14:03:39 -07001777 if (agp_bridge->apbase_config != 0) {
1778 pci_write_config_dword(agp_bridge->dev, AGP_APBASE,
1779 agp_bridge->apbase_config);
1780 } else {
1781 /* address to map to */
1782 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
1783 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
1784 agp_bridge->apbase_config = temp;
1785 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001786
1787 /* attbase - aperture base */
1788 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
1789
1790 /* agpctrl */
1791 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
1792
1793 /* agpm */
1794 pci_read_config_byte(agp_bridge->dev, INTEL_I845_AGPM, &temp2);
1795 pci_write_config_byte(agp_bridge->dev, INTEL_I845_AGPM, temp2 | (1 << 1));
1796 /* clear any possible error conditions */
1797 pci_write_config_word(agp_bridge->dev, INTEL_I845_ERRSTS, 0x001c);
Dave Airlie2162e6a2007-11-21 16:36:31 +10001798
1799 intel_i830_setup_flush();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001800 return 0;
1801}
1802
1803static int intel_850_configure(void)
1804{
1805 u32 temp;
1806 u16 temp2;
1807 struct aper_size_info_8 *current_size;
1808
1809 current_size = A_SIZE_8(agp_bridge->current_size);
1810
1811 /* aperture size */
1812 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
1813
1814 /* address to map to */
1815 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
1816 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
1817
1818 /* attbase - aperture base */
1819 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
1820
1821 /* agpctrl */
1822 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
1823
1824 /* mcgcfg */
1825 pci_read_config_word(agp_bridge->dev, INTEL_I850_MCHCFG, &temp2);
1826 pci_write_config_word(agp_bridge->dev, INTEL_I850_MCHCFG, temp2 | (1 << 9));
1827 /* clear any possible AGP-related error conditions */
1828 pci_write_config_word(agp_bridge->dev, INTEL_I850_ERRSTS, 0x001c);
1829 return 0;
1830}
1831
1832static int intel_860_configure(void)
1833{
1834 u32 temp;
1835 u16 temp2;
1836 struct aper_size_info_8 *current_size;
1837
1838 current_size = A_SIZE_8(agp_bridge->current_size);
1839
1840 /* aperture size */
1841 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
1842
1843 /* address to map to */
1844 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
1845 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
1846
1847 /* attbase - aperture base */
1848 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
1849
1850 /* agpctrl */
1851 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
1852
1853 /* mcgcfg */
1854 pci_read_config_word(agp_bridge->dev, INTEL_I860_MCHCFG, &temp2);
1855 pci_write_config_word(agp_bridge->dev, INTEL_I860_MCHCFG, temp2 | (1 << 9));
1856 /* clear any possible AGP-related error conditions */
1857 pci_write_config_word(agp_bridge->dev, INTEL_I860_ERRSTS, 0xf700);
1858 return 0;
1859}
1860
1861static int intel_830mp_configure(void)
1862{
1863 u32 temp;
1864 u16 temp2;
1865 struct aper_size_info_8 *current_size;
1866
1867 current_size = A_SIZE_8(agp_bridge->current_size);
1868
1869 /* aperture size */
1870 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
1871
1872 /* address to map to */
1873 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
1874 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
1875
1876 /* attbase - aperture base */
1877 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
1878
1879 /* agpctrl */
1880 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
1881
1882 /* gmch */
1883 pci_read_config_word(agp_bridge->dev, INTEL_NBXCFG, &temp2);
1884 pci_write_config_word(agp_bridge->dev, INTEL_NBXCFG, temp2 | (1 << 9));
1885 /* clear any possible AGP-related error conditions */
1886 pci_write_config_word(agp_bridge->dev, INTEL_I830_ERRSTS, 0x1c);
1887 return 0;
1888}
1889
1890static int intel_7505_configure(void)
1891{
1892 u32 temp;
1893 u16 temp2;
1894 struct aper_size_info_8 *current_size;
1895
1896 current_size = A_SIZE_8(agp_bridge->current_size);
1897
1898 /* aperture size */
1899 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
1900
1901 /* address to map to */
1902 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
1903 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
1904
1905 /* attbase - aperture base */
1906 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
1907
1908 /* agpctrl */
1909 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
1910
1911 /* mchcfg */
1912 pci_read_config_word(agp_bridge->dev, INTEL_I7505_MCHCFG, &temp2);
1913 pci_write_config_word(agp_bridge->dev, INTEL_I7505_MCHCFG, temp2 | (1 << 9));
1914
1915 return 0;
1916}
1917
1918/* Setup function */
Dave Jonese5524f32007-02-22 18:41:28 -05001919static const struct gatt_mask intel_generic_masks[] =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001920{
1921 {.mask = 0x00000017, .type = 0}
1922};
1923
Dave Jonese5524f32007-02-22 18:41:28 -05001924static const struct aper_size_info_8 intel_815_sizes[2] =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001925{
1926 {64, 16384, 4, 0},
1927 {32, 8192, 3, 8},
1928};
1929
Dave Jonese5524f32007-02-22 18:41:28 -05001930static const struct aper_size_info_8 intel_8xx_sizes[7] =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001931{
1932 {256, 65536, 6, 0},
1933 {128, 32768, 5, 32},
1934 {64, 16384, 4, 48},
1935 {32, 8192, 3, 56},
1936 {16, 4096, 2, 60},
1937 {8, 2048, 1, 62},
1938 {4, 1024, 0, 63}
1939};
1940
Dave Jonese5524f32007-02-22 18:41:28 -05001941static const struct aper_size_info_16 intel_generic_sizes[7] =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001942{
1943 {256, 65536, 6, 0},
1944 {128, 32768, 5, 32},
1945 {64, 16384, 4, 48},
1946 {32, 8192, 3, 56},
1947 {16, 4096, 2, 60},
1948 {8, 2048, 1, 62},
1949 {4, 1024, 0, 63}
1950};
1951
Dave Jonese5524f32007-02-22 18:41:28 -05001952static const struct aper_size_info_8 intel_830mp_sizes[4] =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001953{
1954 {256, 65536, 6, 0},
1955 {128, 32768, 5, 32},
1956 {64, 16384, 4, 48},
1957 {32, 8192, 3, 56}
1958};
1959
Dave Jonese5524f32007-02-22 18:41:28 -05001960static const struct agp_bridge_driver intel_generic_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001961 .owner = THIS_MODULE,
1962 .aperture_sizes = intel_generic_sizes,
1963 .size_type = U16_APER_SIZE,
1964 .num_aperture_sizes = 7,
1965 .configure = intel_configure,
1966 .fetch_size = intel_fetch_size,
1967 .cleanup = intel_cleanup,
1968 .tlb_flush = intel_tlbflush,
1969 .mask_memory = agp_generic_mask_memory,
1970 .masks = intel_generic_masks,
1971 .agp_enable = agp_generic_enable,
1972 .cache_flush = global_cache_flush,
1973 .create_gatt_table = agp_generic_create_gatt_table,
1974 .free_gatt_table = agp_generic_free_gatt_table,
1975 .insert_memory = agp_generic_insert_memory,
1976 .remove_memory = agp_generic_remove_memory,
1977 .alloc_by_type = agp_generic_alloc_by_type,
1978 .free_by_type = agp_generic_free_by_type,
1979 .agp_alloc_page = agp_generic_alloc_page,
Shaohua Li37acee12008-08-21 10:46:11 +08001980 .agp_alloc_pages = agp_generic_alloc_pages,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001981 .agp_destroy_page = agp_generic_destroy_page,
Shaohua Libd079282008-08-21 10:46:17 +08001982 .agp_destroy_pages = agp_generic_destroy_pages,
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001983 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001984};
1985
Dave Jonese5524f32007-02-22 18:41:28 -05001986static const struct agp_bridge_driver intel_810_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001987 .owner = THIS_MODULE,
1988 .aperture_sizes = intel_i810_sizes,
1989 .size_type = FIXED_APER_SIZE,
1990 .num_aperture_sizes = 2,
Joe Perchesc7258012008-03-26 14:10:02 -07001991 .needs_scratch_page = true,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001992 .configure = intel_i810_configure,
1993 .fetch_size = intel_i810_fetch_size,
1994 .cleanup = intel_i810_cleanup,
1995 .tlb_flush = intel_i810_tlbflush,
1996 .mask_memory = intel_i810_mask_memory,
1997 .masks = intel_i810_masks,
1998 .agp_enable = intel_i810_agp_enable,
1999 .cache_flush = global_cache_flush,
2000 .create_gatt_table = agp_generic_create_gatt_table,
2001 .free_gatt_table = agp_generic_free_gatt_table,
2002 .insert_memory = intel_i810_insert_entries,
2003 .remove_memory = intel_i810_remove_entries,
2004 .alloc_by_type = intel_i810_alloc_by_type,
2005 .free_by_type = intel_i810_free_by_type,
2006 .agp_alloc_page = agp_generic_alloc_page,
Shaohua Li37acee12008-08-21 10:46:11 +08002007 .agp_alloc_pages = agp_generic_alloc_pages,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002008 .agp_destroy_page = agp_generic_destroy_page,
Shaohua Libd079282008-08-21 10:46:17 +08002009 .agp_destroy_pages = agp_generic_destroy_pages,
Thomas Hellstroma030ce42007-01-23 10:33:43 +01002010 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002011};
2012
Dave Jonese5524f32007-02-22 18:41:28 -05002013static const struct agp_bridge_driver intel_815_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002014 .owner = THIS_MODULE,
2015 .aperture_sizes = intel_815_sizes,
2016 .size_type = U8_APER_SIZE,
2017 .num_aperture_sizes = 2,
2018 .configure = intel_815_configure,
2019 .fetch_size = intel_815_fetch_size,
2020 .cleanup = intel_8xx_cleanup,
2021 .tlb_flush = intel_8xx_tlbflush,
2022 .mask_memory = agp_generic_mask_memory,
2023 .masks = intel_generic_masks,
2024 .agp_enable = agp_generic_enable,
2025 .cache_flush = global_cache_flush,
2026 .create_gatt_table = agp_generic_create_gatt_table,
2027 .free_gatt_table = agp_generic_free_gatt_table,
2028 .insert_memory = agp_generic_insert_memory,
2029 .remove_memory = agp_generic_remove_memory,
2030 .alloc_by_type = agp_generic_alloc_by_type,
2031 .free_by_type = agp_generic_free_by_type,
2032 .agp_alloc_page = agp_generic_alloc_page,
Shaohua Li37acee12008-08-21 10:46:11 +08002033 .agp_alloc_pages = agp_generic_alloc_pages,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002034 .agp_destroy_page = agp_generic_destroy_page,
Shaohua Libd079282008-08-21 10:46:17 +08002035 .agp_destroy_pages = agp_generic_destroy_pages,
Dave Airlie62c96b92008-06-19 14:27:53 +10002036 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002037};
2038
Dave Jonese5524f32007-02-22 18:41:28 -05002039static const struct agp_bridge_driver intel_830_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002040 .owner = THIS_MODULE,
2041 .aperture_sizes = intel_i830_sizes,
2042 .size_type = FIXED_APER_SIZE,
Dave Jonesc14635e2006-09-06 11:59:35 -04002043 .num_aperture_sizes = 4,
Joe Perchesc7258012008-03-26 14:10:02 -07002044 .needs_scratch_page = true,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002045 .configure = intel_i830_configure,
2046 .fetch_size = intel_i830_fetch_size,
2047 .cleanup = intel_i830_cleanup,
2048 .tlb_flush = intel_i810_tlbflush,
2049 .mask_memory = intel_i810_mask_memory,
2050 .masks = intel_i810_masks,
2051 .agp_enable = intel_i810_agp_enable,
2052 .cache_flush = global_cache_flush,
2053 .create_gatt_table = intel_i830_create_gatt_table,
2054 .free_gatt_table = intel_i830_free_gatt_table,
2055 .insert_memory = intel_i830_insert_entries,
2056 .remove_memory = intel_i830_remove_entries,
2057 .alloc_by_type = intel_i830_alloc_by_type,
2058 .free_by_type = intel_i810_free_by_type,
2059 .agp_alloc_page = agp_generic_alloc_page,
Shaohua Li37acee12008-08-21 10:46:11 +08002060 .agp_alloc_pages = agp_generic_alloc_pages,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002061 .agp_destroy_page = agp_generic_destroy_page,
Shaohua Libd079282008-08-21 10:46:17 +08002062 .agp_destroy_pages = agp_generic_destroy_pages,
Thomas Hellstroma030ce42007-01-23 10:33:43 +01002063 .agp_type_to_mask_type = intel_i830_type_to_mask_type,
Dave Airlie2162e6a2007-11-21 16:36:31 +10002064 .chipset_flush = intel_i830_chipset_flush,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002065};
2066
Dave Jonese5524f32007-02-22 18:41:28 -05002067static const struct agp_bridge_driver intel_820_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002068 .owner = THIS_MODULE,
2069 .aperture_sizes = intel_8xx_sizes,
2070 .size_type = U8_APER_SIZE,
2071 .num_aperture_sizes = 7,
2072 .configure = intel_820_configure,
2073 .fetch_size = intel_8xx_fetch_size,
2074 .cleanup = intel_820_cleanup,
2075 .tlb_flush = intel_820_tlbflush,
2076 .mask_memory = agp_generic_mask_memory,
2077 .masks = intel_generic_masks,
2078 .agp_enable = agp_generic_enable,
2079 .cache_flush = global_cache_flush,
2080 .create_gatt_table = agp_generic_create_gatt_table,
2081 .free_gatt_table = agp_generic_free_gatt_table,
2082 .insert_memory = agp_generic_insert_memory,
2083 .remove_memory = agp_generic_remove_memory,
2084 .alloc_by_type = agp_generic_alloc_by_type,
2085 .free_by_type = agp_generic_free_by_type,
2086 .agp_alloc_page = agp_generic_alloc_page,
Shaohua Li37acee12008-08-21 10:46:11 +08002087 .agp_alloc_pages = agp_generic_alloc_pages,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002088 .agp_destroy_page = agp_generic_destroy_page,
Shaohua Libd079282008-08-21 10:46:17 +08002089 .agp_destroy_pages = agp_generic_destroy_pages,
Thomas Hellstroma030ce42007-01-23 10:33:43 +01002090 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002091};
2092
Dave Jonese5524f32007-02-22 18:41:28 -05002093static const struct agp_bridge_driver intel_830mp_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002094 .owner = THIS_MODULE,
2095 .aperture_sizes = intel_830mp_sizes,
2096 .size_type = U8_APER_SIZE,
2097 .num_aperture_sizes = 4,
2098 .configure = intel_830mp_configure,
2099 .fetch_size = intel_8xx_fetch_size,
2100 .cleanup = intel_8xx_cleanup,
2101 .tlb_flush = intel_8xx_tlbflush,
2102 .mask_memory = agp_generic_mask_memory,
2103 .masks = intel_generic_masks,
2104 .agp_enable = agp_generic_enable,
2105 .cache_flush = global_cache_flush,
2106 .create_gatt_table = agp_generic_create_gatt_table,
2107 .free_gatt_table = agp_generic_free_gatt_table,
2108 .insert_memory = agp_generic_insert_memory,
2109 .remove_memory = agp_generic_remove_memory,
2110 .alloc_by_type = agp_generic_alloc_by_type,
2111 .free_by_type = agp_generic_free_by_type,
2112 .agp_alloc_page = agp_generic_alloc_page,
Shaohua Li37acee12008-08-21 10:46:11 +08002113 .agp_alloc_pages = agp_generic_alloc_pages,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002114 .agp_destroy_page = agp_generic_destroy_page,
Shaohua Libd079282008-08-21 10:46:17 +08002115 .agp_destroy_pages = agp_generic_destroy_pages,
Thomas Hellstroma030ce42007-01-23 10:33:43 +01002116 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002117};
2118
Dave Jonese5524f32007-02-22 18:41:28 -05002119static const struct agp_bridge_driver intel_840_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002120 .owner = THIS_MODULE,
2121 .aperture_sizes = intel_8xx_sizes,
2122 .size_type = U8_APER_SIZE,
2123 .num_aperture_sizes = 7,
2124 .configure = intel_840_configure,
2125 .fetch_size = intel_8xx_fetch_size,
2126 .cleanup = intel_8xx_cleanup,
2127 .tlb_flush = intel_8xx_tlbflush,
2128 .mask_memory = agp_generic_mask_memory,
2129 .masks = intel_generic_masks,
2130 .agp_enable = agp_generic_enable,
2131 .cache_flush = global_cache_flush,
2132 .create_gatt_table = agp_generic_create_gatt_table,
2133 .free_gatt_table = agp_generic_free_gatt_table,
2134 .insert_memory = agp_generic_insert_memory,
2135 .remove_memory = agp_generic_remove_memory,
2136 .alloc_by_type = agp_generic_alloc_by_type,
2137 .free_by_type = agp_generic_free_by_type,
2138 .agp_alloc_page = agp_generic_alloc_page,
Shaohua Li37acee12008-08-21 10:46:11 +08002139 .agp_alloc_pages = agp_generic_alloc_pages,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002140 .agp_destroy_page = agp_generic_destroy_page,
Shaohua Libd079282008-08-21 10:46:17 +08002141 .agp_destroy_pages = agp_generic_destroy_pages,
Thomas Hellstroma030ce42007-01-23 10:33:43 +01002142 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002143};
2144
Dave Jonese5524f32007-02-22 18:41:28 -05002145static const struct agp_bridge_driver intel_845_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002146 .owner = THIS_MODULE,
2147 .aperture_sizes = intel_8xx_sizes,
2148 .size_type = U8_APER_SIZE,
2149 .num_aperture_sizes = 7,
2150 .configure = intel_845_configure,
2151 .fetch_size = intel_8xx_fetch_size,
2152 .cleanup = intel_8xx_cleanup,
2153 .tlb_flush = intel_8xx_tlbflush,
2154 .mask_memory = agp_generic_mask_memory,
2155 .masks = intel_generic_masks,
2156 .agp_enable = agp_generic_enable,
2157 .cache_flush = global_cache_flush,
2158 .create_gatt_table = agp_generic_create_gatt_table,
2159 .free_gatt_table = agp_generic_free_gatt_table,
2160 .insert_memory = agp_generic_insert_memory,
2161 .remove_memory = agp_generic_remove_memory,
2162 .alloc_by_type = agp_generic_alloc_by_type,
2163 .free_by_type = agp_generic_free_by_type,
2164 .agp_alloc_page = agp_generic_alloc_page,
Shaohua Li37acee12008-08-21 10:46:11 +08002165 .agp_alloc_pages = agp_generic_alloc_pages,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002166 .agp_destroy_page = agp_generic_destroy_page,
Shaohua Libd079282008-08-21 10:46:17 +08002167 .agp_destroy_pages = agp_generic_destroy_pages,
Thomas Hellstroma030ce42007-01-23 10:33:43 +01002168 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
Dave Airlie2162e6a2007-11-21 16:36:31 +10002169 .chipset_flush = intel_i830_chipset_flush,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002170};
2171
Dave Jonese5524f32007-02-22 18:41:28 -05002172static const struct agp_bridge_driver intel_850_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002173 .owner = THIS_MODULE,
2174 .aperture_sizes = intel_8xx_sizes,
2175 .size_type = U8_APER_SIZE,
2176 .num_aperture_sizes = 7,
2177 .configure = intel_850_configure,
2178 .fetch_size = intel_8xx_fetch_size,
2179 .cleanup = intel_8xx_cleanup,
2180 .tlb_flush = intel_8xx_tlbflush,
2181 .mask_memory = agp_generic_mask_memory,
2182 .masks = intel_generic_masks,
2183 .agp_enable = agp_generic_enable,
2184 .cache_flush = global_cache_flush,
2185 .create_gatt_table = agp_generic_create_gatt_table,
2186 .free_gatt_table = agp_generic_free_gatt_table,
2187 .insert_memory = agp_generic_insert_memory,
2188 .remove_memory = agp_generic_remove_memory,
2189 .alloc_by_type = agp_generic_alloc_by_type,
2190 .free_by_type = agp_generic_free_by_type,
2191 .agp_alloc_page = agp_generic_alloc_page,
Shaohua Li37acee12008-08-21 10:46:11 +08002192 .agp_alloc_pages = agp_generic_alloc_pages,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002193 .agp_destroy_page = agp_generic_destroy_page,
Shaohua Libd079282008-08-21 10:46:17 +08002194 .agp_destroy_pages = agp_generic_destroy_pages,
Thomas Hellstroma030ce42007-01-23 10:33:43 +01002195 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002196};
2197
Dave Jonese5524f32007-02-22 18:41:28 -05002198static const struct agp_bridge_driver intel_860_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002199 .owner = THIS_MODULE,
2200 .aperture_sizes = intel_8xx_sizes,
2201 .size_type = U8_APER_SIZE,
2202 .num_aperture_sizes = 7,
2203 .configure = intel_860_configure,
2204 .fetch_size = intel_8xx_fetch_size,
2205 .cleanup = intel_8xx_cleanup,
2206 .tlb_flush = intel_8xx_tlbflush,
2207 .mask_memory = agp_generic_mask_memory,
2208 .masks = intel_generic_masks,
2209 .agp_enable = agp_generic_enable,
2210 .cache_flush = global_cache_flush,
2211 .create_gatt_table = agp_generic_create_gatt_table,
2212 .free_gatt_table = agp_generic_free_gatt_table,
2213 .insert_memory = agp_generic_insert_memory,
2214 .remove_memory = agp_generic_remove_memory,
2215 .alloc_by_type = agp_generic_alloc_by_type,
2216 .free_by_type = agp_generic_free_by_type,
2217 .agp_alloc_page = agp_generic_alloc_page,
Shaohua Li37acee12008-08-21 10:46:11 +08002218 .agp_alloc_pages = agp_generic_alloc_pages,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002219 .agp_destroy_page = agp_generic_destroy_page,
Shaohua Libd079282008-08-21 10:46:17 +08002220 .agp_destroy_pages = agp_generic_destroy_pages,
Thomas Hellstroma030ce42007-01-23 10:33:43 +01002221 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002222};
2223
Dave Jonese5524f32007-02-22 18:41:28 -05002224static const struct agp_bridge_driver intel_915_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002225 .owner = THIS_MODULE,
2226 .aperture_sizes = intel_i830_sizes,
2227 .size_type = FIXED_APER_SIZE,
Dave Jonesc14635e2006-09-06 11:59:35 -04002228 .num_aperture_sizes = 4,
Joe Perchesc7258012008-03-26 14:10:02 -07002229 .needs_scratch_page = true,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002230 .configure = intel_i915_configure,
Eric Anholtc41e0de2006-12-19 12:57:24 -08002231 .fetch_size = intel_i9xx_fetch_size,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002232 .cleanup = intel_i915_cleanup,
2233 .tlb_flush = intel_i810_tlbflush,
2234 .mask_memory = intel_i810_mask_memory,
2235 .masks = intel_i810_masks,
2236 .agp_enable = intel_i810_agp_enable,
2237 .cache_flush = global_cache_flush,
2238 .create_gatt_table = intel_i915_create_gatt_table,
2239 .free_gatt_table = intel_i830_free_gatt_table,
2240 .insert_memory = intel_i915_insert_entries,
2241 .remove_memory = intel_i915_remove_entries,
2242 .alloc_by_type = intel_i830_alloc_by_type,
2243 .free_by_type = intel_i810_free_by_type,
2244 .agp_alloc_page = agp_generic_alloc_page,
Shaohua Li37acee12008-08-21 10:46:11 +08002245 .agp_alloc_pages = agp_generic_alloc_pages,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002246 .agp_destroy_page = agp_generic_destroy_page,
Shaohua Libd079282008-08-21 10:46:17 +08002247 .agp_destroy_pages = agp_generic_destroy_pages,
Thomas Hellstroma030ce42007-01-23 10:33:43 +01002248 .agp_type_to_mask_type = intel_i830_type_to_mask_type,
Dave Airlie6c00a612007-10-29 18:06:10 +10002249 .chipset_flush = intel_i915_chipset_flush,
Zhenyu Wang17661682009-07-27 12:59:57 +01002250#ifdef USE_PCI_DMA_API
2251 .agp_map_page = intel_agp_map_page,
2252 .agp_unmap_page = intel_agp_unmap_page,
2253 .agp_map_memory = intel_agp_map_memory,
2254 .agp_unmap_memory = intel_agp_unmap_memory,
2255#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002256};
2257
Dave Jonese5524f32007-02-22 18:41:28 -05002258static const struct agp_bridge_driver intel_i965_driver = {
Dave Airlie62c96b92008-06-19 14:27:53 +10002259 .owner = THIS_MODULE,
2260 .aperture_sizes = intel_i830_sizes,
2261 .size_type = FIXED_APER_SIZE,
2262 .num_aperture_sizes = 4,
2263 .needs_scratch_page = true,
Dave Airlie0e480e52008-06-19 14:57:31 +10002264 .configure = intel_i915_configure,
2265 .fetch_size = intel_i9xx_fetch_size,
Dave Airlie62c96b92008-06-19 14:27:53 +10002266 .cleanup = intel_i915_cleanup,
2267 .tlb_flush = intel_i810_tlbflush,
2268 .mask_memory = intel_i965_mask_memory,
2269 .masks = intel_i810_masks,
2270 .agp_enable = intel_i810_agp_enable,
2271 .cache_flush = global_cache_flush,
2272 .create_gatt_table = intel_i965_create_gatt_table,
2273 .free_gatt_table = intel_i830_free_gatt_table,
2274 .insert_memory = intel_i915_insert_entries,
2275 .remove_memory = intel_i915_remove_entries,
2276 .alloc_by_type = intel_i830_alloc_by_type,
2277 .free_by_type = intel_i810_free_by_type,
2278 .agp_alloc_page = agp_generic_alloc_page,
Shaohua Li37acee12008-08-21 10:46:11 +08002279 .agp_alloc_pages = agp_generic_alloc_pages,
Dave Airlie62c96b92008-06-19 14:27:53 +10002280 .agp_destroy_page = agp_generic_destroy_page,
Shaohua Libd079282008-08-21 10:46:17 +08002281 .agp_destroy_pages = agp_generic_destroy_pages,
Dave Airlie62c96b92008-06-19 14:27:53 +10002282 .agp_type_to_mask_type = intel_i830_type_to_mask_type,
Dave Airlie6c00a612007-10-29 18:06:10 +10002283 .chipset_flush = intel_i915_chipset_flush,
Zhenyu Wang17661682009-07-27 12:59:57 +01002284#ifdef USE_PCI_DMA_API
2285 .agp_map_page = intel_agp_map_page,
2286 .agp_unmap_page = intel_agp_unmap_page,
2287 .agp_map_memory = intel_agp_map_memory,
2288 .agp_unmap_memory = intel_agp_unmap_memory,
2289#endif
Eric Anholt65c25aa2006-09-06 11:57:18 -04002290};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002291
Dave Jonese5524f32007-02-22 18:41:28 -05002292static const struct agp_bridge_driver intel_7505_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002293 .owner = THIS_MODULE,
2294 .aperture_sizes = intel_8xx_sizes,
2295 .size_type = U8_APER_SIZE,
2296 .num_aperture_sizes = 7,
2297 .configure = intel_7505_configure,
2298 .fetch_size = intel_8xx_fetch_size,
2299 .cleanup = intel_8xx_cleanup,
2300 .tlb_flush = intel_8xx_tlbflush,
2301 .mask_memory = agp_generic_mask_memory,
2302 .masks = intel_generic_masks,
2303 .agp_enable = agp_generic_enable,
2304 .cache_flush = global_cache_flush,
2305 .create_gatt_table = agp_generic_create_gatt_table,
2306 .free_gatt_table = agp_generic_free_gatt_table,
2307 .insert_memory = agp_generic_insert_memory,
2308 .remove_memory = agp_generic_remove_memory,
2309 .alloc_by_type = agp_generic_alloc_by_type,
2310 .free_by_type = agp_generic_free_by_type,
2311 .agp_alloc_page = agp_generic_alloc_page,
Shaohua Li37acee12008-08-21 10:46:11 +08002312 .agp_alloc_pages = agp_generic_alloc_pages,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002313 .agp_destroy_page = agp_generic_destroy_page,
Shaohua Libd079282008-08-21 10:46:17 +08002314 .agp_destroy_pages = agp_generic_destroy_pages,
Thomas Hellstroma030ce42007-01-23 10:33:43 +01002315 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002316};
2317
Wang Zhenyu874808c62007-06-06 11:16:25 +08002318static const struct agp_bridge_driver intel_g33_driver = {
Dave Airlie62c96b92008-06-19 14:27:53 +10002319 .owner = THIS_MODULE,
2320 .aperture_sizes = intel_i830_sizes,
2321 .size_type = FIXED_APER_SIZE,
2322 .num_aperture_sizes = 4,
2323 .needs_scratch_page = true,
2324 .configure = intel_i915_configure,
2325 .fetch_size = intel_i9xx_fetch_size,
2326 .cleanup = intel_i915_cleanup,
2327 .tlb_flush = intel_i810_tlbflush,
2328 .mask_memory = intel_i965_mask_memory,
2329 .masks = intel_i810_masks,
2330 .agp_enable = intel_i810_agp_enable,
2331 .cache_flush = global_cache_flush,
2332 .create_gatt_table = intel_i915_create_gatt_table,
2333 .free_gatt_table = intel_i830_free_gatt_table,
2334 .insert_memory = intel_i915_insert_entries,
2335 .remove_memory = intel_i915_remove_entries,
2336 .alloc_by_type = intel_i830_alloc_by_type,
2337 .free_by_type = intel_i810_free_by_type,
2338 .agp_alloc_page = agp_generic_alloc_page,
Shaohua Li37acee12008-08-21 10:46:11 +08002339 .agp_alloc_pages = agp_generic_alloc_pages,
Dave Airlie62c96b92008-06-19 14:27:53 +10002340 .agp_destroy_page = agp_generic_destroy_page,
Shaohua Libd079282008-08-21 10:46:17 +08002341 .agp_destroy_pages = agp_generic_destroy_pages,
Dave Airlie62c96b92008-06-19 14:27:53 +10002342 .agp_type_to_mask_type = intel_i830_type_to_mask_type,
Dave Airlie6c00a612007-10-29 18:06:10 +10002343 .chipset_flush = intel_i915_chipset_flush,
Zhenyu Wang17661682009-07-27 12:59:57 +01002344#ifdef USE_PCI_DMA_API
2345 .agp_map_page = intel_agp_map_page,
2346 .agp_unmap_page = intel_agp_unmap_page,
2347 .agp_map_memory = intel_agp_map_memory,
2348 .agp_unmap_memory = intel_agp_unmap_memory,
2349#endif
Wang Zhenyu874808c62007-06-06 11:16:25 +08002350};
Wang Zhenyu9614ece2007-05-30 09:45:58 +08002351
2352static int find_gmch(u16 device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002353{
Wang Zhenyu9614ece2007-05-30 09:45:58 +08002354 struct pci_dev *gmch_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002355
Wang Zhenyu9614ece2007-05-30 09:45:58 +08002356 gmch_device = pci_get_device(PCI_VENDOR_ID_INTEL, device, NULL);
2357 if (gmch_device && PCI_FUNC(gmch_device->devfn) != 0) {
2358 gmch_device = pci_get_device(PCI_VENDOR_ID_INTEL,
Dave Airlief011ae72008-01-25 11:23:04 +10002359 device, gmch_device);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002360 }
2361
Wang Zhenyu9614ece2007-05-30 09:45:58 +08002362 if (!gmch_device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002363 return 0;
2364
Wang Zhenyu9614ece2007-05-30 09:45:58 +08002365 intel_private.pcidev = gmch_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002366 return 1;
2367}
2368
Wang Zhenyu9614ece2007-05-30 09:45:58 +08002369/* Table to describe Intel GMCH and AGP/PCIE GART drivers. At least one of
2370 * driver and gmch_driver must be non-null, and find_gmch will determine
2371 * which one should be used if a gmch_chip_id is present.
2372 */
2373static const struct intel_driver_description {
2374 unsigned int chip_id;
2375 unsigned int gmch_chip_id;
Wang Zhenyu88889852007-06-14 10:01:04 +08002376 unsigned int multi_gmch_chip; /* if we have more gfx chip type on this HB. */
Wang Zhenyu9614ece2007-05-30 09:45:58 +08002377 char *name;
2378 const struct agp_bridge_driver *driver;
2379 const struct agp_bridge_driver *gmch_driver;
2380} intel_agp_chipsets[] = {
Wang Zhenyu88889852007-06-14 10:01:04 +08002381 { PCI_DEVICE_ID_INTEL_82443LX_0, 0, 0, "440LX", &intel_generic_driver, NULL },
2382 { PCI_DEVICE_ID_INTEL_82443BX_0, 0, 0, "440BX", &intel_generic_driver, NULL },
2383 { PCI_DEVICE_ID_INTEL_82443GX_0, 0, 0, "440GX", &intel_generic_driver, NULL },
2384 { PCI_DEVICE_ID_INTEL_82810_MC1, PCI_DEVICE_ID_INTEL_82810_IG1, 0, "i810",
Wang Zhenyu9614ece2007-05-30 09:45:58 +08002385 NULL, &intel_810_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +08002386 { PCI_DEVICE_ID_INTEL_82810_MC3, PCI_DEVICE_ID_INTEL_82810_IG3, 0, "i810",
Wang Zhenyu9614ece2007-05-30 09:45:58 +08002387 NULL, &intel_810_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +08002388 { PCI_DEVICE_ID_INTEL_82810E_MC, PCI_DEVICE_ID_INTEL_82810E_IG, 0, "i810",
Wang Zhenyu9614ece2007-05-30 09:45:58 +08002389 NULL, &intel_810_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +08002390 { PCI_DEVICE_ID_INTEL_82815_MC, PCI_DEVICE_ID_INTEL_82815_CGC, 0, "i815",
2391 &intel_815_driver, &intel_810_driver },
2392 { PCI_DEVICE_ID_INTEL_82820_HB, 0, 0, "i820", &intel_820_driver, NULL },
2393 { PCI_DEVICE_ID_INTEL_82820_UP_HB, 0, 0, "i820", &intel_820_driver, NULL },
2394 { PCI_DEVICE_ID_INTEL_82830_HB, PCI_DEVICE_ID_INTEL_82830_CGC, 0, "830M",
Wang Zhenyu9614ece2007-05-30 09:45:58 +08002395 &intel_830mp_driver, &intel_830_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +08002396 { PCI_DEVICE_ID_INTEL_82840_HB, 0, 0, "i840", &intel_840_driver, NULL },
2397 { PCI_DEVICE_ID_INTEL_82845_HB, 0, 0, "845G", &intel_845_driver, NULL },
2398 { PCI_DEVICE_ID_INTEL_82845G_HB, PCI_DEVICE_ID_INTEL_82845G_IG, 0, "830M",
Wang Zhenyu9614ece2007-05-30 09:45:58 +08002399 &intel_845_driver, &intel_830_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +08002400 { PCI_DEVICE_ID_INTEL_82850_HB, 0, 0, "i850", &intel_850_driver, NULL },
Stefan Husemann347486b2009-04-13 14:40:10 -07002401 { PCI_DEVICE_ID_INTEL_82854_HB, PCI_DEVICE_ID_INTEL_82854_IG, 0, "854",
2402 &intel_845_driver, &intel_830_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +08002403 { PCI_DEVICE_ID_INTEL_82855PM_HB, 0, 0, "855PM", &intel_845_driver, NULL },
2404 { PCI_DEVICE_ID_INTEL_82855GM_HB, PCI_DEVICE_ID_INTEL_82855GM_IG, 0, "855GM",
Wang Zhenyu9614ece2007-05-30 09:45:58 +08002405 &intel_845_driver, &intel_830_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +08002406 { PCI_DEVICE_ID_INTEL_82860_HB, 0, 0, "i860", &intel_860_driver, NULL },
2407 { PCI_DEVICE_ID_INTEL_82865_HB, PCI_DEVICE_ID_INTEL_82865_IG, 0, "865",
Wang Zhenyu9614ece2007-05-30 09:45:58 +08002408 &intel_845_driver, &intel_830_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +08002409 { PCI_DEVICE_ID_INTEL_82875_HB, 0, 0, "i875", &intel_845_driver, NULL },
Carlos Martíne914a362008-01-24 10:34:09 +10002410 { PCI_DEVICE_ID_INTEL_E7221_HB, PCI_DEVICE_ID_INTEL_E7221_IG, 0, "E7221 (i915)",
2411 NULL, &intel_915_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +08002412 { PCI_DEVICE_ID_INTEL_82915G_HB, PCI_DEVICE_ID_INTEL_82915G_IG, 0, "915G",
Wang Zhenyu47d46372007-06-21 13:43:18 +08002413 NULL, &intel_915_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +08002414 { PCI_DEVICE_ID_INTEL_82915GM_HB, PCI_DEVICE_ID_INTEL_82915GM_IG, 0, "915GM",
Wang Zhenyu47d46372007-06-21 13:43:18 +08002415 NULL, &intel_915_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +08002416 { PCI_DEVICE_ID_INTEL_82945G_HB, PCI_DEVICE_ID_INTEL_82945G_IG, 0, "945G",
Wang Zhenyu47d46372007-06-21 13:43:18 +08002417 NULL, &intel_915_driver },
Zhenyu Wangdde47872007-07-26 09:18:09 +08002418 { PCI_DEVICE_ID_INTEL_82945GM_HB, PCI_DEVICE_ID_INTEL_82945GM_IG, 0, "945GM",
Wang Zhenyu47d46372007-06-21 13:43:18 +08002419 NULL, &intel_915_driver },
Zhenyu Wangdde47872007-07-26 09:18:09 +08002420 { PCI_DEVICE_ID_INTEL_82945GME_HB, PCI_DEVICE_ID_INTEL_82945GME_IG, 0, "945GME",
Wang Zhenyu47d46372007-06-21 13:43:18 +08002421 NULL, &intel_915_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +08002422 { PCI_DEVICE_ID_INTEL_82946GZ_HB, PCI_DEVICE_ID_INTEL_82946GZ_IG, 0, "946GZ",
Wang Zhenyu47d46372007-06-21 13:43:18 +08002423 NULL, &intel_i965_driver },
Zhenyu Wang9119f852008-01-23 15:49:26 +10002424 { PCI_DEVICE_ID_INTEL_82G35_HB, PCI_DEVICE_ID_INTEL_82G35_IG, 0, "G35",
Wang Zhenyu47d46372007-06-21 13:43:18 +08002425 NULL, &intel_i965_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +08002426 { PCI_DEVICE_ID_INTEL_82965Q_HB, PCI_DEVICE_ID_INTEL_82965Q_IG, 0, "965Q",
Wang Zhenyu47d46372007-06-21 13:43:18 +08002427 NULL, &intel_i965_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +08002428 { PCI_DEVICE_ID_INTEL_82965G_HB, PCI_DEVICE_ID_INTEL_82965G_IG, 0, "965G",
Wang Zhenyu47d46372007-06-21 13:43:18 +08002429 NULL, &intel_i965_driver },
Zhenyu Wangdde47872007-07-26 09:18:09 +08002430 { PCI_DEVICE_ID_INTEL_82965GM_HB, PCI_DEVICE_ID_INTEL_82965GM_IG, 0, "965GM",
Wang Zhenyu47d46372007-06-21 13:43:18 +08002431 NULL, &intel_i965_driver },
Zhenyu Wangdde47872007-07-26 09:18:09 +08002432 { PCI_DEVICE_ID_INTEL_82965GME_HB, PCI_DEVICE_ID_INTEL_82965GME_IG, 0, "965GME/GLE",
Wang Zhenyu47d46372007-06-21 13:43:18 +08002433 NULL, &intel_i965_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +08002434 { PCI_DEVICE_ID_INTEL_7505_0, 0, 0, "E7505", &intel_7505_driver, NULL },
2435 { PCI_DEVICE_ID_INTEL_7205_0, 0, 0, "E7205", &intel_7505_driver, NULL },
2436 { PCI_DEVICE_ID_INTEL_G33_HB, PCI_DEVICE_ID_INTEL_G33_IG, 0, "G33",
Wang Zhenyu47d46372007-06-21 13:43:18 +08002437 NULL, &intel_g33_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +08002438 { PCI_DEVICE_ID_INTEL_Q35_HB, PCI_DEVICE_ID_INTEL_Q35_IG, 0, "Q35",
Wang Zhenyu47d46372007-06-21 13:43:18 +08002439 NULL, &intel_g33_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +08002440 { PCI_DEVICE_ID_INTEL_Q33_HB, PCI_DEVICE_ID_INTEL_Q33_IG, 0, "Q33",
Wang Zhenyu47d46372007-06-21 13:43:18 +08002441 NULL, &intel_g33_driver },
Zhenyu Wangaf86d4b2010-02-10 10:39:33 +08002442 { PCI_DEVICE_ID_INTEL_PINEVIEW_M_HB, PCI_DEVICE_ID_INTEL_PINEVIEW_M_IG, 0, "GMA3150",
Shaohua Li21778322009-02-23 15:19:16 +08002443 NULL, &intel_g33_driver },
Zhenyu Wangaf86d4b2010-02-10 10:39:33 +08002444 { PCI_DEVICE_ID_INTEL_PINEVIEW_HB, PCI_DEVICE_ID_INTEL_PINEVIEW_IG, 0, "GMA3150",
Shaohua Li21778322009-02-23 15:19:16 +08002445 NULL, &intel_g33_driver },
Zhenyu Wang99d32bd2008-07-30 12:26:50 -07002446 { PCI_DEVICE_ID_INTEL_GM45_HB, PCI_DEVICE_ID_INTEL_GM45_IG, 0,
Adam Jackson107f5172009-12-03 17:14:41 -05002447 "GM45", NULL, &intel_i965_driver },
2448 { PCI_DEVICE_ID_INTEL_EAGLELAKE_HB, PCI_DEVICE_ID_INTEL_EAGLELAKE_IG, 0,
2449 "Eaglelake", NULL, &intel_i965_driver },
Zhenyu Wang25ce77a2008-06-19 14:17:58 +10002450 { PCI_DEVICE_ID_INTEL_Q45_HB, PCI_DEVICE_ID_INTEL_Q45_IG, 0,
2451 "Q45/Q43", NULL, &intel_i965_driver },
2452 { PCI_DEVICE_ID_INTEL_G45_HB, PCI_DEVICE_ID_INTEL_G45_IG, 0,
2453 "G45/G43", NULL, &intel_i965_driver },
Fabian Henze38d8a952009-09-08 00:59:58 +08002454 { PCI_DEVICE_ID_INTEL_B43_HB, PCI_DEVICE_ID_INTEL_B43_IG, 0,
2455 "B43", NULL, &intel_i965_driver },
Zhenyu Wanga50ccc62008-11-17 14:39:00 +08002456 { PCI_DEVICE_ID_INTEL_G41_HB, PCI_DEVICE_ID_INTEL_G41_IG, 0,
2457 "G41", NULL, &intel_i965_driver },
Adam Jackson107f5172009-12-03 17:14:41 -05002458 { PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_D_IG, 0,
Zhenyu Wangaf86d4b2010-02-10 10:39:33 +08002459 "HD Graphics", NULL, &intel_i965_driver },
Adam Jackson107f5172009-12-03 17:14:41 -05002460 { PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG, 0,
Zhenyu Wangaf86d4b2010-02-10 10:39:33 +08002461 "HD Graphics", NULL, &intel_i965_driver },
Adam Jackson107f5172009-12-03 17:14:41 -05002462 { PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG, 0,
Zhenyu Wangaf86d4b2010-02-10 10:39:33 +08002463 "HD Graphics", NULL, &intel_i965_driver },
Dave Airlie3ff99162009-12-08 14:03:47 +10002464 { PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG, 0,
Zhenyu Wangaf86d4b2010-02-10 10:39:33 +08002465 "HD Graphics", NULL, &intel_i965_driver },
Eric Anholt1089e302009-10-22 16:10:52 -07002466 { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_IG, 0,
2467 "Sandybridge", NULL, &intel_i965_driver },
Eric Anholt954bce52010-01-07 16:21:46 -08002468 { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_IG, 0,
2469 "Sandybridge", NULL, &intel_i965_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +08002470 { 0, 0, 0, NULL, NULL, NULL }
Wang Zhenyu9614ece2007-05-30 09:45:58 +08002471};
2472
Linus Torvalds1da177e2005-04-16 15:20:36 -07002473static int __devinit agp_intel_probe(struct pci_dev *pdev,
2474 const struct pci_device_id *ent)
2475{
2476 struct agp_bridge_data *bridge;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002477 u8 cap_ptr = 0;
2478 struct resource *r;
Zhenyu Wang1f7a6e32010-02-23 14:05:24 +08002479 int i, err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002480
2481 cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
2482
2483 bridge = agp_alloc_bridge();
2484 if (!bridge)
2485 return -ENOMEM;
2486
Wang Zhenyu9614ece2007-05-30 09:45:58 +08002487 for (i = 0; intel_agp_chipsets[i].name != NULL; i++) {
2488 /* In case that multiple models of gfx chip may
2489 stand on same host bridge type, this can be
2490 sure we detect the right IGD. */
Wang Zhenyu88889852007-06-14 10:01:04 +08002491 if (pdev->device == intel_agp_chipsets[i].chip_id) {
2492 if ((intel_agp_chipsets[i].gmch_chip_id != 0) &&
2493 find_gmch(intel_agp_chipsets[i].gmch_chip_id)) {
2494 bridge->driver =
2495 intel_agp_chipsets[i].gmch_driver;
2496 break;
2497 } else if (intel_agp_chipsets[i].multi_gmch_chip) {
2498 continue;
2499 } else {
2500 bridge->driver = intel_agp_chipsets[i].driver;
2501 break;
2502 }
2503 }
Wang Zhenyu9614ece2007-05-30 09:45:58 +08002504 }
2505
2506 if (intel_agp_chipsets[i].name == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002507 if (cap_ptr)
Bjorn Helgaase3cf6952008-07-30 12:26:51 -07002508 dev_warn(&pdev->dev, "unsupported Intel chipset [%04x/%04x]\n",
2509 pdev->vendor, pdev->device);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002510 agp_put_bridge(bridge);
2511 return -ENODEV;
Wang Zhenyu9614ece2007-05-30 09:45:58 +08002512 }
2513
Wang Zhenyu9614ece2007-05-30 09:45:58 +08002514 if (bridge->driver == NULL) {
Wang Zhenyu47d46372007-06-21 13:43:18 +08002515 /* bridge has no AGP and no IGD detected */
2516 if (cap_ptr)
Bjorn Helgaase3cf6952008-07-30 12:26:51 -07002517 dev_warn(&pdev->dev, "can't find bridge device (chip_id: %04x)\n",
2518 intel_agp_chipsets[i].gmch_chip_id);
Wang Zhenyu9614ece2007-05-30 09:45:58 +08002519 agp_put_bridge(bridge);
2520 return -ENODEV;
Dave Airlief011ae72008-01-25 11:23:04 +10002521 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002522
2523 bridge->dev = pdev;
2524 bridge->capndx = cap_ptr;
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08002525 bridge->dev_private_data = &intel_private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002526
Bjorn Helgaase3cf6952008-07-30 12:26:51 -07002527 dev_info(&pdev->dev, "Intel %s Chipset\n", intel_agp_chipsets[i].name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002528
2529 /*
2530 * The following fixes the case where the BIOS has "forgotten" to
2531 * provide an address range for the GART.
2532 * 20030610 - hamish@zot.org
2533 */
2534 r = &pdev->resource[0];
2535 if (!r->start && r->end) {
Dave Jones6a92a4e2006-02-28 00:54:25 -05002536 if (pci_assign_resource(pdev, 0)) {
Bjorn Helgaase3cf6952008-07-30 12:26:51 -07002537 dev_err(&pdev->dev, "can't assign resource 0\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002538 agp_put_bridge(bridge);
2539 return -ENODEV;
2540 }
2541 }
2542
2543 /*
2544 * If the device has not been properly setup, the following will catch
2545 * the problem and should stop the system from crashing.
2546 * 20030610 - hamish@zot.org
2547 */
2548 if (pci_enable_device(pdev)) {
Bjorn Helgaase3cf6952008-07-30 12:26:51 -07002549 dev_err(&pdev->dev, "can't enable PCI device\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002550 agp_put_bridge(bridge);
2551 return -ENODEV;
2552 }
2553
2554 /* Fill in the mode register */
2555 if (cap_ptr) {
2556 pci_read_config_dword(pdev,
2557 bridge->capndx+PCI_AGP_STATUS,
2558 &bridge->mode);
2559 }
2560
Zhenyu Wang9b974cc2010-01-05 11:25:06 +08002561 if (bridge->driver->mask_memory == intel_i965_mask_memory) {
David Woodhouseec402ba2009-11-18 10:22:46 +00002562 if (pci_set_dma_mask(intel_private.pcidev, DMA_BIT_MASK(36)))
2563 dev_err(&intel_private.pcidev->dev,
2564 "set gfx device dma mask 36bit failed!\n");
Zhenyu Wang9b974cc2010-01-05 11:25:06 +08002565 else
2566 pci_set_consistent_dma_mask(intel_private.pcidev,
2567 DMA_BIT_MASK(36));
2568 }
David Woodhouseec402ba2009-11-18 10:22:46 +00002569
Linus Torvalds1da177e2005-04-16 15:20:36 -07002570 pci_set_drvdata(pdev, bridge);
Zhenyu Wang1f7a6e32010-02-23 14:05:24 +08002571 err = agp_add_bridge(bridge);
2572 if (!err)
2573 intel_agp_enabled = 1;
2574 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002575}
2576
2577static void __devexit agp_intel_remove(struct pci_dev *pdev)
2578{
2579 struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
2580
2581 agp_remove_bridge(bridge);
2582
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08002583 if (intel_private.pcidev)
2584 pci_dev_put(intel_private.pcidev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002585
2586 agp_put_bridge(bridge);
2587}
2588
Alexey Dobriyan85be7d62006-08-12 02:02:02 +04002589#ifdef CONFIG_PM
Linus Torvalds1da177e2005-04-16 15:20:36 -07002590static int agp_intel_resume(struct pci_dev *pdev)
2591{
2592 struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
Keith Packarda8c84df2008-07-31 15:48:07 +10002593 int ret_val;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002594
Linus Torvalds1da177e2005-04-16 15:20:36 -07002595 if (bridge->driver == &intel_generic_driver)
2596 intel_configure();
2597 else if (bridge->driver == &intel_850_driver)
2598 intel_850_configure();
2599 else if (bridge->driver == &intel_845_driver)
2600 intel_845_configure();
2601 else if (bridge->driver == &intel_830mp_driver)
2602 intel_830mp_configure();
2603 else if (bridge->driver == &intel_915_driver)
2604 intel_i915_configure();
2605 else if (bridge->driver == &intel_830_driver)
2606 intel_i830_configure();
2607 else if (bridge->driver == &intel_810_driver)
2608 intel_i810_configure();
Dave Jones08da3f42006-09-10 21:09:26 -04002609 else if (bridge->driver == &intel_i965_driver)
2610 intel_i915_configure();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002611
Keith Packarda8c84df2008-07-31 15:48:07 +10002612 ret_val = agp_rebind_memory();
2613 if (ret_val != 0)
2614 return ret_val;
2615
Linus Torvalds1da177e2005-04-16 15:20:36 -07002616 return 0;
2617}
Alexey Dobriyan85be7d62006-08-12 02:02:02 +04002618#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002619
2620static struct pci_device_id agp_intel_pci_table[] = {
2621#define ID(x) \
2622 { \
2623 .class = (PCI_CLASS_BRIDGE_HOST << 8), \
2624 .class_mask = ~0, \
2625 .vendor = PCI_VENDOR_ID_INTEL, \
2626 .device = x, \
2627 .subvendor = PCI_ANY_ID, \
2628 .subdevice = PCI_ANY_ID, \
2629 }
2630 ID(PCI_DEVICE_ID_INTEL_82443LX_0),
2631 ID(PCI_DEVICE_ID_INTEL_82443BX_0),
2632 ID(PCI_DEVICE_ID_INTEL_82443GX_0),
2633 ID(PCI_DEVICE_ID_INTEL_82810_MC1),
2634 ID(PCI_DEVICE_ID_INTEL_82810_MC3),
2635 ID(PCI_DEVICE_ID_INTEL_82810E_MC),
2636 ID(PCI_DEVICE_ID_INTEL_82815_MC),
2637 ID(PCI_DEVICE_ID_INTEL_82820_HB),
2638 ID(PCI_DEVICE_ID_INTEL_82820_UP_HB),
2639 ID(PCI_DEVICE_ID_INTEL_82830_HB),
2640 ID(PCI_DEVICE_ID_INTEL_82840_HB),
2641 ID(PCI_DEVICE_ID_INTEL_82845_HB),
2642 ID(PCI_DEVICE_ID_INTEL_82845G_HB),
2643 ID(PCI_DEVICE_ID_INTEL_82850_HB),
Stefan Husemann347486b2009-04-13 14:40:10 -07002644 ID(PCI_DEVICE_ID_INTEL_82854_HB),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002645 ID(PCI_DEVICE_ID_INTEL_82855PM_HB),
2646 ID(PCI_DEVICE_ID_INTEL_82855GM_HB),
2647 ID(PCI_DEVICE_ID_INTEL_82860_HB),
2648 ID(PCI_DEVICE_ID_INTEL_82865_HB),
2649 ID(PCI_DEVICE_ID_INTEL_82875_HB),
2650 ID(PCI_DEVICE_ID_INTEL_7505_0),
2651 ID(PCI_DEVICE_ID_INTEL_7205_0),
Carlos Martíne914a362008-01-24 10:34:09 +10002652 ID(PCI_DEVICE_ID_INTEL_E7221_HB),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002653 ID(PCI_DEVICE_ID_INTEL_82915G_HB),
2654 ID(PCI_DEVICE_ID_INTEL_82915GM_HB),
Alan Hourihaned0de98f2005-05-31 19:50:49 +01002655 ID(PCI_DEVICE_ID_INTEL_82945G_HB),
Alan Hourihane3b0e8ea2006-01-19 14:08:40 +00002656 ID(PCI_DEVICE_ID_INTEL_82945GM_HB),
Zhenyu Wangdde47872007-07-26 09:18:09 +08002657 ID(PCI_DEVICE_ID_INTEL_82945GME_HB),
Adam Jackson107f5172009-12-03 17:14:41 -05002658 ID(PCI_DEVICE_ID_INTEL_PINEVIEW_M_HB),
2659 ID(PCI_DEVICE_ID_INTEL_PINEVIEW_HB),
Eric Anholt65c25aa2006-09-06 11:57:18 -04002660 ID(PCI_DEVICE_ID_INTEL_82946GZ_HB),
Zhenyu Wang9119f852008-01-23 15:49:26 +10002661 ID(PCI_DEVICE_ID_INTEL_82G35_HB),
Eric Anholt65c25aa2006-09-06 11:57:18 -04002662 ID(PCI_DEVICE_ID_INTEL_82965Q_HB),
2663 ID(PCI_DEVICE_ID_INTEL_82965G_HB),
Wang Zhenyu4598af32007-04-09 08:51:36 +08002664 ID(PCI_DEVICE_ID_INTEL_82965GM_HB),
Zhenyu Wangdde47872007-07-26 09:18:09 +08002665 ID(PCI_DEVICE_ID_INTEL_82965GME_HB),
Wang Zhenyu874808c62007-06-06 11:16:25 +08002666 ID(PCI_DEVICE_ID_INTEL_G33_HB),
2667 ID(PCI_DEVICE_ID_INTEL_Q35_HB),
2668 ID(PCI_DEVICE_ID_INTEL_Q33_HB),
Zhenyu Wang99d32bd2008-07-30 12:26:50 -07002669 ID(PCI_DEVICE_ID_INTEL_GM45_HB),
Adam Jackson107f5172009-12-03 17:14:41 -05002670 ID(PCI_DEVICE_ID_INTEL_EAGLELAKE_HB),
Zhenyu Wang25ce77a2008-06-19 14:17:58 +10002671 ID(PCI_DEVICE_ID_INTEL_Q45_HB),
2672 ID(PCI_DEVICE_ID_INTEL_G45_HB),
Zhenyu Wanga50ccc62008-11-17 14:39:00 +08002673 ID(PCI_DEVICE_ID_INTEL_G41_HB),
Fabian Henze38d8a952009-09-08 00:59:58 +08002674 ID(PCI_DEVICE_ID_INTEL_B43_HB),
Adam Jackson107f5172009-12-03 17:14:41 -05002675 ID(PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB),
2676 ID(PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB),
2677 ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB),
Dave Airlie3ff99162009-12-08 14:03:47 +10002678 ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB),
Eric Anholt1089e302009-10-22 16:10:52 -07002679 ID(PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB),
Eric Anholt954bce52010-01-07 16:21:46 -08002680 ID(PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002681 { }
2682};
2683
2684MODULE_DEVICE_TABLE(pci, agp_intel_pci_table);
2685
2686static struct pci_driver agp_intel_pci_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002687 .name = "agpgart-intel",
2688 .id_table = agp_intel_pci_table,
2689 .probe = agp_intel_probe,
2690 .remove = __devexit_p(agp_intel_remove),
Alexey Dobriyan85be7d62006-08-12 02:02:02 +04002691#ifdef CONFIG_PM
Linus Torvalds1da177e2005-04-16 15:20:36 -07002692 .resume = agp_intel_resume,
Alexey Dobriyan85be7d62006-08-12 02:02:02 +04002693#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002694};
2695
2696static int __init agp_intel_init(void)
2697{
2698 if (agp_off)
2699 return -EINVAL;
2700 return pci_register_driver(&agp_intel_pci_driver);
2701}
2702
2703static void __exit agp_intel_cleanup(void)
2704{
2705 pci_unregister_driver(&agp_intel_pci_driver);
2706}
2707
2708module_init(agp_intel_init);
2709module_exit(agp_intel_cleanup);
2710
Dave Jonesf4432c52008-10-20 13:31:45 -04002711MODULE_AUTHOR("Dave Jones <davej@redhat.com>");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002712MODULE_LICENSE("GPL and additional rights");