0001
0002
0003
0004
0005 #include <linux/module.h>
0006 #include <linux/pci.h>
0007 #include <linux/slab.h>
0008 #include <linux/init.h>
0009 #include <linux/pagemap.h>
0010 #include <linux/agp_backend.h>
0011 #include <linux/delay.h>
0012 #include <linux/vmalloc.h>
0013 #include <asm/uninorth.h>
0014 #include <asm/prom.h>
0015 #include <asm/pmac_feature.h>
0016 #include "agp.h"
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029 static int uninorth_rev;
0030 static int is_u3;
0031 static u32 scratch_value;
0032
0033 #define DEFAULT_APERTURE_SIZE 256
0034 #define DEFAULT_APERTURE_STRING "256"
0035 static char *aperture = NULL;
0036
0037 static int uninorth_fetch_size(void)
0038 {
0039 int i, size = 0;
0040 struct aper_size_info_32 *values =
0041 A_SIZE_32(agp_bridge->driver->aperture_sizes);
0042
0043 if (aperture) {
0044 char *save = aperture;
0045
0046 size = memparse(aperture, &aperture) >> 20;
0047 aperture = save;
0048
0049 for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++)
0050 if (size == values[i].size)
0051 break;
0052
0053 if (i == agp_bridge->driver->num_aperture_sizes) {
0054 dev_err(&agp_bridge->dev->dev, "invalid aperture size, "
0055 "using default\n");
0056 size = 0;
0057 aperture = NULL;
0058 }
0059 }
0060
0061 if (!size) {
0062 for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++)
0063 if (values[i].size == DEFAULT_APERTURE_SIZE)
0064 break;
0065 }
0066
0067 agp_bridge->previous_size =
0068 agp_bridge->current_size = (void *)(values + i);
0069 agp_bridge->aperture_size_idx = i;
0070 return values[i].size;
0071 }
0072
0073 static void uninorth_tlbflush(struct agp_memory *mem)
0074 {
0075 u32 ctrl = UNI_N_CFG_GART_ENABLE;
0076
0077 if (is_u3)
0078 ctrl |= U3_N_CFG_GART_PERFRD;
0079 pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL,
0080 ctrl | UNI_N_CFG_GART_INVAL);
0081 pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL, ctrl);
0082
0083 if (!mem && uninorth_rev <= 0x30) {
0084 pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL,
0085 ctrl | UNI_N_CFG_GART_2xRESET);
0086 pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL,
0087 ctrl);
0088 }
0089 }
0090
0091 static void uninorth_cleanup(void)
0092 {
0093 u32 tmp;
0094
0095 pci_read_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL, &tmp);
0096 if (!(tmp & UNI_N_CFG_GART_ENABLE))
0097 return;
0098 tmp |= UNI_N_CFG_GART_INVAL;
0099 pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL, tmp);
0100 pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL, 0);
0101
0102 if (uninorth_rev <= 0x30) {
0103 pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL,
0104 UNI_N_CFG_GART_2xRESET);
0105 pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL,
0106 0);
0107 }
0108 }
0109
0110 static int uninorth_configure(void)
0111 {
0112 struct aper_size_info_32 *current_size;
0113
0114 current_size = A_SIZE_32(agp_bridge->current_size);
0115
0116 dev_info(&agp_bridge->dev->dev, "configuring for size idx: %d\n",
0117 current_size->size_value);
0118
0119
0120 pci_write_config_dword(agp_bridge->dev,
0121 UNI_N_CFG_GART_BASE,
0122 (agp_bridge->gatt_bus_addr & 0xfffff000)
0123 | current_size->size_value);
0124
0125
0126
0127
0128
0129 agp_bridge->gart_bus_addr = 0;
0130 #ifdef CONFIG_PPC64
0131
0132
0133 pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_AGP_BASE,
0134 (agp_bridge->gatt_bus_addr >> 32) & 0xf);
0135 #else
0136 pci_write_config_dword(agp_bridge->dev,
0137 UNI_N_CFG_AGP_BASE, agp_bridge->gart_bus_addr);
0138 #endif
0139
0140 if (is_u3) {
0141 pci_write_config_dword(agp_bridge->dev,
0142 UNI_N_CFG_GART_DUMMY_PAGE,
0143 page_to_phys(agp_bridge->scratch_page_page) >> 12);
0144 }
0145
0146 return 0;
0147 }
0148
0149 static int uninorth_insert_memory(struct agp_memory *mem, off_t pg_start, int type)
0150 {
0151 int i, num_entries;
0152 void *temp;
0153 u32 *gp;
0154 int mask_type;
0155
0156 if (type != mem->type)
0157 return -EINVAL;
0158
0159 mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type);
0160 if (mask_type != 0) {
0161
0162 return -EINVAL;
0163 }
0164
0165 if (mem->page_count == 0)
0166 return 0;
0167
0168 temp = agp_bridge->current_size;
0169 num_entries = A_SIZE_32(temp)->num_entries;
0170
0171 if ((pg_start + mem->page_count) > num_entries)
0172 return -EINVAL;
0173
0174 gp = (u32 *) &agp_bridge->gatt_table[pg_start];
0175 for (i = 0; i < mem->page_count; ++i) {
0176 if (gp[i] != scratch_value) {
0177 dev_info(&agp_bridge->dev->dev,
0178 "uninorth_insert_memory: entry 0x%x occupied (%x)\n",
0179 i, gp[i]);
0180 return -EBUSY;
0181 }
0182 }
0183
0184 for (i = 0; i < mem->page_count; i++) {
0185 if (is_u3)
0186 gp[i] = (page_to_phys(mem->pages[i]) >> PAGE_SHIFT) | 0x80000000UL;
0187 else
0188 gp[i] = cpu_to_le32((page_to_phys(mem->pages[i]) & 0xFFFFF000UL) |
0189 0x1UL);
0190 flush_dcache_range((unsigned long)__va(page_to_phys(mem->pages[i])),
0191 (unsigned long)__va(page_to_phys(mem->pages[i]))+0x1000);
0192 }
0193 mb();
0194 uninorth_tlbflush(mem);
0195
0196 return 0;
0197 }
0198
0199 static int uninorth_remove_memory(struct agp_memory *mem, off_t pg_start, int type)
0200 {
0201 size_t i;
0202 u32 *gp;
0203 int mask_type;
0204
0205 if (type != mem->type)
0206 return -EINVAL;
0207
0208 mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type);
0209 if (mask_type != 0) {
0210
0211 return -EINVAL;
0212 }
0213
0214 if (mem->page_count == 0)
0215 return 0;
0216
0217 gp = (u32 *) &agp_bridge->gatt_table[pg_start];
0218 for (i = 0; i < mem->page_count; ++i) {
0219 gp[i] = scratch_value;
0220 }
0221 mb();
0222 uninorth_tlbflush(mem);
0223
0224 return 0;
0225 }
0226
0227 static void uninorth_agp_enable(struct agp_bridge_data *bridge, u32 mode)
0228 {
0229 u32 command, scratch, status;
0230 int timeout;
0231
0232 pci_read_config_dword(bridge->dev,
0233 bridge->capndx + PCI_AGP_STATUS,
0234 &status);
0235
0236 command = agp_collect_device_status(bridge, mode, status);
0237 command |= PCI_AGP_COMMAND_AGP;
0238
0239 if (uninorth_rev == 0x21) {
0240
0241
0242
0243
0244 command &= ~AGPSTAT2_4X;
0245 }
0246
0247 if ((uninorth_rev >= 0x30) && (uninorth_rev <= 0x33)) {
0248
0249
0250
0251
0252 if ((command >> AGPSTAT_RQ_DEPTH_SHIFT) > 7)
0253 command = (command & ~AGPSTAT_RQ_DEPTH)
0254 | (7 << AGPSTAT_RQ_DEPTH_SHIFT);
0255 }
0256
0257 uninorth_tlbflush(NULL);
0258
0259 timeout = 0;
0260 do {
0261 pci_write_config_dword(bridge->dev,
0262 bridge->capndx + PCI_AGP_COMMAND,
0263 command);
0264 pci_read_config_dword(bridge->dev,
0265 bridge->capndx + PCI_AGP_COMMAND,
0266 &scratch);
0267 } while ((scratch & PCI_AGP_COMMAND_AGP) == 0 && ++timeout < 1000);
0268 if ((scratch & PCI_AGP_COMMAND_AGP) == 0)
0269 dev_err(&bridge->dev->dev, "can't write UniNorth AGP "
0270 "command register\n");
0271
0272 if (uninorth_rev >= 0x30) {
0273
0274 agp_device_command(command, (status & AGPSTAT_MODE_3_0) != 0);
0275 } else {
0276
0277 agp_device_command(command, false);
0278 }
0279
0280 uninorth_tlbflush(NULL);
0281 }
0282
0283 #ifdef CONFIG_PM
0284
0285
0286
0287
0288
0289 static int agp_uninorth_suspend(struct pci_dev *pdev)
0290 {
0291 struct agp_bridge_data *bridge;
0292 u32 cmd;
0293 u8 agp;
0294 struct pci_dev *device = NULL;
0295
0296 bridge = agp_find_bridge(pdev);
0297 if (bridge == NULL)
0298 return -ENODEV;
0299
0300
0301 if (bridge->dev_private_data)
0302 return 0;
0303
0304
0305 for_each_pci_dev(device) {
0306
0307 if (device == pdev)
0308 continue;
0309
0310
0311
0312
0313
0314
0315 if (device->bus != pdev->bus)
0316 continue;
0317 agp = pci_find_capability(device, PCI_CAP_ID_AGP);
0318 if (!agp)
0319 continue;
0320 pci_read_config_dword(device, agp + PCI_AGP_COMMAND, &cmd);
0321 if (!(cmd & PCI_AGP_COMMAND_AGP))
0322 continue;
0323 dev_info(&pdev->dev, "disabling AGP on device %s\n",
0324 pci_name(device));
0325 cmd &= ~PCI_AGP_COMMAND_AGP;
0326 pci_write_config_dword(device, agp + PCI_AGP_COMMAND, cmd);
0327 }
0328
0329
0330 agp = pci_find_capability(pdev, PCI_CAP_ID_AGP);
0331 pci_read_config_dword(pdev, agp + PCI_AGP_COMMAND, &cmd);
0332 bridge->dev_private_data = (void *)(long)cmd;
0333 if (cmd & PCI_AGP_COMMAND_AGP) {
0334 dev_info(&pdev->dev, "disabling AGP on bridge\n");
0335 cmd &= ~PCI_AGP_COMMAND_AGP;
0336 pci_write_config_dword(pdev, agp + PCI_AGP_COMMAND, cmd);
0337 }
0338
0339 uninorth_cleanup();
0340
0341 return 0;
0342 }
0343
0344 static int agp_uninorth_resume(struct pci_dev *pdev)
0345 {
0346 struct agp_bridge_data *bridge;
0347 u32 command;
0348
0349 bridge = agp_find_bridge(pdev);
0350 if (bridge == NULL)
0351 return -ENODEV;
0352
0353 command = (long)bridge->dev_private_data;
0354 bridge->dev_private_data = NULL;
0355 if (!(command & PCI_AGP_COMMAND_AGP))
0356 return 0;
0357
0358 uninorth_agp_enable(bridge, command);
0359
0360 return 0;
0361 }
0362 #endif
0363
0364 static struct {
0365 struct page **pages_arr;
0366 } uninorth_priv;
0367
0368 static int uninorth_create_gatt_table(struct agp_bridge_data *bridge)
0369 {
0370 char *table;
0371 char *table_end;
0372 int size;
0373 int page_order;
0374 int num_entries;
0375 int i;
0376 void *temp;
0377 struct page *page;
0378
0379
0380 if (bridge->driver->size_type == LVL2_APER_SIZE)
0381 return -EINVAL;
0382
0383 table = NULL;
0384 i = bridge->aperture_size_idx;
0385 temp = bridge->current_size;
0386 size = page_order = num_entries = 0;
0387
0388 do {
0389 size = A_SIZE_32(temp)->size;
0390 page_order = A_SIZE_32(temp)->page_order;
0391 num_entries = A_SIZE_32(temp)->num_entries;
0392
0393 table = (char *) __get_free_pages(GFP_KERNEL, page_order);
0394
0395 if (table == NULL) {
0396 i++;
0397 bridge->current_size = A_IDX32(bridge);
0398 } else {
0399 bridge->aperture_size_idx = i;
0400 }
0401 } while (!table && (i < bridge->driver->num_aperture_sizes));
0402
0403 if (table == NULL)
0404 return -ENOMEM;
0405
0406 uninorth_priv.pages_arr = kmalloc_array(1 << page_order,
0407 sizeof(struct page *),
0408 GFP_KERNEL);
0409 if (uninorth_priv.pages_arr == NULL)
0410 goto enomem;
0411
0412 table_end = table + ((PAGE_SIZE * (1 << page_order)) - 1);
0413
0414 for (page = virt_to_page(table), i = 0; page <= virt_to_page(table_end);
0415 page++, i++) {
0416 SetPageReserved(page);
0417 uninorth_priv.pages_arr[i] = page;
0418 }
0419
0420 bridge->gatt_table_real = (u32 *) table;
0421
0422 flush_dcache_range((unsigned long)table,
0423 (unsigned long)table_end + 1);
0424 bridge->gatt_table = vmap(uninorth_priv.pages_arr, (1 << page_order), 0, PAGE_KERNEL_NCG);
0425
0426 if (bridge->gatt_table == NULL)
0427 goto enomem;
0428
0429 bridge->gatt_bus_addr = virt_to_phys(table);
0430
0431 if (is_u3)
0432 scratch_value = (page_to_phys(agp_bridge->scratch_page_page) >> PAGE_SHIFT) | 0x80000000UL;
0433 else
0434 scratch_value = cpu_to_le32((page_to_phys(agp_bridge->scratch_page_page) & 0xFFFFF000UL) |
0435 0x1UL);
0436 for (i = 0; i < num_entries; i++)
0437 bridge->gatt_table[i] = scratch_value;
0438
0439 return 0;
0440
0441 enomem:
0442 kfree(uninorth_priv.pages_arr);
0443 if (table)
0444 free_pages((unsigned long)table, page_order);
0445 return -ENOMEM;
0446 }
0447
0448 static int uninorth_free_gatt_table(struct agp_bridge_data *bridge)
0449 {
0450 int page_order;
0451 char *table, *table_end;
0452 void *temp;
0453 struct page *page;
0454
0455 temp = bridge->current_size;
0456 page_order = A_SIZE_32(temp)->page_order;
0457
0458
0459
0460
0461
0462
0463 vunmap(bridge->gatt_table);
0464 kfree(uninorth_priv.pages_arr);
0465 table = (char *) bridge->gatt_table_real;
0466 table_end = table + ((PAGE_SIZE * (1 << page_order)) - 1);
0467
0468 for (page = virt_to_page(table); page <= virt_to_page(table_end); page++)
0469 ClearPageReserved(page);
0470
0471 free_pages((unsigned long) bridge->gatt_table_real, page_order);
0472
0473 return 0;
0474 }
0475
0476 static void null_cache_flush(void)
0477 {
0478 mb();
0479 }
0480
0481
0482
0483 static const struct aper_size_info_32 uninorth_sizes[] =
0484 {
0485 {256, 65536, 6, 64},
0486 {128, 32768, 5, 32},
0487 {64, 16384, 4, 16},
0488 {32, 8192, 3, 8},
0489 {16, 4096, 2, 4},
0490 {8, 2048, 1, 2},
0491 {4, 1024, 0, 1}
0492 };
0493
0494
0495
0496
0497
0498 static const struct aper_size_info_32 u3_sizes[] =
0499 {
0500 {512, 131072, 7, 128},
0501 {256, 65536, 6, 64},
0502 {128, 32768, 5, 32},
0503 {64, 16384, 4, 16},
0504 {32, 8192, 3, 8},
0505 {16, 4096, 2, 4},
0506 {8, 2048, 1, 2},
0507 {4, 1024, 0, 1}
0508 };
0509
0510 const struct agp_bridge_driver uninorth_agp_driver = {
0511 .owner = THIS_MODULE,
0512 .aperture_sizes = (void *)uninorth_sizes,
0513 .size_type = U32_APER_SIZE,
0514 .num_aperture_sizes = ARRAY_SIZE(uninorth_sizes),
0515 .configure = uninorth_configure,
0516 .fetch_size = uninorth_fetch_size,
0517 .cleanup = uninorth_cleanup,
0518 .tlb_flush = uninorth_tlbflush,
0519 .mask_memory = agp_generic_mask_memory,
0520 .masks = NULL,
0521 .cache_flush = null_cache_flush,
0522 .agp_enable = uninorth_agp_enable,
0523 .create_gatt_table = uninorth_create_gatt_table,
0524 .free_gatt_table = uninorth_free_gatt_table,
0525 .insert_memory = uninorth_insert_memory,
0526 .remove_memory = uninorth_remove_memory,
0527 .alloc_by_type = agp_generic_alloc_by_type,
0528 .free_by_type = agp_generic_free_by_type,
0529 .agp_alloc_page = agp_generic_alloc_page,
0530 .agp_alloc_pages = agp_generic_alloc_pages,
0531 .agp_destroy_page = agp_generic_destroy_page,
0532 .agp_destroy_pages = agp_generic_destroy_pages,
0533 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
0534 .cant_use_aperture = true,
0535 .needs_scratch_page = true,
0536 };
0537
0538 const struct agp_bridge_driver u3_agp_driver = {
0539 .owner = THIS_MODULE,
0540 .aperture_sizes = (void *)u3_sizes,
0541 .size_type = U32_APER_SIZE,
0542 .num_aperture_sizes = ARRAY_SIZE(u3_sizes),
0543 .configure = uninorth_configure,
0544 .fetch_size = uninorth_fetch_size,
0545 .cleanup = uninorth_cleanup,
0546 .tlb_flush = uninorth_tlbflush,
0547 .mask_memory = agp_generic_mask_memory,
0548 .masks = NULL,
0549 .cache_flush = null_cache_flush,
0550 .agp_enable = uninorth_agp_enable,
0551 .create_gatt_table = uninorth_create_gatt_table,
0552 .free_gatt_table = uninorth_free_gatt_table,
0553 .insert_memory = uninorth_insert_memory,
0554 .remove_memory = uninorth_remove_memory,
0555 .alloc_by_type = agp_generic_alloc_by_type,
0556 .free_by_type = agp_generic_free_by_type,
0557 .agp_alloc_page = agp_generic_alloc_page,
0558 .agp_alloc_pages = agp_generic_alloc_pages,
0559 .agp_destroy_page = agp_generic_destroy_page,
0560 .agp_destroy_pages = agp_generic_destroy_pages,
0561 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
0562 .cant_use_aperture = true,
0563 .needs_scratch_page = true,
0564 };
0565
0566 static struct agp_device_ids uninorth_agp_device_ids[] = {
0567 {
0568 .device_id = PCI_DEVICE_ID_APPLE_UNI_N_AGP,
0569 .chipset_name = "UniNorth",
0570 },
0571 {
0572 .device_id = PCI_DEVICE_ID_APPLE_UNI_N_AGP_P,
0573 .chipset_name = "UniNorth/Pangea",
0574 },
0575 {
0576 .device_id = PCI_DEVICE_ID_APPLE_UNI_N_AGP15,
0577 .chipset_name = "UniNorth 1.5",
0578 },
0579 {
0580 .device_id = PCI_DEVICE_ID_APPLE_UNI_N_AGP2,
0581 .chipset_name = "UniNorth 2",
0582 },
0583 {
0584 .device_id = PCI_DEVICE_ID_APPLE_U3_AGP,
0585 .chipset_name = "U3",
0586 },
0587 {
0588 .device_id = PCI_DEVICE_ID_APPLE_U3L_AGP,
0589 .chipset_name = "U3L",
0590 },
0591 {
0592 .device_id = PCI_DEVICE_ID_APPLE_U3H_AGP,
0593 .chipset_name = "U3H",
0594 },
0595 {
0596 .device_id = PCI_DEVICE_ID_APPLE_IPID2_AGP,
0597 .chipset_name = "UniNorth/Intrepid2",
0598 },
0599 };
0600
0601 static int agp_uninorth_probe(struct pci_dev *pdev,
0602 const struct pci_device_id *ent)
0603 {
0604 struct agp_device_ids *devs = uninorth_agp_device_ids;
0605 struct agp_bridge_data *bridge;
0606 struct device_node *uninorth_node;
0607 u8 cap_ptr;
0608 int j;
0609
0610 cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
0611 if (cap_ptr == 0)
0612 return -ENODEV;
0613
0614
0615 for (j = 0; devs[j].chipset_name != NULL; ++j) {
0616 if (pdev->device == devs[j].device_id) {
0617 dev_info(&pdev->dev, "Apple %s chipset\n",
0618 devs[j].chipset_name);
0619 goto found;
0620 }
0621 }
0622
0623 dev_err(&pdev->dev, "unsupported Apple chipset [%04x/%04x]\n",
0624 pdev->vendor, pdev->device);
0625 return -ENODEV;
0626
0627 found:
0628
0629 uninorth_rev = 0;
0630 is_u3 = 0;
0631
0632 uninorth_node = of_find_node_by_name(NULL, "uni-n");
0633
0634 if (uninorth_node == NULL) {
0635 is_u3 = 1;
0636 uninorth_node = of_find_node_by_name(NULL, "u3");
0637 }
0638 if (uninorth_node) {
0639 const int *revprop = of_get_property(uninorth_node,
0640 "device-rev", NULL);
0641 if (revprop != NULL)
0642 uninorth_rev = *revprop & 0x3f;
0643 of_node_put(uninorth_node);
0644 }
0645
0646 #ifdef CONFIG_PM
0647
0648 pmac_register_agp_pm(pdev, agp_uninorth_suspend, agp_uninorth_resume);
0649 #endif
0650
0651
0652 bridge = agp_alloc_bridge();
0653 if (!bridge)
0654 return -ENOMEM;
0655
0656 if (is_u3)
0657 bridge->driver = &u3_agp_driver;
0658 else
0659 bridge->driver = &uninorth_agp_driver;
0660
0661 bridge->dev = pdev;
0662 bridge->capndx = cap_ptr;
0663 bridge->flags = AGP_ERRATA_FASTWRITES;
0664
0665
0666 pci_read_config_dword(pdev, cap_ptr+PCI_AGP_STATUS, &bridge->mode);
0667
0668 pci_set_drvdata(pdev, bridge);
0669 return agp_add_bridge(bridge);
0670 }
0671
0672 static void agp_uninorth_remove(struct pci_dev *pdev)
0673 {
0674 struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
0675
0676 #ifdef CONFIG_PM
0677
0678 pmac_register_agp_pm(pdev, NULL, NULL);
0679 #endif
0680
0681 agp_remove_bridge(bridge);
0682 agp_put_bridge(bridge);
0683 }
0684
0685 static const struct pci_device_id agp_uninorth_pci_table[] = {
0686 {
0687 .class = (PCI_CLASS_BRIDGE_HOST << 8),
0688 .class_mask = ~0,
0689 .vendor = PCI_VENDOR_ID_APPLE,
0690 .device = PCI_ANY_ID,
0691 .subvendor = PCI_ANY_ID,
0692 .subdevice = PCI_ANY_ID,
0693 },
0694 { }
0695 };
0696
0697 MODULE_DEVICE_TABLE(pci, agp_uninorth_pci_table);
0698
0699 static struct pci_driver agp_uninorth_pci_driver = {
0700 .name = "agpgart-uninorth",
0701 .id_table = agp_uninorth_pci_table,
0702 .probe = agp_uninorth_probe,
0703 .remove = agp_uninorth_remove,
0704 };
0705
0706 static int __init agp_uninorth_init(void)
0707 {
0708 if (agp_off)
0709 return -EINVAL;
0710 return pci_register_driver(&agp_uninorth_pci_driver);
0711 }
0712
0713 static void __exit agp_uninorth_cleanup(void)
0714 {
0715 pci_unregister_driver(&agp_uninorth_pci_driver);
0716 }
0717
0718 module_init(agp_uninorth_init);
0719 module_exit(agp_uninorth_cleanup);
0720
0721 module_param(aperture, charp, 0);
0722 MODULE_PARM_DESC(aperture,
0723 "Aperture size, must be power of two between 4MB and an\n"
0724 "\t\tupper limit specific to the UniNorth revision.\n"
0725 "\t\tDefault: " DEFAULT_APERTURE_STRING "M");
0726
0727 MODULE_AUTHOR("Ben Herrenschmidt & Paul Mackerras");
0728 MODULE_LICENSE("GPL");