Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * ATi AGPGART routines.
0003  */
0004 
0005 #include <linux/types.h>
0006 #include <linux/module.h>
0007 #include <linux/pci.h>
0008 #include <linux/init.h>
0009 #include <linux/string.h>
0010 #include <linux/slab.h>
0011 #include <linux/agp_backend.h>
0012 #include <asm/agp.h>
0013 #include <asm/set_memory.h>
0014 #include "agp.h"
0015 
0016 #define ATI_GART_MMBASE_BAR 1
0017 #define ATI_RS100_APSIZE    0xac
0018 #define ATI_RS100_IG_AGPMODE    0xb0
0019 #define ATI_RS300_APSIZE    0xf8
0020 #define ATI_RS300_IG_AGPMODE    0xfc
0021 #define ATI_GART_FEATURE_ID     0x00
0022 #define ATI_GART_BASE           0x04
0023 #define ATI_GART_CACHE_SZBASE       0x08
0024 #define ATI_GART_CACHE_CNTRL        0x0c
0025 #define ATI_GART_CACHE_ENTRY_CNTRL  0x10
0026 
0027 
0028 static const struct aper_size_info_lvl2 ati_generic_sizes[7] =
0029 {
0030     {2048, 524288, 0x0000000c},
0031     {1024, 262144, 0x0000000a},
0032     {512, 131072, 0x00000008},
0033     {256, 65536, 0x00000006},
0034     {128, 32768, 0x00000004},
0035     {64, 16384, 0x00000002},
0036     {32, 8192, 0x00000000}
0037 };
0038 
0039 static struct gatt_mask ati_generic_masks[] =
0040 {
0041     { .mask = 1, .type = 0}
0042 };
0043 
0044 
0045 struct ati_page_map {
0046     unsigned long *real;
0047     unsigned long __iomem *remapped;
0048 };
0049 
0050 static struct _ati_generic_private {
0051     volatile u8 __iomem *registers;
0052     struct ati_page_map **gatt_pages;
0053     int num_tables;
0054 } ati_generic_private;
0055 
0056 static int ati_create_page_map(struct ati_page_map *page_map)
0057 {
0058     int i, err;
0059 
0060     page_map->real = (unsigned long *) __get_free_page(GFP_KERNEL);
0061     if (page_map->real == NULL)
0062         return -ENOMEM;
0063 
0064     set_memory_uc((unsigned long)page_map->real, 1);
0065     err = map_page_into_agp(virt_to_page(page_map->real));
0066     if (err) {
0067         free_page((unsigned long)page_map->real);
0068         return err;
0069     }
0070     page_map->remapped = page_map->real;
0071 
0072     for (i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++) {
0073         writel(agp_bridge->scratch_page, page_map->remapped+i);
0074         readl(page_map->remapped+i);    /* PCI Posting. */
0075     }
0076 
0077     return 0;
0078 }
0079 
0080 
0081 static void ati_free_page_map(struct ati_page_map *page_map)
0082 {
0083     unmap_page_from_agp(virt_to_page(page_map->real));
0084     set_memory_wb((unsigned long)page_map->real, 1);
0085     free_page((unsigned long) page_map->real);
0086 }
0087 
0088 
0089 static void ati_free_gatt_pages(void)
0090 {
0091     int i;
0092     struct ati_page_map **tables;
0093     struct ati_page_map *entry;
0094 
0095     tables = ati_generic_private.gatt_pages;
0096     for (i = 0; i < ati_generic_private.num_tables; i++) {
0097         entry = tables[i];
0098         if (entry != NULL) {
0099             if (entry->real != NULL)
0100                 ati_free_page_map(entry);
0101             kfree(entry);
0102         }
0103     }
0104     kfree(tables);
0105 }
0106 
0107 
0108 static int ati_create_gatt_pages(int nr_tables)
0109 {
0110     struct ati_page_map **tables;
0111     struct ati_page_map *entry;
0112     int retval = 0;
0113     int i;
0114 
0115     tables = kcalloc(nr_tables + 1, sizeof(struct ati_page_map *),
0116              GFP_KERNEL);
0117     if (tables == NULL)
0118         return -ENOMEM;
0119 
0120     for (i = 0; i < nr_tables; i++) {
0121         entry = kzalloc(sizeof(struct ati_page_map), GFP_KERNEL);
0122         tables[i] = entry;
0123         if (entry == NULL) {
0124             retval = -ENOMEM;
0125             break;
0126         }
0127         retval = ati_create_page_map(entry);
0128         if (retval != 0)
0129             break;
0130     }
0131     ati_generic_private.num_tables = i;
0132     ati_generic_private.gatt_pages = tables;
0133 
0134     if (retval != 0)
0135         ati_free_gatt_pages();
0136 
0137     return retval;
0138 }
0139 
0140 static int is_r200(void)
0141 {
0142     if ((agp_bridge->dev->device == PCI_DEVICE_ID_ATI_RS100) ||
0143         (agp_bridge->dev->device == PCI_DEVICE_ID_ATI_RS200) ||
0144         (agp_bridge->dev->device == PCI_DEVICE_ID_ATI_RS200_B) ||
0145         (agp_bridge->dev->device == PCI_DEVICE_ID_ATI_RS250))
0146         return 1;
0147     return 0;
0148 }
0149 
0150 static int ati_fetch_size(void)
0151 {
0152     int i;
0153     u32 temp;
0154     struct aper_size_info_lvl2 *values;
0155 
0156     if (is_r200())
0157         pci_read_config_dword(agp_bridge->dev, ATI_RS100_APSIZE, &temp);
0158     else
0159         pci_read_config_dword(agp_bridge->dev, ATI_RS300_APSIZE, &temp);
0160 
0161     temp = (temp & 0x0000000e);
0162     values = A_SIZE_LVL2(agp_bridge->driver->aperture_sizes);
0163     for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) {
0164         if (temp == values[i].size_value) {
0165             agp_bridge->previous_size =
0166                 agp_bridge->current_size = (void *) (values + i);
0167 
0168             agp_bridge->aperture_size_idx = i;
0169             return values[i].size;
0170         }
0171     }
0172 
0173     return 0;
0174 }
0175 
0176 static void ati_tlbflush(struct agp_memory * mem)
0177 {
0178     writel(1, ati_generic_private.registers+ATI_GART_CACHE_CNTRL);
0179     readl(ati_generic_private.registers+ATI_GART_CACHE_CNTRL);  /* PCI Posting. */
0180 }
0181 
0182 static void ati_cleanup(void)
0183 {
0184     struct aper_size_info_lvl2 *previous_size;
0185     u32 temp;
0186 
0187     previous_size = A_SIZE_LVL2(agp_bridge->previous_size);
0188 
0189     /* Write back the previous size and disable gart translation */
0190     if (is_r200()) {
0191         pci_read_config_dword(agp_bridge->dev, ATI_RS100_APSIZE, &temp);
0192         temp = ((temp & ~(0x0000000f)) | previous_size->size_value);
0193         pci_write_config_dword(agp_bridge->dev, ATI_RS100_APSIZE, temp);
0194     } else {
0195         pci_read_config_dword(agp_bridge->dev, ATI_RS300_APSIZE, &temp);
0196         temp = ((temp & ~(0x0000000f)) | previous_size->size_value);
0197         pci_write_config_dword(agp_bridge->dev, ATI_RS300_APSIZE, temp);
0198     }
0199     iounmap((volatile u8 __iomem *)ati_generic_private.registers);
0200 }
0201 
0202 
0203 static int ati_configure(void)
0204 {
0205     phys_addr_t reg;
0206     u32 temp;
0207 
0208     /* Get the memory mapped registers */
0209     reg = pci_resource_start(agp_bridge->dev, ATI_GART_MMBASE_BAR);
0210     ati_generic_private.registers = (volatile u8 __iomem *) ioremap(reg, 4096);
0211 
0212     if (!ati_generic_private.registers)
0213         return -ENOMEM;
0214 
0215     if (is_r200())
0216         pci_write_config_dword(agp_bridge->dev, ATI_RS100_IG_AGPMODE, 0x20000);
0217     else
0218         pci_write_config_dword(agp_bridge->dev, ATI_RS300_IG_AGPMODE, 0x20000);
0219 
0220     /* address to map to */
0221     /*
0222     agp_bridge.gart_bus_addr = pci_bus_address(agp_bridge.dev,
0223                            AGP_APERTURE_BAR);
0224     printk(KERN_INFO PFX "IGP320 gart_bus_addr: %x\n", agp_bridge.gart_bus_addr);
0225     */
0226     writel(0x60000, ati_generic_private.registers+ATI_GART_FEATURE_ID);
0227     readl(ati_generic_private.registers+ATI_GART_FEATURE_ID);   /* PCI Posting.*/
0228 
0229     /* SIGNALED_SYSTEM_ERROR @ NB_STATUS */
0230     pci_read_config_dword(agp_bridge->dev, PCI_COMMAND, &temp);
0231     pci_write_config_dword(agp_bridge->dev, PCI_COMMAND, temp | (1<<14));
0232 
0233     /* Write out the address of the gatt table */
0234     writel(agp_bridge->gatt_bus_addr, ati_generic_private.registers+ATI_GART_BASE);
0235     readl(ati_generic_private.registers+ATI_GART_BASE); /* PCI Posting. */
0236 
0237     return 0;
0238 }
0239 
0240 
0241 #ifdef CONFIG_PM
0242 static int agp_ati_suspend(struct pci_dev *dev, pm_message_t state)
0243 {
0244     pci_save_state(dev);
0245     pci_set_power_state(dev, PCI_D3hot);
0246 
0247     return 0;
0248 }
0249 
0250 static int agp_ati_resume(struct pci_dev *dev)
0251 {
0252     pci_set_power_state(dev, PCI_D0);
0253     pci_restore_state(dev);
0254 
0255     return ati_configure();
0256 }
0257 #endif
0258 
0259 /*
0260  *Since we don't need contiguous memory we just try
0261  * to get the gatt table once
0262  */
0263 
0264 #define GET_PAGE_DIR_OFF(addr) (addr >> 22)
0265 #define GET_PAGE_DIR_IDX(addr) (GET_PAGE_DIR_OFF(addr) - \
0266     GET_PAGE_DIR_OFF(agp_bridge->gart_bus_addr))
0267 #define GET_GATT_OFF(addr) ((addr & 0x003ff000) >> 12)
0268 #undef  GET_GATT
0269 #define GET_GATT(addr) (ati_generic_private.gatt_pages[\
0270     GET_PAGE_DIR_IDX(addr)]->remapped)
0271 
0272 static int ati_insert_memory(struct agp_memory * mem,
0273                  off_t pg_start, int type)
0274 {
0275     int i, j, num_entries;
0276     unsigned long __iomem *cur_gatt;
0277     unsigned long addr;
0278     int mask_type;
0279 
0280     num_entries = A_SIZE_LVL2(agp_bridge->current_size)->num_entries;
0281 
0282     mask_type = agp_generic_type_to_mask_type(mem->bridge, type);
0283     if (mask_type != 0 || type != mem->type)
0284         return -EINVAL;
0285 
0286     if (mem->page_count == 0)
0287         return 0;
0288 
0289     if ((pg_start + mem->page_count) > num_entries)
0290         return -EINVAL;
0291 
0292     j = pg_start;
0293     while (j < (pg_start + mem->page_count)) {
0294         addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr;
0295         cur_gatt = GET_GATT(addr);
0296         if (!PGE_EMPTY(agp_bridge,readl(cur_gatt+GET_GATT_OFF(addr))))
0297             return -EBUSY;
0298         j++;
0299     }
0300 
0301     if (!mem->is_flushed) {
0302         /*CACHE_FLUSH(); */
0303         global_cache_flush();
0304         mem->is_flushed = true;
0305     }
0306 
0307     for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
0308         addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr;
0309         cur_gatt = GET_GATT(addr);
0310         writel(agp_bridge->driver->mask_memory(agp_bridge,
0311                                page_to_phys(mem->pages[i]),
0312                                mem->type),
0313                cur_gatt+GET_GATT_OFF(addr));
0314     }
0315     readl(GET_GATT(agp_bridge->gart_bus_addr)); /* PCI posting */
0316     agp_bridge->driver->tlb_flush(mem);
0317     return 0;
0318 }
0319 
0320 static int ati_remove_memory(struct agp_memory * mem, off_t pg_start,
0321                  int type)
0322 {
0323     int i;
0324     unsigned long __iomem *cur_gatt;
0325     unsigned long addr;
0326     int mask_type;
0327 
0328     mask_type = agp_generic_type_to_mask_type(mem->bridge, type);
0329     if (mask_type != 0 || type != mem->type)
0330         return -EINVAL;
0331 
0332     if (mem->page_count == 0)
0333         return 0;
0334 
0335     for (i = pg_start; i < (mem->page_count + pg_start); i++) {
0336         addr = (i * PAGE_SIZE) + agp_bridge->gart_bus_addr;
0337         cur_gatt = GET_GATT(addr);
0338         writel(agp_bridge->scratch_page, cur_gatt+GET_GATT_OFF(addr));
0339     }
0340 
0341     readl(GET_GATT(agp_bridge->gart_bus_addr)); /* PCI posting */
0342     agp_bridge->driver->tlb_flush(mem);
0343     return 0;
0344 }
0345 
0346 static int ati_create_gatt_table(struct agp_bridge_data *bridge)
0347 {
0348     struct aper_size_info_lvl2 *value;
0349     struct ati_page_map page_dir;
0350     unsigned long __iomem *cur_gatt;
0351     unsigned long addr;
0352     int retval;
0353     u32 temp;
0354     int i;
0355     struct aper_size_info_lvl2 *current_size;
0356 
0357     value = A_SIZE_LVL2(agp_bridge->current_size);
0358     retval = ati_create_page_map(&page_dir);
0359     if (retval != 0)
0360         return retval;
0361 
0362     retval = ati_create_gatt_pages(value->num_entries / 1024);
0363     if (retval != 0) {
0364         ati_free_page_map(&page_dir);
0365         return retval;
0366     }
0367 
0368     agp_bridge->gatt_table_real = (u32 *)page_dir.real;
0369     agp_bridge->gatt_table = (u32 __iomem *) page_dir.remapped;
0370     agp_bridge->gatt_bus_addr = virt_to_phys(page_dir.real);
0371 
0372     /* Write out the size register */
0373     current_size = A_SIZE_LVL2(agp_bridge->current_size);
0374 
0375     if (is_r200()) {
0376         pci_read_config_dword(agp_bridge->dev, ATI_RS100_APSIZE, &temp);
0377         temp = (((temp & ~(0x0000000e)) | current_size->size_value)
0378             | 0x00000001);
0379         pci_write_config_dword(agp_bridge->dev, ATI_RS100_APSIZE, temp);
0380         pci_read_config_dword(agp_bridge->dev, ATI_RS100_APSIZE, &temp);
0381     } else {
0382         pci_read_config_dword(agp_bridge->dev, ATI_RS300_APSIZE, &temp);
0383         temp = (((temp & ~(0x0000000e)) | current_size->size_value)
0384             | 0x00000001);
0385         pci_write_config_dword(agp_bridge->dev, ATI_RS300_APSIZE, temp);
0386         pci_read_config_dword(agp_bridge->dev, ATI_RS300_APSIZE, &temp);
0387     }
0388 
0389     /*
0390      * Get the address for the gart region.
0391      * This is a bus address even on the alpha, b/c its
0392      * used to program the agp master not the cpu
0393      */
0394     addr = pci_bus_address(agp_bridge->dev, AGP_APERTURE_BAR);
0395     agp_bridge->gart_bus_addr = addr;
0396 
0397     /* Calculate the agp offset */
0398     for (i = 0; i < value->num_entries / 1024; i++, addr += 0x00400000) {
0399         writel(virt_to_phys(ati_generic_private.gatt_pages[i]->real) | 1,
0400             page_dir.remapped+GET_PAGE_DIR_OFF(addr));
0401         readl(page_dir.remapped+GET_PAGE_DIR_OFF(addr));    /* PCI Posting. */
0402     }
0403 
0404     for (i = 0; i < value->num_entries; i++) {
0405         addr = (i * PAGE_SIZE) + agp_bridge->gart_bus_addr;
0406         cur_gatt = GET_GATT(addr);
0407         writel(agp_bridge->scratch_page, cur_gatt+GET_GATT_OFF(addr));
0408     }
0409 
0410     return 0;
0411 }
0412 
0413 static int ati_free_gatt_table(struct agp_bridge_data *bridge)
0414 {
0415     struct ati_page_map page_dir;
0416 
0417     page_dir.real = (unsigned long *)agp_bridge->gatt_table_real;
0418     page_dir.remapped = (unsigned long __iomem *)agp_bridge->gatt_table;
0419 
0420     ati_free_gatt_pages();
0421     ati_free_page_map(&page_dir);
0422     return 0;
0423 }
0424 
0425 static const struct agp_bridge_driver ati_generic_bridge = {
0426     .owner          = THIS_MODULE,
0427     .aperture_sizes     = ati_generic_sizes,
0428     .size_type      = LVL2_APER_SIZE,
0429     .num_aperture_sizes = 7,
0430     .needs_scratch_page = true,
0431     .configure      = ati_configure,
0432     .fetch_size     = ati_fetch_size,
0433     .cleanup        = ati_cleanup,
0434     .tlb_flush      = ati_tlbflush,
0435     .mask_memory        = agp_generic_mask_memory,
0436     .masks          = ati_generic_masks,
0437     .agp_enable     = agp_generic_enable,
0438     .cache_flush        = global_cache_flush,
0439     .create_gatt_table  = ati_create_gatt_table,
0440     .free_gatt_table    = ati_free_gatt_table,
0441     .insert_memory      = ati_insert_memory,
0442     .remove_memory      = ati_remove_memory,
0443     .alloc_by_type      = agp_generic_alloc_by_type,
0444     .free_by_type       = agp_generic_free_by_type,
0445     .agp_alloc_page     = agp_generic_alloc_page,
0446     .agp_alloc_pages    = agp_generic_alloc_pages,
0447     .agp_destroy_page   = agp_generic_destroy_page,
0448     .agp_destroy_pages  = agp_generic_destroy_pages,
0449     .agp_type_to_mask_type  = agp_generic_type_to_mask_type,
0450 };
0451 
0452 
0453 static struct agp_device_ids ati_agp_device_ids[] =
0454 {
0455     {
0456         .device_id  = PCI_DEVICE_ID_ATI_RS100,
0457         .chipset_name   = "IGP320/M",
0458     },
0459     {
0460         .device_id  = PCI_DEVICE_ID_ATI_RS200,
0461         .chipset_name   = "IGP330/340/345/350/M",
0462     },
0463     {
0464         .device_id  = PCI_DEVICE_ID_ATI_RS200_B,
0465         .chipset_name   = "IGP345M",
0466     },
0467     {
0468         .device_id  = PCI_DEVICE_ID_ATI_RS250,
0469         .chipset_name   = "IGP7000/M",
0470     },
0471     {
0472         .device_id  = PCI_DEVICE_ID_ATI_RS300_100,
0473         .chipset_name   = "IGP9100/M",
0474     },
0475     {
0476         .device_id  = PCI_DEVICE_ID_ATI_RS300_133,
0477         .chipset_name   = "IGP9100/M",
0478     },
0479     {
0480         .device_id  = PCI_DEVICE_ID_ATI_RS300_166,
0481         .chipset_name   = "IGP9100/M",
0482     },
0483     {
0484         .device_id  = PCI_DEVICE_ID_ATI_RS300_200,
0485         .chipset_name   = "IGP9100/M",
0486     },
0487     {
0488         .device_id  = PCI_DEVICE_ID_ATI_RS350_133,
0489         .chipset_name   = "IGP9000/M",
0490     },
0491     {
0492         .device_id  = PCI_DEVICE_ID_ATI_RS350_200,
0493         .chipset_name   = "IGP9100/M",
0494     },
0495     { }, /* dummy final entry, always present */
0496 };
0497 
0498 static int agp_ati_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
0499 {
0500     struct agp_device_ids *devs = ati_agp_device_ids;
0501     struct agp_bridge_data *bridge;
0502     u8 cap_ptr;
0503     int j;
0504 
0505     cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
0506     if (!cap_ptr)
0507         return -ENODEV;
0508 
0509     /* probe for known chipsets */
0510     for (j = 0; devs[j].chipset_name; j++) {
0511         if (pdev->device == devs[j].device_id)
0512             goto found;
0513     }
0514 
0515     dev_err(&pdev->dev, "unsupported Ati chipset [%04x/%04x])\n",
0516         pdev->vendor, pdev->device);
0517     return -ENODEV;
0518 
0519 found:
0520     bridge = agp_alloc_bridge();
0521     if (!bridge)
0522         return -ENOMEM;
0523 
0524     bridge->dev = pdev;
0525     bridge->capndx = cap_ptr;
0526 
0527     bridge->driver = &ati_generic_bridge;
0528 
0529     dev_info(&pdev->dev, "Ati %s chipset\n", devs[j].chipset_name);
0530 
0531     /* Fill in the mode register */
0532     pci_read_config_dword(pdev,
0533             bridge->capndx+PCI_AGP_STATUS,
0534             &bridge->mode);
0535 
0536     pci_set_drvdata(pdev, bridge);
0537     return agp_add_bridge(bridge);
0538 }
0539 
0540 static void agp_ati_remove(struct pci_dev *pdev)
0541 {
0542     struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
0543 
0544     agp_remove_bridge(bridge);
0545     agp_put_bridge(bridge);
0546 }
0547 
0548 static const struct pci_device_id agp_ati_pci_table[] = {
0549     {
0550     .class      = (PCI_CLASS_BRIDGE_HOST << 8),
0551     .class_mask = ~0,
0552     .vendor     = PCI_VENDOR_ID_ATI,
0553     .device     = PCI_ANY_ID,
0554     .subvendor  = PCI_ANY_ID,
0555     .subdevice  = PCI_ANY_ID,
0556     },
0557     { }
0558 };
0559 
0560 MODULE_DEVICE_TABLE(pci, agp_ati_pci_table);
0561 
0562 static struct pci_driver agp_ati_pci_driver = {
0563     .name       = "agpgart-ati",
0564     .id_table   = agp_ati_pci_table,
0565     .probe      = agp_ati_probe,
0566     .remove     = agp_ati_remove,
0567 #ifdef CONFIG_PM
0568     .suspend    = agp_ati_suspend,
0569     .resume     = agp_ati_resume,
0570 #endif
0571 };
0572 
0573 static int __init agp_ati_init(void)
0574 {
0575     if (agp_off)
0576         return -EINVAL;
0577     return pci_register_driver(&agp_ati_pci_driver);
0578 }
0579 
0580 static void __exit agp_ati_cleanup(void)
0581 {
0582     pci_unregister_driver(&agp_ati_pci_driver);
0583 }
0584 
0585 module_init(agp_ati_init);
0586 module_exit(agp_ati_cleanup);
0587 
0588 MODULE_AUTHOR("Dave Jones");
0589 MODULE_LICENSE("GPL and additional rights");
0590