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