ati-agp.c revision 7079060f3e86ea4c1d4e9c1e356592ef9dcaaa1f
1/* 2 * ATi 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/string.h> 10#include <linux/slab.h> 11#include <linux/agp_backend.h> 12#include <asm/agp.h> 13#include "agp.h" 14 15#define ATI_GART_MMBASE_ADDR 0x14 16#define ATI_RS100_APSIZE 0xac 17#define ATI_RS100_IG_AGPMODE 0xb0 18#define ATI_RS300_APSIZE 0xf8 19#define ATI_RS300_IG_AGPMODE 0xfc 20#define ATI_GART_FEATURE_ID 0x00 21#define ATI_GART_BASE 0x04 22#define ATI_GART_CACHE_SZBASE 0x08 23#define ATI_GART_CACHE_CNTRL 0x0c 24#define ATI_GART_CACHE_ENTRY_CNTRL 0x10 25 26 27static struct aper_size_info_lvl2 ati_generic_sizes[7] = 28{ 29 {2048, 524288, 0x0000000c}, 30 {1024, 262144, 0x0000000a}, 31 {512, 131072, 0x00000008}, 32 {256, 65536, 0x00000006}, 33 {128, 32768, 0x00000004}, 34 {64, 16384, 0x00000002}, 35 {32, 8192, 0x00000000} 36}; 37 38static struct gatt_mask ati_generic_masks[] = 39{ 40 { .mask = 1, .type = 0} 41}; 42 43 44 45typedef struct _ati_page_map { 46 unsigned long *real; 47 unsigned long __iomem *remapped; 48} ati_page_map; 49 50static struct _ati_generic_private { 51 volatile u8 __iomem *registers; 52 ati_page_map **gatt_pages; 53 int num_tables; 54} ati_generic_private; 55 56static int ati_create_page_map(ati_page_map *page_map) 57{ 58 int i, err = 0; 59 60 page_map->real = (unsigned long *) __get_free_page(GFP_KERNEL); 61 if (page_map->real == NULL) 62 return -ENOMEM; 63 64 SetPageReserved(virt_to_page(page_map->real)); 65 err = map_page_into_agp(virt_to_page(page_map->real)); 66 page_map->remapped = ioremap_nocache(virt_to_gart(page_map->real), 67 PAGE_SIZE); 68 if (page_map->remapped == NULL || err) { 69 ClearPageReserved(virt_to_page(page_map->real)); 70 free_page((unsigned long) page_map->real); 71 page_map->real = NULL; 72 return -ENOMEM; 73 } 74 /*CACHE_FLUSH();*/ 75 global_cache_flush(); 76 77 for(i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++) { 78 writel(agp_bridge->scratch_page, page_map->remapped+i); 79 readl(page_map->remapped+i); /* PCI Posting. */ 80 } 81 82 return 0; 83} 84 85 86static void ati_free_page_map(ati_page_map *page_map) 87{ 88 unmap_page_from_agp(virt_to_page(page_map->real)); 89 iounmap(page_map->remapped); 90 ClearPageReserved(virt_to_page(page_map->real)); 91 free_page((unsigned long) page_map->real); 92} 93 94 95static void ati_free_gatt_pages(void) 96{ 97 int i; 98 ati_page_map **tables; 99 ati_page_map *entry; 100 101 tables = ati_generic_private.gatt_pages; 102 for(i = 0; i < ati_generic_private.num_tables; i++) { 103 entry = tables[i]; 104 if (entry != NULL) { 105 if (entry->real != NULL) 106 ati_free_page_map(entry); 107 kfree(entry); 108 } 109 } 110 kfree(tables); 111} 112 113 114static int ati_create_gatt_pages(int nr_tables) 115{ 116 ati_page_map **tables; 117 ati_page_map *entry; 118 int retval = 0; 119 int i; 120 121 tables = kzalloc((nr_tables + 1) * sizeof(ati_page_map *),GFP_KERNEL); 122 if (tables == NULL) 123 return -ENOMEM; 124 125 for (i = 0; i < nr_tables; i++) { 126 entry = kzalloc(sizeof(ati_page_map), GFP_KERNEL); 127 if (entry == NULL) { 128 while (i>0) { 129 kfree (tables[i-1]); 130 i--; 131 } 132 kfree (tables); 133 tables = NULL; 134 retval = -ENOMEM; 135 break; 136 } 137 tables[i] = entry; 138 retval = ati_create_page_map(entry); 139 if (retval != 0) break; 140 } 141 ati_generic_private.num_tables = nr_tables; 142 ati_generic_private.gatt_pages = tables; 143 144 if (retval != 0) ati_free_gatt_pages(); 145 146 return retval; 147} 148 149static int is_r200(void) 150{ 151 if ((agp_bridge->dev->device == PCI_DEVICE_ID_ATI_RS100) || 152 (agp_bridge->dev->device == PCI_DEVICE_ID_ATI_RS200) || 153 (agp_bridge->dev->device == PCI_DEVICE_ID_ATI_RS200_B) || 154 (agp_bridge->dev->device == PCI_DEVICE_ID_ATI_RS250)) 155 return 1; 156 return 0; 157} 158 159static int ati_fetch_size(void) 160{ 161 int i; 162 u32 temp; 163 struct aper_size_info_lvl2 *values; 164 165 if (is_r200()) 166 pci_read_config_dword(agp_bridge->dev, ATI_RS100_APSIZE, &temp); 167 else 168 pci_read_config_dword(agp_bridge->dev, ATI_RS300_APSIZE, &temp); 169 170 temp = (temp & 0x0000000e); 171 values = A_SIZE_LVL2(agp_bridge->driver->aperture_sizes); 172 for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) { 173 if (temp == values[i].size_value) { 174 agp_bridge->previous_size = 175 agp_bridge->current_size = (void *) (values + i); 176 177 agp_bridge->aperture_size_idx = i; 178 return values[i].size; 179 } 180 } 181 182 return 0; 183} 184 185static void ati_tlbflush(struct agp_memory * mem) 186{ 187 writel(1, ati_generic_private.registers+ATI_GART_CACHE_CNTRL); 188 readl(ati_generic_private.registers+ATI_GART_CACHE_CNTRL); /* PCI Posting. */ 189} 190 191static void ati_cleanup(void) 192{ 193 struct aper_size_info_lvl2 *previous_size; 194 u32 temp; 195 196 previous_size = A_SIZE_LVL2(agp_bridge->previous_size); 197 198 /* Write back the previous size and disable gart translation */ 199 if (is_r200()) { 200 pci_read_config_dword(agp_bridge->dev, ATI_RS100_APSIZE, &temp); 201 temp = ((temp & ~(0x0000000f)) | previous_size->size_value); 202 pci_write_config_dword(agp_bridge->dev, ATI_RS100_APSIZE, temp); 203 } else { 204 pci_read_config_dword(agp_bridge->dev, ATI_RS300_APSIZE, &temp); 205 temp = ((temp & ~(0x0000000f)) | previous_size->size_value); 206 pci_write_config_dword(agp_bridge->dev, ATI_RS300_APSIZE, temp); 207 } 208 iounmap((volatile u8 __iomem *)ati_generic_private.registers); 209} 210 211 212static int ati_configure(void) 213{ 214 u32 temp; 215 216 /* Get the memory mapped registers */ 217 pci_read_config_dword(agp_bridge->dev, ATI_GART_MMBASE_ADDR, &temp); 218 temp = (temp & 0xfffff000); 219 ati_generic_private.registers = (volatile u8 __iomem *) ioremap(temp, 4096); 220 221 if (is_r200()) 222 pci_write_config_dword(agp_bridge->dev, ATI_RS100_IG_AGPMODE, 0x20000); 223 else 224 pci_write_config_dword(agp_bridge->dev, ATI_RS300_IG_AGPMODE, 0x20000); 225 226 /* address to map too */ 227 /* 228 pci_read_config_dword(agp_bridge.dev, AGP_APBASE, &temp); 229 agp_bridge.gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); 230 printk(KERN_INFO PFX "IGP320 gart_bus_addr: %x\n", agp_bridge.gart_bus_addr); 231 */ 232 writel(0x60000, ati_generic_private.registers+ATI_GART_FEATURE_ID); 233 readl(ati_generic_private.registers+ATI_GART_FEATURE_ID); /* PCI Posting.*/ 234 235 /* SIGNALED_SYSTEM_ERROR @ NB_STATUS */ 236 pci_read_config_dword(agp_bridge->dev, 4, &temp); 237 pci_write_config_dword(agp_bridge->dev, 4, temp | (1<<14)); 238 239 /* Write out the address of the gatt table */ 240 writel(agp_bridge->gatt_bus_addr, ati_generic_private.registers+ATI_GART_BASE); 241 readl(ati_generic_private.registers+ATI_GART_BASE); /* PCI Posting. */ 242 243 return 0; 244} 245 246 247/* 248 *Since we don't need contigious memory we just try 249 * to get the gatt table once 250 */ 251 252#define GET_PAGE_DIR_OFF(addr) (addr >> 22) 253#define GET_PAGE_DIR_IDX(addr) (GET_PAGE_DIR_OFF(addr) - \ 254 GET_PAGE_DIR_OFF(agp_bridge->gart_bus_addr)) 255#define GET_GATT_OFF(addr) ((addr & 0x003ff000) >> 12) 256#undef GET_GATT 257#define GET_GATT(addr) (ati_generic_private.gatt_pages[\ 258 GET_PAGE_DIR_IDX(addr)]->remapped) 259 260static int ati_insert_memory(struct agp_memory * mem, 261 off_t pg_start, int type) 262{ 263 int i, j, num_entries; 264 unsigned long __iomem *cur_gatt; 265 unsigned long addr; 266 267 num_entries = A_SIZE_LVL2(agp_bridge->current_size)->num_entries; 268 269 if (type != 0 || mem->type != 0) 270 return -EINVAL; 271 272 if ((pg_start + mem->page_count) > num_entries) 273 return -EINVAL; 274 275 j = pg_start; 276 while (j < (pg_start + mem->page_count)) { 277 addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr; 278 cur_gatt = GET_GATT(addr); 279 if (!PGE_EMPTY(agp_bridge,readl(cur_gatt+GET_GATT_OFF(addr)))) 280 return -EBUSY; 281 j++; 282 } 283 284 if (mem->is_flushed == FALSE) { 285 /*CACHE_FLUSH(); */ 286 global_cache_flush(); 287 mem->is_flushed = TRUE; 288 } 289 290 for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { 291 addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr; 292 cur_gatt = GET_GATT(addr); 293 writel(agp_bridge->driver->mask_memory(agp_bridge, 294 mem->memory[i], mem->type), cur_gatt+GET_GATT_OFF(addr)); 295 readl(cur_gatt+GET_GATT_OFF(addr)); /* PCI Posting. */ 296 } 297 agp_bridge->driver->tlb_flush(mem); 298 return 0; 299} 300 301static int ati_remove_memory(struct agp_memory * mem, off_t pg_start, 302 int type) 303{ 304 int i; 305 unsigned long __iomem *cur_gatt; 306 unsigned long addr; 307 308 if (type != 0 || mem->type != 0) { 309 return -EINVAL; 310 } 311 for (i = pg_start; i < (mem->page_count + pg_start); i++) { 312 addr = (i * PAGE_SIZE) + agp_bridge->gart_bus_addr; 313 cur_gatt = GET_GATT(addr); 314 writel(agp_bridge->scratch_page, cur_gatt+GET_GATT_OFF(addr)); 315 readl(cur_gatt+GET_GATT_OFF(addr)); /* PCI Posting. */ 316 } 317 318 agp_bridge->driver->tlb_flush(mem); 319 return 0; 320} 321 322static int ati_create_gatt_table(struct agp_bridge_data *bridge) 323{ 324 struct aper_size_info_lvl2 *value; 325 ati_page_map page_dir; 326 unsigned long addr; 327 int retval; 328 u32 temp; 329 int i; 330 struct aper_size_info_lvl2 *current_size; 331 332 value = A_SIZE_LVL2(agp_bridge->current_size); 333 retval = ati_create_page_map(&page_dir); 334 if (retval != 0) 335 return retval; 336 337 retval = ati_create_gatt_pages(value->num_entries / 1024); 338 if (retval != 0) { 339 ati_free_page_map(&page_dir); 340 return retval; 341 } 342 343 agp_bridge->gatt_table_real = (u32 *)page_dir.real; 344 agp_bridge->gatt_table = (u32 __iomem *) page_dir.remapped; 345 agp_bridge->gatt_bus_addr = virt_to_gart(page_dir.real); 346 347 /* Write out the size register */ 348 current_size = A_SIZE_LVL2(agp_bridge->current_size); 349 350 if (is_r200()) { 351 pci_read_config_dword(agp_bridge->dev, ATI_RS100_APSIZE, &temp); 352 temp = (((temp & ~(0x0000000e)) | current_size->size_value) 353 | 0x00000001); 354 pci_write_config_dword(agp_bridge->dev, ATI_RS100_APSIZE, temp); 355 pci_read_config_dword(agp_bridge->dev, ATI_RS100_APSIZE, &temp); 356 } else { 357 pci_read_config_dword(agp_bridge->dev, ATI_RS300_APSIZE, &temp); 358 temp = (((temp & ~(0x0000000e)) | current_size->size_value) 359 | 0x00000001); 360 pci_write_config_dword(agp_bridge->dev, ATI_RS300_APSIZE, temp); 361 pci_read_config_dword(agp_bridge->dev, ATI_RS300_APSIZE, &temp); 362 } 363 364 /* 365 * Get the address for the gart region. 366 * This is a bus address even on the alpha, b/c its 367 * used to program the agp master not the cpu 368 */ 369 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp); 370 addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); 371 agp_bridge->gart_bus_addr = addr; 372 373 /* Calculate the agp offset */ 374 for(i = 0; i < value->num_entries / 1024; i++, addr += 0x00400000) { 375 writel(virt_to_gart(ati_generic_private.gatt_pages[i]->real) | 1, 376 page_dir.remapped+GET_PAGE_DIR_OFF(addr)); 377 readl(page_dir.remapped+GET_PAGE_DIR_OFF(addr)); /* PCI Posting. */ 378 } 379 380 return 0; 381} 382 383static int ati_free_gatt_table(struct agp_bridge_data *bridge) 384{ 385 ati_page_map page_dir; 386 387 page_dir.real = (unsigned long *)agp_bridge->gatt_table_real; 388 page_dir.remapped = (unsigned long __iomem *)agp_bridge->gatt_table; 389 390 ati_free_gatt_pages(); 391 ati_free_page_map(&page_dir); 392 return 0; 393} 394 395static struct agp_bridge_driver ati_generic_bridge = { 396 .owner = THIS_MODULE, 397 .aperture_sizes = ati_generic_sizes, 398 .size_type = LVL2_APER_SIZE, 399 .num_aperture_sizes = 7, 400 .configure = ati_configure, 401 .fetch_size = ati_fetch_size, 402 .cleanup = ati_cleanup, 403 .tlb_flush = ati_tlbflush, 404 .mask_memory = agp_generic_mask_memory, 405 .masks = ati_generic_masks, 406 .agp_enable = agp_generic_enable, 407 .cache_flush = global_cache_flush, 408 .create_gatt_table = ati_create_gatt_table, 409 .free_gatt_table = ati_free_gatt_table, 410 .insert_memory = ati_insert_memory, 411 .remove_memory = ati_remove_memory, 412 .alloc_by_type = agp_generic_alloc_by_type, 413 .free_by_type = agp_generic_free_by_type, 414 .agp_alloc_page = agp_generic_alloc_page, 415 .agp_destroy_page = agp_generic_destroy_page, 416}; 417 418 419static struct agp_device_ids ati_agp_device_ids[] __devinitdata = 420{ 421 { 422 .device_id = PCI_DEVICE_ID_ATI_RS100, 423 .chipset_name = "IGP320/M", 424 }, 425 { 426 .device_id = PCI_DEVICE_ID_ATI_RS200, 427 .chipset_name = "IGP330/340/345/350/M", 428 }, 429 { 430 .device_id = PCI_DEVICE_ID_ATI_RS200_B, 431 .chipset_name = "IGP345M", 432 }, 433 { 434 .device_id = PCI_DEVICE_ID_ATI_RS250, 435 .chipset_name = "IGP7000/M", 436 }, 437 { 438 .device_id = PCI_DEVICE_ID_ATI_RS300_100, 439 .chipset_name = "IGP9100/M", 440 }, 441 { 442 .device_id = PCI_DEVICE_ID_ATI_RS300_133, 443 .chipset_name = "IGP9100/M", 444 }, 445 { 446 .device_id = PCI_DEVICE_ID_ATI_RS300_166, 447 .chipset_name = "IGP9100/M", 448 }, 449 { 450 .device_id = PCI_DEVICE_ID_ATI_RS300_200, 451 .chipset_name = "IGP9100/M", 452 }, 453 { }, /* dummy final entry, always present */ 454}; 455 456static int __devinit agp_ati_probe(struct pci_dev *pdev, 457 const struct pci_device_id *ent) 458{ 459 struct agp_device_ids *devs = ati_agp_device_ids; 460 struct agp_bridge_data *bridge; 461 u8 cap_ptr; 462 int j; 463 464 cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP); 465 if (!cap_ptr) 466 return -ENODEV; 467 468 /* probe for known chipsets */ 469 for (j = 0; devs[j].chipset_name; j++) { 470 if (pdev->device == devs[j].device_id) 471 goto found; 472 } 473 474 printk(KERN_ERR PFX 475 "Unsupported Ati chipset (device id: %04x)\n", pdev->device); 476 return -ENODEV; 477 478found: 479 bridge = agp_alloc_bridge(); 480 if (!bridge) 481 return -ENOMEM; 482 483 bridge->dev = pdev; 484 bridge->capndx = cap_ptr; 485 486 bridge->driver = &ati_generic_bridge; 487 488 489 printk(KERN_INFO PFX "Detected Ati %s chipset\n", 490 devs[j].chipset_name); 491 492 /* Fill in the mode register */ 493 pci_read_config_dword(pdev, 494 bridge->capndx+PCI_AGP_STATUS, 495 &bridge->mode); 496 497 pci_set_drvdata(pdev, bridge); 498 return agp_add_bridge(bridge); 499} 500 501static void __devexit agp_ati_remove(struct pci_dev *pdev) 502{ 503 struct agp_bridge_data *bridge = pci_get_drvdata(pdev); 504 505 agp_remove_bridge(bridge); 506 agp_put_bridge(bridge); 507} 508 509static struct pci_device_id agp_ati_pci_table[] = { 510 { 511 .class = (PCI_CLASS_BRIDGE_HOST << 8), 512 .class_mask = ~0, 513 .vendor = PCI_VENDOR_ID_ATI, 514 .device = PCI_ANY_ID, 515 .subvendor = PCI_ANY_ID, 516 .subdevice = PCI_ANY_ID, 517 }, 518 { } 519}; 520 521MODULE_DEVICE_TABLE(pci, agp_ati_pci_table); 522 523static struct pci_driver agp_ati_pci_driver = { 524 .owner = THIS_MODULE, 525 .name = "agpgart-ati", 526 .id_table = agp_ati_pci_table, 527 .probe = agp_ati_probe, 528 .remove = agp_ati_remove, 529}; 530 531static int __init agp_ati_init(void) 532{ 533 if (agp_off) 534 return -EINVAL; 535 return pci_register_driver(&agp_ati_pci_driver); 536} 537 538static void __exit agp_ati_cleanup(void) 539{ 540 pci_unregister_driver(&agp_ati_pci_driver); 541} 542 543module_init(agp_ati_init); 544module_exit(agp_ati_cleanup); 545 546MODULE_AUTHOR("Dave Jones <davej@codemonkey.org.uk>"); 547MODULE_LICENSE("GPL and additional rights"); 548 549