0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023 #include <linux/module.h>
0024 #include <linux/pci.h>
0025 #include <linux/init.h>
0026 #include <linux/agp_backend.h>
0027 #include <linux/gfp.h>
0028 #include <linux/page-flags.h>
0029 #include <linux/mm.h>
0030 #include "agp.h"
0031 #include "intel-agp.h"
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053 #define EFFICEON_ATTPAGE 0xb8
0054 #define EFFICEON_L1_SIZE 64
0055
0056 #define EFFICEON_PATI (0 << 9)
0057 #define EFFICEON_PRESENT (1 << 8)
0058
0059 static struct _efficeon_private {
0060 unsigned long l1_table[EFFICEON_L1_SIZE];
0061 } efficeon_private;
0062
0063 static const struct gatt_mask efficeon_generic_masks[] =
0064 {
0065 {.mask = 0x00000001, .type = 0}
0066 };
0067
0068
0069 static inline unsigned long efficeon_mask_memory(struct page *page)
0070 {
0071 unsigned long addr = page_to_phys(page);
0072 return addr | 0x00000001;
0073 }
0074
0075 static const struct aper_size_info_lvl2 efficeon_generic_sizes[4] =
0076 {
0077 {256, 65536, 0},
0078 {128, 32768, 32},
0079 {64, 16384, 48},
0080 {32, 8192, 56}
0081 };
0082
0083
0084
0085
0086
0087
0088 static int efficeon_fetch_size(void)
0089 {
0090 int i;
0091 u16 temp;
0092 struct aper_size_info_lvl2 *values;
0093
0094 pci_read_config_word(agp_bridge->dev, INTEL_APSIZE, &temp);
0095 values = A_SIZE_LVL2(agp_bridge->driver->aperture_sizes);
0096
0097 for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) {
0098 if (temp == values[i].size_value) {
0099 agp_bridge->previous_size =
0100 agp_bridge->current_size = (void *) (values + i);
0101 agp_bridge->aperture_size_idx = i;
0102 return values[i].size;
0103 }
0104 }
0105
0106 return 0;
0107 }
0108
0109 static void efficeon_tlbflush(struct agp_memory * mem)
0110 {
0111 printk(KERN_DEBUG PFX "efficeon_tlbflush()\n");
0112 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x2200);
0113 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x2280);
0114 }
0115
0116 static void efficeon_cleanup(void)
0117 {
0118 u16 temp;
0119 struct aper_size_info_lvl2 *previous_size;
0120
0121 printk(KERN_DEBUG PFX "efficeon_cleanup()\n");
0122 previous_size = A_SIZE_LVL2(agp_bridge->previous_size);
0123 pci_read_config_word(agp_bridge->dev, INTEL_NBXCFG, &temp);
0124 pci_write_config_word(agp_bridge->dev, INTEL_NBXCFG, temp & ~(1 << 9));
0125 pci_write_config_word(agp_bridge->dev, INTEL_APSIZE,
0126 previous_size->size_value);
0127 }
0128
0129 static int efficeon_configure(void)
0130 {
0131 u16 temp2;
0132 struct aper_size_info_lvl2 *current_size;
0133
0134 printk(KERN_DEBUG PFX "efficeon_configure()\n");
0135
0136 current_size = A_SIZE_LVL2(agp_bridge->current_size);
0137
0138
0139 pci_write_config_word(agp_bridge->dev, INTEL_APSIZE,
0140 current_size->size_value);
0141
0142
0143 agp_bridge->gart_bus_addr = pci_bus_address(agp_bridge->dev,
0144 AGP_APERTURE_BAR);
0145
0146
0147 pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x2280);
0148
0149
0150 pci_read_config_word(agp_bridge->dev, INTEL_NBXCFG, &temp2);
0151 pci_write_config_word(agp_bridge->dev, INTEL_NBXCFG,
0152 (temp2 & ~(1 << 10)) | (1 << 9) | (1 << 11));
0153
0154 pci_write_config_byte(agp_bridge->dev, INTEL_ERRSTS + 1, 7);
0155 return 0;
0156 }
0157
0158 static int efficeon_free_gatt_table(struct agp_bridge_data *bridge)
0159 {
0160 int index, freed = 0;
0161
0162 for (index = 0; index < EFFICEON_L1_SIZE; index++) {
0163 unsigned long page = efficeon_private.l1_table[index];
0164 if (page) {
0165 efficeon_private.l1_table[index] = 0;
0166 free_page(page);
0167 freed++;
0168 }
0169 printk(KERN_DEBUG PFX "efficeon_free_gatt_table(%p, %02x, %08x)\n",
0170 agp_bridge->dev, EFFICEON_ATTPAGE, index);
0171 pci_write_config_dword(agp_bridge->dev,
0172 EFFICEON_ATTPAGE, index);
0173 }
0174 printk(KERN_DEBUG PFX "efficeon_free_gatt_table() freed %d pages\n", freed);
0175 return 0;
0176 }
0177
0178
0179
0180
0181
0182
0183
0184 #define GET_PAGE_DIR_OFF(addr) (addr >> 22)
0185 #define GET_PAGE_DIR_IDX(addr) (GET_PAGE_DIR_OFF(addr) - \
0186 GET_PAGE_DIR_OFF(agp_bridge->gart_bus_addr))
0187 #define GET_GATT_OFF(addr) ((addr & 0x003ff000) >> 12)
0188 #undef GET_GATT
0189 #define GET_GATT(addr) (efficeon_private.gatt_pages[\
0190 GET_PAGE_DIR_IDX(addr)]->remapped)
0191
0192 static int efficeon_create_gatt_table(struct agp_bridge_data *bridge)
0193 {
0194 int index;
0195 const int pati = EFFICEON_PATI;
0196 const int present = EFFICEON_PRESENT;
0197 const int clflush_chunk = ((cpuid_ebx(1) >> 8) & 0xff) << 3;
0198 int num_entries, l1_pages;
0199
0200 num_entries = A_SIZE_LVL2(agp_bridge->current_size)->num_entries;
0201
0202 printk(KERN_DEBUG PFX "efficeon_create_gatt_table(%d)\n", num_entries);
0203
0204
0205 BUG_ON(num_entries & 0x3ff);
0206 l1_pages = num_entries >> 10;
0207
0208 for (index = 0 ; index < l1_pages ; index++) {
0209 int offset;
0210 unsigned long page;
0211 unsigned long value;
0212
0213 page = efficeon_private.l1_table[index];
0214 BUG_ON(page);
0215
0216 page = get_zeroed_page(GFP_KERNEL);
0217 if (!page) {
0218 efficeon_free_gatt_table(agp_bridge);
0219 return -ENOMEM;
0220 }
0221
0222 for (offset = 0; offset < PAGE_SIZE; offset += clflush_chunk)
0223 clflush((char *)page+offset);
0224
0225 efficeon_private.l1_table[index] = page;
0226
0227 value = virt_to_phys((unsigned long *)page) | pati | present | index;
0228
0229 pci_write_config_dword(agp_bridge->dev,
0230 EFFICEON_ATTPAGE, value);
0231 }
0232
0233 return 0;
0234 }
0235
0236 static int efficeon_insert_memory(struct agp_memory * mem, off_t pg_start, int type)
0237 {
0238 int i, count = mem->page_count, num_entries;
0239 unsigned int *page, *last_page;
0240 const int clflush_chunk = ((cpuid_ebx(1) >> 8) & 0xff) << 3;
0241 const unsigned long clflush_mask = ~(clflush_chunk-1);
0242
0243 printk(KERN_DEBUG PFX "efficeon_insert_memory(%lx, %d)\n", pg_start, count);
0244
0245 num_entries = A_SIZE_LVL2(agp_bridge->current_size)->num_entries;
0246 if ((pg_start + mem->page_count) > num_entries)
0247 return -EINVAL;
0248 if (type != 0 || mem->type != 0)
0249 return -EINVAL;
0250
0251 if (!mem->is_flushed) {
0252 global_cache_flush();
0253 mem->is_flushed = true;
0254 }
0255
0256 last_page = NULL;
0257 for (i = 0; i < count; i++) {
0258 int index = pg_start + i;
0259 unsigned long insert = efficeon_mask_memory(mem->pages[i]);
0260
0261 page = (unsigned int *) efficeon_private.l1_table[index >> 10];
0262
0263 if (!page)
0264 continue;
0265
0266 page += (index & 0x3ff);
0267 *page = insert;
0268
0269
0270 if (last_page &&
0271 (((unsigned long)page^(unsigned long)last_page) &
0272 clflush_mask))
0273 clflush(last_page);
0274
0275 last_page = page;
0276 }
0277
0278 if ( last_page )
0279 clflush(last_page);
0280
0281 agp_bridge->driver->tlb_flush(mem);
0282 return 0;
0283 }
0284
0285 static int efficeon_remove_memory(struct agp_memory * mem, off_t pg_start, int type)
0286 {
0287 int i, count = mem->page_count, num_entries;
0288
0289 printk(KERN_DEBUG PFX "efficeon_remove_memory(%lx, %d)\n", pg_start, count);
0290
0291 num_entries = A_SIZE_LVL2(agp_bridge->current_size)->num_entries;
0292
0293 if ((pg_start + mem->page_count) > num_entries)
0294 return -EINVAL;
0295 if (type != 0 || mem->type != 0)
0296 return -EINVAL;
0297
0298 for (i = 0; i < count; i++) {
0299 int index = pg_start + i;
0300 unsigned int *page = (unsigned int *) efficeon_private.l1_table[index >> 10];
0301
0302 if (!page)
0303 continue;
0304 page += (index & 0x3ff);
0305 *page = 0;
0306 }
0307 agp_bridge->driver->tlb_flush(mem);
0308 return 0;
0309 }
0310
0311
0312 static const struct agp_bridge_driver efficeon_driver = {
0313 .owner = THIS_MODULE,
0314 .aperture_sizes = efficeon_generic_sizes,
0315 .size_type = LVL2_APER_SIZE,
0316 .num_aperture_sizes = 4,
0317 .configure = efficeon_configure,
0318 .fetch_size = efficeon_fetch_size,
0319 .cleanup = efficeon_cleanup,
0320 .tlb_flush = efficeon_tlbflush,
0321 .mask_memory = agp_generic_mask_memory,
0322 .masks = efficeon_generic_masks,
0323 .agp_enable = agp_generic_enable,
0324 .cache_flush = global_cache_flush,
0325
0326
0327 .create_gatt_table = efficeon_create_gatt_table,
0328 .free_gatt_table = efficeon_free_gatt_table,
0329 .insert_memory = efficeon_insert_memory,
0330 .remove_memory = efficeon_remove_memory,
0331 .cant_use_aperture = false,
0332
0333
0334 .alloc_by_type = agp_generic_alloc_by_type,
0335 .free_by_type = agp_generic_free_by_type,
0336 .agp_alloc_page = agp_generic_alloc_page,
0337 .agp_alloc_pages = agp_generic_alloc_pages,
0338 .agp_destroy_page = agp_generic_destroy_page,
0339 .agp_destroy_pages = agp_generic_destroy_pages,
0340 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
0341 };
0342
0343 static int agp_efficeon_probe(struct pci_dev *pdev,
0344 const struct pci_device_id *ent)
0345 {
0346 struct agp_bridge_data *bridge;
0347 u8 cap_ptr;
0348 struct resource *r;
0349
0350 cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
0351 if (!cap_ptr)
0352 return -ENODEV;
0353
0354
0355 if (pdev->device != PCI_DEVICE_ID_EFFICEON) {
0356 printk(KERN_ERR PFX "Unsupported Efficeon chipset (device id: %04x)\n",
0357 pdev->device);
0358 return -ENODEV;
0359 }
0360
0361 printk(KERN_INFO PFX "Detected Transmeta Efficeon TM8000 series chipset\n");
0362
0363 bridge = agp_alloc_bridge();
0364 if (!bridge)
0365 return -ENOMEM;
0366
0367 bridge->driver = &efficeon_driver;
0368 bridge->dev = pdev;
0369 bridge->capndx = cap_ptr;
0370
0371
0372
0373
0374
0375
0376 if (pci_enable_device(pdev)) {
0377 printk(KERN_ERR PFX "Unable to Enable PCI device\n");
0378 agp_put_bridge(bridge);
0379 return -ENODEV;
0380 }
0381
0382
0383
0384
0385
0386
0387 r = &pdev->resource[0];
0388 if (!r->start && r->end) {
0389 if (pci_assign_resource(pdev, 0)) {
0390 printk(KERN_ERR PFX "could not assign resource 0\n");
0391 agp_put_bridge(bridge);
0392 return -ENODEV;
0393 }
0394 }
0395
0396
0397 if (cap_ptr) {
0398 pci_read_config_dword(pdev,
0399 bridge->capndx+PCI_AGP_STATUS,
0400 &bridge->mode);
0401 }
0402
0403 pci_set_drvdata(pdev, bridge);
0404 return agp_add_bridge(bridge);
0405 }
0406
0407 static void agp_efficeon_remove(struct pci_dev *pdev)
0408 {
0409 struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
0410
0411 agp_remove_bridge(bridge);
0412 agp_put_bridge(bridge);
0413 }
0414
0415 #ifdef CONFIG_PM
0416 static int agp_efficeon_suspend(struct pci_dev *dev, pm_message_t state)
0417 {
0418 return 0;
0419 }
0420
0421 static int agp_efficeon_resume(struct pci_dev *pdev)
0422 {
0423 printk(KERN_DEBUG PFX "agp_efficeon_resume()\n");
0424 return efficeon_configure();
0425 }
0426 #endif
0427
0428 static const struct pci_device_id agp_efficeon_pci_table[] = {
0429 {
0430 .class = (PCI_CLASS_BRIDGE_HOST << 8),
0431 .class_mask = ~0,
0432 .vendor = PCI_VENDOR_ID_TRANSMETA,
0433 .device = PCI_ANY_ID,
0434 .subvendor = PCI_ANY_ID,
0435 .subdevice = PCI_ANY_ID,
0436 },
0437 { }
0438 };
0439
0440 MODULE_DEVICE_TABLE(pci, agp_efficeon_pci_table);
0441
0442 static struct pci_driver agp_efficeon_pci_driver = {
0443 .name = "agpgart-efficeon",
0444 .id_table = agp_efficeon_pci_table,
0445 .probe = agp_efficeon_probe,
0446 .remove = agp_efficeon_remove,
0447 #ifdef CONFIG_PM
0448 .suspend = agp_efficeon_suspend,
0449 .resume = agp_efficeon_resume,
0450 #endif
0451 };
0452
0453 static int __init agp_efficeon_init(void)
0454 {
0455 static int agp_initialised=0;
0456
0457 if (agp_off)
0458 return -EINVAL;
0459
0460 if (agp_initialised == 1)
0461 return 0;
0462 agp_initialised=1;
0463
0464 return pci_register_driver(&agp_efficeon_pci_driver);
0465 }
0466
0467 static void __exit agp_efficeon_cleanup(void)
0468 {
0469 pci_unregister_driver(&agp_efficeon_pci_driver);
0470 }
0471
0472 module_init(agp_efficeon_init);
0473 module_exit(agp_efficeon_cleanup);
0474
0475 MODULE_AUTHOR("Carlos Puchol <cpglinux@puchol.com>");
0476 MODULE_LICENSE("GPL and additional rights");