hp-agp.c revision 24b8e0cc09483adc0fdd9c68914b19597bb9fddc
1/*
2 * HP zx1 AGPGART routines.
3 *
4 * (c) Copyright 2002, 2003 Hewlett-Packard Development Company, L.P.
5 *	Bjorn Helgaas <bjorn.helgaas@hp.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#include <linux/acpi.h>
13#include <linux/module.h>
14#include <linux/pci.h>
15#include <linux/init.h>
16#include <linux/agp_backend.h>
17
18#include <asm/acpi-ext.h>
19
20#include "agp.h"
21
22#ifndef log2
23#define log2(x)		ffz(~(x))
24#endif
25
26#define HP_ZX1_IOC_OFFSET	0x1000  /* ACPI reports SBA, we want IOC */
27
28/* HP ZX1 IOC registers */
29#define HP_ZX1_IBASE		0x300
30#define HP_ZX1_IMASK		0x308
31#define HP_ZX1_PCOM		0x310
32#define HP_ZX1_TCNFG		0x318
33#define HP_ZX1_PDIR_BASE	0x320
34
35#define HP_ZX1_IOVA_BASE	GB(1UL)
36#define HP_ZX1_IOVA_SIZE	GB(1UL)
37#define HP_ZX1_GART_SIZE	(HP_ZX1_IOVA_SIZE / 2)
38#define HP_ZX1_SBA_IOMMU_COOKIE	0x0000badbadc0ffeeUL
39
40#define HP_ZX1_PDIR_VALID_BIT	0x8000000000000000UL
41#define HP_ZX1_IOVA_TO_PDIR(va)	((va - hp_private.iova_base) >> hp_private.io_tlb_shift)
42
43#define AGP8X_MODE_BIT		3
44#define AGP8X_MODE		(1 << AGP8X_MODE_BIT)
45
46/* AGP bridge need not be PCI device, but DRM thinks it is. */
47static struct pci_dev fake_bridge_dev;
48
49static int hp_zx1_gart_found;
50
51static struct aper_size_info_fixed hp_zx1_sizes[] =
52{
53	{0, 0, 0},		/* filled in by hp_zx1_fetch_size() */
54};
55
56static struct gatt_mask hp_zx1_masks[] =
57{
58	{.mask = HP_ZX1_PDIR_VALID_BIT, .type = 0}
59};
60
61static struct _hp_private {
62	volatile u8 __iomem *ioc_regs;
63	volatile u8 __iomem *lba_regs;
64	int lba_cap_offset;
65	u64 *io_pdir;		// PDIR for entire IOVA
66	u64 *gatt;		// PDIR just for GART (subset of above)
67	u64 gatt_entries;
68	u64 iova_base;
69	u64 gart_base;
70	u64 gart_size;
71	u64 io_pdir_size;
72	int io_pdir_owner;	// do we own it, or share it with sba_iommu?
73	int io_page_size;
74	int io_tlb_shift;
75	int io_tlb_ps;		// IOC ps config
76	int io_pages_per_kpage;
77} hp_private;
78
79static int __init hp_zx1_ioc_shared(void)
80{
81	struct _hp_private *hp = &hp_private;
82
83	printk(KERN_INFO PFX "HP ZX1 IOC: IOPDIR shared with sba_iommu\n");
84
85	/*
86	 * IOC already configured by sba_iommu module; just use
87	 * its setup.  We assume:
88	 * 	- IOVA space is 1Gb in size
89	 * 	- first 512Mb is IOMMU, second 512Mb is GART
90	 */
91	hp->io_tlb_ps = readq(hp->ioc_regs+HP_ZX1_TCNFG);
92	switch (hp->io_tlb_ps) {
93		case 0: hp->io_tlb_shift = 12; break;
94		case 1: hp->io_tlb_shift = 13; break;
95		case 2: hp->io_tlb_shift = 14; break;
96		case 3: hp->io_tlb_shift = 16; break;
97		default:
98			printk(KERN_ERR PFX "Invalid IOTLB page size "
99			       "configuration 0x%x\n", hp->io_tlb_ps);
100			hp->gatt = NULL;
101			hp->gatt_entries = 0;
102			return -ENODEV;
103	}
104	hp->io_page_size = 1 << hp->io_tlb_shift;
105	hp->io_pages_per_kpage = PAGE_SIZE / hp->io_page_size;
106
107	hp->iova_base = readq(hp->ioc_regs+HP_ZX1_IBASE) & ~0x1;
108	hp->gart_base = hp->iova_base + HP_ZX1_IOVA_SIZE - HP_ZX1_GART_SIZE;
109
110	hp->gart_size = HP_ZX1_GART_SIZE;
111	hp->gatt_entries = hp->gart_size / hp->io_page_size;
112
113	hp->io_pdir = gart_to_virt(readq(hp->ioc_regs+HP_ZX1_PDIR_BASE));
114	hp->gatt = &hp->io_pdir[HP_ZX1_IOVA_TO_PDIR(hp->gart_base)];
115
116	if (hp->gatt[0] != HP_ZX1_SBA_IOMMU_COOKIE) {
117		/* Normal case when no AGP device in system */
118	    	hp->gatt = NULL;
119		hp->gatt_entries = 0;
120		printk(KERN_ERR PFX "No reserved IO PDIR entry found; "
121		       "GART disabled\n");
122		return -ENODEV;
123	}
124
125	return 0;
126}
127
128static int __init
129hp_zx1_ioc_owner (void)
130{
131	struct _hp_private *hp = &hp_private;
132
133	printk(KERN_INFO PFX "HP ZX1 IOC: IOPDIR dedicated to GART\n");
134
135	/*
136	 * Select an IOV page size no larger than system page size.
137	 */
138	if (PAGE_SIZE >= KB(64)) {
139		hp->io_tlb_shift = 16;
140		hp->io_tlb_ps = 3;
141	} else if (PAGE_SIZE >= KB(16)) {
142		hp->io_tlb_shift = 14;
143		hp->io_tlb_ps = 2;
144	} else if (PAGE_SIZE >= KB(8)) {
145		hp->io_tlb_shift = 13;
146		hp->io_tlb_ps = 1;
147	} else {
148		hp->io_tlb_shift = 12;
149		hp->io_tlb_ps = 0;
150	}
151	hp->io_page_size = 1 << hp->io_tlb_shift;
152	hp->io_pages_per_kpage = PAGE_SIZE / hp->io_page_size;
153
154	hp->iova_base = HP_ZX1_IOVA_BASE;
155	hp->gart_size = HP_ZX1_GART_SIZE;
156	hp->gart_base = hp->iova_base + HP_ZX1_IOVA_SIZE - hp->gart_size;
157
158	hp->gatt_entries = hp->gart_size / hp->io_page_size;
159	hp->io_pdir_size = (HP_ZX1_IOVA_SIZE / hp->io_page_size) * sizeof(u64);
160
161	return 0;
162}
163
164static int __init
165hp_zx1_ioc_init (u64 hpa)
166{
167	struct _hp_private *hp = &hp_private;
168
169	hp->ioc_regs = ioremap(hpa, 1024);
170	if (!hp->ioc_regs)
171		return -ENOMEM;
172
173	/*
174	 * If the IOTLB is currently disabled, we can take it over.
175	 * Otherwise, we have to share with sba_iommu.
176	 */
177	hp->io_pdir_owner = (readq(hp->ioc_regs+HP_ZX1_IBASE) & 0x1) == 0;
178
179	if (hp->io_pdir_owner)
180		return hp_zx1_ioc_owner();
181
182	return hp_zx1_ioc_shared();
183}
184
185static int
186hp_zx1_lba_find_capability (volatile u8 __iomem *hpa, int cap)
187{
188	u16 status;
189	u8 pos, id;
190	int ttl = 48;
191
192	status = readw(hpa+PCI_STATUS);
193	if (!(status & PCI_STATUS_CAP_LIST))
194		return 0;
195	pos = readb(hpa+PCI_CAPABILITY_LIST);
196	while (ttl-- && pos >= 0x40) {
197		pos &= ~3;
198		id = readb(hpa+pos+PCI_CAP_LIST_ID);
199		if (id == 0xff)
200			break;
201		if (id == cap)
202			return pos;
203		pos = readb(hpa+pos+PCI_CAP_LIST_NEXT);
204	}
205	return 0;
206}
207
208static int __init
209hp_zx1_lba_init (u64 hpa)
210{
211	struct _hp_private *hp = &hp_private;
212	int cap;
213
214	hp->lba_regs = ioremap(hpa, 256);
215	if (!hp->lba_regs)
216		return -ENOMEM;
217
218	hp->lba_cap_offset = hp_zx1_lba_find_capability(hp->lba_regs, PCI_CAP_ID_AGP);
219
220	cap = readl(hp->lba_regs+hp->lba_cap_offset) & 0xff;
221	if (cap != PCI_CAP_ID_AGP) {
222		printk(KERN_ERR PFX "Invalid capability ID 0x%02x at 0x%x\n",
223		       cap, hp->lba_cap_offset);
224		return -ENODEV;
225	}
226
227	return 0;
228}
229
230static int
231hp_zx1_fetch_size(void)
232{
233	int size;
234
235	size = hp_private.gart_size / MB(1);
236	hp_zx1_sizes[0].size = size;
237	agp_bridge->current_size = (void *) &hp_zx1_sizes[0];
238	return size;
239}
240
241static int
242hp_zx1_configure (void)
243{
244	struct _hp_private *hp = &hp_private;
245
246	agp_bridge->gart_bus_addr = hp->gart_base;
247	agp_bridge->capndx = hp->lba_cap_offset;
248	agp_bridge->mode = readl(hp->lba_regs+hp->lba_cap_offset+PCI_AGP_STATUS);
249
250	if (hp->io_pdir_owner) {
251		writel(virt_to_gart(hp->io_pdir), hp->ioc_regs+HP_ZX1_PDIR_BASE);
252		readl(hp->ioc_regs+HP_ZX1_PDIR_BASE);
253		writel(hp->io_tlb_ps, hp->ioc_regs+HP_ZX1_TCNFG);
254		readl(hp->ioc_regs+HP_ZX1_TCNFG);
255		writel((unsigned int)(~(HP_ZX1_IOVA_SIZE-1)), hp->ioc_regs+HP_ZX1_IMASK);
256		readl(hp->ioc_regs+HP_ZX1_IMASK);
257		writel(hp->iova_base|1, hp->ioc_regs+HP_ZX1_IBASE);
258		readl(hp->ioc_regs+HP_ZX1_IBASE);
259		writel(hp->iova_base|log2(HP_ZX1_IOVA_SIZE), hp->ioc_regs+HP_ZX1_PCOM);
260		readl(hp->ioc_regs+HP_ZX1_PCOM);
261	}
262
263	return 0;
264}
265
266static void
267hp_zx1_cleanup (void)
268{
269	struct _hp_private *hp = &hp_private;
270
271	if (hp->ioc_regs) {
272		if (hp->io_pdir_owner) {
273			writeq(0, hp->ioc_regs+HP_ZX1_IBASE);
274			readq(hp->ioc_regs+HP_ZX1_IBASE);
275		}
276		iounmap(hp->ioc_regs);
277	}
278	if (hp->lba_regs)
279		iounmap(hp->lba_regs);
280}
281
282static void
283hp_zx1_tlbflush (struct agp_memory *mem)
284{
285	struct _hp_private *hp = &hp_private;
286
287	writeq(hp->gart_base | log2(hp->gart_size), hp->ioc_regs+HP_ZX1_PCOM);
288	readq(hp->ioc_regs+HP_ZX1_PCOM);
289}
290
291static int
292hp_zx1_create_gatt_table (struct agp_bridge_data *bridge)
293{
294	struct _hp_private *hp = &hp_private;
295	int i;
296
297	if (hp->io_pdir_owner) {
298		hp->io_pdir = (u64 *) __get_free_pages(GFP_KERNEL,
299						get_order(hp->io_pdir_size));
300		if (!hp->io_pdir) {
301			printk(KERN_ERR PFX "Couldn't allocate contiguous "
302				"memory for I/O PDIR\n");
303			hp->gatt = NULL;
304			hp->gatt_entries = 0;
305			return -ENOMEM;
306		}
307		memset(hp->io_pdir, 0, hp->io_pdir_size);
308
309		hp->gatt = &hp->io_pdir[HP_ZX1_IOVA_TO_PDIR(hp->gart_base)];
310	}
311
312	for (i = 0; i < hp->gatt_entries; i++) {
313		hp->gatt[i] = (unsigned long) agp_bridge->scratch_page;
314	}
315
316	return 0;
317}
318
319static int
320hp_zx1_free_gatt_table (struct agp_bridge_data *bridge)
321{
322	struct _hp_private *hp = &hp_private;
323
324	if (hp->io_pdir_owner)
325		free_pages((unsigned long) hp->io_pdir,
326			    get_order(hp->io_pdir_size));
327	else
328		hp->gatt[0] = HP_ZX1_SBA_IOMMU_COOKIE;
329	return 0;
330}
331
332static int
333hp_zx1_insert_memory (struct agp_memory *mem, off_t pg_start, int type)
334{
335	struct _hp_private *hp = &hp_private;
336	int i, k;
337	off_t j, io_pg_start;
338	int io_pg_count;
339
340	if (type != 0 || mem->type != 0) {
341		return -EINVAL;
342	}
343
344	io_pg_start = hp->io_pages_per_kpage * pg_start;
345	io_pg_count = hp->io_pages_per_kpage * mem->page_count;
346	if ((io_pg_start + io_pg_count) > hp->gatt_entries) {
347		return -EINVAL;
348	}
349
350	j = io_pg_start;
351	while (j < (io_pg_start + io_pg_count)) {
352		if (hp->gatt[j]) {
353			return -EBUSY;
354		}
355		j++;
356	}
357
358	if (mem->is_flushed == FALSE) {
359		global_cache_flush();
360		mem->is_flushed = TRUE;
361	}
362
363	for (i = 0, j = io_pg_start; i < mem->page_count; i++) {
364		unsigned long paddr;
365
366		paddr = mem->memory[i];
367		for (k = 0;
368		     k < hp->io_pages_per_kpage;
369		     k++, j++, paddr += hp->io_page_size) {
370			hp->gatt[j] =
371				agp_bridge->driver->mask_memory(agp_bridge,
372					paddr, type);
373		}
374	}
375
376	agp_bridge->driver->tlb_flush(mem);
377	return 0;
378}
379
380static int
381hp_zx1_remove_memory (struct agp_memory *mem, off_t pg_start, int type)
382{
383	struct _hp_private *hp = &hp_private;
384	int i, io_pg_start, io_pg_count;
385
386	if (type != 0 || mem->type != 0) {
387		return -EINVAL;
388	}
389
390	io_pg_start = hp->io_pages_per_kpage * pg_start;
391	io_pg_count = hp->io_pages_per_kpage * mem->page_count;
392	for (i = io_pg_start; i < io_pg_count + io_pg_start; i++) {
393		hp->gatt[i] = agp_bridge->scratch_page;
394	}
395
396	agp_bridge->driver->tlb_flush(mem);
397	return 0;
398}
399
400static unsigned long
401hp_zx1_mask_memory (struct agp_bridge_data *bridge,
402	unsigned long addr, int type)
403{
404	return HP_ZX1_PDIR_VALID_BIT | addr;
405}
406
407static void
408hp_zx1_enable (struct agp_bridge_data *bridge, u32 mode)
409{
410	struct _hp_private *hp = &hp_private;
411	u32 command;
412
413	command = readl(hp->lba_regs+hp->lba_cap_offset+PCI_AGP_STATUS);
414	command = agp_collect_device_status(bridge, mode, command);
415	command |= 0x00000100;
416
417	writel(command, hp->lba_regs+hp->lba_cap_offset+PCI_AGP_COMMAND);
418
419	agp_device_command(command, (mode & AGP8X_MODE) != 0);
420}
421
422struct agp_bridge_driver hp_zx1_driver = {
423	.owner			= THIS_MODULE,
424	.size_type		= FIXED_APER_SIZE,
425	.configure		= hp_zx1_configure,
426	.fetch_size		= hp_zx1_fetch_size,
427	.cleanup		= hp_zx1_cleanup,
428	.tlb_flush		= hp_zx1_tlbflush,
429	.mask_memory		= hp_zx1_mask_memory,
430	.masks			= hp_zx1_masks,
431	.agp_enable		= hp_zx1_enable,
432	.cache_flush		= global_cache_flush,
433	.create_gatt_table	= hp_zx1_create_gatt_table,
434	.free_gatt_table	= hp_zx1_free_gatt_table,
435	.insert_memory		= hp_zx1_insert_memory,
436	.remove_memory		= hp_zx1_remove_memory,
437	.alloc_by_type		= agp_generic_alloc_by_type,
438	.free_by_type		= agp_generic_free_by_type,
439	.agp_alloc_page		= agp_generic_alloc_page,
440	.agp_destroy_page	= agp_generic_destroy_page,
441	.cant_use_aperture	= 1,
442};
443
444static int __init
445hp_zx1_setup (u64 ioc_hpa, u64 lba_hpa)
446{
447	struct agp_bridge_data *bridge;
448	int error = 0;
449
450	error = hp_zx1_ioc_init(ioc_hpa);
451	if (error)
452		goto fail;
453
454	error = hp_zx1_lba_init(lba_hpa);
455	if (error)
456		goto fail;
457
458	bridge = agp_alloc_bridge();
459	if (!bridge) {
460		error = -ENOMEM;
461		goto fail;
462	}
463	bridge->driver = &hp_zx1_driver;
464
465	fake_bridge_dev.vendor = PCI_VENDOR_ID_HP;
466	fake_bridge_dev.device = PCI_DEVICE_ID_HP_PCIX_LBA;
467	bridge->dev = &fake_bridge_dev;
468
469	error = agp_add_bridge(bridge);
470  fail:
471	if (error)
472		hp_zx1_cleanup();
473	return error;
474}
475
476static acpi_status __init
477zx1_gart_probe (acpi_handle obj, u32 depth, void *context, void **ret)
478{
479	acpi_handle handle, parent;
480	acpi_status status;
481	struct acpi_buffer buffer;
482	struct acpi_device_info *info;
483	u64 lba_hpa, sba_hpa, length;
484	int match;
485
486	status = hp_acpi_csr_space(obj, &lba_hpa, &length);
487	if (ACPI_FAILURE(status))
488		return AE_OK; /* keep looking for another bridge */
489
490	/* Look for an enclosing IOC scope and find its CSR space */
491	handle = obj;
492	do {
493		buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
494		status = acpi_get_object_info(handle, &buffer);
495		if (ACPI_SUCCESS(status)) {
496			/* TBD check _CID also */
497			info = buffer.pointer;
498			info->hardware_id.value[sizeof(info->hardware_id)-1] = '\0';
499			match = (strcmp(info->hardware_id.value, "HWP0001") == 0);
500			ACPI_MEM_FREE(info);
501			if (match) {
502				status = hp_acpi_csr_space(handle, &sba_hpa, &length);
503				if (ACPI_SUCCESS(status))
504					break;
505				else {
506					printk(KERN_ERR PFX "Detected HP ZX1 "
507					       "AGP LBA but no IOC.\n");
508					return AE_OK;
509				}
510			}
511		}
512
513		status = acpi_get_parent(handle, &parent);
514		handle = parent;
515	} while (ACPI_SUCCESS(status));
516
517	if (hp_zx1_setup(sba_hpa + HP_ZX1_IOC_OFFSET, lba_hpa))
518		return AE_OK;
519
520	printk(KERN_INFO PFX "Detected HP ZX1 %s AGP chipset (ioc=%lx, lba=%lx)\n",
521		(char *) context, sba_hpa + HP_ZX1_IOC_OFFSET, lba_hpa);
522
523	hp_zx1_gart_found = 1;
524	return AE_CTRL_TERMINATE; /* we only support one bridge; quit looking */
525}
526
527static int __init
528agp_hp_init (void)
529{
530	if (agp_off)
531		return -EINVAL;
532
533	acpi_get_devices("HWP0003", zx1_gart_probe, "HWP0003", NULL);
534	if (hp_zx1_gart_found)
535		return 0;
536
537	acpi_get_devices("HWP0007", zx1_gart_probe, "HWP0007", NULL);
538	if (hp_zx1_gart_found)
539		return 0;
540
541	return -ENODEV;
542}
543
544static void __exit
545agp_hp_cleanup (void)
546{
547}
548
549module_init(agp_hp_init);
550module_exit(agp_hp_cleanup);
551
552MODULE_LICENSE("GPL and additional rights");
553