diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/char/agp/ali-agp.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/char/agp/ali-agp.c')
-rw-r--r-- | drivers/char/agp/ali-agp.c | 414 |
1 files changed, 414 insertions, 0 deletions
diff --git a/drivers/char/agp/ali-agp.c b/drivers/char/agp/ali-agp.c new file mode 100644 index 000000000000..c86a22c5499b --- /dev/null +++ b/drivers/char/agp/ali-agp.c | |||
@@ -0,0 +1,414 @@ | |||
1 | /* | ||
2 | * ALi AGPGART routines. | ||
3 | */ | ||
4 | |||
5 | #include <linux/types.h> | ||
6 | #include <linux/module.h> | ||
7 | #include <linux/pci.h> | ||
8 | #include <linux/init.h> | ||
9 | #include <linux/agp_backend.h> | ||
10 | #include "agp.h" | ||
11 | |||
12 | #define ALI_AGPCTRL 0xb8 | ||
13 | #define ALI_ATTBASE 0xbc | ||
14 | #define ALI_TLBCTRL 0xc0 | ||
15 | #define ALI_TAGCTRL 0xc4 | ||
16 | #define ALI_CACHE_FLUSH_CTRL 0xD0 | ||
17 | #define ALI_CACHE_FLUSH_ADDR_MASK 0xFFFFF000 | ||
18 | #define ALI_CACHE_FLUSH_EN 0x100 | ||
19 | |||
20 | static int ali_fetch_size(void) | ||
21 | { | ||
22 | int i; | ||
23 | u32 temp; | ||
24 | struct aper_size_info_32 *values; | ||
25 | |||
26 | pci_read_config_dword(agp_bridge->dev, ALI_ATTBASE, &temp); | ||
27 | temp &= ~(0xfffffff0); | ||
28 | values = A_SIZE_32(agp_bridge->driver->aperture_sizes); | ||
29 | |||
30 | for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) { | ||
31 | if (temp == values[i].size_value) { | ||
32 | agp_bridge->previous_size = | ||
33 | agp_bridge->current_size = (void *) (values + i); | ||
34 | agp_bridge->aperture_size_idx = i; | ||
35 | return values[i].size; | ||
36 | } | ||
37 | } | ||
38 | |||
39 | return 0; | ||
40 | } | ||
41 | |||
42 | static void ali_tlbflush(struct agp_memory *mem) | ||
43 | { | ||
44 | u32 temp; | ||
45 | |||
46 | pci_read_config_dword(agp_bridge->dev, ALI_TLBCTRL, &temp); | ||
47 | temp &= 0xfffffff0; | ||
48 | temp |= (1<<0 | 1<<1); | ||
49 | pci_write_config_dword(agp_bridge->dev, ALI_TAGCTRL, temp); | ||
50 | } | ||
51 | |||
52 | static void ali_cleanup(void) | ||
53 | { | ||
54 | struct aper_size_info_32 *previous_size; | ||
55 | u32 temp; | ||
56 | |||
57 | previous_size = A_SIZE_32(agp_bridge->previous_size); | ||
58 | |||
59 | pci_read_config_dword(agp_bridge->dev, ALI_TLBCTRL, &temp); | ||
60 | // clear tag | ||
61 | pci_write_config_dword(agp_bridge->dev, ALI_TAGCTRL, | ||
62 | ((temp & 0xffffff00) | 0x00000001|0x00000002)); | ||
63 | |||
64 | pci_read_config_dword(agp_bridge->dev, ALI_ATTBASE, &temp); | ||
65 | pci_write_config_dword(agp_bridge->dev, ALI_ATTBASE, | ||
66 | ((temp & 0x00000ff0) | previous_size->size_value)); | ||
67 | } | ||
68 | |||
69 | static int ali_configure(void) | ||
70 | { | ||
71 | u32 temp; | ||
72 | struct aper_size_info_32 *current_size; | ||
73 | |||
74 | current_size = A_SIZE_32(agp_bridge->current_size); | ||
75 | |||
76 | /* aperture size and gatt addr */ | ||
77 | pci_read_config_dword(agp_bridge->dev, ALI_ATTBASE, &temp); | ||
78 | temp = (((temp & 0x00000ff0) | (agp_bridge->gatt_bus_addr & 0xfffff000)) | ||
79 | | (current_size->size_value & 0xf)); | ||
80 | pci_write_config_dword(agp_bridge->dev, ALI_ATTBASE, temp); | ||
81 | |||
82 | /* tlb control */ | ||
83 | pci_read_config_dword(agp_bridge->dev, ALI_TLBCTRL, &temp); | ||
84 | pci_write_config_dword(agp_bridge->dev, ALI_TLBCTRL, ((temp & 0xffffff00) | 0x00000010)); | ||
85 | |||
86 | /* address to map to */ | ||
87 | pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp); | ||
88 | agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); | ||
89 | |||
90 | #if 0 | ||
91 | if (agp_bridge->type == ALI_M1541) { | ||
92 | u32 nlvm_addr = 0; | ||
93 | |||
94 | switch (current_size->size_value) { | ||
95 | case 0: break; | ||
96 | case 1: nlvm_addr = 0x100000;break; | ||
97 | case 2: nlvm_addr = 0x200000;break; | ||
98 | case 3: nlvm_addr = 0x400000;break; | ||
99 | case 4: nlvm_addr = 0x800000;break; | ||
100 | case 6: nlvm_addr = 0x1000000;break; | ||
101 | case 7: nlvm_addr = 0x2000000;break; | ||
102 | case 8: nlvm_addr = 0x4000000;break; | ||
103 | case 9: nlvm_addr = 0x8000000;break; | ||
104 | case 10: nlvm_addr = 0x10000000;break; | ||
105 | default: break; | ||
106 | } | ||
107 | nlvm_addr--; | ||
108 | nlvm_addr&=0xfff00000; | ||
109 | |||
110 | nlvm_addr+= agp_bridge->gart_bus_addr; | ||
111 | nlvm_addr|=(agp_bridge->gart_bus_addr>>12); | ||
112 | printk(KERN_INFO PFX "nlvm top &base = %8x\n",nlvm_addr); | ||
113 | } | ||
114 | #endif | ||
115 | |||
116 | pci_read_config_dword(agp_bridge->dev, ALI_TLBCTRL, &temp); | ||
117 | temp &= 0xffffff7f; //enable TLB | ||
118 | pci_write_config_dword(agp_bridge->dev, ALI_TLBCTRL, temp); | ||
119 | |||
120 | return 0; | ||
121 | } | ||
122 | |||
123 | |||
124 | static void m1541_cache_flush(void) | ||
125 | { | ||
126 | int i, page_count; | ||
127 | u32 temp; | ||
128 | |||
129 | global_cache_flush(); | ||
130 | |||
131 | page_count = 1 << A_SIZE_32(agp_bridge->current_size)->page_order; | ||
132 | for (i = 0; i < PAGE_SIZE * page_count; i += PAGE_SIZE) { | ||
133 | pci_read_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, | ||
134 | &temp); | ||
135 | pci_write_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, | ||
136 | (((temp & ALI_CACHE_FLUSH_ADDR_MASK) | | ||
137 | (agp_bridge->gatt_bus_addr + i)) | | ||
138 | ALI_CACHE_FLUSH_EN)); | ||
139 | } | ||
140 | } | ||
141 | |||
142 | static void *m1541_alloc_page(struct agp_bridge_data *bridge) | ||
143 | { | ||
144 | void *addr = agp_generic_alloc_page(agp_bridge); | ||
145 | u32 temp; | ||
146 | |||
147 | if (!addr) | ||
148 | return NULL; | ||
149 | |||
150 | pci_read_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, &temp); | ||
151 | pci_write_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, | ||
152 | (((temp & ALI_CACHE_FLUSH_ADDR_MASK) | | ||
153 | virt_to_phys(addr)) | ALI_CACHE_FLUSH_EN )); | ||
154 | return addr; | ||
155 | } | ||
156 | |||
157 | static void ali_destroy_page(void * addr) | ||
158 | { | ||
159 | if (addr) { | ||
160 | global_cache_flush(); /* is this really needed? --hch */ | ||
161 | agp_generic_destroy_page(addr); | ||
162 | } | ||
163 | } | ||
164 | |||
165 | static void m1541_destroy_page(void * addr) | ||
166 | { | ||
167 | u32 temp; | ||
168 | |||
169 | if (addr == NULL) | ||
170 | return; | ||
171 | |||
172 | global_cache_flush(); | ||
173 | |||
174 | pci_read_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, &temp); | ||
175 | pci_write_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, | ||
176 | (((temp & ALI_CACHE_FLUSH_ADDR_MASK) | | ||
177 | virt_to_phys(addr)) | ALI_CACHE_FLUSH_EN)); | ||
178 | agp_generic_destroy_page(addr); | ||
179 | } | ||
180 | |||
181 | |||
182 | /* Setup function */ | ||
183 | |||
184 | static struct aper_size_info_32 ali_generic_sizes[7] = | ||
185 | { | ||
186 | {256, 65536, 6, 10}, | ||
187 | {128, 32768, 5, 9}, | ||
188 | {64, 16384, 4, 8}, | ||
189 | {32, 8192, 3, 7}, | ||
190 | {16, 4096, 2, 6}, | ||
191 | {8, 2048, 1, 4}, | ||
192 | {4, 1024, 0, 3} | ||
193 | }; | ||
194 | |||
195 | struct agp_bridge_driver ali_generic_bridge = { | ||
196 | .owner = THIS_MODULE, | ||
197 | .aperture_sizes = ali_generic_sizes, | ||
198 | .size_type = U32_APER_SIZE, | ||
199 | .num_aperture_sizes = 7, | ||
200 | .configure = ali_configure, | ||
201 | .fetch_size = ali_fetch_size, | ||
202 | .cleanup = ali_cleanup, | ||
203 | .tlb_flush = ali_tlbflush, | ||
204 | .mask_memory = agp_generic_mask_memory, | ||
205 | .masks = NULL, | ||
206 | .agp_enable = agp_generic_enable, | ||
207 | .cache_flush = global_cache_flush, | ||
208 | .create_gatt_table = agp_generic_create_gatt_table, | ||
209 | .free_gatt_table = agp_generic_free_gatt_table, | ||
210 | .insert_memory = agp_generic_insert_memory, | ||
211 | .remove_memory = agp_generic_remove_memory, | ||
212 | .alloc_by_type = agp_generic_alloc_by_type, | ||
213 | .free_by_type = agp_generic_free_by_type, | ||
214 | .agp_alloc_page = agp_generic_alloc_page, | ||
215 | .agp_destroy_page = ali_destroy_page, | ||
216 | }; | ||
217 | |||
218 | struct agp_bridge_driver ali_m1541_bridge = { | ||
219 | .owner = THIS_MODULE, | ||
220 | .aperture_sizes = ali_generic_sizes, | ||
221 | .size_type = U32_APER_SIZE, | ||
222 | .num_aperture_sizes = 7, | ||
223 | .configure = ali_configure, | ||
224 | .fetch_size = ali_fetch_size, | ||
225 | .cleanup = ali_cleanup, | ||
226 | .tlb_flush = ali_tlbflush, | ||
227 | .mask_memory = agp_generic_mask_memory, | ||
228 | .masks = NULL, | ||
229 | .agp_enable = agp_generic_enable, | ||
230 | .cache_flush = m1541_cache_flush, | ||
231 | .create_gatt_table = agp_generic_create_gatt_table, | ||
232 | .free_gatt_table = agp_generic_free_gatt_table, | ||
233 | .insert_memory = agp_generic_insert_memory, | ||
234 | .remove_memory = agp_generic_remove_memory, | ||
235 | .alloc_by_type = agp_generic_alloc_by_type, | ||
236 | .free_by_type = agp_generic_free_by_type, | ||
237 | .agp_alloc_page = m1541_alloc_page, | ||
238 | .agp_destroy_page = m1541_destroy_page, | ||
239 | }; | ||
240 | |||
241 | |||
242 | static struct agp_device_ids ali_agp_device_ids[] __devinitdata = | ||
243 | { | ||
244 | { | ||
245 | .device_id = PCI_DEVICE_ID_AL_M1541, | ||
246 | .chipset_name = "M1541", | ||
247 | }, | ||
248 | { | ||
249 | .device_id = PCI_DEVICE_ID_AL_M1621, | ||
250 | .chipset_name = "M1621", | ||
251 | }, | ||
252 | { | ||
253 | .device_id = PCI_DEVICE_ID_AL_M1631, | ||
254 | .chipset_name = "M1631", | ||
255 | }, | ||
256 | { | ||
257 | .device_id = PCI_DEVICE_ID_AL_M1632, | ||
258 | .chipset_name = "M1632", | ||
259 | }, | ||
260 | { | ||
261 | .device_id = PCI_DEVICE_ID_AL_M1641, | ||
262 | .chipset_name = "M1641", | ||
263 | }, | ||
264 | { | ||
265 | .device_id = PCI_DEVICE_ID_AL_M1644, | ||
266 | .chipset_name = "M1644", | ||
267 | }, | ||
268 | { | ||
269 | .device_id = PCI_DEVICE_ID_AL_M1647, | ||
270 | .chipset_name = "M1647", | ||
271 | }, | ||
272 | { | ||
273 | .device_id = PCI_DEVICE_ID_AL_M1651, | ||
274 | .chipset_name = "M1651", | ||
275 | }, | ||
276 | { | ||
277 | .device_id = PCI_DEVICE_ID_AL_M1671, | ||
278 | .chipset_name = "M1671", | ||
279 | }, | ||
280 | { | ||
281 | .device_id = PCI_DEVICE_ID_AL_M1681, | ||
282 | .chipset_name = "M1681", | ||
283 | }, | ||
284 | { | ||
285 | .device_id = PCI_DEVICE_ID_AL_M1683, | ||
286 | .chipset_name = "M1683", | ||
287 | }, | ||
288 | |||
289 | { }, /* dummy final entry, always present */ | ||
290 | }; | ||
291 | |||
292 | static int __devinit agp_ali_probe(struct pci_dev *pdev, | ||
293 | const struct pci_device_id *ent) | ||
294 | { | ||
295 | struct agp_device_ids *devs = ali_agp_device_ids; | ||
296 | struct agp_bridge_data *bridge; | ||
297 | u8 hidden_1621_id, cap_ptr; | ||
298 | int j; | ||
299 | |||
300 | cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP); | ||
301 | if (!cap_ptr) | ||
302 | return -ENODEV; | ||
303 | |||
304 | /* probe for known chipsets */ | ||
305 | for (j = 0; devs[j].chipset_name; j++) { | ||
306 | if (pdev->device == devs[j].device_id) | ||
307 | goto found; | ||
308 | } | ||
309 | |||
310 | printk(KERN_ERR PFX "Unsupported ALi chipset (device id: %04x)\n", | ||
311 | pdev->device); | ||
312 | return -ENODEV; | ||
313 | |||
314 | |||
315 | found: | ||
316 | bridge = agp_alloc_bridge(); | ||
317 | if (!bridge) | ||
318 | return -ENOMEM; | ||
319 | |||
320 | bridge->dev = pdev; | ||
321 | bridge->capndx = cap_ptr; | ||
322 | |||
323 | switch (pdev->device) { | ||
324 | case PCI_DEVICE_ID_AL_M1541: | ||
325 | bridge->driver = &ali_m1541_bridge; | ||
326 | break; | ||
327 | case PCI_DEVICE_ID_AL_M1621: | ||
328 | pci_read_config_byte(pdev, 0xFB, &hidden_1621_id); | ||
329 | switch (hidden_1621_id) { | ||
330 | case 0x31: | ||
331 | devs[j].chipset_name = "M1631"; | ||
332 | break; | ||
333 | case 0x32: | ||
334 | devs[j].chipset_name = "M1632"; | ||
335 | break; | ||
336 | case 0x41: | ||
337 | devs[j].chipset_name = "M1641"; | ||
338 | break; | ||
339 | case 0x43: | ||
340 | devs[j].chipset_name = "M????"; | ||
341 | break; | ||
342 | case 0x47: | ||
343 | devs[j].chipset_name = "M1647"; | ||
344 | break; | ||
345 | case 0x51: | ||
346 | devs[j].chipset_name = "M1651"; | ||
347 | break; | ||
348 | default: | ||
349 | break; | ||
350 | } | ||
351 | /*FALLTHROUGH*/ | ||
352 | default: | ||
353 | bridge->driver = &ali_generic_bridge; | ||
354 | } | ||
355 | |||
356 | printk(KERN_INFO PFX "Detected ALi %s chipset\n", | ||
357 | devs[j].chipset_name); | ||
358 | |||
359 | /* Fill in the mode register */ | ||
360 | pci_read_config_dword(pdev, | ||
361 | bridge->capndx+PCI_AGP_STATUS, | ||
362 | &bridge->mode); | ||
363 | |||
364 | pci_set_drvdata(pdev, bridge); | ||
365 | return agp_add_bridge(bridge); | ||
366 | } | ||
367 | |||
368 | static void __devexit agp_ali_remove(struct pci_dev *pdev) | ||
369 | { | ||
370 | struct agp_bridge_data *bridge = pci_get_drvdata(pdev); | ||
371 | |||
372 | agp_remove_bridge(bridge); | ||
373 | agp_put_bridge(bridge); | ||
374 | } | ||
375 | |||
376 | static struct pci_device_id agp_ali_pci_table[] = { | ||
377 | { | ||
378 | .class = (PCI_CLASS_BRIDGE_HOST << 8), | ||
379 | .class_mask = ~0, | ||
380 | .vendor = PCI_VENDOR_ID_AL, | ||
381 | .device = PCI_ANY_ID, | ||
382 | .subvendor = PCI_ANY_ID, | ||
383 | .subdevice = PCI_ANY_ID, | ||
384 | }, | ||
385 | { } | ||
386 | }; | ||
387 | |||
388 | MODULE_DEVICE_TABLE(pci, agp_ali_pci_table); | ||
389 | |||
390 | static struct pci_driver agp_ali_pci_driver = { | ||
391 | .name = "agpgart-ali", | ||
392 | .id_table = agp_ali_pci_table, | ||
393 | .probe = agp_ali_probe, | ||
394 | .remove = agp_ali_remove, | ||
395 | }; | ||
396 | |||
397 | static int __init agp_ali_init(void) | ||
398 | { | ||
399 | if (agp_off) | ||
400 | return -EINVAL; | ||
401 | return pci_register_driver(&agp_ali_pci_driver); | ||
402 | } | ||
403 | |||
404 | static void __exit agp_ali_cleanup(void) | ||
405 | { | ||
406 | pci_unregister_driver(&agp_ali_pci_driver); | ||
407 | } | ||
408 | |||
409 | module_init(agp_ali_init); | ||
410 | module_exit(agp_ali_cleanup); | ||
411 | |||
412 | MODULE_AUTHOR("Dave Jones <davej@codemonkey.org.uk>"); | ||
413 | MODULE_LICENSE("GPL and additional rights"); | ||
414 | |||