Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * ALi 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/agp_backend.h>
0010 #include <asm/page.h>       /* PAGE_SIZE */
0011 #include "agp.h"
0012 
0013 #define ALI_AGPCTRL 0xb8
0014 #define ALI_ATTBASE 0xbc
0015 #define ALI_TLBCTRL 0xc0
0016 #define ALI_TAGCTRL 0xc4
0017 #define ALI_CACHE_FLUSH_CTRL    0xD0
0018 #define ALI_CACHE_FLUSH_ADDR_MASK   0xFFFFF000
0019 #define ALI_CACHE_FLUSH_EN  0x100
0020 
0021 static int ali_fetch_size(void)
0022 {
0023     int i;
0024     u32 temp;
0025     struct aper_size_info_32 *values;
0026 
0027     pci_read_config_dword(agp_bridge->dev, ALI_ATTBASE, &temp);
0028     temp &= ~(0xfffffff0);
0029     values = A_SIZE_32(agp_bridge->driver->aperture_sizes);
0030 
0031     for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) {
0032         if (temp == values[i].size_value) {
0033             agp_bridge->previous_size =
0034                 agp_bridge->current_size = (void *) (values + i);
0035             agp_bridge->aperture_size_idx = i;
0036             return values[i].size;
0037         }
0038     }
0039 
0040     return 0;
0041 }
0042 
0043 static void ali_tlbflush(struct agp_memory *mem)
0044 {
0045     u32 temp;
0046 
0047     pci_read_config_dword(agp_bridge->dev, ALI_TLBCTRL, &temp);
0048     temp &= 0xfffffff0;
0049     temp |= (1<<0 | 1<<1);
0050     pci_write_config_dword(agp_bridge->dev, ALI_TAGCTRL, temp);
0051 }
0052 
0053 static void ali_cleanup(void)
0054 {
0055     struct aper_size_info_32 *previous_size;
0056     u32 temp;
0057 
0058     previous_size = A_SIZE_32(agp_bridge->previous_size);
0059 
0060     pci_read_config_dword(agp_bridge->dev, ALI_TLBCTRL, &temp);
0061 // clear tag
0062     pci_write_config_dword(agp_bridge->dev, ALI_TAGCTRL,
0063             ((temp & 0xffffff00) | 0x00000001|0x00000002));
0064 
0065     pci_read_config_dword(agp_bridge->dev,  ALI_ATTBASE, &temp);
0066     pci_write_config_dword(agp_bridge->dev, ALI_ATTBASE,
0067             ((temp & 0x00000ff0) | previous_size->size_value));
0068 }
0069 
0070 static int ali_configure(void)
0071 {
0072     u32 temp;
0073     struct aper_size_info_32 *current_size;
0074 
0075     current_size = A_SIZE_32(agp_bridge->current_size);
0076 
0077     /* aperture size and gatt addr */
0078     pci_read_config_dword(agp_bridge->dev, ALI_ATTBASE, &temp);
0079     temp = (((temp & 0x00000ff0) | (agp_bridge->gatt_bus_addr & 0xfffff000))
0080             | (current_size->size_value & 0xf));
0081     pci_write_config_dword(agp_bridge->dev, ALI_ATTBASE, temp);
0082 
0083     /* tlb control */
0084     pci_read_config_dword(agp_bridge->dev, ALI_TLBCTRL, &temp);
0085     pci_write_config_dword(agp_bridge->dev, ALI_TLBCTRL, ((temp & 0xffffff00) | 0x00000010));
0086 
0087     /* address to map to */
0088     agp_bridge->gart_bus_addr = pci_bus_address(agp_bridge->dev,
0089                             AGP_APERTURE_BAR);
0090 
0091 #if 0
0092     if (agp_bridge->type == ALI_M1541) {
0093         u32 nlvm_addr = 0;
0094 
0095         switch (current_size->size_value) {
0096             case 0:  break;
0097             case 1:  nlvm_addr = 0x100000;break;
0098             case 2:  nlvm_addr = 0x200000;break;
0099             case 3:  nlvm_addr = 0x400000;break;
0100             case 4:  nlvm_addr = 0x800000;break;
0101             case 6:  nlvm_addr = 0x1000000;break;
0102             case 7:  nlvm_addr = 0x2000000;break;
0103             case 8:  nlvm_addr = 0x4000000;break;
0104             case 9:  nlvm_addr = 0x8000000;break;
0105             case 10: nlvm_addr = 0x10000000;break;
0106             default: break;
0107         }
0108         nlvm_addr--;
0109         nlvm_addr&=0xfff00000;
0110 
0111         nlvm_addr+= agp_bridge->gart_bus_addr;
0112         nlvm_addr|=(agp_bridge->gart_bus_addr>>12);
0113         dev_info(&agp_bridge->dev->dev, "nlvm top &base = %8x\n",
0114              nlvm_addr);
0115     }
0116 #endif
0117 
0118     pci_read_config_dword(agp_bridge->dev, ALI_TLBCTRL, &temp);
0119     temp &= 0xffffff7f;     //enable TLB
0120     pci_write_config_dword(agp_bridge->dev, ALI_TLBCTRL, temp);
0121 
0122     return 0;
0123 }
0124 
0125 
0126 static void m1541_cache_flush(void)
0127 {
0128     int i, page_count;
0129     u32 temp;
0130 
0131     global_cache_flush();
0132 
0133     page_count = 1 << A_SIZE_32(agp_bridge->current_size)->page_order;
0134     for (i = 0; i < PAGE_SIZE * page_count; i += PAGE_SIZE) {
0135         pci_read_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL,
0136                 &temp);
0137         pci_write_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL,
0138                 (((temp & ALI_CACHE_FLUSH_ADDR_MASK) |
0139                   (agp_bridge->gatt_bus_addr + i)) |
0140                  ALI_CACHE_FLUSH_EN));
0141     }
0142 }
0143 
0144 static struct page *m1541_alloc_page(struct agp_bridge_data *bridge)
0145 {
0146     struct page *page = agp_generic_alloc_page(agp_bridge);
0147     u32 temp;
0148 
0149     if (!page)
0150         return NULL;
0151 
0152     pci_read_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, &temp);
0153     pci_write_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL,
0154             (((temp & ALI_CACHE_FLUSH_ADDR_MASK) |
0155               page_to_phys(page)) | ALI_CACHE_FLUSH_EN ));
0156     return page;
0157 }
0158 
0159 static void ali_destroy_page(struct page *page, int flags)
0160 {
0161     if (page) {
0162         if (flags & AGP_PAGE_DESTROY_UNMAP) {
0163             global_cache_flush();   /* is this really needed?  --hch */
0164             agp_generic_destroy_page(page, flags);
0165         } else
0166             agp_generic_destroy_page(page, flags);
0167     }
0168 }
0169 
0170 static void m1541_destroy_page(struct page *page, int flags)
0171 {
0172     u32 temp;
0173 
0174     if (page == NULL)
0175         return;
0176 
0177     if (flags & AGP_PAGE_DESTROY_UNMAP) {
0178         global_cache_flush();
0179 
0180         pci_read_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, &temp);
0181         pci_write_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL,
0182                        (((temp & ALI_CACHE_FLUSH_ADDR_MASK) |
0183                      page_to_phys(page)) | ALI_CACHE_FLUSH_EN));
0184     }
0185     agp_generic_destroy_page(page, flags);
0186 }
0187 
0188 
0189 /* Setup function */
0190 
0191 static const struct aper_size_info_32 ali_generic_sizes[7] =
0192 {
0193     {256, 65536, 6, 10},
0194     {128, 32768, 5, 9},
0195     {64, 16384, 4, 8},
0196     {32, 8192, 3, 7},
0197     {16, 4096, 2, 6},
0198     {8, 2048, 1, 4},
0199     {4, 1024, 0, 3}
0200 };
0201 
0202 static const struct agp_bridge_driver ali_generic_bridge = {
0203     .owner          = THIS_MODULE,
0204     .aperture_sizes     = ali_generic_sizes,
0205     .size_type      = U32_APER_SIZE,
0206     .num_aperture_sizes = 7,
0207     .needs_scratch_page = true,
0208     .configure      = ali_configure,
0209     .fetch_size     = ali_fetch_size,
0210     .cleanup        = ali_cleanup,
0211     .tlb_flush      = ali_tlbflush,
0212     .mask_memory        = agp_generic_mask_memory,
0213     .masks          = NULL,
0214     .agp_enable     = agp_generic_enable,
0215     .cache_flush        = global_cache_flush,
0216     .create_gatt_table  = agp_generic_create_gatt_table,
0217     .free_gatt_table    = agp_generic_free_gatt_table,
0218     .insert_memory      = agp_generic_insert_memory,
0219     .remove_memory      = agp_generic_remove_memory,
0220     .alloc_by_type      = agp_generic_alloc_by_type,
0221     .free_by_type       = agp_generic_free_by_type,
0222     .agp_alloc_page     = agp_generic_alloc_page,
0223     .agp_destroy_page   = ali_destroy_page,
0224     .agp_type_to_mask_type  = agp_generic_type_to_mask_type,
0225 };
0226 
0227 static const struct agp_bridge_driver ali_m1541_bridge = {
0228     .owner          = THIS_MODULE,
0229     .aperture_sizes     = ali_generic_sizes,
0230     .size_type      = U32_APER_SIZE,
0231     .num_aperture_sizes = 7,
0232     .configure      = ali_configure,
0233     .fetch_size     = ali_fetch_size,
0234     .cleanup        = ali_cleanup,
0235     .tlb_flush      = ali_tlbflush,
0236     .mask_memory        = agp_generic_mask_memory,
0237     .masks          = NULL,
0238     .agp_enable     = agp_generic_enable,
0239     .cache_flush        = m1541_cache_flush,
0240     .create_gatt_table  = agp_generic_create_gatt_table,
0241     .free_gatt_table    = agp_generic_free_gatt_table,
0242     .insert_memory      = agp_generic_insert_memory,
0243     .remove_memory      = agp_generic_remove_memory,
0244     .alloc_by_type      = agp_generic_alloc_by_type,
0245     .free_by_type       = agp_generic_free_by_type,
0246     .agp_alloc_page     = m1541_alloc_page,
0247     .agp_destroy_page   = m1541_destroy_page,
0248     .agp_type_to_mask_type  = agp_generic_type_to_mask_type,
0249 };
0250 
0251 
0252 static struct agp_device_ids ali_agp_device_ids[] =
0253 {
0254     {
0255         .device_id  = PCI_DEVICE_ID_AL_M1541,
0256         .chipset_name   = "M1541",
0257     },
0258     {
0259         .device_id  = PCI_DEVICE_ID_AL_M1621,
0260         .chipset_name   = "M1621",
0261     },
0262     {
0263         .device_id  = PCI_DEVICE_ID_AL_M1631,
0264         .chipset_name   = "M1631",
0265     },
0266     {
0267         .device_id  = PCI_DEVICE_ID_AL_M1632,
0268         .chipset_name   = "M1632",
0269     },
0270     {
0271         .device_id  = PCI_DEVICE_ID_AL_M1641,
0272         .chipset_name   = "M1641",
0273     },
0274     {
0275         .device_id  = PCI_DEVICE_ID_AL_M1644,
0276         .chipset_name   = "M1644",
0277     },
0278     {
0279         .device_id  = PCI_DEVICE_ID_AL_M1647,
0280         .chipset_name   = "M1647",
0281     },
0282     {
0283         .device_id  = PCI_DEVICE_ID_AL_M1651,
0284         .chipset_name   = "M1651",
0285     },
0286     {
0287         .device_id  = PCI_DEVICE_ID_AL_M1671,
0288         .chipset_name   = "M1671",
0289     },
0290     {
0291         .device_id  = PCI_DEVICE_ID_AL_M1681,
0292         .chipset_name   = "M1681",
0293     },
0294     {
0295         .device_id  = PCI_DEVICE_ID_AL_M1683,
0296         .chipset_name   = "M1683",
0297     },
0298 
0299     { }, /* dummy final entry, always present */
0300 };
0301 
0302 static int agp_ali_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
0303 {
0304     struct agp_device_ids *devs = ali_agp_device_ids;
0305     struct agp_bridge_data *bridge;
0306     u8 hidden_1621_id, cap_ptr;
0307     int j;
0308 
0309     cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
0310     if (!cap_ptr)
0311         return -ENODEV;
0312 
0313     /* probe for known chipsets */
0314     for (j = 0; devs[j].chipset_name; j++) {
0315         if (pdev->device == devs[j].device_id)
0316             goto found;
0317     }
0318 
0319     dev_err(&pdev->dev, "unsupported ALi chipset [%04x/%04x])\n",
0320         pdev->vendor, pdev->device);
0321     return -ENODEV;
0322 
0323 
0324 found:
0325     bridge = agp_alloc_bridge();
0326     if (!bridge)
0327         return -ENOMEM;
0328 
0329     bridge->dev = pdev;
0330     bridge->capndx = cap_ptr;
0331 
0332     switch (pdev->device) {
0333     case PCI_DEVICE_ID_AL_M1541:
0334         bridge->driver = &ali_m1541_bridge;
0335         break;
0336     case PCI_DEVICE_ID_AL_M1621:
0337         pci_read_config_byte(pdev, 0xFB, &hidden_1621_id);
0338         switch (hidden_1621_id) {
0339         case 0x31:
0340             devs[j].chipset_name = "M1631";
0341             break;
0342         case 0x32:
0343             devs[j].chipset_name = "M1632";
0344             break;
0345         case 0x41:
0346             devs[j].chipset_name = "M1641";
0347             break;
0348         case 0x43:
0349             devs[j].chipset_name = "M1621";
0350             break;
0351         case 0x47:
0352             devs[j].chipset_name = "M1647";
0353             break;
0354         case 0x51:
0355             devs[j].chipset_name = "M1651";
0356             break;
0357         default:
0358             break;
0359         }
0360         fallthrough;
0361     default:
0362         bridge->driver = &ali_generic_bridge;
0363     }
0364 
0365     dev_info(&pdev->dev, "ALi %s chipset\n", devs[j].chipset_name);
0366 
0367     /* Fill in the mode register */
0368     pci_read_config_dword(pdev,
0369             bridge->capndx+PCI_AGP_STATUS,
0370             &bridge->mode);
0371 
0372     pci_set_drvdata(pdev, bridge);
0373     return agp_add_bridge(bridge);
0374 }
0375 
0376 static void agp_ali_remove(struct pci_dev *pdev)
0377 {
0378     struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
0379 
0380     agp_remove_bridge(bridge);
0381     agp_put_bridge(bridge);
0382 }
0383 
0384 static const struct pci_device_id agp_ali_pci_table[] = {
0385     {
0386     .class      = (PCI_CLASS_BRIDGE_HOST << 8),
0387     .class_mask = ~0,
0388     .vendor     = PCI_VENDOR_ID_AL,
0389     .device     = PCI_ANY_ID,
0390     .subvendor  = PCI_ANY_ID,
0391     .subdevice  = PCI_ANY_ID,
0392     },
0393     { }
0394 };
0395 
0396 MODULE_DEVICE_TABLE(pci, agp_ali_pci_table);
0397 
0398 static struct pci_driver agp_ali_pci_driver = {
0399     .name       = "agpgart-ali",
0400     .id_table   = agp_ali_pci_table,
0401     .probe      = agp_ali_probe,
0402     .remove     = agp_ali_remove,
0403 };
0404 
0405 static int __init agp_ali_init(void)
0406 {
0407     if (agp_off)
0408         return -EINVAL;
0409     return pci_register_driver(&agp_ali_pci_driver);
0410 }
0411 
0412 static void __exit agp_ali_cleanup(void)
0413 {
0414     pci_unregister_driver(&agp_ali_pci_driver);
0415 }
0416 
0417 module_init(agp_ali_init);
0418 module_exit(agp_ali_cleanup);
0419 
0420 MODULE_AUTHOR("Dave Jones");
0421 MODULE_LICENSE("GPL and additional rights");
0422