root/drivers/char/agp/ati-agp.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ati_create_page_map
  2. ati_free_page_map
  3. ati_free_gatt_pages
  4. ati_create_gatt_pages
  5. is_r200
  6. ati_fetch_size
  7. ati_tlbflush
  8. ati_cleanup
  9. ati_configure
  10. agp_ati_suspend
  11. agp_ati_resume
  12. ati_insert_memory
  13. ati_remove_memory
  14. ati_create_gatt_table
  15. ati_free_gatt_table
  16. agp_ati_probe
  17. agp_ati_remove
  18. agp_ati_init
  19. agp_ati_cleanup

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

/* [<][>][^][v][top][bottom][index][help] */