cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

uninorth-agp.c (18547B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * UniNorth AGPGART routines.
      4 */
      5#include <linux/module.h>
      6#include <linux/pci.h>
      7#include <linux/slab.h>
      8#include <linux/init.h>
      9#include <linux/pagemap.h>
     10#include <linux/agp_backend.h>
     11#include <linux/delay.h>
     12#include <linux/vmalloc.h>
     13#include <asm/uninorth.h>
     14#include <asm/prom.h>
     15#include <asm/pmac_feature.h>
     16#include "agp.h"
     17
     18/*
     19 * NOTES for uninorth3 (G5 AGP) supports :
     20 *
     21 * There maybe also possibility to have bigger cache line size for
     22 * agp (see pmac_pci.c and look for cache line). Need to be investigated
     23 * by someone.
     24 *
     25 * PAGE size are hardcoded but this may change, see asm/page.h.
     26 *
     27 * Jerome Glisse <j.glisse@gmail.com>
     28 */
     29static int uninorth_rev;
     30static int is_u3;
     31static u32 scratch_value;
     32
     33#define DEFAULT_APERTURE_SIZE 256
     34#define DEFAULT_APERTURE_STRING "256"
     35static char *aperture = NULL;
     36
     37static int uninorth_fetch_size(void)
     38{
     39	int i, size = 0;
     40	struct aper_size_info_32 *values =
     41	    A_SIZE_32(agp_bridge->driver->aperture_sizes);
     42
     43	if (aperture) {
     44		char *save = aperture;
     45
     46		size = memparse(aperture, &aperture) >> 20;
     47		aperture = save;
     48
     49		for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++)
     50			if (size == values[i].size)
     51				break;
     52
     53		if (i == agp_bridge->driver->num_aperture_sizes) {
     54			dev_err(&agp_bridge->dev->dev, "invalid aperture size, "
     55				"using default\n");
     56			size = 0;
     57			aperture = NULL;
     58		}
     59	}
     60
     61	if (!size) {
     62		for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++)
     63			if (values[i].size == DEFAULT_APERTURE_SIZE)
     64				break;
     65	}
     66
     67	agp_bridge->previous_size =
     68	    agp_bridge->current_size = (void *)(values + i);
     69	agp_bridge->aperture_size_idx = i;
     70	return values[i].size;
     71}
     72
     73static void uninorth_tlbflush(struct agp_memory *mem)
     74{
     75	u32 ctrl = UNI_N_CFG_GART_ENABLE;
     76
     77	if (is_u3)
     78		ctrl |= U3_N_CFG_GART_PERFRD;
     79	pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL,
     80			       ctrl | UNI_N_CFG_GART_INVAL);
     81	pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL, ctrl);
     82
     83	if (!mem && uninorth_rev <= 0x30) {
     84		pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL,
     85				       ctrl | UNI_N_CFG_GART_2xRESET);
     86		pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL,
     87				       ctrl);
     88	}
     89}
     90
     91static void uninorth_cleanup(void)
     92{
     93	u32 tmp;
     94
     95	pci_read_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL, &tmp);
     96	if (!(tmp & UNI_N_CFG_GART_ENABLE))
     97		return;
     98	tmp |= UNI_N_CFG_GART_INVAL;
     99	pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL, tmp);
    100	pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL, 0);
    101
    102	if (uninorth_rev <= 0x30) {
    103		pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL,
    104				       UNI_N_CFG_GART_2xRESET);
    105		pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL,
    106				       0);
    107	}
    108}
    109
    110static int uninorth_configure(void)
    111{
    112	struct aper_size_info_32 *current_size;
    113
    114	current_size = A_SIZE_32(agp_bridge->current_size);
    115
    116	dev_info(&agp_bridge->dev->dev, "configuring for size idx: %d\n",
    117		 current_size->size_value);
    118
    119	/* aperture size and gatt addr */
    120	pci_write_config_dword(agp_bridge->dev,
    121		UNI_N_CFG_GART_BASE,
    122		(agp_bridge->gatt_bus_addr & 0xfffff000)
    123			| current_size->size_value);
    124
    125	/* HACK ALERT
    126	 * UniNorth seem to be buggy enough not to handle properly when
    127	 * the AGP aperture isn't mapped at bus physical address 0
    128	 */
    129	agp_bridge->gart_bus_addr = 0;
    130#ifdef CONFIG_PPC64
    131	/* Assume U3 or later on PPC64 systems */
    132	/* high 4 bits of GART physical address go in UNI_N_CFG_AGP_BASE */
    133	pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_AGP_BASE,
    134			       (agp_bridge->gatt_bus_addr >> 32) & 0xf);
    135#else
    136	pci_write_config_dword(agp_bridge->dev,
    137		UNI_N_CFG_AGP_BASE, agp_bridge->gart_bus_addr);
    138#endif
    139
    140	if (is_u3) {
    141		pci_write_config_dword(agp_bridge->dev,
    142				       UNI_N_CFG_GART_DUMMY_PAGE,
    143				       page_to_phys(agp_bridge->scratch_page_page) >> 12);
    144	}
    145
    146	return 0;
    147}
    148
    149static int uninorth_insert_memory(struct agp_memory *mem, off_t pg_start, int type)
    150{
    151	int i, num_entries;
    152	void *temp;
    153	u32 *gp;
    154	int mask_type;
    155
    156	if (type != mem->type)
    157		return -EINVAL;
    158
    159	mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type);
    160	if (mask_type != 0) {
    161		/* We know nothing of memory types */
    162		return -EINVAL;
    163	}
    164
    165	if (mem->page_count == 0)
    166		return 0;
    167
    168	temp = agp_bridge->current_size;
    169	num_entries = A_SIZE_32(temp)->num_entries;
    170
    171	if ((pg_start + mem->page_count) > num_entries)
    172		return -EINVAL;
    173
    174	gp = (u32 *) &agp_bridge->gatt_table[pg_start];
    175	for (i = 0; i < mem->page_count; ++i) {
    176		if (gp[i] != scratch_value) {
    177			dev_info(&agp_bridge->dev->dev,
    178				 "uninorth_insert_memory: entry 0x%x occupied (%x)\n",
    179				 i, gp[i]);
    180			return -EBUSY;
    181		}
    182	}
    183
    184	for (i = 0; i < mem->page_count; i++) {
    185		if (is_u3)
    186			gp[i] = (page_to_phys(mem->pages[i]) >> PAGE_SHIFT) | 0x80000000UL;
    187		else
    188			gp[i] =	cpu_to_le32((page_to_phys(mem->pages[i]) & 0xFFFFF000UL) |
    189					    0x1UL);
    190		flush_dcache_range((unsigned long)__va(page_to_phys(mem->pages[i])),
    191				   (unsigned long)__va(page_to_phys(mem->pages[i]))+0x1000);
    192	}
    193	mb();
    194	uninorth_tlbflush(mem);
    195
    196	return 0;
    197}
    198
    199static int uninorth_remove_memory(struct agp_memory *mem, off_t pg_start, int type)
    200{
    201	size_t i;
    202	u32 *gp;
    203	int mask_type;
    204
    205	if (type != mem->type)
    206		return -EINVAL;
    207
    208	mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type);
    209	if (mask_type != 0) {
    210		/* We know nothing of memory types */
    211		return -EINVAL;
    212	}
    213
    214	if (mem->page_count == 0)
    215		return 0;
    216
    217	gp = (u32 *) &agp_bridge->gatt_table[pg_start];
    218	for (i = 0; i < mem->page_count; ++i) {
    219		gp[i] = scratch_value;
    220	}
    221	mb();
    222	uninorth_tlbflush(mem);
    223
    224	return 0;
    225}
    226
    227static void uninorth_agp_enable(struct agp_bridge_data *bridge, u32 mode)
    228{
    229	u32 command, scratch, status;
    230	int timeout;
    231
    232	pci_read_config_dword(bridge->dev,
    233			      bridge->capndx + PCI_AGP_STATUS,
    234			      &status);
    235
    236	command = agp_collect_device_status(bridge, mode, status);
    237	command |= PCI_AGP_COMMAND_AGP;
    238
    239	if (uninorth_rev == 0x21) {
    240		/*
    241		 * Darwin disable AGP 4x on this revision, thus we
    242		 * may assume it's broken. This is an AGP2 controller.
    243		 */
    244		command &= ~AGPSTAT2_4X;
    245	}
    246
    247	if ((uninorth_rev >= 0x30) && (uninorth_rev <= 0x33)) {
    248		/*
    249		 * We need to set REQ_DEPTH to 7 for U3 versions 1.0, 2.1,
    250		 * 2.2 and 2.3, Darwin do so.
    251		 */
    252		if ((command >> AGPSTAT_RQ_DEPTH_SHIFT) > 7)
    253			command = (command & ~AGPSTAT_RQ_DEPTH)
    254				| (7 << AGPSTAT_RQ_DEPTH_SHIFT);
    255	}
    256
    257	uninorth_tlbflush(NULL);
    258
    259	timeout = 0;
    260	do {
    261		pci_write_config_dword(bridge->dev,
    262				       bridge->capndx + PCI_AGP_COMMAND,
    263				       command);
    264		pci_read_config_dword(bridge->dev,
    265				      bridge->capndx + PCI_AGP_COMMAND,
    266				       &scratch);
    267	} while ((scratch & PCI_AGP_COMMAND_AGP) == 0 && ++timeout < 1000);
    268	if ((scratch & PCI_AGP_COMMAND_AGP) == 0)
    269		dev_err(&bridge->dev->dev, "can't write UniNorth AGP "
    270			"command register\n");
    271
    272	if (uninorth_rev >= 0x30) {
    273		/* This is an AGP V3 */
    274		agp_device_command(command, (status & AGPSTAT_MODE_3_0) != 0);
    275	} else {
    276		/* AGP V2 */
    277		agp_device_command(command, false);
    278	}
    279
    280	uninorth_tlbflush(NULL);
    281}
    282
    283#ifdef CONFIG_PM
    284/*
    285 * These Power Management routines are _not_ called by the normal PCI PM layer,
    286 * but directly by the video driver through function pointers in the device
    287 * tree.
    288 */
    289static int agp_uninorth_suspend(struct pci_dev *pdev)
    290{
    291	struct agp_bridge_data *bridge;
    292	u32 cmd;
    293	u8 agp;
    294	struct pci_dev *device = NULL;
    295
    296	bridge = agp_find_bridge(pdev);
    297	if (bridge == NULL)
    298		return -ENODEV;
    299
    300	/* Only one suspend supported */
    301	if (bridge->dev_private_data)
    302		return 0;
    303
    304	/* turn off AGP on the video chip, if it was enabled */
    305	for_each_pci_dev(device) {
    306		/* Don't touch the bridge yet, device first */
    307		if (device == pdev)
    308			continue;
    309		/* Only deal with devices on the same bus here, no Mac has a P2P
    310		 * bridge on the AGP port, and mucking around the entire PCI
    311		 * tree is source of problems on some machines because of a bug
    312		 * in some versions of pci_find_capability() when hitting a dead
    313		 * device
    314		 */
    315		if (device->bus != pdev->bus)
    316			continue;
    317		agp = pci_find_capability(device, PCI_CAP_ID_AGP);
    318		if (!agp)
    319			continue;
    320		pci_read_config_dword(device, agp + PCI_AGP_COMMAND, &cmd);
    321		if (!(cmd & PCI_AGP_COMMAND_AGP))
    322			continue;
    323		dev_info(&pdev->dev, "disabling AGP on device %s\n",
    324			 pci_name(device));
    325		cmd &= ~PCI_AGP_COMMAND_AGP;
    326		pci_write_config_dword(device, agp + PCI_AGP_COMMAND, cmd);
    327	}
    328
    329	/* turn off AGP on the bridge */
    330	agp = pci_find_capability(pdev, PCI_CAP_ID_AGP);
    331	pci_read_config_dword(pdev, agp + PCI_AGP_COMMAND, &cmd);
    332	bridge->dev_private_data = (void *)(long)cmd;
    333	if (cmd & PCI_AGP_COMMAND_AGP) {
    334		dev_info(&pdev->dev, "disabling AGP on bridge\n");
    335		cmd &= ~PCI_AGP_COMMAND_AGP;
    336		pci_write_config_dword(pdev, agp + PCI_AGP_COMMAND, cmd);
    337	}
    338	/* turn off the GART */
    339	uninorth_cleanup();
    340
    341	return 0;
    342}
    343
    344static int agp_uninorth_resume(struct pci_dev *pdev)
    345{
    346	struct agp_bridge_data *bridge;
    347	u32 command;
    348
    349	bridge = agp_find_bridge(pdev);
    350	if (bridge == NULL)
    351		return -ENODEV;
    352
    353	command = (long)bridge->dev_private_data;
    354	bridge->dev_private_data = NULL;
    355	if (!(command & PCI_AGP_COMMAND_AGP))
    356		return 0;
    357
    358	uninorth_agp_enable(bridge, command);
    359
    360	return 0;
    361}
    362#endif /* CONFIG_PM */
    363
    364static struct {
    365	struct page **pages_arr;
    366} uninorth_priv;
    367
    368static int uninorth_create_gatt_table(struct agp_bridge_data *bridge)
    369{
    370	char *table;
    371	char *table_end;
    372	int size;
    373	int page_order;
    374	int num_entries;
    375	int i;
    376	void *temp;
    377	struct page *page;
    378
    379	/* We can't handle 2 level gatt's */
    380	if (bridge->driver->size_type == LVL2_APER_SIZE)
    381		return -EINVAL;
    382
    383	table = NULL;
    384	i = bridge->aperture_size_idx;
    385	temp = bridge->current_size;
    386	size = page_order = num_entries = 0;
    387
    388	do {
    389		size = A_SIZE_32(temp)->size;
    390		page_order = A_SIZE_32(temp)->page_order;
    391		num_entries = A_SIZE_32(temp)->num_entries;
    392
    393		table = (char *) __get_free_pages(GFP_KERNEL, page_order);
    394
    395		if (table == NULL) {
    396			i++;
    397			bridge->current_size = A_IDX32(bridge);
    398		} else {
    399			bridge->aperture_size_idx = i;
    400		}
    401	} while (!table && (i < bridge->driver->num_aperture_sizes));
    402
    403	if (table == NULL)
    404		return -ENOMEM;
    405
    406	uninorth_priv.pages_arr = kmalloc_array(1 << page_order,
    407						sizeof(struct page *),
    408						GFP_KERNEL);
    409	if (uninorth_priv.pages_arr == NULL)
    410		goto enomem;
    411
    412	table_end = table + ((PAGE_SIZE * (1 << page_order)) - 1);
    413
    414	for (page = virt_to_page(table), i = 0; page <= virt_to_page(table_end);
    415	     page++, i++) {
    416		SetPageReserved(page);
    417		uninorth_priv.pages_arr[i] = page;
    418	}
    419
    420	bridge->gatt_table_real = (u32 *) table;
    421	/* Need to clear out any dirty data still sitting in caches */
    422	flush_dcache_range((unsigned long)table,
    423			   (unsigned long)table_end + 1);
    424	bridge->gatt_table = vmap(uninorth_priv.pages_arr, (1 << page_order), 0, PAGE_KERNEL_NCG);
    425
    426	if (bridge->gatt_table == NULL)
    427		goto enomem;
    428
    429	bridge->gatt_bus_addr = virt_to_phys(table);
    430
    431	if (is_u3)
    432		scratch_value = (page_to_phys(agp_bridge->scratch_page_page) >> PAGE_SHIFT) | 0x80000000UL;
    433	else
    434		scratch_value =	cpu_to_le32((page_to_phys(agp_bridge->scratch_page_page) & 0xFFFFF000UL) |
    435				0x1UL);
    436	for (i = 0; i < num_entries; i++)
    437		bridge->gatt_table[i] = scratch_value;
    438
    439	return 0;
    440
    441enomem:
    442	kfree(uninorth_priv.pages_arr);
    443	if (table)
    444		free_pages((unsigned long)table, page_order);
    445	return -ENOMEM;
    446}
    447
    448static int uninorth_free_gatt_table(struct agp_bridge_data *bridge)
    449{
    450	int page_order;
    451	char *table, *table_end;
    452	void *temp;
    453	struct page *page;
    454
    455	temp = bridge->current_size;
    456	page_order = A_SIZE_32(temp)->page_order;
    457
    458	/* Do not worry about freeing memory, because if this is
    459	 * called, then all agp memory is deallocated and removed
    460	 * from the table.
    461	 */
    462
    463	vunmap(bridge->gatt_table);
    464	kfree(uninorth_priv.pages_arr);
    465	table = (char *) bridge->gatt_table_real;
    466	table_end = table + ((PAGE_SIZE * (1 << page_order)) - 1);
    467
    468	for (page = virt_to_page(table); page <= virt_to_page(table_end); page++)
    469		ClearPageReserved(page);
    470
    471	free_pages((unsigned long) bridge->gatt_table_real, page_order);
    472
    473	return 0;
    474}
    475
    476static void null_cache_flush(void)
    477{
    478	mb();
    479}
    480
    481/* Setup function */
    482
    483static const struct aper_size_info_32 uninorth_sizes[] =
    484{
    485	{256, 65536, 6, 64},
    486	{128, 32768, 5, 32},
    487	{64, 16384, 4, 16},
    488	{32, 8192, 3, 8},
    489	{16, 4096, 2, 4},
    490	{8, 2048, 1, 2},
    491	{4, 1024, 0, 1}
    492};
    493
    494/*
    495 * Not sure that u3 supports that high aperture sizes but it
    496 * would strange if it did not :)
    497 */
    498static const struct aper_size_info_32 u3_sizes[] =
    499{
    500	{512, 131072, 7, 128},
    501	{256, 65536, 6, 64},
    502	{128, 32768, 5, 32},
    503	{64, 16384, 4, 16},
    504	{32, 8192, 3, 8},
    505	{16, 4096, 2, 4},
    506	{8, 2048, 1, 2},
    507	{4, 1024, 0, 1}
    508};
    509
    510const struct agp_bridge_driver uninorth_agp_driver = {
    511	.owner			= THIS_MODULE,
    512	.aperture_sizes		= (void *)uninorth_sizes,
    513	.size_type		= U32_APER_SIZE,
    514	.num_aperture_sizes	= ARRAY_SIZE(uninorth_sizes),
    515	.configure		= uninorth_configure,
    516	.fetch_size		= uninorth_fetch_size,
    517	.cleanup		= uninorth_cleanup,
    518	.tlb_flush		= uninorth_tlbflush,
    519	.mask_memory		= agp_generic_mask_memory,
    520	.masks			= NULL,
    521	.cache_flush		= null_cache_flush,
    522	.agp_enable		= uninorth_agp_enable,
    523	.create_gatt_table	= uninorth_create_gatt_table,
    524	.free_gatt_table	= uninorth_free_gatt_table,
    525	.insert_memory		= uninorth_insert_memory,
    526	.remove_memory		= uninorth_remove_memory,
    527	.alloc_by_type		= agp_generic_alloc_by_type,
    528	.free_by_type		= agp_generic_free_by_type,
    529	.agp_alloc_page		= agp_generic_alloc_page,
    530	.agp_alloc_pages	= agp_generic_alloc_pages,
    531	.agp_destroy_page	= agp_generic_destroy_page,
    532	.agp_destroy_pages	= agp_generic_destroy_pages,
    533	.agp_type_to_mask_type  = agp_generic_type_to_mask_type,
    534	.cant_use_aperture	= true,
    535	.needs_scratch_page	= true,
    536};
    537
    538const struct agp_bridge_driver u3_agp_driver = {
    539	.owner			= THIS_MODULE,
    540	.aperture_sizes		= (void *)u3_sizes,
    541	.size_type		= U32_APER_SIZE,
    542	.num_aperture_sizes	= ARRAY_SIZE(u3_sizes),
    543	.configure		= uninorth_configure,
    544	.fetch_size		= uninorth_fetch_size,
    545	.cleanup		= uninorth_cleanup,
    546	.tlb_flush		= uninorth_tlbflush,
    547	.mask_memory		= agp_generic_mask_memory,
    548	.masks			= NULL,
    549	.cache_flush		= null_cache_flush,
    550	.agp_enable		= uninorth_agp_enable,
    551	.create_gatt_table	= uninorth_create_gatt_table,
    552	.free_gatt_table	= uninorth_free_gatt_table,
    553	.insert_memory		= uninorth_insert_memory,
    554	.remove_memory		= uninorth_remove_memory,
    555	.alloc_by_type		= agp_generic_alloc_by_type,
    556	.free_by_type		= agp_generic_free_by_type,
    557	.agp_alloc_page		= agp_generic_alloc_page,
    558	.agp_alloc_pages	= agp_generic_alloc_pages,
    559	.agp_destroy_page	= agp_generic_destroy_page,
    560	.agp_destroy_pages	= agp_generic_destroy_pages,
    561	.agp_type_to_mask_type  = agp_generic_type_to_mask_type,
    562	.cant_use_aperture	= true,
    563	.needs_scratch_page	= true,
    564};
    565
    566static struct agp_device_ids uninorth_agp_device_ids[] = {
    567	{
    568		.device_id	= PCI_DEVICE_ID_APPLE_UNI_N_AGP,
    569		.chipset_name	= "UniNorth",
    570	},
    571	{
    572		.device_id	= PCI_DEVICE_ID_APPLE_UNI_N_AGP_P,
    573		.chipset_name	= "UniNorth/Pangea",
    574	},
    575	{
    576		.device_id	= PCI_DEVICE_ID_APPLE_UNI_N_AGP15,
    577		.chipset_name	= "UniNorth 1.5",
    578	},
    579	{
    580		.device_id	= PCI_DEVICE_ID_APPLE_UNI_N_AGP2,
    581		.chipset_name	= "UniNorth 2",
    582	},
    583	{
    584		.device_id	= PCI_DEVICE_ID_APPLE_U3_AGP,
    585		.chipset_name	= "U3",
    586	},
    587	{
    588		.device_id	= PCI_DEVICE_ID_APPLE_U3L_AGP,
    589		.chipset_name	= "U3L",
    590	},
    591	{
    592		.device_id	= PCI_DEVICE_ID_APPLE_U3H_AGP,
    593		.chipset_name	= "U3H",
    594	},
    595	{
    596		.device_id	= PCI_DEVICE_ID_APPLE_IPID2_AGP,
    597		.chipset_name	= "UniNorth/Intrepid2",
    598	},
    599};
    600
    601static int agp_uninorth_probe(struct pci_dev *pdev,
    602			      const struct pci_device_id *ent)
    603{
    604	struct agp_device_ids *devs = uninorth_agp_device_ids;
    605	struct agp_bridge_data *bridge;
    606	struct device_node *uninorth_node;
    607	u8 cap_ptr;
    608	int j;
    609
    610	cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
    611	if (cap_ptr == 0)
    612		return -ENODEV;
    613
    614	/* probe for known chipsets */
    615	for (j = 0; devs[j].chipset_name != NULL; ++j) {
    616		if (pdev->device == devs[j].device_id) {
    617			dev_info(&pdev->dev, "Apple %s chipset\n",
    618				 devs[j].chipset_name);
    619			goto found;
    620		}
    621	}
    622
    623	dev_err(&pdev->dev, "unsupported Apple chipset [%04x/%04x]\n",
    624		pdev->vendor, pdev->device);
    625	return -ENODEV;
    626
    627 found:
    628	/* Set revision to 0 if we could not read it. */
    629	uninorth_rev = 0;
    630	is_u3 = 0;
    631	/* Locate core99 Uni-N */
    632	uninorth_node = of_find_node_by_name(NULL, "uni-n");
    633	/* Locate G5 u3 */
    634	if (uninorth_node == NULL) {
    635		is_u3 = 1;
    636		uninorth_node = of_find_node_by_name(NULL, "u3");
    637	}
    638	if (uninorth_node) {
    639		const int *revprop = of_get_property(uninorth_node,
    640				"device-rev", NULL);
    641		if (revprop != NULL)
    642			uninorth_rev = *revprop & 0x3f;
    643		of_node_put(uninorth_node);
    644	}
    645
    646#ifdef CONFIG_PM
    647	/* Inform platform of our suspend/resume caps */
    648	pmac_register_agp_pm(pdev, agp_uninorth_suspend, agp_uninorth_resume);
    649#endif
    650
    651	/* Allocate & setup our driver */
    652	bridge = agp_alloc_bridge();
    653	if (!bridge)
    654		return -ENOMEM;
    655
    656	if (is_u3)
    657		bridge->driver = &u3_agp_driver;
    658	else
    659		bridge->driver = &uninorth_agp_driver;
    660
    661	bridge->dev = pdev;
    662	bridge->capndx = cap_ptr;
    663	bridge->flags = AGP_ERRATA_FASTWRITES;
    664
    665	/* Fill in the mode register */
    666	pci_read_config_dword(pdev, cap_ptr+PCI_AGP_STATUS, &bridge->mode);
    667
    668	pci_set_drvdata(pdev, bridge);
    669	return agp_add_bridge(bridge);
    670}
    671
    672static void agp_uninorth_remove(struct pci_dev *pdev)
    673{
    674	struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
    675
    676#ifdef CONFIG_PM
    677	/* Inform platform of our suspend/resume caps */
    678	pmac_register_agp_pm(pdev, NULL, NULL);
    679#endif
    680
    681	agp_remove_bridge(bridge);
    682	agp_put_bridge(bridge);
    683}
    684
    685static const struct pci_device_id agp_uninorth_pci_table[] = {
    686	{
    687	.class		= (PCI_CLASS_BRIDGE_HOST << 8),
    688	.class_mask	= ~0,
    689	.vendor		= PCI_VENDOR_ID_APPLE,
    690	.device		= PCI_ANY_ID,
    691	.subvendor	= PCI_ANY_ID,
    692	.subdevice	= PCI_ANY_ID,
    693	},
    694	{ }
    695};
    696
    697MODULE_DEVICE_TABLE(pci, agp_uninorth_pci_table);
    698
    699static struct pci_driver agp_uninorth_pci_driver = {
    700	.name		= "agpgart-uninorth",
    701	.id_table	= agp_uninorth_pci_table,
    702	.probe		= agp_uninorth_probe,
    703	.remove		= agp_uninorth_remove,
    704};
    705
    706static int __init agp_uninorth_init(void)
    707{
    708	if (agp_off)
    709		return -EINVAL;
    710	return pci_register_driver(&agp_uninorth_pci_driver);
    711}
    712
    713static void __exit agp_uninorth_cleanup(void)
    714{
    715	pci_unregister_driver(&agp_uninorth_pci_driver);
    716}
    717
    718module_init(agp_uninorth_init);
    719module_exit(agp_uninorth_cleanup);
    720
    721module_param(aperture, charp, 0);
    722MODULE_PARM_DESC(aperture,
    723		 "Aperture size, must be power of two between 4MB and an\n"
    724		 "\t\tupper limit specific to the UniNorth revision.\n"
    725		 "\t\tDefault: " DEFAULT_APERTURE_STRING "M");
    726
    727MODULE_AUTHOR("Ben Herrenschmidt & Paul Mackerras");
    728MODULE_LICENSE("GPL");