blob: 918e484f41b717b9ec5e55cd9261d28dd5ebb160 [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 Wang17661682009-07-27 12:59:57 +010013/*
14 * If we have Intel graphics, we're not going to have anything other than
15 * an Intel IOMMU. So make the correct use of the PCI DMA API contingent
16 * on the Intel IOMMU support (CONFIG_DMAR).
17 * Only newer chipsets need to bother with this, of course.
18 */
19#ifdef CONFIG_DMAR
20#define USE_PCI_DMA_API 1
21#endif
22
Carlos Martíne914a362008-01-24 10:34:09 +100023#define PCI_DEVICE_ID_INTEL_E7221_HB 0x2588
24#define PCI_DEVICE_ID_INTEL_E7221_IG 0x258a
Eric Anholt65c25aa2006-09-06 11:57:18 -040025#define PCI_DEVICE_ID_INTEL_82946GZ_HB 0x2970
26#define PCI_DEVICE_ID_INTEL_82946GZ_IG 0x2972
Zhenyu Wang9119f852008-01-23 15:49:26 +100027#define PCI_DEVICE_ID_INTEL_82G35_HB 0x2980
28#define PCI_DEVICE_ID_INTEL_82G35_IG 0x2982
Eric Anholt65c25aa2006-09-06 11:57:18 -040029#define PCI_DEVICE_ID_INTEL_82965Q_HB 0x2990
30#define PCI_DEVICE_ID_INTEL_82965Q_IG 0x2992
31#define PCI_DEVICE_ID_INTEL_82965G_HB 0x29A0
32#define PCI_DEVICE_ID_INTEL_82965G_IG 0x29A2
Wang Zhenyu4598af32007-04-09 08:51:36 +080033#define PCI_DEVICE_ID_INTEL_82965GM_HB 0x2A00
34#define PCI_DEVICE_ID_INTEL_82965GM_IG 0x2A02
Zhenyu Wangdde47872007-07-26 09:18:09 +080035#define PCI_DEVICE_ID_INTEL_82965GME_HB 0x2A10
Wang Zhenyuc8eebfd2007-05-31 11:34:06 +080036#define PCI_DEVICE_ID_INTEL_82965GME_IG 0x2A12
Zhenyu Wangdde47872007-07-26 09:18:09 +080037#define PCI_DEVICE_ID_INTEL_82945GME_HB 0x27AC
Wang Zhenyudf80b142007-05-31 11:51:12 +080038#define PCI_DEVICE_ID_INTEL_82945GME_IG 0x27AE
Adam Jackson107f5172009-12-03 17:14:41 -050039#define PCI_DEVICE_ID_INTEL_PINEVIEW_M_HB 0xA010
40#define PCI_DEVICE_ID_INTEL_PINEVIEW_M_IG 0xA011
41#define PCI_DEVICE_ID_INTEL_PINEVIEW_HB 0xA000
42#define PCI_DEVICE_ID_INTEL_PINEVIEW_IG 0xA001
Wang Zhenyu874808c62007-06-06 11:16:25 +080043#define PCI_DEVICE_ID_INTEL_G33_HB 0x29C0
44#define PCI_DEVICE_ID_INTEL_G33_IG 0x29C2
45#define PCI_DEVICE_ID_INTEL_Q35_HB 0x29B0
46#define PCI_DEVICE_ID_INTEL_Q35_IG 0x29B2
47#define PCI_DEVICE_ID_INTEL_Q33_HB 0x29D0
48#define PCI_DEVICE_ID_INTEL_Q33_IG 0x29D2
Fabian Henze38d8a952009-09-08 00:59:58 +080049#define PCI_DEVICE_ID_INTEL_B43_HB 0x2E40
50#define PCI_DEVICE_ID_INTEL_B43_IG 0x2E42
Zhenyu Wang99d32bd2008-07-30 12:26:50 -070051#define PCI_DEVICE_ID_INTEL_GM45_HB 0x2A40
52#define PCI_DEVICE_ID_INTEL_GM45_IG 0x2A42
Adam Jackson107f5172009-12-03 17:14:41 -050053#define PCI_DEVICE_ID_INTEL_EAGLELAKE_HB 0x2E00
54#define PCI_DEVICE_ID_INTEL_EAGLELAKE_IG 0x2E02
Zhenyu Wang25ce77a2008-06-19 14:17:58 +100055#define PCI_DEVICE_ID_INTEL_Q45_HB 0x2E10
56#define PCI_DEVICE_ID_INTEL_Q45_IG 0x2E12
57#define PCI_DEVICE_ID_INTEL_G45_HB 0x2E20
58#define PCI_DEVICE_ID_INTEL_G45_IG 0x2E22
Zhenyu Wanga50ccc62008-11-17 14:39:00 +080059#define PCI_DEVICE_ID_INTEL_G41_HB 0x2E30
60#define PCI_DEVICE_ID_INTEL_G41_IG 0x2E32
Adam Jackson107f5172009-12-03 17:14:41 -050061#define PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB 0x0040
62#define PCI_DEVICE_ID_INTEL_IRONLAKE_D_IG 0x0042
63#define PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB 0x0044
64#define PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB 0x0062
Dave Airlie3ff99162009-12-08 14:03:47 +100065#define PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB 0x006a
Adam Jackson107f5172009-12-03 17:14:41 -050066#define PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG 0x0046
Eric Anholt1089e302009-10-22 16:10:52 -070067#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB 0x0100
68#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_IG 0x0102
Eric Anholt954bce52010-01-07 16:21:46 -080069#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB 0x0104
70#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_IG 0x0106
Eric Anholt65c25aa2006-09-06 11:57:18 -040071
Dave Airlief011ae72008-01-25 11:23:04 +100072/* cover 915 and 945 variants */
73#define IS_I915 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_E7221_HB || \
74 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB || \
75 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB || \
76 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB || \
77 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB || \
78 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GME_HB)
79
Eric Anholt65c25aa2006-09-06 11:57:18 -040080#define IS_I965 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82946GZ_HB || \
Dave Airlief011ae72008-01-25 11:23:04 +100081 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82G35_HB || \
82 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965Q_HB || \
83 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965G_HB || \
84 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965GM_HB || \
Eric Anholt82e14a62008-10-14 11:28:58 -070085 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965GME_HB)
Eric Anholt65c25aa2006-09-06 11:57:18 -040086
Wang Zhenyu874808c62007-06-06 11:16:25 +080087#define IS_G33 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G33_HB || \
88 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q35_HB || \
Shaohua Li21778322009-02-23 15:19:16 +080089 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q33_HB || \
Adam Jackson107f5172009-12-03 17:14:41 -050090 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_PINEVIEW_M_HB || \
91 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_PINEVIEW_HB)
Shaohua Li21778322009-02-23 15:19:16 +080092
Adam Jackson107f5172009-12-03 17:14:41 -050093#define IS_PINEVIEW (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_PINEVIEW_M_HB || \
94 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_PINEVIEW_HB)
Eric Anholt65c25aa2006-09-06 11:57:18 -040095
Adam Jackson107f5172009-12-03 17:14:41 -050096#define IS_G4X (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_EAGLELAKE_HB || \
Zhenyu Wang25ce77a2008-06-19 14:17:58 +100097 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q45_HB || \
Eric Anholt82e14a62008-10-14 11:28:58 -070098 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G45_HB || \
Zhenyu Wanga50ccc62008-11-17 14:39:00 +080099 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_GM45_HB || \
Zhenyu Wang32cb0552009-06-05 15:38:36 +0800100 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G41_HB || \
Fabian Henze38d8a952009-09-08 00:59:58 +0800101 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_B43_HB || \
Adam Jackson107f5172009-12-03 17:14:41 -0500102 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB || \
103 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB || \
Dave Airlie3ff99162009-12-08 14:03:47 +1000104 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB || \
Eric Anholt1089e302009-10-22 16:10:52 -0700105 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB || \
Eric Anholt954bce52010-01-07 16:21:46 -0800106 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB || \
107 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB)
Zhenyu Wang25ce77a2008-06-19 14:17:58 +1000108
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100109extern int agp_memory_reserved;
110
111
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112/* Intel 815 register */
113#define INTEL_815_APCONT 0x51
114#define INTEL_815_ATTBASE_MASK ~0x1FFFFFFF
115
116/* Intel i820 registers */
117#define INTEL_I820_RDCR 0x51
118#define INTEL_I820_ERRSTS 0xc8
119
120/* Intel i840 registers */
121#define INTEL_I840_MCHCFG 0x50
122#define INTEL_I840_ERRSTS 0xc8
123
124/* Intel i850 registers */
125#define INTEL_I850_MCHCFG 0x50
126#define INTEL_I850_ERRSTS 0xc8
127
128/* intel 915G registers */
129#define I915_GMADDR 0x18
130#define I915_MMADDR 0x10
131#define I915_PTEADDR 0x1C
132#define I915_GMCH_GMS_STOLEN_48M (0x6 << 4)
133#define I915_GMCH_GMS_STOLEN_64M (0x7 << 4)
Zhenyu Wang25ce77a2008-06-19 14:17:58 +1000134#define G33_GMCH_GMS_STOLEN_128M (0x8 << 4)
135#define G33_GMCH_GMS_STOLEN_256M (0x9 << 4)
136#define INTEL_GMCH_GMS_STOLEN_96M (0xa << 4)
137#define INTEL_GMCH_GMS_STOLEN_160M (0xb << 4)
138#define INTEL_GMCH_GMS_STOLEN_224M (0xc << 4)
139#define INTEL_GMCH_GMS_STOLEN_352M (0xd << 4)
140
Dave Airlie6c00a612007-10-29 18:06:10 +1000141#define I915_IFPADDR 0x60
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142
Eric Anholt65c25aa2006-09-06 11:57:18 -0400143/* Intel 965G registers */
144#define I965_MSAC 0x62
Dave Airlie6c00a612007-10-29 18:06:10 +1000145#define I965_IFPADDR 0x70
Linus Torvalds1da177e2005-04-16 15:20:36 -0700146
147/* Intel 7505 registers */
148#define INTEL_I7505_APSIZE 0x74
149#define INTEL_I7505_NCAPID 0x60
150#define INTEL_I7505_NISTAT 0x6c
151#define INTEL_I7505_ATTBASE 0x78
152#define INTEL_I7505_ERRSTS 0x42
153#define INTEL_I7505_AGPCTRL 0x70
154#define INTEL_I7505_MCHCFG 0x50
155
Zhenyu Wang14bc4902009-11-11 01:25:25 +0800156#define SNB_GMCH_CTRL 0x50
157#define SNB_GMCH_GMS_STOLEN_MASK 0xF8
158#define SNB_GMCH_GMS_STOLEN_32M (1 << 3)
159#define SNB_GMCH_GMS_STOLEN_64M (2 << 3)
160#define SNB_GMCH_GMS_STOLEN_96M (3 << 3)
161#define SNB_GMCH_GMS_STOLEN_128M (4 << 3)
162#define SNB_GMCH_GMS_STOLEN_160M (5 << 3)
163#define SNB_GMCH_GMS_STOLEN_192M (6 << 3)
164#define SNB_GMCH_GMS_STOLEN_224M (7 << 3)
165#define SNB_GMCH_GMS_STOLEN_256M (8 << 3)
166#define SNB_GMCH_GMS_STOLEN_288M (9 << 3)
167#define SNB_GMCH_GMS_STOLEN_320M (0xa << 3)
168#define SNB_GMCH_GMS_STOLEN_352M (0xb << 3)
169#define SNB_GMCH_GMS_STOLEN_384M (0xc << 3)
170#define SNB_GMCH_GMS_STOLEN_416M (0xd << 3)
171#define SNB_GMCH_GMS_STOLEN_448M (0xe << 3)
172#define SNB_GMCH_GMS_STOLEN_480M (0xf << 3)
173#define SNB_GMCH_GMS_STOLEN_512M (0x10 << 3)
174
Dave Jonese5524f32007-02-22 18:41:28 -0500175static const struct aper_size_info_fixed intel_i810_sizes[] =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700176{
177 {64, 16384, 4},
178 /* The 32M mode still requires a 64k gatt */
179 {32, 8192, 4}
180};
181
182#define AGP_DCACHE_MEMORY 1
183#define AGP_PHYS_MEMORY 2
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100184#define INTEL_AGP_CACHED_MEMORY 3
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185
186static struct gatt_mask intel_i810_masks[] =
187{
188 {.mask = I810_PTE_VALID, .type = 0},
189 {.mask = (I810_PTE_VALID | I810_PTE_LOCAL), .type = AGP_DCACHE_MEMORY},
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100190 {.mask = I810_PTE_VALID, .type = 0},
191 {.mask = I810_PTE_VALID | I830_PTE_SYSTEM_CACHED,
192 .type = INTEL_AGP_CACHED_MEMORY}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193};
194
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800195static struct _intel_private {
196 struct pci_dev *pcidev; /* device one */
197 u8 __iomem *registers;
198 u32 __iomem *gtt; /* I915G */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700199 int num_dcache_entries;
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800200 /* gtt_entries is the number of gtt entries that are already mapped
201 * to stolen memory. Stolen memory is larger than the memory mapped
202 * through gtt_entries, as it includes some reserved space for the BIOS
203 * popup and for the GTT.
204 */
205 int gtt_entries; /* i830+ */
David Woodhousefc619012009-12-02 11:00:05 +0000206 int gtt_total_size;
Dave Airlie2162e6a2007-11-21 16:36:31 +1000207 union {
208 void __iomem *i9xx_flush_page;
209 void *i8xx_flush_page;
210 };
211 struct page *i8xx_page;
Dave Airlie6c00a612007-10-29 18:06:10 +1000212 struct resource ifp_resource;
Dave Airlie4d64dd92008-01-23 15:34:29 +1000213 int resource_valid;
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800214} intel_private;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215
Zhenyu Wang17661682009-07-27 12:59:57 +0100216#ifdef USE_PCI_DMA_API
David Woodhousec2980d82009-07-29 08:39:26 +0100217static int intel_agp_map_page(struct page *page, dma_addr_t *ret)
Zhenyu Wang17661682009-07-27 12:59:57 +0100218{
David Woodhousec2980d82009-07-29 08:39:26 +0100219 *ret = pci_map_page(intel_private.pcidev, page, 0,
220 PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
Zhenyu Wang17661682009-07-27 12:59:57 +0100221 if (pci_dma_mapping_error(intel_private.pcidev, *ret))
222 return -EINVAL;
223 return 0;
224}
225
David Woodhousec2980d82009-07-29 08:39:26 +0100226static void intel_agp_unmap_page(struct page *page, dma_addr_t dma)
Zhenyu Wang17661682009-07-27 12:59:57 +0100227{
David Woodhousec2980d82009-07-29 08:39:26 +0100228 pci_unmap_page(intel_private.pcidev, dma,
229 PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
Zhenyu Wang17661682009-07-27 12:59:57 +0100230}
231
David Woodhouse91b8e302009-07-29 08:49:12 +0100232static void intel_agp_free_sglist(struct agp_memory *mem)
233{
David Woodhousef6927752009-07-29 09:28:45 +0100234 struct sg_table st;
David Woodhouse91b8e302009-07-29 08:49:12 +0100235
David Woodhousef6927752009-07-29 09:28:45 +0100236 st.sgl = mem->sg_list;
237 st.orig_nents = st.nents = mem->page_count;
238
239 sg_free_table(&st);
240
David Woodhouse91b8e302009-07-29 08:49:12 +0100241 mem->sg_list = NULL;
242 mem->num_sg = 0;
243}
244
Zhenyu Wang17661682009-07-27 12:59:57 +0100245static int intel_agp_map_memory(struct agp_memory *mem)
246{
David Woodhousef6927752009-07-29 09:28:45 +0100247 struct sg_table st;
Zhenyu Wang17661682009-07-27 12:59:57 +0100248 struct scatterlist *sg;
249 int i;
250
251 DBG("try mapping %lu pages\n", (unsigned long)mem->page_count);
252
David Woodhousef6927752009-07-29 09:28:45 +0100253 if (sg_alloc_table(&st, mem->page_count, GFP_KERNEL))
Zhenyu Wang17661682009-07-27 12:59:57 +0100254 return -ENOMEM;
Zhenyu Wang17661682009-07-27 12:59:57 +0100255
David Woodhousef6927752009-07-29 09:28:45 +0100256 mem->sg_list = sg = st.sgl;
257
Zhenyu Wang17661682009-07-27 12:59:57 +0100258 for (i = 0 ; i < mem->page_count; i++, sg = sg_next(sg))
259 sg_set_page(sg, mem->pages[i], PAGE_SIZE, 0);
260
261 mem->num_sg = pci_map_sg(intel_private.pcidev, mem->sg_list,
262 mem->page_count, PCI_DMA_BIDIRECTIONAL);
David Woodhouse91b8e302009-07-29 08:49:12 +0100263 if (unlikely(!mem->num_sg)) {
264 intel_agp_free_sglist(mem);
Zhenyu Wang17661682009-07-27 12:59:57 +0100265 return -ENOMEM;
266 }
267 return 0;
268}
269
270static void intel_agp_unmap_memory(struct agp_memory *mem)
271{
272 DBG("try unmapping %lu pages\n", (unsigned long)mem->page_count);
273
274 pci_unmap_sg(intel_private.pcidev, mem->sg_list,
275 mem->page_count, PCI_DMA_BIDIRECTIONAL);
David Woodhouse91b8e302009-07-29 08:49:12 +0100276 intel_agp_free_sglist(mem);
Zhenyu Wang17661682009-07-27 12:59:57 +0100277}
278
279static void intel_agp_insert_sg_entries(struct agp_memory *mem,
280 off_t pg_start, int mask_type)
281{
282 struct scatterlist *sg;
283 int i, j;
284
285 j = pg_start;
286
287 WARN_ON(!mem->num_sg);
288
289 if (mem->num_sg == mem->page_count) {
290 for_each_sg(mem->sg_list, sg, mem->page_count, i) {
291 writel(agp_bridge->driver->mask_memory(agp_bridge,
292 sg_dma_address(sg), mask_type),
293 intel_private.gtt+j);
294 j++;
295 }
296 } else {
297 /* sg may merge pages, but we have to seperate
298 * per-page addr for GTT */
299 unsigned int len, m;
300
301 for_each_sg(mem->sg_list, sg, mem->num_sg, i) {
302 len = sg_dma_len(sg) / PAGE_SIZE;
303 for (m = 0; m < len; m++) {
304 writel(agp_bridge->driver->mask_memory(agp_bridge,
305 sg_dma_address(sg) + m * PAGE_SIZE,
306 mask_type),
307 intel_private.gtt+j);
308 j++;
309 }
310 }
311 }
312 readl(intel_private.gtt+j-1);
313}
314
315#else
316
317static void intel_agp_insert_sg_entries(struct agp_memory *mem,
318 off_t pg_start, int mask_type)
319{
320 int i, j;
Eric Anholte3deb202009-11-02 15:33:05 -0800321 u32 cache_bits = 0;
322
Eric Anholt954bce52010-01-07 16:21:46 -0800323 if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB ||
324 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB)
325 {
Eric Anholte3deb202009-11-02 15:33:05 -0800326 cache_bits = I830_PTE_SYSTEM_CACHED;
327 }
Zhenyu Wang17661682009-07-27 12:59:57 +0100328
329 for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
330 writel(agp_bridge->driver->mask_memory(agp_bridge,
David Woodhouse6a122352009-07-29 10:25:58 +0100331 page_to_phys(mem->pages[i]), mask_type),
Zhenyu Wang17661682009-07-27 12:59:57 +0100332 intel_private.gtt+j);
333 }
334
335 readl(intel_private.gtt+j-1);
336}
337
338#endif
339
Linus Torvalds1da177e2005-04-16 15:20:36 -0700340static int intel_i810_fetch_size(void)
341{
342 u32 smram_miscc;
343 struct aper_size_info_fixed *values;
344
345 pci_read_config_dword(agp_bridge->dev, I810_SMRAM_MISCC, &smram_miscc);
346 values = A_SIZE_FIX(agp_bridge->driver->aperture_sizes);
347
348 if ((smram_miscc & I810_GMS) == I810_GMS_DISABLE) {
Bjorn Helgaase3cf6952008-07-30 12:26:51 -0700349 dev_warn(&agp_bridge->dev->dev, "i810 is disabled\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350 return 0;
351 }
352 if ((smram_miscc & I810_GFX_MEM_WIN_SIZE) == I810_GFX_MEM_WIN_32M) {
353 agp_bridge->previous_size =
354 agp_bridge->current_size = (void *) (values + 1);
355 agp_bridge->aperture_size_idx = 1;
356 return values[1].size;
357 } else {
358 agp_bridge->previous_size =
359 agp_bridge->current_size = (void *) (values);
360 agp_bridge->aperture_size_idx = 0;
361 return values[0].size;
362 }
363
364 return 0;
365}
366
367static int intel_i810_configure(void)
368{
369 struct aper_size_info_fixed *current_size;
370 u32 temp;
371 int i;
372
373 current_size = A_SIZE_FIX(agp_bridge->current_size);
374
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800375 if (!intel_private.registers) {
376 pci_read_config_dword(intel_private.pcidev, I810_MMADDR, &temp);
Dave Jonese4ac5e42007-02-04 17:37:42 -0500377 temp &= 0xfff80000;
378
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800379 intel_private.registers = ioremap(temp, 128 * 4096);
380 if (!intel_private.registers) {
Bjorn Helgaase3cf6952008-07-30 12:26:51 -0700381 dev_err(&intel_private.pcidev->dev,
382 "can't remap memory\n");
Dave Jonese4ac5e42007-02-04 17:37:42 -0500383 return -ENOMEM;
384 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385 }
386
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800387 if ((readl(intel_private.registers+I810_DRAM_CTL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388 & I810_DRAM_ROW_0) == I810_DRAM_ROW_0_SDRAM) {
389 /* This will need to be dynamically assigned */
Bjorn Helgaase3cf6952008-07-30 12:26:51 -0700390 dev_info(&intel_private.pcidev->dev,
391 "detected 4MB dedicated video ram\n");
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800392 intel_private.num_dcache_entries = 1024;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393 }
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800394 pci_read_config_dword(intel_private.pcidev, I810_GMADDR, &temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800396 writel(agp_bridge->gatt_bus_addr | I810_PGETBL_ENABLED, intel_private.registers+I810_PGETBL_CTL);
397 readl(intel_private.registers+I810_PGETBL_CTL); /* PCI Posting. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398
399 if (agp_bridge->driver->needs_scratch_page) {
400 for (i = 0; i < current_size->num_entries; i++) {
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800401 writel(agp_bridge->scratch_page, intel_private.registers+I810_PTE_BASE+(i*4));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402 }
Keith Packard44d49442008-10-14 17:18:45 -0700403 readl(intel_private.registers+I810_PTE_BASE+((i-1)*4)); /* PCI posting. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700404 }
405 global_cache_flush();
406 return 0;
407}
408
409static void intel_i810_cleanup(void)
410{
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800411 writel(0, intel_private.registers+I810_PGETBL_CTL);
412 readl(intel_private.registers); /* PCI Posting. */
413 iounmap(intel_private.registers);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414}
415
416static void intel_i810_tlbflush(struct agp_memory *mem)
417{
418 return;
419}
420
421static void intel_i810_agp_enable(struct agp_bridge_data *bridge, u32 mode)
422{
423 return;
424}
425
426/* Exists to support ARGB cursors */
Dave Airlie07613ba2009-06-12 14:11:41 +1000427static struct page *i8xx_alloc_pages(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428{
Dave Airlief011ae72008-01-25 11:23:04 +1000429 struct page *page;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430
Linus Torvalds66c669b2006-11-22 14:55:29 -0800431 page = alloc_pages(GFP_KERNEL | GFP_DMA32, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432 if (page == NULL)
433 return NULL;
434
Arjan van de Ven6d238cc2008-01-30 13:34:06 +0100435 if (set_pages_uc(page, 4) < 0) {
436 set_pages_wb(page, 4);
Jan Beulich89cf7cc2007-04-02 14:50:14 +0100437 __free_pages(page, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438 return NULL;
439 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440 get_page(page);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441 atomic_inc(&agp_bridge->current_memory_agp);
Dave Airlie07613ba2009-06-12 14:11:41 +1000442 return page;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443}
444
Dave Airlie07613ba2009-06-12 14:11:41 +1000445static void i8xx_destroy_pages(struct page *page)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446{
Dave Airlie07613ba2009-06-12 14:11:41 +1000447 if (page == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448 return;
449
Arjan van de Ven6d238cc2008-01-30 13:34:06 +0100450 set_pages_wb(page, 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451 put_page(page);
Jan Beulich89cf7cc2007-04-02 14:50:14 +0100452 __free_pages(page, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700453 atomic_dec(&agp_bridge->current_memory_agp);
454}
455
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100456static int intel_i830_type_to_mask_type(struct agp_bridge_data *bridge,
457 int type)
458{
459 if (type < AGP_USER_TYPES)
460 return type;
461 else if (type == AGP_USER_CACHED_MEMORY)
462 return INTEL_AGP_CACHED_MEMORY;
463 else
464 return 0;
465}
466
Linus Torvalds1da177e2005-04-16 15:20:36 -0700467static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start,
468 int type)
469{
470 int i, j, num_entries;
471 void *temp;
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100472 int ret = -EINVAL;
473 int mask_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +0100475 if (mem->page_count == 0)
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100476 goto out;
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +0100477
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478 temp = agp_bridge->current_size;
479 num_entries = A_SIZE_FIX(temp)->num_entries;
480
Dave Jones6a92a4e2006-02-28 00:54:25 -0500481 if ((pg_start + mem->page_count) > num_entries)
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100482 goto out_err;
483
Dave Jones6a92a4e2006-02-28 00:54:25 -0500484
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485 for (j = pg_start; j < (pg_start + mem->page_count); j++) {
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100486 if (!PGE_EMPTY(agp_bridge, readl(agp_bridge->gatt_table+j))) {
487 ret = -EBUSY;
488 goto out_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490 }
491
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100492 if (type != mem->type)
493 goto out_err;
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +0100494
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100495 mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type);
496
497 switch (mask_type) {
498 case AGP_DCACHE_MEMORY:
499 if (!mem->is_flushed)
500 global_cache_flush();
501 for (i = pg_start; i < (pg_start + mem->page_count); i++) {
502 writel((i*4096)|I810_PTE_LOCAL|I810_PTE_VALID,
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800503 intel_private.registers+I810_PTE_BASE+(i*4));
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100504 }
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800505 readl(intel_private.registers+I810_PTE_BASE+((i-1)*4));
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100506 break;
507 case AGP_PHYS_MEMORY:
508 case AGP_NORMAL_MEMORY:
509 if (!mem->is_flushed)
510 global_cache_flush();
511 for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
512 writel(agp_bridge->driver->mask_memory(agp_bridge,
David Woodhouse6a122352009-07-29 10:25:58 +0100513 page_to_phys(mem->pages[i]), mask_type),
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800514 intel_private.registers+I810_PTE_BASE+(j*4));
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100515 }
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800516 readl(intel_private.registers+I810_PTE_BASE+((j-1)*4));
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100517 break;
518 default:
519 goto out_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521
522 agp_bridge->driver->tlb_flush(mem);
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100523out:
524 ret = 0;
525out_err:
Dave Airlie9516b032008-06-19 10:42:17 +1000526 mem->is_flushed = true;
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100527 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528}
529
530static int intel_i810_remove_entries(struct agp_memory *mem, off_t pg_start,
531 int type)
532{
533 int i;
534
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +0100535 if (mem->page_count == 0)
536 return 0;
537
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538 for (i = pg_start; i < (mem->page_count + pg_start); i++) {
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800539 writel(agp_bridge->scratch_page, intel_private.registers+I810_PTE_BASE+(i*4));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540 }
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800541 readl(intel_private.registers+I810_PTE_BASE+((i-1)*4));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700542
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543 agp_bridge->driver->tlb_flush(mem);
544 return 0;
545}
546
547/*
548 * The i810/i830 requires a physical address to program its mouse
549 * pointer into hardware.
550 * However the Xserver still writes to it through the agp aperture.
551 */
552static struct agp_memory *alloc_agpphysmem_i8xx(size_t pg_count, int type)
553{
554 struct agp_memory *new;
Dave Airlie07613ba2009-06-12 14:11:41 +1000555 struct page *page;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700556
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557 switch (pg_count) {
Dave Airlie07613ba2009-06-12 14:11:41 +1000558 case 1: page = agp_bridge->driver->agp_alloc_page(agp_bridge);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559 break;
560 case 4:
561 /* kludge to get 4 physical pages for ARGB cursor */
Dave Airlie07613ba2009-06-12 14:11:41 +1000562 page = i8xx_alloc_pages();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700563 break;
564 default:
565 return NULL;
566 }
567
Dave Airlie07613ba2009-06-12 14:11:41 +1000568 if (page == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569 return NULL;
570
571 new = agp_create_memory(pg_count);
572 if (new == NULL)
573 return NULL;
574
Dave Airlie07613ba2009-06-12 14:11:41 +1000575 new->pages[0] = page;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700576 if (pg_count == 4) {
577 /* kludge to get 4 physical pages for ARGB cursor */
Dave Airlie07613ba2009-06-12 14:11:41 +1000578 new->pages[1] = new->pages[0] + 1;
579 new->pages[2] = new->pages[1] + 1;
580 new->pages[3] = new->pages[2] + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700581 }
582 new->page_count = pg_count;
583 new->num_scratch_pages = pg_count;
584 new->type = AGP_PHYS_MEMORY;
Dave Airlie07613ba2009-06-12 14:11:41 +1000585 new->physical = page_to_phys(new->pages[0]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586 return new;
587}
588
589static struct agp_memory *intel_i810_alloc_by_type(size_t pg_count, int type)
590{
591 struct agp_memory *new;
592
593 if (type == AGP_DCACHE_MEMORY) {
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800594 if (pg_count != intel_private.num_dcache_entries)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595 return NULL;
596
597 new = agp_create_memory(1);
598 if (new == NULL)
599 return NULL;
600
601 new->type = AGP_DCACHE_MEMORY;
602 new->page_count = pg_count;
603 new->num_scratch_pages = 0;
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100604 agp_free_page_array(new);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700605 return new;
606 }
607 if (type == AGP_PHYS_MEMORY)
608 return alloc_agpphysmem_i8xx(pg_count, type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609 return NULL;
610}
611
612static void intel_i810_free_by_type(struct agp_memory *curr)
613{
614 agp_free_key(curr->key);
Dave Jones6a92a4e2006-02-28 00:54:25 -0500615 if (curr->type == AGP_PHYS_MEMORY) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616 if (curr->page_count == 4)
Dave Airlie07613ba2009-06-12 14:11:41 +1000617 i8xx_destroy_pages(curr->pages[0]);
Alan Hourihane88d51962005-11-06 23:35:34 -0800618 else {
Dave Airlie07613ba2009-06-12 14:11:41 +1000619 agp_bridge->driver->agp_destroy_page(curr->pages[0],
Dave Airliea2721e92007-10-15 10:19:16 +1000620 AGP_PAGE_DESTROY_UNMAP);
Dave Airlie07613ba2009-06-12 14:11:41 +1000621 agp_bridge->driver->agp_destroy_page(curr->pages[0],
Dave Airliea2721e92007-10-15 10:19:16 +1000622 AGP_PAGE_DESTROY_FREE);
Alan Hourihane88d51962005-11-06 23:35:34 -0800623 }
Thomas Hellstroma030ce42007-01-23 10:33:43 +0100624 agp_free_page_array(curr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700625 }
626 kfree(curr);
627}
628
629static unsigned long intel_i810_mask_memory(struct agp_bridge_data *bridge,
David Woodhouse2a4ceb62009-07-27 10:27:29 +0100630 dma_addr_t addr, int type)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700631{
632 /* Type checking must be done elsewhere */
633 return addr | bridge->driver->masks[type].mask;
634}
635
636static struct aper_size_info_fixed intel_i830_sizes[] =
637{
638 {128, 32768, 5},
639 /* The 64M mode still requires a 128k gatt */
640 {64, 16384, 5},
641 {256, 65536, 6},
Eric Anholt65c25aa2006-09-06 11:57:18 -0400642 {512, 131072, 7},
Linus Torvalds1da177e2005-04-16 15:20:36 -0700643};
644
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645static void intel_i830_init_gtt_entries(void)
646{
647 u16 gmch_ctrl;
Zhenyu Wang14bc4902009-11-11 01:25:25 +0800648 int gtt_entries = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700649 u8 rdct;
650 int local = 0;
651 static const int ddt[4] = { 0, 16, 32, 64 };
Eric Anholtc41e0de2006-12-19 12:57:24 -0800652 int size; /* reserved space (in kb) at the top of stolen memory */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653
Dave Airlief011ae72008-01-25 11:23:04 +1000654 pci_read_config_word(agp_bridge->dev, I830_GMCH_CTRL, &gmch_ctrl);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655
Eric Anholtc41e0de2006-12-19 12:57:24 -0800656 if (IS_I965) {
657 u32 pgetbl_ctl;
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800658 pgetbl_ctl = readl(intel_private.registers+I810_PGETBL_CTL);
Eric Anholtc41e0de2006-12-19 12:57:24 -0800659
Eric Anholtc41e0de2006-12-19 12:57:24 -0800660 /* The 965 has a field telling us the size of the GTT,
661 * which may be larger than what is necessary to map the
662 * aperture.
663 */
664 switch (pgetbl_ctl & I965_PGETBL_SIZE_MASK) {
665 case I965_PGETBL_SIZE_128KB:
666 size = 128;
667 break;
668 case I965_PGETBL_SIZE_256KB:
669 size = 256;
670 break;
671 case I965_PGETBL_SIZE_512KB:
672 size = 512;
673 break;
Zhenyu Wang4e8b6e22008-01-23 14:54:37 +1000674 case I965_PGETBL_SIZE_1MB:
675 size = 1024;
676 break;
677 case I965_PGETBL_SIZE_2MB:
678 size = 2048;
679 break;
680 case I965_PGETBL_SIZE_1_5MB:
681 size = 1024 + 512;
682 break;
Eric Anholtc41e0de2006-12-19 12:57:24 -0800683 default:
Bjorn Helgaase3cf6952008-07-30 12:26:51 -0700684 dev_info(&intel_private.pcidev->dev,
685 "unknown page table size, assuming 512KB\n");
Eric Anholtc41e0de2006-12-19 12:57:24 -0800686 size = 512;
687 }
688 size += 4; /* add in BIOS popup space */
Adam Jackson107f5172009-12-03 17:14:41 -0500689 } else if (IS_G33 && !IS_PINEVIEW) {
Wang Zhenyu874808c62007-06-06 11:16:25 +0800690 /* G33's GTT size defined in gmch_ctrl */
691 switch (gmch_ctrl & G33_PGETBL_SIZE_MASK) {
692 case G33_PGETBL_SIZE_1M:
693 size = 1024;
694 break;
695 case G33_PGETBL_SIZE_2M:
696 size = 2048;
697 break;
698 default:
Bjorn Helgaase3cf6952008-07-30 12:26:51 -0700699 dev_info(&agp_bridge->dev->dev,
700 "unknown page table size 0x%x, assuming 512KB\n",
Wang Zhenyu874808c62007-06-06 11:16:25 +0800701 (gmch_ctrl & G33_PGETBL_SIZE_MASK));
702 size = 512;
703 }
704 size += 4;
Adam Jackson107f5172009-12-03 17:14:41 -0500705 } else if (IS_G4X || IS_PINEVIEW) {
Zhenyu Wang25ce77a2008-06-19 14:17:58 +1000706 /* On 4 series hardware, GTT stolen is separate from graphics
Eric Anholt82e14a62008-10-14 11:28:58 -0700707 * stolen, ignore it in stolen gtt entries counting. However,
708 * 4KB of the stolen memory doesn't get mapped to the GTT.
709 */
710 size = 4;
Eric Anholtc41e0de2006-12-19 12:57:24 -0800711 } else {
712 /* On previous hardware, the GTT size was just what was
713 * required to map the aperture.
714 */
715 size = agp_bridge->driver->fetch_size() + 4;
716 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717
718 if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82830_HB ||
719 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82845G_HB) {
720 switch (gmch_ctrl & I830_GMCH_GMS_MASK) {
721 case I830_GMCH_GMS_STOLEN_512:
722 gtt_entries = KB(512) - KB(size);
723 break;
724 case I830_GMCH_GMS_STOLEN_1024:
725 gtt_entries = MB(1) - KB(size);
726 break;
727 case I830_GMCH_GMS_STOLEN_8192:
728 gtt_entries = MB(8) - KB(size);
729 break;
730 case I830_GMCH_GMS_LOCAL:
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800731 rdct = readb(intel_private.registers+I830_RDRAM_CHANNEL_TYPE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732 gtt_entries = (I830_RDRAM_ND(rdct) + 1) *
733 MB(ddt[I830_RDRAM_DDT(rdct)]);
734 local = 1;
735 break;
736 default:
737 gtt_entries = 0;
738 break;
739 }
Eric Anholt954bce52010-01-07 16:21:46 -0800740 } else if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB ||
741 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB) {
Zhenyu Wang14bc4902009-11-11 01:25:25 +0800742 /*
743 * SandyBridge has new memory control reg at 0x50.w
Eric Anholt1089e302009-10-22 16:10:52 -0700744 */
Zhenyu Wang14bc4902009-11-11 01:25:25 +0800745 u16 snb_gmch_ctl;
746 pci_read_config_word(intel_private.pcidev, SNB_GMCH_CTRL, &snb_gmch_ctl);
747 switch (snb_gmch_ctl & SNB_GMCH_GMS_STOLEN_MASK) {
748 case SNB_GMCH_GMS_STOLEN_32M:
749 gtt_entries = MB(32) - KB(size);
750 break;
751 case SNB_GMCH_GMS_STOLEN_64M:
752 gtt_entries = MB(64) - KB(size);
753 break;
754 case SNB_GMCH_GMS_STOLEN_96M:
755 gtt_entries = MB(96) - KB(size);
756 break;
757 case SNB_GMCH_GMS_STOLEN_128M:
758 gtt_entries = MB(128) - KB(size);
759 break;
760 case SNB_GMCH_GMS_STOLEN_160M:
761 gtt_entries = MB(160) - KB(size);
762 break;
763 case SNB_GMCH_GMS_STOLEN_192M:
764 gtt_entries = MB(192) - KB(size);
765 break;
766 case SNB_GMCH_GMS_STOLEN_224M:
767 gtt_entries = MB(224) - KB(size);
768 break;
769 case SNB_GMCH_GMS_STOLEN_256M:
770 gtt_entries = MB(256) - KB(size);
771 break;
772 case SNB_GMCH_GMS_STOLEN_288M:
773 gtt_entries = MB(288) - KB(size);
774 break;
775 case SNB_GMCH_GMS_STOLEN_320M:
776 gtt_entries = MB(320) - KB(size);
777 break;
778 case SNB_GMCH_GMS_STOLEN_352M:
779 gtt_entries = MB(352) - KB(size);
780 break;
781 case SNB_GMCH_GMS_STOLEN_384M:
782 gtt_entries = MB(384) - KB(size);
783 break;
784 case SNB_GMCH_GMS_STOLEN_416M:
785 gtt_entries = MB(416) - KB(size);
786 break;
787 case SNB_GMCH_GMS_STOLEN_448M:
788 gtt_entries = MB(448) - KB(size);
789 break;
790 case SNB_GMCH_GMS_STOLEN_480M:
791 gtt_entries = MB(480) - KB(size);
792 break;
793 case SNB_GMCH_GMS_STOLEN_512M:
794 gtt_entries = MB(512) - KB(size);
795 break;
796 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797 } else {
Dave Airliee67aa272007-09-18 22:46:35 -0700798 switch (gmch_ctrl & I855_GMCH_GMS_MASK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799 case I855_GMCH_GMS_STOLEN_1M:
800 gtt_entries = MB(1) - KB(size);
801 break;
802 case I855_GMCH_GMS_STOLEN_4M:
803 gtt_entries = MB(4) - KB(size);
804 break;
805 case I855_GMCH_GMS_STOLEN_8M:
806 gtt_entries = MB(8) - KB(size);
807 break;
808 case I855_GMCH_GMS_STOLEN_16M:
809 gtt_entries = MB(16) - KB(size);
810 break;
811 case I855_GMCH_GMS_STOLEN_32M:
812 gtt_entries = MB(32) - KB(size);
813 break;
814 case I915_GMCH_GMS_STOLEN_48M:
815 /* Check it's really I915G */
Zhenyu Wang25ce77a2008-06-19 14:17:58 +1000816 if (IS_I915 || IS_I965 || IS_G33 || IS_G4X)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700817 gtt_entries = MB(48) - KB(size);
818 else
819 gtt_entries = 0;
820 break;
821 case I915_GMCH_GMS_STOLEN_64M:
822 /* Check it's really I915G */
Zhenyu Wang25ce77a2008-06-19 14:17:58 +1000823 if (IS_I915 || IS_I965 || IS_G33 || IS_G4X)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700824 gtt_entries = MB(64) - KB(size);
825 else
826 gtt_entries = 0;
Wang Zhenyu874808c62007-06-06 11:16:25 +0800827 break;
828 case G33_GMCH_GMS_STOLEN_128M:
Zhenyu Wang25ce77a2008-06-19 14:17:58 +1000829 if (IS_G33 || IS_I965 || IS_G4X)
Wang Zhenyu874808c62007-06-06 11:16:25 +0800830 gtt_entries = MB(128) - KB(size);
831 else
832 gtt_entries = 0;
833 break;
834 case G33_GMCH_GMS_STOLEN_256M:
Zhenyu Wang25ce77a2008-06-19 14:17:58 +1000835 if (IS_G33 || IS_I965 || IS_G4X)
Wang Zhenyu874808c62007-06-06 11:16:25 +0800836 gtt_entries = MB(256) - KB(size);
837 else
838 gtt_entries = 0;
839 break;
Zhenyu Wang25ce77a2008-06-19 14:17:58 +1000840 case INTEL_GMCH_GMS_STOLEN_96M:
841 if (IS_I965 || IS_G4X)
842 gtt_entries = MB(96) - KB(size);
843 else
844 gtt_entries = 0;
845 break;
846 case INTEL_GMCH_GMS_STOLEN_160M:
847 if (IS_I965 || IS_G4X)
848 gtt_entries = MB(160) - KB(size);
849 else
850 gtt_entries = 0;
851 break;
852 case INTEL_GMCH_GMS_STOLEN_224M:
853 if (IS_I965 || IS_G4X)
854 gtt_entries = MB(224) - KB(size);
855 else
856 gtt_entries = 0;
857 break;
858 case INTEL_GMCH_GMS_STOLEN_352M:
859 if (IS_I965 || IS_G4X)
860 gtt_entries = MB(352) - KB(size);
861 else
862 gtt_entries = 0;
863 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700864 default:
865 gtt_entries = 0;
866 break;
867 }
868 }
Lubomir Rintel9c1e8a42009-03-10 12:55:54 -0700869 if (gtt_entries > 0) {
Bjorn Helgaase3cf6952008-07-30 12:26:51 -0700870 dev_info(&agp_bridge->dev->dev, "detected %dK %s memory\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871 gtt_entries / KB(1), local ? "local" : "stolen");
Lubomir Rintel9c1e8a42009-03-10 12:55:54 -0700872 gtt_entries /= KB(4);
873 } else {
Bjorn Helgaase3cf6952008-07-30 12:26:51 -0700874 dev_info(&agp_bridge->dev->dev,
875 "no pre-allocated video memory detected\n");
Lubomir Rintel9c1e8a42009-03-10 12:55:54 -0700876 gtt_entries = 0;
877 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700878
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800879 intel_private.gtt_entries = gtt_entries;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880}
881
Dave Airlie2162e6a2007-11-21 16:36:31 +1000882static void intel_i830_fini_flush(void)
883{
884 kunmap(intel_private.i8xx_page);
885 intel_private.i8xx_flush_page = NULL;
886 unmap_page_from_agp(intel_private.i8xx_page);
Dave Airlie2162e6a2007-11-21 16:36:31 +1000887
888 __free_page(intel_private.i8xx_page);
Dave Airlie4d64dd92008-01-23 15:34:29 +1000889 intel_private.i8xx_page = NULL;
Dave Airlie2162e6a2007-11-21 16:36:31 +1000890}
891
892static void intel_i830_setup_flush(void)
893{
Dave Airlie4d64dd92008-01-23 15:34:29 +1000894 /* return if we've already set the flush mechanism up */
895 if (intel_private.i8xx_page)
896 return;
Dave Airlie2162e6a2007-11-21 16:36:31 +1000897
898 intel_private.i8xx_page = alloc_page(GFP_KERNEL | __GFP_ZERO | GFP_DMA32);
Dave Airlief011ae72008-01-25 11:23:04 +1000899 if (!intel_private.i8xx_page)
Dave Airlie2162e6a2007-11-21 16:36:31 +1000900 return;
Dave Airlie2162e6a2007-11-21 16:36:31 +1000901
Dave Airlie2162e6a2007-11-21 16:36:31 +1000902 intel_private.i8xx_flush_page = kmap(intel_private.i8xx_page);
903 if (!intel_private.i8xx_flush_page)
904 intel_i830_fini_flush();
905}
906
Eric Anholte517a5e2009-09-10 17:48:48 -0700907static void
908do_wbinvd(void *null)
909{
910 wbinvd();
911}
912
913/* The chipset_flush interface needs to get data that has already been
914 * flushed out of the CPU all the way out to main memory, because the GPU
915 * doesn't snoop those buffers.
916 *
917 * The 8xx series doesn't have the same lovely interface for flushing the
918 * chipset write buffers that the later chips do. According to the 865
919 * specs, it's 64 octwords, or 1KB. So, to get those previous things in
920 * that buffer out, we just fill 1KB and clflush it out, on the assumption
921 * that it'll push whatever was in there out. It appears to work.
922 */
Dave Airlie2162e6a2007-11-21 16:36:31 +1000923static void intel_i830_chipset_flush(struct agp_bridge_data *bridge)
924{
925 unsigned int *pg = intel_private.i8xx_flush_page;
Dave Airlie2162e6a2007-11-21 16:36:31 +1000926
Eric Anholte517a5e2009-09-10 17:48:48 -0700927 memset(pg, 0, 1024);
Dave Airlief011ae72008-01-25 11:23:04 +1000928
Eric Anholte517a5e2009-09-10 17:48:48 -0700929 if (cpu_has_clflush) {
930 clflush_cache_range(pg, 1024);
931 } else {
932 if (on_each_cpu(do_wbinvd, NULL, 1) != 0)
933 printk(KERN_ERR "Timed out waiting for cache flush.\n");
934 }
Dave Airlie2162e6a2007-11-21 16:36:31 +1000935}
936
Linus Torvalds1da177e2005-04-16 15:20:36 -0700937/* The intel i830 automatically initializes the agp aperture during POST.
938 * Use the memory already set aside for in the GTT.
939 */
940static int intel_i830_create_gatt_table(struct agp_bridge_data *bridge)
941{
942 int page_order;
943 struct aper_size_info_fixed *size;
944 int num_entries;
945 u32 temp;
946
947 size = agp_bridge->current_size;
948 page_order = size->page_order;
949 num_entries = size->num_entries;
950 agp_bridge->gatt_table_real = NULL;
951
Dave Airlief011ae72008-01-25 11:23:04 +1000952 pci_read_config_dword(intel_private.pcidev, I810_MMADDR, &temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953 temp &= 0xfff80000;
954
Dave Airlief011ae72008-01-25 11:23:04 +1000955 intel_private.registers = ioremap(temp, 128 * 4096);
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800956 if (!intel_private.registers)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700957 return -ENOMEM;
958
Wang Zhenyuc4ca8812007-05-30 09:40:46 +0800959 temp = readl(intel_private.registers+I810_PGETBL_CTL) & 0xfffff000;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700960 global_cache_flush(); /* FIXME: ?? */
961
962 /* we have to call this as early as possible after the MMIO base address is known */
963 intel_i830_init_gtt_entries();
964
965 agp_bridge->gatt_table = NULL;
966
967 agp_bridge->gatt_bus_addr = temp;
968
969 return 0;
970}
971
972/* Return the gatt table to a sane state. Use the top of stolen
973 * memory for the GTT.
974 */
975static int intel_i830_free_gatt_table(struct agp_bridge_data *bridge)
976{
977 return 0;
978}
979
980static int intel_i830_fetch_size(void)
981{
982 u16 gmch_ctrl;
983 struct aper_size_info_fixed *values;
984
985 values = A_SIZE_FIX(agp_bridge->driver->aperture_sizes);
986
987 if (agp_bridge->dev->device != PCI_DEVICE_ID_INTEL_82830_HB &&
988 agp_bridge->dev->device != PCI_DEVICE_ID_INTEL_82845G_HB) {
989 /* 855GM/852GM/865G has 128MB aperture size */
990 agp_bridge->previous_size = agp_bridge->current_size = (void *) values;
991 agp_bridge->aperture_size_idx = 0;
992 return values[0].size;
993 }
994
Dave Airlief011ae72008-01-25 11:23:04 +1000995 pci_read_config_word(agp_bridge->dev, I830_GMCH_CTRL, &gmch_ctrl);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996
997 if ((gmch_ctrl & I830_GMCH_MEM_MASK) == I830_GMCH_MEM_128M) {
998 agp_bridge->previous_size = agp_bridge->current_size = (void *) values;
999 agp_bridge->aperture_size_idx = 0;
1000 return values[0].size;
1001 } else {
1002 agp_bridge->previous_size = agp_bridge->current_size = (void *) (values + 1);
1003 agp_bridge->aperture_size_idx = 1;
1004 return values[1].size;
1005 }
1006
1007 return 0;
1008}
1009
1010static int intel_i830_configure(void)
1011{
1012 struct aper_size_info_fixed *current_size;
1013 u32 temp;
1014 u16 gmch_ctrl;
1015 int i;
1016
1017 current_size = A_SIZE_FIX(agp_bridge->current_size);
1018
Dave Airlief011ae72008-01-25 11:23:04 +10001019 pci_read_config_dword(intel_private.pcidev, I810_GMADDR, &temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
1021
Dave Airlief011ae72008-01-25 11:23:04 +10001022 pci_read_config_word(agp_bridge->dev, I830_GMCH_CTRL, &gmch_ctrl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023 gmch_ctrl |= I830_GMCH_ENABLED;
Dave Airlief011ae72008-01-25 11:23:04 +10001024 pci_write_config_word(agp_bridge->dev, I830_GMCH_CTRL, gmch_ctrl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001025
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001026 writel(agp_bridge->gatt_bus_addr|I810_PGETBL_ENABLED, intel_private.registers+I810_PGETBL_CTL);
1027 readl(intel_private.registers+I810_PGETBL_CTL); /* PCI Posting. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028
1029 if (agp_bridge->driver->needs_scratch_page) {
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001030 for (i = intel_private.gtt_entries; i < current_size->num_entries; i++) {
1031 writel(agp_bridge->scratch_page, intel_private.registers+I810_PTE_BASE+(i*4));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001032 }
Keith Packard44d49442008-10-14 17:18:45 -07001033 readl(intel_private.registers+I810_PTE_BASE+((i-1)*4)); /* PCI Posting. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034 }
1035
1036 global_cache_flush();
Dave Airlie2162e6a2007-11-21 16:36:31 +10001037
1038 intel_i830_setup_flush();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039 return 0;
1040}
1041
1042static void intel_i830_cleanup(void)
1043{
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001044 iounmap(intel_private.registers);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045}
1046
Dave Airlief011ae72008-01-25 11:23:04 +10001047static int intel_i830_insert_entries(struct agp_memory *mem, off_t pg_start,
1048 int type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049{
Dave Airlief011ae72008-01-25 11:23:04 +10001050 int i, j, num_entries;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051 void *temp;
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001052 int ret = -EINVAL;
1053 int mask_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +01001055 if (mem->page_count == 0)
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001056 goto out;
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +01001057
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058 temp = agp_bridge->current_size;
1059 num_entries = A_SIZE_FIX(temp)->num_entries;
1060
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001061 if (pg_start < intel_private.gtt_entries) {
Bjorn Helgaase3cf6952008-07-30 12:26:51 -07001062 dev_printk(KERN_DEBUG, &intel_private.pcidev->dev,
1063 "pg_start == 0x%.8lx, intel_private.gtt_entries == 0x%.8x\n",
1064 pg_start, intel_private.gtt_entries);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001065
Bjorn Helgaase3cf6952008-07-30 12:26:51 -07001066 dev_info(&intel_private.pcidev->dev,
1067 "trying to insert into local/stolen memory\n");
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001068 goto out_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069 }
1070
1071 if ((pg_start + mem->page_count) > num_entries)
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001072 goto out_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073
1074 /* The i830 can't check the GTT for entries since its read only,
1075 * depend on the caller to make the correct offset decisions.
1076 */
1077
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001078 if (type != mem->type)
1079 goto out_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001081 mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type);
1082
1083 if (mask_type != 0 && mask_type != AGP_PHYS_MEMORY &&
1084 mask_type != INTEL_AGP_CACHED_MEMORY)
1085 goto out_err;
1086
1087 if (!mem->is_flushed)
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +01001088 global_cache_flush();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089
1090 for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
1091 writel(agp_bridge->driver->mask_memory(agp_bridge,
David Woodhouse6a122352009-07-29 10:25:58 +01001092 page_to_phys(mem->pages[i]), mask_type),
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001093 intel_private.registers+I810_PTE_BASE+(j*4));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094 }
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001095 readl(intel_private.registers+I810_PTE_BASE+((j-1)*4));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096 agp_bridge->driver->tlb_flush(mem);
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001097
1098out:
1099 ret = 0;
1100out_err:
Dave Airlie9516b032008-06-19 10:42:17 +10001101 mem->is_flushed = true;
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001102 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103}
1104
Dave Airlief011ae72008-01-25 11:23:04 +10001105static int intel_i830_remove_entries(struct agp_memory *mem, off_t pg_start,
1106 int type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107{
1108 int i;
1109
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +01001110 if (mem->page_count == 0)
1111 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001113 if (pg_start < intel_private.gtt_entries) {
Bjorn Helgaase3cf6952008-07-30 12:26:51 -07001114 dev_info(&intel_private.pcidev->dev,
1115 "trying to disable local/stolen memory\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116 return -EINVAL;
1117 }
1118
1119 for (i = pg_start; i < (mem->page_count + pg_start); i++) {
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001120 writel(agp_bridge->scratch_page, intel_private.registers+I810_PTE_BASE+(i*4));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121 }
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001122 readl(intel_private.registers+I810_PTE_BASE+((i-1)*4));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124 agp_bridge->driver->tlb_flush(mem);
1125 return 0;
1126}
1127
Dave Airlief011ae72008-01-25 11:23:04 +10001128static struct agp_memory *intel_i830_alloc_by_type(size_t pg_count, int type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001129{
1130 if (type == AGP_PHYS_MEMORY)
1131 return alloc_agpphysmem_i8xx(pg_count, type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132 /* always return NULL for other allocation types for now */
1133 return NULL;
1134}
1135
Dave Airlie6c00a612007-10-29 18:06:10 +10001136static int intel_alloc_chipset_flush_resource(void)
1137{
1138 int ret;
1139 ret = pci_bus_alloc_resource(agp_bridge->dev->bus, &intel_private.ifp_resource, PAGE_SIZE,
1140 PAGE_SIZE, PCIBIOS_MIN_MEM, 0,
1141 pcibios_align_resource, agp_bridge->dev);
Dave Airlie6c00a612007-10-29 18:06:10 +10001142
Dave Airlie2162e6a2007-11-21 16:36:31 +10001143 return ret;
Dave Airlie6c00a612007-10-29 18:06:10 +10001144}
1145
1146static void intel_i915_setup_chipset_flush(void)
1147{
1148 int ret;
1149 u32 temp;
1150
1151 pci_read_config_dword(agp_bridge->dev, I915_IFPADDR, &temp);
1152 if (!(temp & 0x1)) {
1153 intel_alloc_chipset_flush_resource();
Dave Airlie4d64dd92008-01-23 15:34:29 +10001154 intel_private.resource_valid = 1;
Dave Airlie6c00a612007-10-29 18:06:10 +10001155 pci_write_config_dword(agp_bridge->dev, I915_IFPADDR, (intel_private.ifp_resource.start & 0xffffffff) | 0x1);
1156 } else {
1157 temp &= ~1;
1158
Dave Airlie4d64dd92008-01-23 15:34:29 +10001159 intel_private.resource_valid = 1;
Dave Airlie6c00a612007-10-29 18:06:10 +10001160 intel_private.ifp_resource.start = temp;
1161 intel_private.ifp_resource.end = temp + PAGE_SIZE;
1162 ret = request_resource(&iomem_resource, &intel_private.ifp_resource);
Dave Airlie4d64dd92008-01-23 15:34:29 +10001163 /* some BIOSes reserve this area in a pnp some don't */
1164 if (ret)
1165 intel_private.resource_valid = 0;
Dave Airlie6c00a612007-10-29 18:06:10 +10001166 }
1167}
1168
1169static void intel_i965_g33_setup_chipset_flush(void)
1170{
1171 u32 temp_hi, temp_lo;
1172 int ret;
1173
1174 pci_read_config_dword(agp_bridge->dev, I965_IFPADDR + 4, &temp_hi);
1175 pci_read_config_dword(agp_bridge->dev, I965_IFPADDR, &temp_lo);
1176
1177 if (!(temp_lo & 0x1)) {
1178
1179 intel_alloc_chipset_flush_resource();
1180
Dave Airlie4d64dd92008-01-23 15:34:29 +10001181 intel_private.resource_valid = 1;
Andrew Morton1fa4db72007-11-29 10:00:48 +10001182 pci_write_config_dword(agp_bridge->dev, I965_IFPADDR + 4,
1183 upper_32_bits(intel_private.ifp_resource.start));
Dave Airlie6c00a612007-10-29 18:06:10 +10001184 pci_write_config_dword(agp_bridge->dev, I965_IFPADDR, (intel_private.ifp_resource.start & 0xffffffff) | 0x1);
Dave Airlie6c00a612007-10-29 18:06:10 +10001185 } else {
1186 u64 l64;
Dave Airlief011ae72008-01-25 11:23:04 +10001187
Dave Airlie6c00a612007-10-29 18:06:10 +10001188 temp_lo &= ~0x1;
1189 l64 = ((u64)temp_hi << 32) | temp_lo;
1190
Dave Airlie4d64dd92008-01-23 15:34:29 +10001191 intel_private.resource_valid = 1;
Dave Airlie6c00a612007-10-29 18:06:10 +10001192 intel_private.ifp_resource.start = l64;
1193 intel_private.ifp_resource.end = l64 + PAGE_SIZE;
1194 ret = request_resource(&iomem_resource, &intel_private.ifp_resource);
Dave Airlie4d64dd92008-01-23 15:34:29 +10001195 /* some BIOSes reserve this area in a pnp some don't */
1196 if (ret)
1197 intel_private.resource_valid = 0;
Dave Airlie6c00a612007-10-29 18:06:10 +10001198 }
1199}
1200
Dave Airlie2162e6a2007-11-21 16:36:31 +10001201static void intel_i9xx_setup_flush(void)
1202{
Dave Airlie4d64dd92008-01-23 15:34:29 +10001203 /* return if already configured */
1204 if (intel_private.ifp_resource.start)
1205 return;
Dave Airlie2162e6a2007-11-21 16:36:31 +10001206
Dave Airlie4d64dd92008-01-23 15:34:29 +10001207 /* setup a resource for this object */
Dave Airlie2162e6a2007-11-21 16:36:31 +10001208 intel_private.ifp_resource.name = "Intel Flush Page";
1209 intel_private.ifp_resource.flags = IORESOURCE_MEM;
1210
1211 /* Setup chipset flush for 915 */
Zhenyu Wang7d15ddf2008-06-20 11:48:06 +10001212 if (IS_I965 || IS_G33 || IS_G4X) {
Dave Airlie2162e6a2007-11-21 16:36:31 +10001213 intel_i965_g33_setup_chipset_flush();
1214 } else {
1215 intel_i915_setup_chipset_flush();
1216 }
1217
1218 if (intel_private.ifp_resource.start) {
1219 intel_private.i9xx_flush_page = ioremap_nocache(intel_private.ifp_resource.start, PAGE_SIZE);
1220 if (!intel_private.i9xx_flush_page)
Bjorn Helgaase3cf6952008-07-30 12:26:51 -07001221 dev_info(&intel_private.pcidev->dev, "can't ioremap flush page - no chipset flushing");
Dave Airlie2162e6a2007-11-21 16:36:31 +10001222 }
1223}
1224
Linus Torvalds1da177e2005-04-16 15:20:36 -07001225static int intel_i915_configure(void)
1226{
1227 struct aper_size_info_fixed *current_size;
1228 u32 temp;
1229 u16 gmch_ctrl;
1230 int i;
1231
1232 current_size = A_SIZE_FIX(agp_bridge->current_size);
1233
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001234 pci_read_config_dword(intel_private.pcidev, I915_GMADDR, &temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235
1236 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
1237
Dave Airlief011ae72008-01-25 11:23:04 +10001238 pci_read_config_word(agp_bridge->dev, I830_GMCH_CTRL, &gmch_ctrl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001239 gmch_ctrl |= I830_GMCH_ENABLED;
Dave Airlief011ae72008-01-25 11:23:04 +10001240 pci_write_config_word(agp_bridge->dev, I830_GMCH_CTRL, gmch_ctrl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001241
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001242 writel(agp_bridge->gatt_bus_addr|I810_PGETBL_ENABLED, intel_private.registers+I810_PGETBL_CTL);
1243 readl(intel_private.registers+I810_PGETBL_CTL); /* PCI Posting. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001244
1245 if (agp_bridge->driver->needs_scratch_page) {
David Woodhousefc619012009-12-02 11:00:05 +00001246 for (i = intel_private.gtt_entries; i < intel_private.gtt_total_size; i++) {
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001247 writel(agp_bridge->scratch_page, intel_private.gtt+i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001248 }
Keith Packard44d49442008-10-14 17:18:45 -07001249 readl(intel_private.gtt+i-1); /* PCI Posting. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001250 }
1251
1252 global_cache_flush();
Dave Airlie6c00a612007-10-29 18:06:10 +10001253
Dave Airlie2162e6a2007-11-21 16:36:31 +10001254 intel_i9xx_setup_flush();
Dave Airlief011ae72008-01-25 11:23:04 +10001255
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256 return 0;
1257}
1258
1259static void intel_i915_cleanup(void)
1260{
Dave Airlie2162e6a2007-11-21 16:36:31 +10001261 if (intel_private.i9xx_flush_page)
1262 iounmap(intel_private.i9xx_flush_page);
Dave Airlie4d64dd92008-01-23 15:34:29 +10001263 if (intel_private.resource_valid)
1264 release_resource(&intel_private.ifp_resource);
1265 intel_private.ifp_resource.start = 0;
1266 intel_private.resource_valid = 0;
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001267 iounmap(intel_private.gtt);
1268 iounmap(intel_private.registers);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001269}
1270
Dave Airlie6c00a612007-10-29 18:06:10 +10001271static void intel_i915_chipset_flush(struct agp_bridge_data *bridge)
1272{
Dave Airlie2162e6a2007-11-21 16:36:31 +10001273 if (intel_private.i9xx_flush_page)
1274 writel(1, intel_private.i9xx_flush_page);
Dave Airlie6c00a612007-10-29 18:06:10 +10001275}
1276
Dave Airlief011ae72008-01-25 11:23:04 +10001277static int intel_i915_insert_entries(struct agp_memory *mem, off_t pg_start,
1278 int type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001279{
Zhenyu Wang17661682009-07-27 12:59:57 +01001280 int num_entries;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001281 void *temp;
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001282 int ret = -EINVAL;
1283 int mask_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001284
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +01001285 if (mem->page_count == 0)
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001286 goto out;
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +01001287
Linus Torvalds1da177e2005-04-16 15:20:36 -07001288 temp = agp_bridge->current_size;
1289 num_entries = A_SIZE_FIX(temp)->num_entries;
1290
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001291 if (pg_start < intel_private.gtt_entries) {
Bjorn Helgaase3cf6952008-07-30 12:26:51 -07001292 dev_printk(KERN_DEBUG, &intel_private.pcidev->dev,
1293 "pg_start == 0x%.8lx, intel_private.gtt_entries == 0x%.8x\n",
1294 pg_start, intel_private.gtt_entries);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001295
Bjorn Helgaase3cf6952008-07-30 12:26:51 -07001296 dev_info(&intel_private.pcidev->dev,
1297 "trying to insert into local/stolen memory\n");
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001298 goto out_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299 }
1300
1301 if ((pg_start + mem->page_count) > num_entries)
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001302 goto out_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303
Zhenyu Wang17661682009-07-27 12:59:57 +01001304 /* The i915 can't check the GTT for entries since it's read only;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001305 * depend on the caller to make the correct offset decisions.
1306 */
1307
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001308 if (type != mem->type)
1309 goto out_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001310
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001311 mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type);
1312
1313 if (mask_type != 0 && mask_type != AGP_PHYS_MEMORY &&
1314 mask_type != INTEL_AGP_CACHED_MEMORY)
1315 goto out_err;
1316
1317 if (!mem->is_flushed)
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +01001318 global_cache_flush();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001319
Zhenyu Wang17661682009-07-27 12:59:57 +01001320 intel_agp_insert_sg_entries(mem, pg_start, mask_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001321 agp_bridge->driver->tlb_flush(mem);
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001322
1323 out:
1324 ret = 0;
1325 out_err:
Dave Airlie9516b032008-06-19 10:42:17 +10001326 mem->is_flushed = true;
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001327 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001328}
1329
Dave Airlief011ae72008-01-25 11:23:04 +10001330static int intel_i915_remove_entries(struct agp_memory *mem, off_t pg_start,
1331 int type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001332{
1333 int i;
1334
Thomas Hellstrom5aa80c72006-12-20 16:33:41 +01001335 if (mem->page_count == 0)
1336 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001337
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001338 if (pg_start < intel_private.gtt_entries) {
Bjorn Helgaase3cf6952008-07-30 12:26:51 -07001339 dev_info(&intel_private.pcidev->dev,
1340 "trying to disable local/stolen memory\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001341 return -EINVAL;
1342 }
1343
Dave Airlief011ae72008-01-25 11:23:04 +10001344 for (i = pg_start; i < (mem->page_count + pg_start); i++)
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001345 writel(agp_bridge->scratch_page, intel_private.gtt+i);
Dave Airlief011ae72008-01-25 11:23:04 +10001346
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001347 readl(intel_private.gtt+i-1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001348
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349 agp_bridge->driver->tlb_flush(mem);
1350 return 0;
1351}
1352
Eric Anholtc41e0de2006-12-19 12:57:24 -08001353/* Return the aperture size by just checking the resource length. The effect
1354 * described in the spec of the MSAC registers is just changing of the
1355 * resource size.
1356 */
1357static int intel_i9xx_fetch_size(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001358{
Ahmed S. Darwish1eaf1222007-02-06 18:08:28 +02001359 int num_sizes = ARRAY_SIZE(intel_i830_sizes);
Eric Anholtc41e0de2006-12-19 12:57:24 -08001360 int aper_size; /* size in megabytes */
1361 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001362
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001363 aper_size = pci_resource_len(intel_private.pcidev, 2) / MB(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001364
Eric Anholtc41e0de2006-12-19 12:57:24 -08001365 for (i = 0; i < num_sizes; i++) {
1366 if (aper_size == intel_i830_sizes[i].size) {
1367 agp_bridge->current_size = intel_i830_sizes + i;
1368 agp_bridge->previous_size = agp_bridge->current_size;
1369 return aper_size;
1370 }
1371 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001372
Eric Anholtc41e0de2006-12-19 12:57:24 -08001373 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374}
1375
1376/* The intel i915 automatically initializes the agp aperture during POST.
1377 * Use the memory already set aside for in the GTT.
1378 */
1379static int intel_i915_create_gatt_table(struct agp_bridge_data *bridge)
1380{
1381 int page_order;
1382 struct aper_size_info_fixed *size;
1383 int num_entries;
1384 u32 temp, temp2;
Zhenyu Wang47406222007-09-11 15:23:58 -07001385 int gtt_map_size = 256 * 1024;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386
1387 size = agp_bridge->current_size;
1388 page_order = size->page_order;
1389 num_entries = size->num_entries;
1390 agp_bridge->gatt_table_real = NULL;
1391
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001392 pci_read_config_dword(intel_private.pcidev, I915_MMADDR, &temp);
Dave Airlief011ae72008-01-25 11:23:04 +10001393 pci_read_config_dword(intel_private.pcidev, I915_PTEADDR, &temp2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394
Zhenyu Wang47406222007-09-11 15:23:58 -07001395 if (IS_G33)
1396 gtt_map_size = 1024 * 1024; /* 1M on G33 */
1397 intel_private.gtt = ioremap(temp2, gtt_map_size);
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001398 if (!intel_private.gtt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001399 return -ENOMEM;
1400
David Woodhousefc619012009-12-02 11:00:05 +00001401 intel_private.gtt_total_size = gtt_map_size / 4;
1402
Linus Torvalds1da177e2005-04-16 15:20:36 -07001403 temp &= 0xfff80000;
1404
Dave Airlief011ae72008-01-25 11:23:04 +10001405 intel_private.registers = ioremap(temp, 128 * 4096);
Scott Thompson5bdbc7d2007-08-25 18:14:00 +10001406 if (!intel_private.registers) {
1407 iounmap(intel_private.gtt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001408 return -ENOMEM;
Scott Thompson5bdbc7d2007-08-25 18:14:00 +10001409 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001410
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08001411 temp = readl(intel_private.registers+I810_PGETBL_CTL) & 0xfffff000;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001412 global_cache_flush(); /* FIXME: ? */
1413
1414 /* we have to call this as early as possible after the MMIO base address is known */
1415 intel_i830_init_gtt_entries();
1416
1417 agp_bridge->gatt_table = NULL;
1418
1419 agp_bridge->gatt_bus_addr = temp;
1420
1421 return 0;
1422}
Linus Torvalds7d915a32006-11-22 09:37:54 -08001423
1424/*
1425 * The i965 supports 36-bit physical addresses, but to keep
1426 * the format of the GTT the same, the bits that don't fit
1427 * in a 32-bit word are shifted down to bits 4..7.
1428 *
1429 * Gcc is smart enough to notice that "(addr >> 28) & 0xf0"
1430 * is always zero on 32-bit architectures, so no need to make
1431 * this conditional.
1432 */
1433static unsigned long intel_i965_mask_memory(struct agp_bridge_data *bridge,
David Woodhouse2a4ceb62009-07-27 10:27:29 +01001434 dma_addr_t addr, int type)
Linus Torvalds7d915a32006-11-22 09:37:54 -08001435{
1436 /* Shift high bits down */
1437 addr |= (addr >> 28) & 0xf0;
1438
1439 /* Type checking must be done elsewhere */
1440 return addr | bridge->driver->masks[type].mask;
1441}
1442
Zhenyu Wang25ce77a2008-06-19 14:17:58 +10001443static void intel_i965_get_gtt_range(int *gtt_offset, int *gtt_size)
1444{
1445 switch (agp_bridge->dev->device) {
Zhenyu Wang99d32bd2008-07-30 12:26:50 -07001446 case PCI_DEVICE_ID_INTEL_GM45_HB:
Adam Jackson107f5172009-12-03 17:14:41 -05001447 case PCI_DEVICE_ID_INTEL_EAGLELAKE_HB:
Zhenyu Wang25ce77a2008-06-19 14:17:58 +10001448 case PCI_DEVICE_ID_INTEL_Q45_HB:
1449 case PCI_DEVICE_ID_INTEL_G45_HB:
Zhenyu Wanga50ccc62008-11-17 14:39:00 +08001450 case PCI_DEVICE_ID_INTEL_G41_HB:
Fabian Henze38d8a952009-09-08 00:59:58 +08001451 case PCI_DEVICE_ID_INTEL_B43_HB:
Adam Jackson107f5172009-12-03 17:14:41 -05001452 case PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB:
1453 case PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB:
1454 case PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB:
Dave Airlie3ff99162009-12-08 14:03:47 +10001455 case PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB:
Eric Anholt1089e302009-10-22 16:10:52 -07001456 case PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB:
Eric Anholt954bce52010-01-07 16:21:46 -08001457 case PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB:
Zhenyu Wang25ce77a2008-06-19 14:17:58 +10001458 *gtt_offset = *gtt_size = MB(2);
1459 break;
1460 default:
1461 *gtt_offset = *gtt_size = KB(512);
1462 }
1463}
1464
Eric Anholt65c25aa2006-09-06 11:57:18 -04001465/* The intel i965 automatically initializes the agp aperture during POST.
Eric Anholtc41e0de2006-12-19 12:57:24 -08001466 * Use the memory already set aside for in the GTT.
1467 */
Eric Anholt65c25aa2006-09-06 11:57:18 -04001468static int intel_i965_create_gatt_table(struct agp_bridge_data *bridge)
1469{
Dave Airlie62c96b92008-06-19 14:27:53 +10001470 int page_order;
1471 struct aper_size_info_fixed *size;
1472 int num_entries;
1473 u32 temp;
1474 int gtt_offset, gtt_size;
Eric Anholt65c25aa2006-09-06 11:57:18 -04001475
Dave Airlie62c96b92008-06-19 14:27:53 +10001476 size = agp_bridge->current_size;
1477 page_order = size->page_order;
1478 num_entries = size->num_entries;
1479 agp_bridge->gatt_table_real = NULL;
Eric Anholt65c25aa2006-09-06 11:57:18 -04001480
Dave Airlie62c96b92008-06-19 14:27:53 +10001481 pci_read_config_dword(intel_private.pcidev, I915_MMADDR, &temp);
Eric Anholt65c25aa2006-09-06 11:57:18 -04001482
Dave Airlie62c96b92008-06-19 14:27:53 +10001483 temp &= 0xfff00000;
Eric Anholt65c25aa2006-09-06 11:57:18 -04001484
Zhenyu Wang25ce77a2008-06-19 14:17:58 +10001485 intel_i965_get_gtt_range(&gtt_offset, &gtt_size);
Eric Anholt65c25aa2006-09-06 11:57:18 -04001486
Dave Airlie62c96b92008-06-19 14:27:53 +10001487 intel_private.gtt = ioremap((temp + gtt_offset) , gtt_size);
Eric Anholt65c25aa2006-09-06 11:57:18 -04001488
Dave Airlie62c96b92008-06-19 14:27:53 +10001489 if (!intel_private.gtt)
1490 return -ENOMEM;
Zhenyu Wang4e8b6e22008-01-23 14:54:37 +10001491
David Woodhousefc619012009-12-02 11:00:05 +00001492 intel_private.gtt_total_size = gtt_size / 4;
1493
Dave Airlie62c96b92008-06-19 14:27:53 +10001494 intel_private.registers = ioremap(temp, 128 * 4096);
1495 if (!intel_private.registers) {
Scott Thompson5bdbc7d2007-08-25 18:14:00 +10001496 iounmap(intel_private.gtt);
1497 return -ENOMEM;
1498 }
Eric Anholt65c25aa2006-09-06 11:57:18 -04001499
Dave Airlie62c96b92008-06-19 14:27:53 +10001500 temp = readl(intel_private.registers+I810_PGETBL_CTL) & 0xfffff000;
1501 global_cache_flush(); /* FIXME: ? */
Eric Anholt65c25aa2006-09-06 11:57:18 -04001502
Dave Airlie62c96b92008-06-19 14:27:53 +10001503 /* we have to call this as early as possible after the MMIO base address is known */
1504 intel_i830_init_gtt_entries();
Eric Anholt65c25aa2006-09-06 11:57:18 -04001505
Dave Airlie62c96b92008-06-19 14:27:53 +10001506 agp_bridge->gatt_table = NULL;
Eric Anholt65c25aa2006-09-06 11:57:18 -04001507
Dave Airlie62c96b92008-06-19 14:27:53 +10001508 agp_bridge->gatt_bus_addr = temp;
Eric Anholt65c25aa2006-09-06 11:57:18 -04001509
Dave Airlie62c96b92008-06-19 14:27:53 +10001510 return 0;
Eric Anholt65c25aa2006-09-06 11:57:18 -04001511}
1512
Linus Torvalds1da177e2005-04-16 15:20:36 -07001513
1514static int intel_fetch_size(void)
1515{
1516 int i;
1517 u16 temp;
1518 struct aper_size_info_16 *values;
1519
1520 pci_read_config_word(agp_bridge->dev, INTEL_APSIZE, &temp);
1521 values = A_SIZE_16(agp_bridge->driver->aperture_sizes);
1522
1523 for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) {
1524 if (temp == values[i].size_value) {
1525 agp_bridge->previous_size = agp_bridge->current_size = (void *) (values + i);
1526 agp_bridge->aperture_size_idx = i;
1527 return values[i].size;
1528 }
1529 }
1530
1531 return 0;
1532}
1533
1534static int __intel_8xx_fetch_size(u8 temp)
1535{
1536 int i;
1537 struct aper_size_info_8 *values;
1538
1539 values = A_SIZE_8(agp_bridge->driver->aperture_sizes);
1540
1541 for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) {
1542 if (temp == values[i].size_value) {
1543 agp_bridge->previous_size =
1544 agp_bridge->current_size = (void *) (values + i);
1545 agp_bridge->aperture_size_idx = i;
1546 return values[i].size;
1547 }
1548 }
1549 return 0;
1550}
1551
1552static int intel_8xx_fetch_size(void)
1553{
1554 u8 temp;
1555
1556 pci_read_config_byte(agp_bridge->dev, INTEL_APSIZE, &temp);
1557 return __intel_8xx_fetch_size(temp);
1558}
1559
1560static int intel_815_fetch_size(void)
1561{
1562 u8 temp;
1563
1564 /* Intel 815 chipsets have a _weird_ APSIZE register with only
1565 * one non-reserved bit, so mask the others out ... */
1566 pci_read_config_byte(agp_bridge->dev, INTEL_APSIZE, &temp);
1567 temp &= (1 << 3);
1568
1569 return __intel_8xx_fetch_size(temp);
1570}
1571
1572static void intel_tlbflush(struct agp_memory *mem)
1573{
1574 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x2200);
1575 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x2280);
1576}
1577
1578
1579static void intel_8xx_tlbflush(struct agp_memory *mem)
1580{
1581 u32 temp;
1582 pci_read_config_dword(agp_bridge->dev, INTEL_AGPCTRL, &temp);
1583 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, temp & ~(1 << 7));
1584 pci_read_config_dword(agp_bridge->dev, INTEL_AGPCTRL, &temp);
1585 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, temp | (1 << 7));
1586}
1587
1588
1589static void intel_cleanup(void)
1590{
1591 u16 temp;
1592 struct aper_size_info_16 *previous_size;
1593
1594 previous_size = A_SIZE_16(agp_bridge->previous_size);
1595 pci_read_config_word(agp_bridge->dev, INTEL_NBXCFG, &temp);
1596 pci_write_config_word(agp_bridge->dev, INTEL_NBXCFG, temp & ~(1 << 9));
1597 pci_write_config_word(agp_bridge->dev, INTEL_APSIZE, previous_size->size_value);
1598}
1599
1600
1601static void intel_8xx_cleanup(void)
1602{
1603 u16 temp;
1604 struct aper_size_info_8 *previous_size;
1605
1606 previous_size = A_SIZE_8(agp_bridge->previous_size);
1607 pci_read_config_word(agp_bridge->dev, INTEL_NBXCFG, &temp);
1608 pci_write_config_word(agp_bridge->dev, INTEL_NBXCFG, temp & ~(1 << 9));
1609 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, previous_size->size_value);
1610}
1611
1612
1613static int intel_configure(void)
1614{
1615 u32 temp;
1616 u16 temp2;
1617 struct aper_size_info_16 *current_size;
1618
1619 current_size = A_SIZE_16(agp_bridge->current_size);
1620
1621 /* aperture size */
1622 pci_write_config_word(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
1623
1624 /* address to map to */
1625 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
1626 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
1627
1628 /* attbase - aperture base */
1629 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
1630
1631 /* agpctrl */
1632 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x2280);
1633
1634 /* paccfg/nbxcfg */
1635 pci_read_config_word(agp_bridge->dev, INTEL_NBXCFG, &temp2);
1636 pci_write_config_word(agp_bridge->dev, INTEL_NBXCFG,
1637 (temp2 & ~(1 << 10)) | (1 << 9));
1638 /* clear any possible error conditions */
1639 pci_write_config_byte(agp_bridge->dev, INTEL_ERRSTS + 1, 7);
1640 return 0;
1641}
1642
1643static int intel_815_configure(void)
1644{
1645 u32 temp, addr;
1646 u8 temp2;
1647 struct aper_size_info_8 *current_size;
1648
1649 /* attbase - aperture base */
1650 /* the Intel 815 chipset spec. says that bits 29-31 in the
1651 * ATTBASE register are reserved -> try not to write them */
1652 if (agp_bridge->gatt_bus_addr & INTEL_815_ATTBASE_MASK) {
Bjorn Helgaase3cf6952008-07-30 12:26:51 -07001653 dev_emerg(&agp_bridge->dev->dev, "gatt bus addr too high");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001654 return -EINVAL;
1655 }
1656
1657 current_size = A_SIZE_8(agp_bridge->current_size);
1658
1659 /* aperture size */
1660 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE,
1661 current_size->size_value);
1662
1663 /* address to map to */
1664 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
1665 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
1666
1667 pci_read_config_dword(agp_bridge->dev, INTEL_ATTBASE, &addr);
1668 addr &= INTEL_815_ATTBASE_MASK;
1669 addr |= agp_bridge->gatt_bus_addr;
1670 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, addr);
1671
1672 /* agpctrl */
1673 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
1674
1675 /* apcont */
1676 pci_read_config_byte(agp_bridge->dev, INTEL_815_APCONT, &temp2);
1677 pci_write_config_byte(agp_bridge->dev, INTEL_815_APCONT, temp2 | (1 << 1));
1678
1679 /* clear any possible error conditions */
1680 /* Oddness : this chipset seems to have no ERRSTS register ! */
1681 return 0;
1682}
1683
1684static void intel_820_tlbflush(struct agp_memory *mem)
1685{
1686 return;
1687}
1688
1689static void intel_820_cleanup(void)
1690{
1691 u8 temp;
1692 struct aper_size_info_8 *previous_size;
1693
1694 previous_size = A_SIZE_8(agp_bridge->previous_size);
1695 pci_read_config_byte(agp_bridge->dev, INTEL_I820_RDCR, &temp);
1696 pci_write_config_byte(agp_bridge->dev, INTEL_I820_RDCR,
1697 temp & ~(1 << 1));
1698 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE,
1699 previous_size->size_value);
1700}
1701
1702
1703static int intel_820_configure(void)
1704{
1705 u32 temp;
1706 u8 temp2;
1707 struct aper_size_info_8 *current_size;
1708
1709 current_size = A_SIZE_8(agp_bridge->current_size);
1710
1711 /* aperture size */
1712 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
1713
1714 /* address to map to */
1715 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
1716 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
1717
1718 /* attbase - aperture base */
1719 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
1720
1721 /* agpctrl */
1722 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
1723
1724 /* global enable aperture access */
1725 /* This flag is not accessed through MCHCFG register as in */
1726 /* i850 chipset. */
1727 pci_read_config_byte(agp_bridge->dev, INTEL_I820_RDCR, &temp2);
1728 pci_write_config_byte(agp_bridge->dev, INTEL_I820_RDCR, temp2 | (1 << 1));
1729 /* clear any possible AGP-related error conditions */
1730 pci_write_config_word(agp_bridge->dev, INTEL_I820_ERRSTS, 0x001c);
1731 return 0;
1732}
1733
1734static int intel_840_configure(void)
1735{
1736 u32 temp;
1737 u16 temp2;
1738 struct aper_size_info_8 *current_size;
1739
1740 current_size = A_SIZE_8(agp_bridge->current_size);
1741
1742 /* aperture size */
1743 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
1744
1745 /* address to map to */
1746 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
1747 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
1748
1749 /* attbase - aperture base */
1750 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
1751
1752 /* agpctrl */
1753 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
1754
1755 /* mcgcfg */
1756 pci_read_config_word(agp_bridge->dev, INTEL_I840_MCHCFG, &temp2);
1757 pci_write_config_word(agp_bridge->dev, INTEL_I840_MCHCFG, temp2 | (1 << 9));
1758 /* clear any possible error conditions */
1759 pci_write_config_word(agp_bridge->dev, INTEL_I840_ERRSTS, 0xc000);
1760 return 0;
1761}
1762
1763static int intel_845_configure(void)
1764{
1765 u32 temp;
1766 u8 temp2;
1767 struct aper_size_info_8 *current_size;
1768
1769 current_size = A_SIZE_8(agp_bridge->current_size);
1770
1771 /* aperture size */
1772 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
1773
Matthew Garrettb0825482005-07-29 14:03:39 -07001774 if (agp_bridge->apbase_config != 0) {
1775 pci_write_config_dword(agp_bridge->dev, AGP_APBASE,
1776 agp_bridge->apbase_config);
1777 } else {
1778 /* address to map to */
1779 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
1780 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
1781 agp_bridge->apbase_config = temp;
1782 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001783
1784 /* attbase - aperture base */
1785 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
1786
1787 /* agpctrl */
1788 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
1789
1790 /* agpm */
1791 pci_read_config_byte(agp_bridge->dev, INTEL_I845_AGPM, &temp2);
1792 pci_write_config_byte(agp_bridge->dev, INTEL_I845_AGPM, temp2 | (1 << 1));
1793 /* clear any possible error conditions */
1794 pci_write_config_word(agp_bridge->dev, INTEL_I845_ERRSTS, 0x001c);
Dave Airlie2162e6a2007-11-21 16:36:31 +10001795
1796 intel_i830_setup_flush();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001797 return 0;
1798}
1799
1800static int intel_850_configure(void)
1801{
1802 u32 temp;
1803 u16 temp2;
1804 struct aper_size_info_8 *current_size;
1805
1806 current_size = A_SIZE_8(agp_bridge->current_size);
1807
1808 /* aperture size */
1809 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
1810
1811 /* address to map to */
1812 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
1813 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
1814
1815 /* attbase - aperture base */
1816 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
1817
1818 /* agpctrl */
1819 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
1820
1821 /* mcgcfg */
1822 pci_read_config_word(agp_bridge->dev, INTEL_I850_MCHCFG, &temp2);
1823 pci_write_config_word(agp_bridge->dev, INTEL_I850_MCHCFG, temp2 | (1 << 9));
1824 /* clear any possible AGP-related error conditions */
1825 pci_write_config_word(agp_bridge->dev, INTEL_I850_ERRSTS, 0x001c);
1826 return 0;
1827}
1828
1829static int intel_860_configure(void)
1830{
1831 u32 temp;
1832 u16 temp2;
1833 struct aper_size_info_8 *current_size;
1834
1835 current_size = A_SIZE_8(agp_bridge->current_size);
1836
1837 /* aperture size */
1838 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
1839
1840 /* address to map to */
1841 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
1842 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
1843
1844 /* attbase - aperture base */
1845 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
1846
1847 /* agpctrl */
1848 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
1849
1850 /* mcgcfg */
1851 pci_read_config_word(agp_bridge->dev, INTEL_I860_MCHCFG, &temp2);
1852 pci_write_config_word(agp_bridge->dev, INTEL_I860_MCHCFG, temp2 | (1 << 9));
1853 /* clear any possible AGP-related error conditions */
1854 pci_write_config_word(agp_bridge->dev, INTEL_I860_ERRSTS, 0xf700);
1855 return 0;
1856}
1857
1858static int intel_830mp_configure(void)
1859{
1860 u32 temp;
1861 u16 temp2;
1862 struct aper_size_info_8 *current_size;
1863
1864 current_size = A_SIZE_8(agp_bridge->current_size);
1865
1866 /* aperture size */
1867 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
1868
1869 /* address to map to */
1870 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
1871 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
1872
1873 /* attbase - aperture base */
1874 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
1875
1876 /* agpctrl */
1877 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
1878
1879 /* gmch */
1880 pci_read_config_word(agp_bridge->dev, INTEL_NBXCFG, &temp2);
1881 pci_write_config_word(agp_bridge->dev, INTEL_NBXCFG, temp2 | (1 << 9));
1882 /* clear any possible AGP-related error conditions */
1883 pci_write_config_word(agp_bridge->dev, INTEL_I830_ERRSTS, 0x1c);
1884 return 0;
1885}
1886
1887static int intel_7505_configure(void)
1888{
1889 u32 temp;
1890 u16 temp2;
1891 struct aper_size_info_8 *current_size;
1892
1893 current_size = A_SIZE_8(agp_bridge->current_size);
1894
1895 /* aperture size */
1896 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
1897
1898 /* address to map to */
1899 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
1900 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
1901
1902 /* attbase - aperture base */
1903 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
1904
1905 /* agpctrl */
1906 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
1907
1908 /* mchcfg */
1909 pci_read_config_word(agp_bridge->dev, INTEL_I7505_MCHCFG, &temp2);
1910 pci_write_config_word(agp_bridge->dev, INTEL_I7505_MCHCFG, temp2 | (1 << 9));
1911
1912 return 0;
1913}
1914
1915/* Setup function */
Dave Jonese5524f32007-02-22 18:41:28 -05001916static const struct gatt_mask intel_generic_masks[] =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001917{
1918 {.mask = 0x00000017, .type = 0}
1919};
1920
Dave Jonese5524f32007-02-22 18:41:28 -05001921static const struct aper_size_info_8 intel_815_sizes[2] =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001922{
1923 {64, 16384, 4, 0},
1924 {32, 8192, 3, 8},
1925};
1926
Dave Jonese5524f32007-02-22 18:41:28 -05001927static const struct aper_size_info_8 intel_8xx_sizes[7] =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001928{
1929 {256, 65536, 6, 0},
1930 {128, 32768, 5, 32},
1931 {64, 16384, 4, 48},
1932 {32, 8192, 3, 56},
1933 {16, 4096, 2, 60},
1934 {8, 2048, 1, 62},
1935 {4, 1024, 0, 63}
1936};
1937
Dave Jonese5524f32007-02-22 18:41:28 -05001938static const struct aper_size_info_16 intel_generic_sizes[7] =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001939{
1940 {256, 65536, 6, 0},
1941 {128, 32768, 5, 32},
1942 {64, 16384, 4, 48},
1943 {32, 8192, 3, 56},
1944 {16, 4096, 2, 60},
1945 {8, 2048, 1, 62},
1946 {4, 1024, 0, 63}
1947};
1948
Dave Jonese5524f32007-02-22 18:41:28 -05001949static const struct aper_size_info_8 intel_830mp_sizes[4] =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001950{
1951 {256, 65536, 6, 0},
1952 {128, 32768, 5, 32},
1953 {64, 16384, 4, 48},
1954 {32, 8192, 3, 56}
1955};
1956
Dave Jonese5524f32007-02-22 18:41:28 -05001957static const struct agp_bridge_driver intel_generic_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001958 .owner = THIS_MODULE,
1959 .aperture_sizes = intel_generic_sizes,
1960 .size_type = U16_APER_SIZE,
1961 .num_aperture_sizes = 7,
1962 .configure = intel_configure,
1963 .fetch_size = intel_fetch_size,
1964 .cleanup = intel_cleanup,
1965 .tlb_flush = intel_tlbflush,
1966 .mask_memory = agp_generic_mask_memory,
1967 .masks = intel_generic_masks,
1968 .agp_enable = agp_generic_enable,
1969 .cache_flush = global_cache_flush,
1970 .create_gatt_table = agp_generic_create_gatt_table,
1971 .free_gatt_table = agp_generic_free_gatt_table,
1972 .insert_memory = agp_generic_insert_memory,
1973 .remove_memory = agp_generic_remove_memory,
1974 .alloc_by_type = agp_generic_alloc_by_type,
1975 .free_by_type = agp_generic_free_by_type,
1976 .agp_alloc_page = agp_generic_alloc_page,
Shaohua Li37acee12008-08-21 10:46:11 +08001977 .agp_alloc_pages = agp_generic_alloc_pages,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001978 .agp_destroy_page = agp_generic_destroy_page,
Shaohua Libd079282008-08-21 10:46:17 +08001979 .agp_destroy_pages = agp_generic_destroy_pages,
Thomas Hellstroma030ce42007-01-23 10:33:43 +01001980 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001981};
1982
Dave Jonese5524f32007-02-22 18:41:28 -05001983static const struct agp_bridge_driver intel_810_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001984 .owner = THIS_MODULE,
1985 .aperture_sizes = intel_i810_sizes,
1986 .size_type = FIXED_APER_SIZE,
1987 .num_aperture_sizes = 2,
Joe Perchesc7258012008-03-26 14:10:02 -07001988 .needs_scratch_page = true,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001989 .configure = intel_i810_configure,
1990 .fetch_size = intel_i810_fetch_size,
1991 .cleanup = intel_i810_cleanup,
1992 .tlb_flush = intel_i810_tlbflush,
1993 .mask_memory = intel_i810_mask_memory,
1994 .masks = intel_i810_masks,
1995 .agp_enable = intel_i810_agp_enable,
1996 .cache_flush = global_cache_flush,
1997 .create_gatt_table = agp_generic_create_gatt_table,
1998 .free_gatt_table = agp_generic_free_gatt_table,
1999 .insert_memory = intel_i810_insert_entries,
2000 .remove_memory = intel_i810_remove_entries,
2001 .alloc_by_type = intel_i810_alloc_by_type,
2002 .free_by_type = intel_i810_free_by_type,
2003 .agp_alloc_page = agp_generic_alloc_page,
Shaohua Li37acee12008-08-21 10:46:11 +08002004 .agp_alloc_pages = agp_generic_alloc_pages,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002005 .agp_destroy_page = agp_generic_destroy_page,
Shaohua Libd079282008-08-21 10:46:17 +08002006 .agp_destroy_pages = agp_generic_destroy_pages,
Thomas Hellstroma030ce42007-01-23 10:33:43 +01002007 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002008};
2009
Dave Jonese5524f32007-02-22 18:41:28 -05002010static const struct agp_bridge_driver intel_815_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002011 .owner = THIS_MODULE,
2012 .aperture_sizes = intel_815_sizes,
2013 .size_type = U8_APER_SIZE,
2014 .num_aperture_sizes = 2,
2015 .configure = intel_815_configure,
2016 .fetch_size = intel_815_fetch_size,
2017 .cleanup = intel_8xx_cleanup,
2018 .tlb_flush = intel_8xx_tlbflush,
2019 .mask_memory = agp_generic_mask_memory,
2020 .masks = intel_generic_masks,
2021 .agp_enable = agp_generic_enable,
2022 .cache_flush = global_cache_flush,
2023 .create_gatt_table = agp_generic_create_gatt_table,
2024 .free_gatt_table = agp_generic_free_gatt_table,
2025 .insert_memory = agp_generic_insert_memory,
2026 .remove_memory = agp_generic_remove_memory,
2027 .alloc_by_type = agp_generic_alloc_by_type,
2028 .free_by_type = agp_generic_free_by_type,
2029 .agp_alloc_page = agp_generic_alloc_page,
Shaohua Li37acee12008-08-21 10:46:11 +08002030 .agp_alloc_pages = agp_generic_alloc_pages,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002031 .agp_destroy_page = agp_generic_destroy_page,
Shaohua Libd079282008-08-21 10:46:17 +08002032 .agp_destroy_pages = agp_generic_destroy_pages,
Dave Airlie62c96b92008-06-19 14:27:53 +10002033 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002034};
2035
Dave Jonese5524f32007-02-22 18:41:28 -05002036static const struct agp_bridge_driver intel_830_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002037 .owner = THIS_MODULE,
2038 .aperture_sizes = intel_i830_sizes,
2039 .size_type = FIXED_APER_SIZE,
Dave Jonesc14635e2006-09-06 11:59:35 -04002040 .num_aperture_sizes = 4,
Joe Perchesc7258012008-03-26 14:10:02 -07002041 .needs_scratch_page = true,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002042 .configure = intel_i830_configure,
2043 .fetch_size = intel_i830_fetch_size,
2044 .cleanup = intel_i830_cleanup,
2045 .tlb_flush = intel_i810_tlbflush,
2046 .mask_memory = intel_i810_mask_memory,
2047 .masks = intel_i810_masks,
2048 .agp_enable = intel_i810_agp_enable,
2049 .cache_flush = global_cache_flush,
2050 .create_gatt_table = intel_i830_create_gatt_table,
2051 .free_gatt_table = intel_i830_free_gatt_table,
2052 .insert_memory = intel_i830_insert_entries,
2053 .remove_memory = intel_i830_remove_entries,
2054 .alloc_by_type = intel_i830_alloc_by_type,
2055 .free_by_type = intel_i810_free_by_type,
2056 .agp_alloc_page = agp_generic_alloc_page,
Shaohua Li37acee12008-08-21 10:46:11 +08002057 .agp_alloc_pages = agp_generic_alloc_pages,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002058 .agp_destroy_page = agp_generic_destroy_page,
Shaohua Libd079282008-08-21 10:46:17 +08002059 .agp_destroy_pages = agp_generic_destroy_pages,
Thomas Hellstroma030ce42007-01-23 10:33:43 +01002060 .agp_type_to_mask_type = intel_i830_type_to_mask_type,
Dave Airlie2162e6a2007-11-21 16:36:31 +10002061 .chipset_flush = intel_i830_chipset_flush,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002062};
2063
Dave Jonese5524f32007-02-22 18:41:28 -05002064static const struct agp_bridge_driver intel_820_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002065 .owner = THIS_MODULE,
2066 .aperture_sizes = intel_8xx_sizes,
2067 .size_type = U8_APER_SIZE,
2068 .num_aperture_sizes = 7,
2069 .configure = intel_820_configure,
2070 .fetch_size = intel_8xx_fetch_size,
2071 .cleanup = intel_820_cleanup,
2072 .tlb_flush = intel_820_tlbflush,
2073 .mask_memory = agp_generic_mask_memory,
2074 .masks = intel_generic_masks,
2075 .agp_enable = agp_generic_enable,
2076 .cache_flush = global_cache_flush,
2077 .create_gatt_table = agp_generic_create_gatt_table,
2078 .free_gatt_table = agp_generic_free_gatt_table,
2079 .insert_memory = agp_generic_insert_memory,
2080 .remove_memory = agp_generic_remove_memory,
2081 .alloc_by_type = agp_generic_alloc_by_type,
2082 .free_by_type = agp_generic_free_by_type,
2083 .agp_alloc_page = agp_generic_alloc_page,
Shaohua Li37acee12008-08-21 10:46:11 +08002084 .agp_alloc_pages = agp_generic_alloc_pages,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002085 .agp_destroy_page = agp_generic_destroy_page,
Shaohua Libd079282008-08-21 10:46:17 +08002086 .agp_destroy_pages = agp_generic_destroy_pages,
Thomas Hellstroma030ce42007-01-23 10:33:43 +01002087 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002088};
2089
Dave Jonese5524f32007-02-22 18:41:28 -05002090static const struct agp_bridge_driver intel_830mp_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002091 .owner = THIS_MODULE,
2092 .aperture_sizes = intel_830mp_sizes,
2093 .size_type = U8_APER_SIZE,
2094 .num_aperture_sizes = 4,
2095 .configure = intel_830mp_configure,
2096 .fetch_size = intel_8xx_fetch_size,
2097 .cleanup = intel_8xx_cleanup,
2098 .tlb_flush = intel_8xx_tlbflush,
2099 .mask_memory = agp_generic_mask_memory,
2100 .masks = intel_generic_masks,
2101 .agp_enable = agp_generic_enable,
2102 .cache_flush = global_cache_flush,
2103 .create_gatt_table = agp_generic_create_gatt_table,
2104 .free_gatt_table = agp_generic_free_gatt_table,
2105 .insert_memory = agp_generic_insert_memory,
2106 .remove_memory = agp_generic_remove_memory,
2107 .alloc_by_type = agp_generic_alloc_by_type,
2108 .free_by_type = agp_generic_free_by_type,
2109 .agp_alloc_page = agp_generic_alloc_page,
Shaohua Li37acee12008-08-21 10:46:11 +08002110 .agp_alloc_pages = agp_generic_alloc_pages,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002111 .agp_destroy_page = agp_generic_destroy_page,
Shaohua Libd079282008-08-21 10:46:17 +08002112 .agp_destroy_pages = agp_generic_destroy_pages,
Thomas Hellstroma030ce42007-01-23 10:33:43 +01002113 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002114};
2115
Dave Jonese5524f32007-02-22 18:41:28 -05002116static const struct agp_bridge_driver intel_840_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002117 .owner = THIS_MODULE,
2118 .aperture_sizes = intel_8xx_sizes,
2119 .size_type = U8_APER_SIZE,
2120 .num_aperture_sizes = 7,
2121 .configure = intel_840_configure,
2122 .fetch_size = intel_8xx_fetch_size,
2123 .cleanup = intel_8xx_cleanup,
2124 .tlb_flush = intel_8xx_tlbflush,
2125 .mask_memory = agp_generic_mask_memory,
2126 .masks = intel_generic_masks,
2127 .agp_enable = agp_generic_enable,
2128 .cache_flush = global_cache_flush,
2129 .create_gatt_table = agp_generic_create_gatt_table,
2130 .free_gatt_table = agp_generic_free_gatt_table,
2131 .insert_memory = agp_generic_insert_memory,
2132 .remove_memory = agp_generic_remove_memory,
2133 .alloc_by_type = agp_generic_alloc_by_type,
2134 .free_by_type = agp_generic_free_by_type,
2135 .agp_alloc_page = agp_generic_alloc_page,
Shaohua Li37acee12008-08-21 10:46:11 +08002136 .agp_alloc_pages = agp_generic_alloc_pages,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002137 .agp_destroy_page = agp_generic_destroy_page,
Shaohua Libd079282008-08-21 10:46:17 +08002138 .agp_destroy_pages = agp_generic_destroy_pages,
Thomas Hellstroma030ce42007-01-23 10:33:43 +01002139 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002140};
2141
Dave Jonese5524f32007-02-22 18:41:28 -05002142static const struct agp_bridge_driver intel_845_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002143 .owner = THIS_MODULE,
2144 .aperture_sizes = intel_8xx_sizes,
2145 .size_type = U8_APER_SIZE,
2146 .num_aperture_sizes = 7,
2147 .configure = intel_845_configure,
2148 .fetch_size = intel_8xx_fetch_size,
2149 .cleanup = intel_8xx_cleanup,
2150 .tlb_flush = intel_8xx_tlbflush,
2151 .mask_memory = agp_generic_mask_memory,
2152 .masks = intel_generic_masks,
2153 .agp_enable = agp_generic_enable,
2154 .cache_flush = global_cache_flush,
2155 .create_gatt_table = agp_generic_create_gatt_table,
2156 .free_gatt_table = agp_generic_free_gatt_table,
2157 .insert_memory = agp_generic_insert_memory,
2158 .remove_memory = agp_generic_remove_memory,
2159 .alloc_by_type = agp_generic_alloc_by_type,
2160 .free_by_type = agp_generic_free_by_type,
2161 .agp_alloc_page = agp_generic_alloc_page,
Shaohua Li37acee12008-08-21 10:46:11 +08002162 .agp_alloc_pages = agp_generic_alloc_pages,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002163 .agp_destroy_page = agp_generic_destroy_page,
Shaohua Libd079282008-08-21 10:46:17 +08002164 .agp_destroy_pages = agp_generic_destroy_pages,
Thomas Hellstroma030ce42007-01-23 10:33:43 +01002165 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
Dave Airlie2162e6a2007-11-21 16:36:31 +10002166 .chipset_flush = intel_i830_chipset_flush,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002167};
2168
Dave Jonese5524f32007-02-22 18:41:28 -05002169static const struct agp_bridge_driver intel_850_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002170 .owner = THIS_MODULE,
2171 .aperture_sizes = intel_8xx_sizes,
2172 .size_type = U8_APER_SIZE,
2173 .num_aperture_sizes = 7,
2174 .configure = intel_850_configure,
2175 .fetch_size = intel_8xx_fetch_size,
2176 .cleanup = intel_8xx_cleanup,
2177 .tlb_flush = intel_8xx_tlbflush,
2178 .mask_memory = agp_generic_mask_memory,
2179 .masks = intel_generic_masks,
2180 .agp_enable = agp_generic_enable,
2181 .cache_flush = global_cache_flush,
2182 .create_gatt_table = agp_generic_create_gatt_table,
2183 .free_gatt_table = agp_generic_free_gatt_table,
2184 .insert_memory = agp_generic_insert_memory,
2185 .remove_memory = agp_generic_remove_memory,
2186 .alloc_by_type = agp_generic_alloc_by_type,
2187 .free_by_type = agp_generic_free_by_type,
2188 .agp_alloc_page = agp_generic_alloc_page,
Shaohua Li37acee12008-08-21 10:46:11 +08002189 .agp_alloc_pages = agp_generic_alloc_pages,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002190 .agp_destroy_page = agp_generic_destroy_page,
Shaohua Libd079282008-08-21 10:46:17 +08002191 .agp_destroy_pages = agp_generic_destroy_pages,
Thomas Hellstroma030ce42007-01-23 10:33:43 +01002192 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002193};
2194
Dave Jonese5524f32007-02-22 18:41:28 -05002195static const struct agp_bridge_driver intel_860_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002196 .owner = THIS_MODULE,
2197 .aperture_sizes = intel_8xx_sizes,
2198 .size_type = U8_APER_SIZE,
2199 .num_aperture_sizes = 7,
2200 .configure = intel_860_configure,
2201 .fetch_size = intel_8xx_fetch_size,
2202 .cleanup = intel_8xx_cleanup,
2203 .tlb_flush = intel_8xx_tlbflush,
2204 .mask_memory = agp_generic_mask_memory,
2205 .masks = intel_generic_masks,
2206 .agp_enable = agp_generic_enable,
2207 .cache_flush = global_cache_flush,
2208 .create_gatt_table = agp_generic_create_gatt_table,
2209 .free_gatt_table = agp_generic_free_gatt_table,
2210 .insert_memory = agp_generic_insert_memory,
2211 .remove_memory = agp_generic_remove_memory,
2212 .alloc_by_type = agp_generic_alloc_by_type,
2213 .free_by_type = agp_generic_free_by_type,
2214 .agp_alloc_page = agp_generic_alloc_page,
Shaohua Li37acee12008-08-21 10:46:11 +08002215 .agp_alloc_pages = agp_generic_alloc_pages,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002216 .agp_destroy_page = agp_generic_destroy_page,
Shaohua Libd079282008-08-21 10:46:17 +08002217 .agp_destroy_pages = agp_generic_destroy_pages,
Thomas Hellstroma030ce42007-01-23 10:33:43 +01002218 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002219};
2220
Dave Jonese5524f32007-02-22 18:41:28 -05002221static const struct agp_bridge_driver intel_915_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002222 .owner = THIS_MODULE,
2223 .aperture_sizes = intel_i830_sizes,
2224 .size_type = FIXED_APER_SIZE,
Dave Jonesc14635e2006-09-06 11:59:35 -04002225 .num_aperture_sizes = 4,
Joe Perchesc7258012008-03-26 14:10:02 -07002226 .needs_scratch_page = true,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002227 .configure = intel_i915_configure,
Eric Anholtc41e0de2006-12-19 12:57:24 -08002228 .fetch_size = intel_i9xx_fetch_size,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002229 .cleanup = intel_i915_cleanup,
2230 .tlb_flush = intel_i810_tlbflush,
2231 .mask_memory = intel_i810_mask_memory,
2232 .masks = intel_i810_masks,
2233 .agp_enable = intel_i810_agp_enable,
2234 .cache_flush = global_cache_flush,
2235 .create_gatt_table = intel_i915_create_gatt_table,
2236 .free_gatt_table = intel_i830_free_gatt_table,
2237 .insert_memory = intel_i915_insert_entries,
2238 .remove_memory = intel_i915_remove_entries,
2239 .alloc_by_type = intel_i830_alloc_by_type,
2240 .free_by_type = intel_i810_free_by_type,
2241 .agp_alloc_page = agp_generic_alloc_page,
Shaohua Li37acee12008-08-21 10:46:11 +08002242 .agp_alloc_pages = agp_generic_alloc_pages,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002243 .agp_destroy_page = agp_generic_destroy_page,
Shaohua Libd079282008-08-21 10:46:17 +08002244 .agp_destroy_pages = agp_generic_destroy_pages,
Thomas Hellstroma030ce42007-01-23 10:33:43 +01002245 .agp_type_to_mask_type = intel_i830_type_to_mask_type,
Dave Airlie6c00a612007-10-29 18:06:10 +10002246 .chipset_flush = intel_i915_chipset_flush,
Zhenyu Wang17661682009-07-27 12:59:57 +01002247#ifdef USE_PCI_DMA_API
2248 .agp_map_page = intel_agp_map_page,
2249 .agp_unmap_page = intel_agp_unmap_page,
2250 .agp_map_memory = intel_agp_map_memory,
2251 .agp_unmap_memory = intel_agp_unmap_memory,
2252#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002253};
2254
Dave Jonese5524f32007-02-22 18:41:28 -05002255static const struct agp_bridge_driver intel_i965_driver = {
Dave Airlie62c96b92008-06-19 14:27:53 +10002256 .owner = THIS_MODULE,
2257 .aperture_sizes = intel_i830_sizes,
2258 .size_type = FIXED_APER_SIZE,
2259 .num_aperture_sizes = 4,
2260 .needs_scratch_page = true,
Dave Airlie0e480e52008-06-19 14:57:31 +10002261 .configure = intel_i915_configure,
2262 .fetch_size = intel_i9xx_fetch_size,
Dave Airlie62c96b92008-06-19 14:27:53 +10002263 .cleanup = intel_i915_cleanup,
2264 .tlb_flush = intel_i810_tlbflush,
2265 .mask_memory = intel_i965_mask_memory,
2266 .masks = intel_i810_masks,
2267 .agp_enable = intel_i810_agp_enable,
2268 .cache_flush = global_cache_flush,
2269 .create_gatt_table = intel_i965_create_gatt_table,
2270 .free_gatt_table = intel_i830_free_gatt_table,
2271 .insert_memory = intel_i915_insert_entries,
2272 .remove_memory = intel_i915_remove_entries,
2273 .alloc_by_type = intel_i830_alloc_by_type,
2274 .free_by_type = intel_i810_free_by_type,
2275 .agp_alloc_page = agp_generic_alloc_page,
Shaohua Li37acee12008-08-21 10:46:11 +08002276 .agp_alloc_pages = agp_generic_alloc_pages,
Dave Airlie62c96b92008-06-19 14:27:53 +10002277 .agp_destroy_page = agp_generic_destroy_page,
Shaohua Libd079282008-08-21 10:46:17 +08002278 .agp_destroy_pages = agp_generic_destroy_pages,
Dave Airlie62c96b92008-06-19 14:27:53 +10002279 .agp_type_to_mask_type = intel_i830_type_to_mask_type,
Dave Airlie6c00a612007-10-29 18:06:10 +10002280 .chipset_flush = intel_i915_chipset_flush,
Zhenyu Wang17661682009-07-27 12:59:57 +01002281#ifdef USE_PCI_DMA_API
2282 .agp_map_page = intel_agp_map_page,
2283 .agp_unmap_page = intel_agp_unmap_page,
2284 .agp_map_memory = intel_agp_map_memory,
2285 .agp_unmap_memory = intel_agp_unmap_memory,
2286#endif
Eric Anholt65c25aa2006-09-06 11:57:18 -04002287};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002288
Dave Jonese5524f32007-02-22 18:41:28 -05002289static const struct agp_bridge_driver intel_7505_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002290 .owner = THIS_MODULE,
2291 .aperture_sizes = intel_8xx_sizes,
2292 .size_type = U8_APER_SIZE,
2293 .num_aperture_sizes = 7,
2294 .configure = intel_7505_configure,
2295 .fetch_size = intel_8xx_fetch_size,
2296 .cleanup = intel_8xx_cleanup,
2297 .tlb_flush = intel_8xx_tlbflush,
2298 .mask_memory = agp_generic_mask_memory,
2299 .masks = intel_generic_masks,
2300 .agp_enable = agp_generic_enable,
2301 .cache_flush = global_cache_flush,
2302 .create_gatt_table = agp_generic_create_gatt_table,
2303 .free_gatt_table = agp_generic_free_gatt_table,
2304 .insert_memory = agp_generic_insert_memory,
2305 .remove_memory = agp_generic_remove_memory,
2306 .alloc_by_type = agp_generic_alloc_by_type,
2307 .free_by_type = agp_generic_free_by_type,
2308 .agp_alloc_page = agp_generic_alloc_page,
Shaohua Li37acee12008-08-21 10:46:11 +08002309 .agp_alloc_pages = agp_generic_alloc_pages,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002310 .agp_destroy_page = agp_generic_destroy_page,
Shaohua Libd079282008-08-21 10:46:17 +08002311 .agp_destroy_pages = agp_generic_destroy_pages,
Thomas Hellstroma030ce42007-01-23 10:33:43 +01002312 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002313};
2314
Wang Zhenyu874808c62007-06-06 11:16:25 +08002315static const struct agp_bridge_driver intel_g33_driver = {
Dave Airlie62c96b92008-06-19 14:27:53 +10002316 .owner = THIS_MODULE,
2317 .aperture_sizes = intel_i830_sizes,
2318 .size_type = FIXED_APER_SIZE,
2319 .num_aperture_sizes = 4,
2320 .needs_scratch_page = true,
2321 .configure = intel_i915_configure,
2322 .fetch_size = intel_i9xx_fetch_size,
2323 .cleanup = intel_i915_cleanup,
2324 .tlb_flush = intel_i810_tlbflush,
2325 .mask_memory = intel_i965_mask_memory,
2326 .masks = intel_i810_masks,
2327 .agp_enable = intel_i810_agp_enable,
2328 .cache_flush = global_cache_flush,
2329 .create_gatt_table = intel_i915_create_gatt_table,
2330 .free_gatt_table = intel_i830_free_gatt_table,
2331 .insert_memory = intel_i915_insert_entries,
2332 .remove_memory = intel_i915_remove_entries,
2333 .alloc_by_type = intel_i830_alloc_by_type,
2334 .free_by_type = intel_i810_free_by_type,
2335 .agp_alloc_page = agp_generic_alloc_page,
Shaohua Li37acee12008-08-21 10:46:11 +08002336 .agp_alloc_pages = agp_generic_alloc_pages,
Dave Airlie62c96b92008-06-19 14:27:53 +10002337 .agp_destroy_page = agp_generic_destroy_page,
Shaohua Libd079282008-08-21 10:46:17 +08002338 .agp_destroy_pages = agp_generic_destroy_pages,
Dave Airlie62c96b92008-06-19 14:27:53 +10002339 .agp_type_to_mask_type = intel_i830_type_to_mask_type,
Dave Airlie6c00a612007-10-29 18:06:10 +10002340 .chipset_flush = intel_i915_chipset_flush,
Zhenyu Wang17661682009-07-27 12:59:57 +01002341#ifdef USE_PCI_DMA_API
2342 .agp_map_page = intel_agp_map_page,
2343 .agp_unmap_page = intel_agp_unmap_page,
2344 .agp_map_memory = intel_agp_map_memory,
2345 .agp_unmap_memory = intel_agp_unmap_memory,
2346#endif
Wang Zhenyu874808c62007-06-06 11:16:25 +08002347};
Wang Zhenyu9614ece2007-05-30 09:45:58 +08002348
2349static int find_gmch(u16 device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002350{
Wang Zhenyu9614ece2007-05-30 09:45:58 +08002351 struct pci_dev *gmch_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002352
Wang Zhenyu9614ece2007-05-30 09:45:58 +08002353 gmch_device = pci_get_device(PCI_VENDOR_ID_INTEL, device, NULL);
2354 if (gmch_device && PCI_FUNC(gmch_device->devfn) != 0) {
2355 gmch_device = pci_get_device(PCI_VENDOR_ID_INTEL,
Dave Airlief011ae72008-01-25 11:23:04 +10002356 device, gmch_device);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002357 }
2358
Wang Zhenyu9614ece2007-05-30 09:45:58 +08002359 if (!gmch_device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002360 return 0;
2361
Wang Zhenyu9614ece2007-05-30 09:45:58 +08002362 intel_private.pcidev = gmch_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002363 return 1;
2364}
2365
Wang Zhenyu9614ece2007-05-30 09:45:58 +08002366/* Table to describe Intel GMCH and AGP/PCIE GART drivers. At least one of
2367 * driver and gmch_driver must be non-null, and find_gmch will determine
2368 * which one should be used if a gmch_chip_id is present.
2369 */
2370static const struct intel_driver_description {
2371 unsigned int chip_id;
2372 unsigned int gmch_chip_id;
Wang Zhenyu88889852007-06-14 10:01:04 +08002373 unsigned int multi_gmch_chip; /* if we have more gfx chip type on this HB. */
Wang Zhenyu9614ece2007-05-30 09:45:58 +08002374 char *name;
2375 const struct agp_bridge_driver *driver;
2376 const struct agp_bridge_driver *gmch_driver;
2377} intel_agp_chipsets[] = {
Wang Zhenyu88889852007-06-14 10:01:04 +08002378 { PCI_DEVICE_ID_INTEL_82443LX_0, 0, 0, "440LX", &intel_generic_driver, NULL },
2379 { PCI_DEVICE_ID_INTEL_82443BX_0, 0, 0, "440BX", &intel_generic_driver, NULL },
2380 { PCI_DEVICE_ID_INTEL_82443GX_0, 0, 0, "440GX", &intel_generic_driver, NULL },
2381 { PCI_DEVICE_ID_INTEL_82810_MC1, PCI_DEVICE_ID_INTEL_82810_IG1, 0, "i810",
Wang Zhenyu9614ece2007-05-30 09:45:58 +08002382 NULL, &intel_810_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +08002383 { PCI_DEVICE_ID_INTEL_82810_MC3, PCI_DEVICE_ID_INTEL_82810_IG3, 0, "i810",
Wang Zhenyu9614ece2007-05-30 09:45:58 +08002384 NULL, &intel_810_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +08002385 { PCI_DEVICE_ID_INTEL_82810E_MC, PCI_DEVICE_ID_INTEL_82810E_IG, 0, "i810",
Wang Zhenyu9614ece2007-05-30 09:45:58 +08002386 NULL, &intel_810_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +08002387 { PCI_DEVICE_ID_INTEL_82815_MC, PCI_DEVICE_ID_INTEL_82815_CGC, 0, "i815",
2388 &intel_815_driver, &intel_810_driver },
2389 { PCI_DEVICE_ID_INTEL_82820_HB, 0, 0, "i820", &intel_820_driver, NULL },
2390 { PCI_DEVICE_ID_INTEL_82820_UP_HB, 0, 0, "i820", &intel_820_driver, NULL },
2391 { PCI_DEVICE_ID_INTEL_82830_HB, PCI_DEVICE_ID_INTEL_82830_CGC, 0, "830M",
Wang Zhenyu9614ece2007-05-30 09:45:58 +08002392 &intel_830mp_driver, &intel_830_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +08002393 { PCI_DEVICE_ID_INTEL_82840_HB, 0, 0, "i840", &intel_840_driver, NULL },
2394 { PCI_DEVICE_ID_INTEL_82845_HB, 0, 0, "845G", &intel_845_driver, NULL },
2395 { PCI_DEVICE_ID_INTEL_82845G_HB, PCI_DEVICE_ID_INTEL_82845G_IG, 0, "830M",
Wang Zhenyu9614ece2007-05-30 09:45:58 +08002396 &intel_845_driver, &intel_830_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +08002397 { PCI_DEVICE_ID_INTEL_82850_HB, 0, 0, "i850", &intel_850_driver, NULL },
Stefan Husemann347486b2009-04-13 14:40:10 -07002398 { PCI_DEVICE_ID_INTEL_82854_HB, PCI_DEVICE_ID_INTEL_82854_IG, 0, "854",
2399 &intel_845_driver, &intel_830_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +08002400 { PCI_DEVICE_ID_INTEL_82855PM_HB, 0, 0, "855PM", &intel_845_driver, NULL },
2401 { PCI_DEVICE_ID_INTEL_82855GM_HB, PCI_DEVICE_ID_INTEL_82855GM_IG, 0, "855GM",
Wang Zhenyu9614ece2007-05-30 09:45:58 +08002402 &intel_845_driver, &intel_830_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +08002403 { PCI_DEVICE_ID_INTEL_82860_HB, 0, 0, "i860", &intel_860_driver, NULL },
2404 { PCI_DEVICE_ID_INTEL_82865_HB, PCI_DEVICE_ID_INTEL_82865_IG, 0, "865",
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_82875_HB, 0, 0, "i875", &intel_845_driver, NULL },
Carlos Martíne914a362008-01-24 10:34:09 +10002407 { PCI_DEVICE_ID_INTEL_E7221_HB, PCI_DEVICE_ID_INTEL_E7221_IG, 0, "E7221 (i915)",
2408 NULL, &intel_915_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +08002409 { PCI_DEVICE_ID_INTEL_82915G_HB, PCI_DEVICE_ID_INTEL_82915G_IG, 0, "915G",
Wang Zhenyu47d46372007-06-21 13:43:18 +08002410 NULL, &intel_915_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +08002411 { PCI_DEVICE_ID_INTEL_82915GM_HB, PCI_DEVICE_ID_INTEL_82915GM_IG, 0, "915GM",
Wang Zhenyu47d46372007-06-21 13:43:18 +08002412 NULL, &intel_915_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +08002413 { PCI_DEVICE_ID_INTEL_82945G_HB, PCI_DEVICE_ID_INTEL_82945G_IG, 0, "945G",
Wang Zhenyu47d46372007-06-21 13:43:18 +08002414 NULL, &intel_915_driver },
Zhenyu Wangdde47872007-07-26 09:18:09 +08002415 { PCI_DEVICE_ID_INTEL_82945GM_HB, PCI_DEVICE_ID_INTEL_82945GM_IG, 0, "945GM",
Wang Zhenyu47d46372007-06-21 13:43:18 +08002416 NULL, &intel_915_driver },
Zhenyu Wangdde47872007-07-26 09:18:09 +08002417 { PCI_DEVICE_ID_INTEL_82945GME_HB, PCI_DEVICE_ID_INTEL_82945GME_IG, 0, "945GME",
Wang Zhenyu47d46372007-06-21 13:43:18 +08002418 NULL, &intel_915_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +08002419 { PCI_DEVICE_ID_INTEL_82946GZ_HB, PCI_DEVICE_ID_INTEL_82946GZ_IG, 0, "946GZ",
Wang Zhenyu47d46372007-06-21 13:43:18 +08002420 NULL, &intel_i965_driver },
Zhenyu Wang9119f852008-01-23 15:49:26 +10002421 { PCI_DEVICE_ID_INTEL_82G35_HB, PCI_DEVICE_ID_INTEL_82G35_IG, 0, "G35",
Wang Zhenyu47d46372007-06-21 13:43:18 +08002422 NULL, &intel_i965_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +08002423 { PCI_DEVICE_ID_INTEL_82965Q_HB, PCI_DEVICE_ID_INTEL_82965Q_IG, 0, "965Q",
Wang Zhenyu47d46372007-06-21 13:43:18 +08002424 NULL, &intel_i965_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +08002425 { PCI_DEVICE_ID_INTEL_82965G_HB, PCI_DEVICE_ID_INTEL_82965G_IG, 0, "965G",
Wang Zhenyu47d46372007-06-21 13:43:18 +08002426 NULL, &intel_i965_driver },
Zhenyu Wangdde47872007-07-26 09:18:09 +08002427 { PCI_DEVICE_ID_INTEL_82965GM_HB, PCI_DEVICE_ID_INTEL_82965GM_IG, 0, "965GM",
Wang Zhenyu47d46372007-06-21 13:43:18 +08002428 NULL, &intel_i965_driver },
Zhenyu Wangdde47872007-07-26 09:18:09 +08002429 { PCI_DEVICE_ID_INTEL_82965GME_HB, PCI_DEVICE_ID_INTEL_82965GME_IG, 0, "965GME/GLE",
Wang Zhenyu47d46372007-06-21 13:43:18 +08002430 NULL, &intel_i965_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +08002431 { PCI_DEVICE_ID_INTEL_7505_0, 0, 0, "E7505", &intel_7505_driver, NULL },
2432 { PCI_DEVICE_ID_INTEL_7205_0, 0, 0, "E7205", &intel_7505_driver, NULL },
2433 { PCI_DEVICE_ID_INTEL_G33_HB, PCI_DEVICE_ID_INTEL_G33_IG, 0, "G33",
Wang Zhenyu47d46372007-06-21 13:43:18 +08002434 NULL, &intel_g33_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +08002435 { PCI_DEVICE_ID_INTEL_Q35_HB, PCI_DEVICE_ID_INTEL_Q35_IG, 0, "Q35",
Wang Zhenyu47d46372007-06-21 13:43:18 +08002436 NULL, &intel_g33_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +08002437 { PCI_DEVICE_ID_INTEL_Q33_HB, PCI_DEVICE_ID_INTEL_Q33_IG, 0, "Q33",
Wang Zhenyu47d46372007-06-21 13:43:18 +08002438 NULL, &intel_g33_driver },
Zhenyu Wangaf86d4b2010-02-10 10:39:33 +08002439 { PCI_DEVICE_ID_INTEL_PINEVIEW_M_HB, PCI_DEVICE_ID_INTEL_PINEVIEW_M_IG, 0, "GMA3150",
Shaohua Li21778322009-02-23 15:19:16 +08002440 NULL, &intel_g33_driver },
Zhenyu Wangaf86d4b2010-02-10 10:39:33 +08002441 { PCI_DEVICE_ID_INTEL_PINEVIEW_HB, PCI_DEVICE_ID_INTEL_PINEVIEW_IG, 0, "GMA3150",
Shaohua Li21778322009-02-23 15:19:16 +08002442 NULL, &intel_g33_driver },
Zhenyu Wang99d32bd2008-07-30 12:26:50 -07002443 { PCI_DEVICE_ID_INTEL_GM45_HB, PCI_DEVICE_ID_INTEL_GM45_IG, 0,
Adam Jackson107f5172009-12-03 17:14:41 -05002444 "GM45", NULL, &intel_i965_driver },
2445 { PCI_DEVICE_ID_INTEL_EAGLELAKE_HB, PCI_DEVICE_ID_INTEL_EAGLELAKE_IG, 0,
2446 "Eaglelake", NULL, &intel_i965_driver },
Zhenyu Wang25ce77a2008-06-19 14:17:58 +10002447 { PCI_DEVICE_ID_INTEL_Q45_HB, PCI_DEVICE_ID_INTEL_Q45_IG, 0,
2448 "Q45/Q43", NULL, &intel_i965_driver },
2449 { PCI_DEVICE_ID_INTEL_G45_HB, PCI_DEVICE_ID_INTEL_G45_IG, 0,
2450 "G45/G43", NULL, &intel_i965_driver },
Fabian Henze38d8a952009-09-08 00:59:58 +08002451 { PCI_DEVICE_ID_INTEL_B43_HB, PCI_DEVICE_ID_INTEL_B43_IG, 0,
2452 "B43", NULL, &intel_i965_driver },
Zhenyu Wanga50ccc62008-11-17 14:39:00 +08002453 { PCI_DEVICE_ID_INTEL_G41_HB, PCI_DEVICE_ID_INTEL_G41_IG, 0,
2454 "G41", NULL, &intel_i965_driver },
Adam Jackson107f5172009-12-03 17:14:41 -05002455 { PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_D_IG, 0,
Zhenyu Wangaf86d4b2010-02-10 10:39:33 +08002456 "HD Graphics", NULL, &intel_i965_driver },
Adam Jackson107f5172009-12-03 17:14:41 -05002457 { PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG, 0,
Zhenyu Wangaf86d4b2010-02-10 10:39:33 +08002458 "HD Graphics", NULL, &intel_i965_driver },
Adam Jackson107f5172009-12-03 17:14:41 -05002459 { PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG, 0,
Zhenyu Wangaf86d4b2010-02-10 10:39:33 +08002460 "HD Graphics", NULL, &intel_i965_driver },
Dave Airlie3ff99162009-12-08 14:03:47 +10002461 { PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG, 0,
Zhenyu Wangaf86d4b2010-02-10 10:39:33 +08002462 "HD Graphics", NULL, &intel_i965_driver },
Eric Anholt1089e302009-10-22 16:10:52 -07002463 { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_IG, 0,
2464 "Sandybridge", NULL, &intel_i965_driver },
Eric Anholt954bce52010-01-07 16:21:46 -08002465 { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_IG, 0,
2466 "Sandybridge", NULL, &intel_i965_driver },
Wang Zhenyu88889852007-06-14 10:01:04 +08002467 { 0, 0, 0, NULL, NULL, NULL }
Wang Zhenyu9614ece2007-05-30 09:45:58 +08002468};
2469
Linus Torvalds1da177e2005-04-16 15:20:36 -07002470static int __devinit agp_intel_probe(struct pci_dev *pdev,
2471 const struct pci_device_id *ent)
2472{
2473 struct agp_bridge_data *bridge;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002474 u8 cap_ptr = 0;
2475 struct resource *r;
Wang Zhenyu9614ece2007-05-30 09:45:58 +08002476 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002477
2478 cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
2479
2480 bridge = agp_alloc_bridge();
2481 if (!bridge)
2482 return -ENOMEM;
2483
Wang Zhenyu9614ece2007-05-30 09:45:58 +08002484 for (i = 0; intel_agp_chipsets[i].name != NULL; i++) {
2485 /* In case that multiple models of gfx chip may
2486 stand on same host bridge type, this can be
2487 sure we detect the right IGD. */
Wang Zhenyu88889852007-06-14 10:01:04 +08002488 if (pdev->device == intel_agp_chipsets[i].chip_id) {
2489 if ((intel_agp_chipsets[i].gmch_chip_id != 0) &&
2490 find_gmch(intel_agp_chipsets[i].gmch_chip_id)) {
2491 bridge->driver =
2492 intel_agp_chipsets[i].gmch_driver;
2493 break;
2494 } else if (intel_agp_chipsets[i].multi_gmch_chip) {
2495 continue;
2496 } else {
2497 bridge->driver = intel_agp_chipsets[i].driver;
2498 break;
2499 }
2500 }
Wang Zhenyu9614ece2007-05-30 09:45:58 +08002501 }
2502
2503 if (intel_agp_chipsets[i].name == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002504 if (cap_ptr)
Bjorn Helgaase3cf6952008-07-30 12:26:51 -07002505 dev_warn(&pdev->dev, "unsupported Intel chipset [%04x/%04x]\n",
2506 pdev->vendor, pdev->device);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002507 agp_put_bridge(bridge);
2508 return -ENODEV;
Wang Zhenyu9614ece2007-05-30 09:45:58 +08002509 }
2510
Wang Zhenyu9614ece2007-05-30 09:45:58 +08002511 if (bridge->driver == NULL) {
Wang Zhenyu47d46372007-06-21 13:43:18 +08002512 /* bridge has no AGP and no IGD detected */
2513 if (cap_ptr)
Bjorn Helgaase3cf6952008-07-30 12:26:51 -07002514 dev_warn(&pdev->dev, "can't find bridge device (chip_id: %04x)\n",
2515 intel_agp_chipsets[i].gmch_chip_id);
Wang Zhenyu9614ece2007-05-30 09:45:58 +08002516 agp_put_bridge(bridge);
2517 return -ENODEV;
Dave Airlief011ae72008-01-25 11:23:04 +10002518 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002519
2520 bridge->dev = pdev;
2521 bridge->capndx = cap_ptr;
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08002522 bridge->dev_private_data = &intel_private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002523
Bjorn Helgaase3cf6952008-07-30 12:26:51 -07002524 dev_info(&pdev->dev, "Intel %s Chipset\n", intel_agp_chipsets[i].name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002525
2526 /*
2527 * The following fixes the case where the BIOS has "forgotten" to
2528 * provide an address range for the GART.
2529 * 20030610 - hamish@zot.org
2530 */
2531 r = &pdev->resource[0];
2532 if (!r->start && r->end) {
Dave Jones6a92a4e2006-02-28 00:54:25 -05002533 if (pci_assign_resource(pdev, 0)) {
Bjorn Helgaase3cf6952008-07-30 12:26:51 -07002534 dev_err(&pdev->dev, "can't assign resource 0\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002535 agp_put_bridge(bridge);
2536 return -ENODEV;
2537 }
2538 }
2539
2540 /*
2541 * If the device has not been properly setup, the following will catch
2542 * the problem and should stop the system from crashing.
2543 * 20030610 - hamish@zot.org
2544 */
2545 if (pci_enable_device(pdev)) {
Bjorn Helgaase3cf6952008-07-30 12:26:51 -07002546 dev_err(&pdev->dev, "can't enable PCI device\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002547 agp_put_bridge(bridge);
2548 return -ENODEV;
2549 }
2550
2551 /* Fill in the mode register */
2552 if (cap_ptr) {
2553 pci_read_config_dword(pdev,
2554 bridge->capndx+PCI_AGP_STATUS,
2555 &bridge->mode);
2556 }
2557
Zhenyu Wang9b974cc2010-01-05 11:25:06 +08002558 if (bridge->driver->mask_memory == intel_i965_mask_memory) {
David Woodhouseec402ba2009-11-18 10:22:46 +00002559 if (pci_set_dma_mask(intel_private.pcidev, DMA_BIT_MASK(36)))
2560 dev_err(&intel_private.pcidev->dev,
2561 "set gfx device dma mask 36bit failed!\n");
Zhenyu Wang9b974cc2010-01-05 11:25:06 +08002562 else
2563 pci_set_consistent_dma_mask(intel_private.pcidev,
2564 DMA_BIT_MASK(36));
2565 }
David Woodhouseec402ba2009-11-18 10:22:46 +00002566
Linus Torvalds1da177e2005-04-16 15:20:36 -07002567 pci_set_drvdata(pdev, bridge);
2568 return agp_add_bridge(bridge);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002569}
2570
2571static void __devexit agp_intel_remove(struct pci_dev *pdev)
2572{
2573 struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
2574
2575 agp_remove_bridge(bridge);
2576
Wang Zhenyuc4ca8812007-05-30 09:40:46 +08002577 if (intel_private.pcidev)
2578 pci_dev_put(intel_private.pcidev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002579
2580 agp_put_bridge(bridge);
2581}
2582
Alexey Dobriyan85be7d62006-08-12 02:02:02 +04002583#ifdef CONFIG_PM
Linus Torvalds1da177e2005-04-16 15:20:36 -07002584static int agp_intel_resume(struct pci_dev *pdev)
2585{
2586 struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
Keith Packarda8c84df2008-07-31 15:48:07 +10002587 int ret_val;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002588
Linus Torvalds1da177e2005-04-16 15:20:36 -07002589 if (bridge->driver == &intel_generic_driver)
2590 intel_configure();
2591 else if (bridge->driver == &intel_850_driver)
2592 intel_850_configure();
2593 else if (bridge->driver == &intel_845_driver)
2594 intel_845_configure();
2595 else if (bridge->driver == &intel_830mp_driver)
2596 intel_830mp_configure();
2597 else if (bridge->driver == &intel_915_driver)
2598 intel_i915_configure();
2599 else if (bridge->driver == &intel_830_driver)
2600 intel_i830_configure();
2601 else if (bridge->driver == &intel_810_driver)
2602 intel_i810_configure();
Dave Jones08da3f42006-09-10 21:09:26 -04002603 else if (bridge->driver == &intel_i965_driver)
2604 intel_i915_configure();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002605
Keith Packarda8c84df2008-07-31 15:48:07 +10002606 ret_val = agp_rebind_memory();
2607 if (ret_val != 0)
2608 return ret_val;
2609
Linus Torvalds1da177e2005-04-16 15:20:36 -07002610 return 0;
2611}
Alexey Dobriyan85be7d62006-08-12 02:02:02 +04002612#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002613
2614static struct pci_device_id agp_intel_pci_table[] = {
2615#define ID(x) \
2616 { \
2617 .class = (PCI_CLASS_BRIDGE_HOST << 8), \
2618 .class_mask = ~0, \
2619 .vendor = PCI_VENDOR_ID_INTEL, \
2620 .device = x, \
2621 .subvendor = PCI_ANY_ID, \
2622 .subdevice = PCI_ANY_ID, \
2623 }
2624 ID(PCI_DEVICE_ID_INTEL_82443LX_0),
2625 ID(PCI_DEVICE_ID_INTEL_82443BX_0),
2626 ID(PCI_DEVICE_ID_INTEL_82443GX_0),
2627 ID(PCI_DEVICE_ID_INTEL_82810_MC1),
2628 ID(PCI_DEVICE_ID_INTEL_82810_MC3),
2629 ID(PCI_DEVICE_ID_INTEL_82810E_MC),
2630 ID(PCI_DEVICE_ID_INTEL_82815_MC),
2631 ID(PCI_DEVICE_ID_INTEL_82820_HB),
2632 ID(PCI_DEVICE_ID_INTEL_82820_UP_HB),
2633 ID(PCI_DEVICE_ID_INTEL_82830_HB),
2634 ID(PCI_DEVICE_ID_INTEL_82840_HB),
2635 ID(PCI_DEVICE_ID_INTEL_82845_HB),
2636 ID(PCI_DEVICE_ID_INTEL_82845G_HB),
2637 ID(PCI_DEVICE_ID_INTEL_82850_HB),
Stefan Husemann347486b2009-04-13 14:40:10 -07002638 ID(PCI_DEVICE_ID_INTEL_82854_HB),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002639 ID(PCI_DEVICE_ID_INTEL_82855PM_HB),
2640 ID(PCI_DEVICE_ID_INTEL_82855GM_HB),
2641 ID(PCI_DEVICE_ID_INTEL_82860_HB),
2642 ID(PCI_DEVICE_ID_INTEL_82865_HB),
2643 ID(PCI_DEVICE_ID_INTEL_82875_HB),
2644 ID(PCI_DEVICE_ID_INTEL_7505_0),
2645 ID(PCI_DEVICE_ID_INTEL_7205_0),
Carlos Martíne914a362008-01-24 10:34:09 +10002646 ID(PCI_DEVICE_ID_INTEL_E7221_HB),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002647 ID(PCI_DEVICE_ID_INTEL_82915G_HB),
2648 ID(PCI_DEVICE_ID_INTEL_82915GM_HB),
Alan Hourihaned0de98f2005-05-31 19:50:49 +01002649 ID(PCI_DEVICE_ID_INTEL_82945G_HB),
Alan Hourihane3b0e8ea2006-01-19 14:08:40 +00002650 ID(PCI_DEVICE_ID_INTEL_82945GM_HB),
Zhenyu Wangdde47872007-07-26 09:18:09 +08002651 ID(PCI_DEVICE_ID_INTEL_82945GME_HB),
Adam Jackson107f5172009-12-03 17:14:41 -05002652 ID(PCI_DEVICE_ID_INTEL_PINEVIEW_M_HB),
2653 ID(PCI_DEVICE_ID_INTEL_PINEVIEW_HB),
Eric Anholt65c25aa2006-09-06 11:57:18 -04002654 ID(PCI_DEVICE_ID_INTEL_82946GZ_HB),
Zhenyu Wang9119f852008-01-23 15:49:26 +10002655 ID(PCI_DEVICE_ID_INTEL_82G35_HB),
Eric Anholt65c25aa2006-09-06 11:57:18 -04002656 ID(PCI_DEVICE_ID_INTEL_82965Q_HB),
2657 ID(PCI_DEVICE_ID_INTEL_82965G_HB),
Wang Zhenyu4598af32007-04-09 08:51:36 +08002658 ID(PCI_DEVICE_ID_INTEL_82965GM_HB),
Zhenyu Wangdde47872007-07-26 09:18:09 +08002659 ID(PCI_DEVICE_ID_INTEL_82965GME_HB),
Wang Zhenyu874808c62007-06-06 11:16:25 +08002660 ID(PCI_DEVICE_ID_INTEL_G33_HB),
2661 ID(PCI_DEVICE_ID_INTEL_Q35_HB),
2662 ID(PCI_DEVICE_ID_INTEL_Q33_HB),
Zhenyu Wang99d32bd2008-07-30 12:26:50 -07002663 ID(PCI_DEVICE_ID_INTEL_GM45_HB),
Adam Jackson107f5172009-12-03 17:14:41 -05002664 ID(PCI_DEVICE_ID_INTEL_EAGLELAKE_HB),
Zhenyu Wang25ce77a2008-06-19 14:17:58 +10002665 ID(PCI_DEVICE_ID_INTEL_Q45_HB),
2666 ID(PCI_DEVICE_ID_INTEL_G45_HB),
Zhenyu Wanga50ccc62008-11-17 14:39:00 +08002667 ID(PCI_DEVICE_ID_INTEL_G41_HB),
Fabian Henze38d8a952009-09-08 00:59:58 +08002668 ID(PCI_DEVICE_ID_INTEL_B43_HB),
Adam Jackson107f5172009-12-03 17:14:41 -05002669 ID(PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB),
2670 ID(PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB),
2671 ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB),
Dave Airlie3ff99162009-12-08 14:03:47 +10002672 ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB),
Eric Anholt1089e302009-10-22 16:10:52 -07002673 ID(PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB),
Eric Anholt954bce52010-01-07 16:21:46 -08002674 ID(PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002675 { }
2676};
2677
2678MODULE_DEVICE_TABLE(pci, agp_intel_pci_table);
2679
2680static struct pci_driver agp_intel_pci_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002681 .name = "agpgart-intel",
2682 .id_table = agp_intel_pci_table,
2683 .probe = agp_intel_probe,
2684 .remove = __devexit_p(agp_intel_remove),
Alexey Dobriyan85be7d62006-08-12 02:02:02 +04002685#ifdef CONFIG_PM
Linus Torvalds1da177e2005-04-16 15:20:36 -07002686 .resume = agp_intel_resume,
Alexey Dobriyan85be7d62006-08-12 02:02:02 +04002687#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002688};
2689
2690static int __init agp_intel_init(void)
2691{
2692 if (agp_off)
2693 return -EINVAL;
2694 return pci_register_driver(&agp_intel_pci_driver);
2695}
2696
2697static void __exit agp_intel_cleanup(void)
2698{
2699 pci_unregister_driver(&agp_intel_pci_driver);
2700}
2701
2702module_init(agp_intel_init);
2703module_exit(agp_intel_cleanup);
2704
Dave Jonesf4432c52008-10-20 13:31:45 -04002705MODULE_AUTHOR("Dave Jones <davej@redhat.com>");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002706MODULE_LICENSE("GPL and additional rights");