578 lines · c
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 117#define ATI_RS100_APSIZE 0xac18#define ATI_RS100_IG_AGPMODE 0xb019#define ATI_RS300_APSIZE 0xf820#define ATI_RS300_IG_AGPMODE 0xfc21#define ATI_GART_FEATURE_ID 0x0022#define ATI_GART_BASE 0x0423#define ATI_GART_CACHE_SZBASE 0x0824#define ATI_GART_CACHE_CNTRL 0x0c25#define ATI_GART_CACHE_ENTRY_CNTRL 0x1026 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 else159 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 else218 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 241static int agp_ati_resume(struct device *dev)242{243 return ati_configure();244}245 246/*247 *Since we don't need contiguous memory we just try248 * to get the gatt table once249 */250 251#define GET_PAGE_DIR_OFF(addr) (addr >> 22)252#define GET_PAGE_DIR_IDX(addr) (GET_PAGE_DIR_OFF(addr) - \253 GET_PAGE_DIR_OFF(agp_bridge->gart_bus_addr))254#define GET_GATT_OFF(addr) ((addr & 0x003ff000) >> 12)255#undef GET_GATT256#define GET_GATT(addr) (ati_generic_private.gatt_pages[\257 GET_PAGE_DIR_IDX(addr)]->remapped)258 259static int ati_insert_memory(struct agp_memory * mem,260 off_t pg_start, int type)261{262 int i, j, num_entries;263 unsigned long __iomem *cur_gatt;264 unsigned long addr;265 int mask_type;266 267 num_entries = A_SIZE_LVL2(agp_bridge->current_size)->num_entries;268 269 mask_type = agp_generic_type_to_mask_type(mem->bridge, type);270 if (mask_type != 0 || type != mem->type)271 return -EINVAL;272 273 if (mem->page_count == 0)274 return 0;275 276 if ((pg_start + mem->page_count) > num_entries)277 return -EINVAL;278 279 j = pg_start;280 while (j < (pg_start + mem->page_count)) {281 addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr;282 cur_gatt = GET_GATT(addr);283 if (!PGE_EMPTY(agp_bridge,readl(cur_gatt+GET_GATT_OFF(addr))))284 return -EBUSY;285 j++;286 }287 288 if (!mem->is_flushed) {289 /*CACHE_FLUSH(); */290 global_cache_flush();291 mem->is_flushed = true;292 }293 294 for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {295 addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr;296 cur_gatt = GET_GATT(addr);297 writel(agp_bridge->driver->mask_memory(agp_bridge,298 page_to_phys(mem->pages[i]),299 mem->type),300 cur_gatt+GET_GATT_OFF(addr));301 }302 readl(GET_GATT(agp_bridge->gart_bus_addr)); /* PCI posting */303 agp_bridge->driver->tlb_flush(mem);304 return 0;305}306 307static int ati_remove_memory(struct agp_memory * mem, off_t pg_start,308 int type)309{310 int i;311 unsigned long __iomem *cur_gatt;312 unsigned long addr;313 int mask_type;314 315 mask_type = agp_generic_type_to_mask_type(mem->bridge, type);316 if (mask_type != 0 || type != mem->type)317 return -EINVAL;318 319 if (mem->page_count == 0)320 return 0;321 322 for (i = pg_start; i < (mem->page_count + pg_start); i++) {323 addr = (i * PAGE_SIZE) + agp_bridge->gart_bus_addr;324 cur_gatt = GET_GATT(addr);325 writel(agp_bridge->scratch_page, cur_gatt+GET_GATT_OFF(addr));326 }327 328 readl(GET_GATT(agp_bridge->gart_bus_addr)); /* PCI posting */329 agp_bridge->driver->tlb_flush(mem);330 return 0;331}332 333static int ati_create_gatt_table(struct agp_bridge_data *bridge)334{335 struct aper_size_info_lvl2 *value;336 struct ati_page_map page_dir;337 unsigned long __iomem *cur_gatt;338 unsigned long addr;339 int retval;340 u32 temp;341 int i;342 struct aper_size_info_lvl2 *current_size;343 344 value = A_SIZE_LVL2(agp_bridge->current_size);345 retval = ati_create_page_map(&page_dir);346 if (retval != 0)347 return retval;348 349 retval = ati_create_gatt_pages(value->num_entries / 1024);350 if (retval != 0) {351 ati_free_page_map(&page_dir);352 return retval;353 }354 355 agp_bridge->gatt_table_real = (u32 *)page_dir.real;356 agp_bridge->gatt_table = (u32 __iomem *) page_dir.remapped;357 agp_bridge->gatt_bus_addr = virt_to_phys(page_dir.real);358 359 /* Write out the size register */360 current_size = A_SIZE_LVL2(agp_bridge->current_size);361 362 if (is_r200()) {363 pci_read_config_dword(agp_bridge->dev, ATI_RS100_APSIZE, &temp);364 temp = (((temp & ~(0x0000000e)) | current_size->size_value)365 | 0x00000001);366 pci_write_config_dword(agp_bridge->dev, ATI_RS100_APSIZE, temp);367 pci_read_config_dword(agp_bridge->dev, ATI_RS100_APSIZE, &temp);368 } else {369 pci_read_config_dword(agp_bridge->dev, ATI_RS300_APSIZE, &temp);370 temp = (((temp & ~(0x0000000e)) | current_size->size_value)371 | 0x00000001);372 pci_write_config_dword(agp_bridge->dev, ATI_RS300_APSIZE, temp);373 pci_read_config_dword(agp_bridge->dev, ATI_RS300_APSIZE, &temp);374 }375 376 /*377 * Get the address for the gart region.378 * This is a bus address even on the alpha, b/c its379 * used to program the agp master not the cpu380 */381 addr = pci_bus_address(agp_bridge->dev, AGP_APERTURE_BAR);382 agp_bridge->gart_bus_addr = addr;383 384 /* Calculate the agp offset */385 for (i = 0; i < value->num_entries / 1024; i++, addr += 0x00400000) {386 writel(virt_to_phys(ati_generic_private.gatt_pages[i]->real) | 1,387 page_dir.remapped+GET_PAGE_DIR_OFF(addr));388 readl(page_dir.remapped+GET_PAGE_DIR_OFF(addr)); /* PCI Posting. */389 }390 391 for (i = 0; i < value->num_entries; i++) {392 addr = (i * PAGE_SIZE) + agp_bridge->gart_bus_addr;393 cur_gatt = GET_GATT(addr);394 writel(agp_bridge->scratch_page, cur_gatt+GET_GATT_OFF(addr));395 }396 397 return 0;398}399 400static int ati_free_gatt_table(struct agp_bridge_data *bridge)401{402 struct ati_page_map page_dir;403 404 page_dir.real = (unsigned long *)agp_bridge->gatt_table_real;405 page_dir.remapped = (unsigned long __iomem *)agp_bridge->gatt_table;406 407 ati_free_gatt_pages();408 ati_free_page_map(&page_dir);409 return 0;410}411 412static const struct agp_bridge_driver ati_generic_bridge = {413 .owner = THIS_MODULE,414 .aperture_sizes = ati_generic_sizes,415 .size_type = LVL2_APER_SIZE,416 .num_aperture_sizes = 7,417 .needs_scratch_page = true,418 .configure = ati_configure,419 .fetch_size = ati_fetch_size,420 .cleanup = ati_cleanup,421 .tlb_flush = ati_tlbflush,422 .mask_memory = agp_generic_mask_memory,423 .masks = ati_generic_masks,424 .agp_enable = agp_generic_enable,425 .cache_flush = global_cache_flush,426 .create_gatt_table = ati_create_gatt_table,427 .free_gatt_table = ati_free_gatt_table,428 .insert_memory = ati_insert_memory,429 .remove_memory = ati_remove_memory,430 .alloc_by_type = agp_generic_alloc_by_type,431 .free_by_type = agp_generic_free_by_type,432 .agp_alloc_page = agp_generic_alloc_page,433 .agp_alloc_pages = agp_generic_alloc_pages,434 .agp_destroy_page = agp_generic_destroy_page,435 .agp_destroy_pages = agp_generic_destroy_pages,436 .agp_type_to_mask_type = agp_generic_type_to_mask_type,437};438 439 440static struct agp_device_ids ati_agp_device_ids[] =441{442 {443 .device_id = PCI_DEVICE_ID_ATI_RS100,444 .chipset_name = "IGP320/M",445 },446 {447 .device_id = PCI_DEVICE_ID_ATI_RS200,448 .chipset_name = "IGP330/340/345/350/M",449 },450 {451 .device_id = PCI_DEVICE_ID_ATI_RS200_B,452 .chipset_name = "IGP345M",453 },454 {455 .device_id = PCI_DEVICE_ID_ATI_RS250,456 .chipset_name = "IGP7000/M",457 },458 {459 .device_id = PCI_DEVICE_ID_ATI_RS300_100,460 .chipset_name = "IGP9100/M",461 },462 {463 .device_id = PCI_DEVICE_ID_ATI_RS300_133,464 .chipset_name = "IGP9100/M",465 },466 {467 .device_id = PCI_DEVICE_ID_ATI_RS300_166,468 .chipset_name = "IGP9100/M",469 },470 {471 .device_id = PCI_DEVICE_ID_ATI_RS300_200,472 .chipset_name = "IGP9100/M",473 },474 {475 .device_id = PCI_DEVICE_ID_ATI_RS350_133,476 .chipset_name = "IGP9000/M",477 },478 {479 .device_id = PCI_DEVICE_ID_ATI_RS350_200,480 .chipset_name = "IGP9100/M",481 },482 { }, /* dummy final entry, always present */483};484 485static int agp_ati_probe(struct pci_dev *pdev, const struct pci_device_id *ent)486{487 struct agp_device_ids *devs = ati_agp_device_ids;488 struct agp_bridge_data *bridge;489 u8 cap_ptr;490 int j;491 492 cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);493 if (!cap_ptr)494 return -ENODEV;495 496 /* probe for known chipsets */497 for (j = 0; devs[j].chipset_name; j++) {498 if (pdev->device == devs[j].device_id)499 goto found;500 }501 502 dev_err(&pdev->dev, "unsupported Ati chipset [%04x/%04x])\n",503 pdev->vendor, pdev->device);504 return -ENODEV;505 506found:507 bridge = agp_alloc_bridge();508 if (!bridge)509 return -ENOMEM;510 511 bridge->dev = pdev;512 bridge->capndx = cap_ptr;513 514 bridge->driver = &ati_generic_bridge;515 516 dev_info(&pdev->dev, "Ati %s chipset\n", devs[j].chipset_name);517 518 /* Fill in the mode register */519 pci_read_config_dword(pdev,520 bridge->capndx+PCI_AGP_STATUS,521 &bridge->mode);522 523 pci_set_drvdata(pdev, bridge);524 return agp_add_bridge(bridge);525}526 527static void agp_ati_remove(struct pci_dev *pdev)528{529 struct agp_bridge_data *bridge = pci_get_drvdata(pdev);530 531 agp_remove_bridge(bridge);532 agp_put_bridge(bridge);533}534 535static const struct pci_device_id agp_ati_pci_table[] = {536 {537 .class = (PCI_CLASS_BRIDGE_HOST << 8),538 .class_mask = ~0,539 .vendor = PCI_VENDOR_ID_ATI,540 .device = PCI_ANY_ID,541 .subvendor = PCI_ANY_ID,542 .subdevice = PCI_ANY_ID,543 },544 { }545};546 547MODULE_DEVICE_TABLE(pci, agp_ati_pci_table);548 549static DEFINE_SIMPLE_DEV_PM_OPS(agp_ati_pm_ops, NULL, agp_ati_resume);550 551static struct pci_driver agp_ati_pci_driver = {552 .name = "agpgart-ati",553 .id_table = agp_ati_pci_table,554 .probe = agp_ati_probe,555 .remove = agp_ati_remove,556 .driver.pm = &agp_ati_pm_ops,557};558 559static int __init agp_ati_init(void)560{561 if (agp_off)562 return -EINVAL;563 return pci_register_driver(&agp_ati_pci_driver);564}565 566static void __exit agp_ati_cleanup(void)567{568 pci_unregister_driver(&agp_ati_pci_driver);569}570 571module_init(agp_ati_init);572module_exit(agp_ati_cleanup);573 574MODULE_AUTHOR("Dave Jones");575MODULE_DESCRIPTION("ATi AGPGART routines");576MODULE_LICENSE("GPL and additional rights");577 578