uninorth-agp.c 17 KB

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