Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * UniNorth AGPGART routines.
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  * NOTES for uninorth3 (G5 AGP) supports :
0020  *
0021  * There maybe also possibility to have bigger cache line size for
0022  * agp (see pmac_pci.c and look for cache line). Need to be investigated
0023  * by someone.
0024  *
0025  * PAGE size are hardcoded but this may change, see asm/page.h.
0026  *
0027  * Jerome Glisse <j.glisse@gmail.com>
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     /* aperture size and gatt addr */
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     /* HACK ALERT
0126      * UniNorth seem to be buggy enough not to handle properly when
0127      * the AGP aperture isn't mapped at bus physical address 0
0128      */
0129     agp_bridge->gart_bus_addr = 0;
0130 #ifdef CONFIG_PPC64
0131     /* Assume U3 or later on PPC64 systems */
0132     /* high 4 bits of GART physical address go in UNI_N_CFG_AGP_BASE */
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         /* We know nothing of memory types */
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         /* We know nothing of memory types */
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          * Darwin disable AGP 4x on this revision, thus we
0242          * may assume it's broken. This is an AGP2 controller.
0243          */
0244         command &= ~AGPSTAT2_4X;
0245     }
0246 
0247     if ((uninorth_rev >= 0x30) && (uninorth_rev <= 0x33)) {
0248         /*
0249          * We need to set REQ_DEPTH to 7 for U3 versions 1.0, 2.1,
0250          * 2.2 and 2.3, Darwin do so.
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         /* This is an AGP V3 */
0274         agp_device_command(command, (status & AGPSTAT_MODE_3_0) != 0);
0275     } else {
0276         /* AGP V2 */
0277         agp_device_command(command, false);
0278     }
0279 
0280     uninorth_tlbflush(NULL);
0281 }
0282 
0283 #ifdef CONFIG_PM
0284 /*
0285  * These Power Management routines are _not_ called by the normal PCI PM layer,
0286  * but directly by the video driver through function pointers in the device
0287  * tree.
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     /* Only one suspend supported */
0301     if (bridge->dev_private_data)
0302         return 0;
0303 
0304     /* turn off AGP on the video chip, if it was enabled */
0305     for_each_pci_dev(device) {
0306         /* Don't touch the bridge yet, device first */
0307         if (device == pdev)
0308             continue;
0309         /* Only deal with devices on the same bus here, no Mac has a P2P
0310          * bridge on the AGP port, and mucking around the entire PCI
0311          * tree is source of problems on some machines because of a bug
0312          * in some versions of pci_find_capability() when hitting a dead
0313          * device
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     /* turn off AGP on the bridge */
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     /* turn off the GART */
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 /* CONFIG_PM */
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     /* We can't handle 2 level gatt's */
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     /* Need to clear out any dirty data still sitting in caches */
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     /* Do not worry about freeing memory, because if this is
0459      * called, then all agp memory is deallocated and removed
0460      * from the table.
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 /* Setup function */
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  * Not sure that u3 supports that high aperture sizes but it
0496  * would strange if it did not :)
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     /* probe for known chipsets */
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     /* Set revision to 0 if we could not read it. */
0629     uninorth_rev = 0;
0630     is_u3 = 0;
0631     /* Locate core99 Uni-N */
0632     uninorth_node = of_find_node_by_name(NULL, "uni-n");
0633     /* Locate G5 u3 */
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     /* Inform platform of our suspend/resume caps */
0648     pmac_register_agp_pm(pdev, agp_uninorth_suspend, agp_uninorth_resume);
0649 #endif
0650 
0651     /* Allocate & setup our driver */
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     /* Fill in the mode register */
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     /* Inform platform of our suspend/resume caps */
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");