1/*-
2 * Copyright (c) 2004, 2005 Jung-uk Kim <jkim@FreeBSD.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__KERNEL_RCSID(0, "$NetBSD: agp_amd64.c,v 1.9 2019/11/10 21:16:36 chs Exp $");
29
30#include <sys/param.h>
31#include <sys/systm.h>
32#include <sys/malloc.h>
33#include <sys/kernel.h>
34#include <sys/proc.h>
35#include <sys/conf.h>
36#include <sys/device.h>
37#include <sys/agpio.h>
38
39#include <dev/pci/pcivar.h>
40#include <dev/pci/pcireg.h>
41#include <dev/pci/agpvar.h>
42#include <dev/pci/agpreg.h>
43
44#include <dev/pci/pcidevs.h>
45
46#include <sys/bus.h>
47
48
49#define	AMD64_MAX_MCTRL		8
50
51/* XXX nForce3 requires secondary AGP bridge at 0:11:0. */
52#define AGP_AMD64_NVIDIA_PCITAG(pc)	pci_make_tag(pc, 0, 11, 0)
53/* XXX Some VIA bridge requires secondary AGP bridge at 0:1:0. */
54#define AGP_AMD64_VIA_PCITAG(pc)	pci_make_tag(pc, 0, 1, 0)
55
56
57static uint32_t agp_amd64_get_aperture(struct agp_softc *);
58static int agp_amd64_set_aperture(struct agp_softc *, uint32_t);
59static int agp_amd64_bind_page(struct agp_softc *, off_t, bus_addr_t);
60static int agp_amd64_unbind_page(struct agp_softc *, off_t);
61static void agp_amd64_flush_tlb(struct agp_softc *);
62
63static void agp_amd64_apbase_fixup(struct agp_softc *);
64
65static void agp_amd64_uli_init(struct agp_softc *);
66static int agp_amd64_uli_set_aperture(struct agp_softc *, uint32_t);
67
68static int agp_amd64_nvidia_match(const struct pci_attach_args *, uint16_t);
69static void agp_amd64_nvidia_init(struct agp_softc *);
70static int agp_amd64_nvidia_set_aperture(struct agp_softc *, uint32_t);
71
72static int agp_amd64_via_match(const struct pci_attach_args *);
73static void agp_amd64_via_init(struct agp_softc *);
74static int agp_amd64_via_set_aperture(struct agp_softc *, uint32_t);
75
76
77struct agp_amd64_softc {
78	uint32_t		initial_aperture;
79	struct agp_gatt		*gatt;
80	uint32_t		apbase;
81	pcitag_t		ctrl_tag;	/* use NVIDIA and VIA */
82	pcitag_t		mctrl_tag[AMD64_MAX_MCTRL];
83	int			n_mctrl;
84	int			via_agp;
85};
86
87static struct agp_methods agp_amd64_methods = {
88	agp_amd64_get_aperture,
89	agp_amd64_set_aperture,
90	agp_amd64_bind_page,
91	agp_amd64_unbind_page,
92	agp_amd64_flush_tlb,
93	agp_generic_enable,
94	agp_generic_alloc_memory,
95	agp_generic_free_memory,
96	agp_generic_bind_memory,
97	agp_generic_unbind_memory,
98};
99
100
101int
102agp_amd64_match(const struct pci_attach_args *pa)
103{
104
105	switch (PCI_VENDOR(pa->pa_id)) {
106	case PCI_VENDOR_AMD:
107		switch (PCI_PRODUCT(pa->pa_id)) {
108		case PCI_PRODUCT_AMD_AGP8151_DEV:
109			return 1;
110		}
111		break;
112
113	case PCI_VENDOR_SIS:
114		switch (PCI_PRODUCT(pa->pa_id)) {
115		case PCI_PRODUCT_SIS_755:
116		case PCI_PRODUCT_SIS_760:
117			return 1;
118		}
119		break;
120
121	case PCI_VENDOR_ALI:
122		switch (PCI_PRODUCT(pa->pa_id)) {
123		case PCI_PRODUCT_ALI_M1689:
124			return 1;
125		}
126		break;
127
128	case PCI_VENDOR_NVIDIA:
129		switch (PCI_PRODUCT(pa->pa_id)) {
130		case PCI_PRODUCT_NVIDIA_NFORCE3_PCHB:
131			return agp_amd64_nvidia_match(pa,
132			    PCI_PRODUCT_NVIDIA_NFORCE3_PPB2);
133
134			/* NOTREACHED */
135
136		case PCI_PRODUCT_NVIDIA_NFORCE3_250_PCHB:
137			return agp_amd64_nvidia_match(pa,
138			    PCI_PRODUCT_NVIDIA_NFORCE3_250_AGP);
139
140			/* NOTREACHED */
141		}
142		break;
143
144	case PCI_VENDOR_VIATECH:
145		switch (PCI_PRODUCT(pa->pa_id)) {
146		case PCI_PRODUCT_VIATECH_K8M800_0:
147		case PCI_PRODUCT_VIATECH_K8T890_0:
148		case PCI_PRODUCT_VIATECH_K8HTB_0:
149		case PCI_PRODUCT_VIATECH_K8HTB:
150			return 1;
151		}
152		break;
153	}
154
155	return 0;
156}
157
158static int
159agp_amd64_nvidia_match(const struct pci_attach_args *pa, uint16_t devid)
160{
161	pcitag_t tag;
162	pcireg_t reg;
163
164	tag = AGP_AMD64_NVIDIA_PCITAG(pa->pa_pc);
165
166	reg = pci_conf_read(pa->pa_pc, tag, PCI_CLASS_REG);
167	if (PCI_CLASS(reg) != PCI_CLASS_BRIDGE ||
168	    PCI_SUBCLASS(reg) != PCI_SUBCLASS_BRIDGE_PCI)
169		return 0;
170
171	reg = pci_conf_read(pa->pa_pc, tag, PCI_ID_REG);
172	if (PCI_VENDOR(reg) != PCI_VENDOR_NVIDIA || PCI_PRODUCT(reg) != devid)
173		return 0;
174
175	return 1;
176}
177
178static int
179agp_amd64_via_match(const struct pci_attach_args *pa)
180{
181	pcitag_t tag;
182	pcireg_t reg;
183
184	tag = AGP_AMD64_VIA_PCITAG(pa->pa_pc);
185
186	reg = pci_conf_read(pa->pa_pc, tag, PCI_CLASS_REG);
187	if (PCI_CLASS(reg) != PCI_CLASS_BRIDGE ||
188	    PCI_SUBCLASS(reg) != PCI_SUBCLASS_BRIDGE_PCI)
189		return 0;
190
191	reg = pci_conf_read(pa->pa_pc, tag, PCI_ID_REG);
192	if (PCI_VENDOR(reg) != PCI_VENDOR_VIATECH ||
193	    PCI_PRODUCT(reg) != PCI_PRODUCT_VIATECH_K8HTB_AGP)
194		return 0;
195
196	return 1;
197}
198
199int
200agp_amd64_attach(device_t parent, device_t self, void *aux)
201{
202	struct agp_softc *sc = device_private(self);
203	struct agp_amd64_softc *asc;
204	struct pci_attach_args *pa = aux;
205	struct agp_gatt *gatt;
206	pcitag_t tag;
207	pcireg_t id, attbase, apctrl;
208	int maxdevs, i, n;
209	int error;
210
211	asc = malloc(sizeof(struct agp_amd64_softc), M_AGP, M_WAITOK | M_ZERO);
212
213	if (agp_map_aperture(pa, sc, AGP_APBASE) != 0) {
214		aprint_error(": can't map aperture\n");
215		error = ENXIO;
216		goto fail1;
217	}
218
219	maxdevs = pci_bus_maxdevs(pa->pa_pc, 0);
220	for (i = 0, n = 0; i < maxdevs && n < AMD64_MAX_MCTRL; i++) {
221		tag = pci_make_tag(pa->pa_pc, 0, i, 3);
222		id = pci_conf_read(pa->pa_pc, tag, PCI_ID_REG);
223		if (PCI_VENDOR(id) == PCI_VENDOR_AMD &&
224		    (PCI_PRODUCT(id) == PCI_PRODUCT_AMD_AMD64_MISC ||
225		     PCI_PRODUCT(id) == PCI_PRODUCT_AMD_AMD64_F10_MISC)) {
226			asc->mctrl_tag[n] = tag;
227			n++;
228		}
229	}
230	if (n == 0) {
231		aprint_error(": No Miscellaneous Control unit found.\n");
232		error = ENXIO;
233		goto fail1;
234	}
235	asc->n_mctrl = n;
236
237	aprint_normal(": %d Miscellaneous Control unit(s) found.\n",
238	    asc->n_mctrl);
239	aprint_normal("%s", device_xname(self));
240
241	sc->as_chipc = asc;
242	sc->as_methods = &agp_amd64_methods;
243	pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_AGP, &sc->as_capoff,
244	    NULL);
245	asc->initial_aperture = AGP_GET_APERTURE(sc);
246
247	for (;;) {
248		gatt = agp_alloc_gatt(sc);
249		if (gatt)
250			break;
251
252		/*
253		 * Probably contigmalloc failure. Try reducing the
254		 * aperture so that the gatt size reduces.
255		 */
256		if (AGP_SET_APERTURE(sc, AGP_GET_APERTURE(sc) / 2)) {
257			error = ENOMEM;
258			goto fail1;
259		}
260	}
261	asc->gatt = gatt;
262
263	switch (PCI_VENDOR(sc->as_id)) {
264	case PCI_VENDOR_ALI:
265		agp_amd64_uli_init(sc);
266		if (agp_amd64_uli_set_aperture(sc, asc->initial_aperture)) {
267			/* XXX Back out agp_amd64_uli_init?  */
268			error = ENXIO;
269			goto fail2;
270		}
271		break;
272
273	case PCI_VENDOR_NVIDIA:
274		asc->ctrl_tag = AGP_AMD64_NVIDIA_PCITAG(pa->pa_pc);
275		agp_amd64_nvidia_init(sc);
276		if (agp_amd64_nvidia_set_aperture(sc, asc->initial_aperture)) {
277			/* XXX Back out agp_amd64_nvidia_init?  */
278			error = ENXIO;
279			goto fail2;
280		}
281		break;
282
283	case PCI_VENDOR_VIATECH:
284		asc->via_agp = agp_amd64_via_match(pa);
285		if (asc->via_agp) {
286			asc->ctrl_tag = AGP_AMD64_VIA_PCITAG(pa->pa_pc);
287			agp_amd64_via_init(sc);
288			if (agp_amd64_via_set_aperture(sc,
289			    asc->initial_aperture)) {
290				/* XXX Back out agp_amd64_via_init?  */
291				error = ENXIO;
292				goto fail2;
293			}
294		}
295		break;
296	}
297
298	/* Install the gatt and enable aperture. */
299	attbase = (uint32_t)(gatt->ag_physical >> 8) & AGP_AMD64_ATTBASE_MASK;
300	for (i = 0; i < asc->n_mctrl; i++) {
301		pci_conf_write(pa->pa_pc, asc->mctrl_tag[i], AGP_AMD64_ATTBASE,
302		    attbase);
303		apctrl = pci_conf_read(pa->pa_pc, asc->mctrl_tag[i],
304		    AGP_AMD64_APCTRL);
305		apctrl |= AGP_AMD64_APCTRL_GARTEN;
306		apctrl &=
307		    ~(AGP_AMD64_APCTRL_DISGARTCPU | AGP_AMD64_APCTRL_DISGARTIO);
308		pci_conf_write(pa->pa_pc, asc->mctrl_tag[i], AGP_AMD64_APCTRL,
309		    apctrl);
310	}
311
312	agp_flush_cache();
313
314	/* Success!  */
315	return 0;
316
317fail2:	agp_free_gatt(sc, gatt);
318fail1:	free(asc, M_AGP);
319	agp_generic_detach(sc);
320	KASSERT(error);
321	return error;
322}
323
324
325static uint32_t agp_amd64_table[] = {
326	0x02000000,	/*   32 MB */
327	0x04000000,	/*   64 MB */
328	0x08000000,	/*  128 MB */
329	0x10000000,	/*  256 MB */
330	0x20000000,	/*  512 MB */
331	0x40000000,	/* 1024 MB */
332	0x80000000,	/* 2048 MB */
333};
334
335#define AGP_AMD64_TABLE_SIZE \
336	(sizeof(agp_amd64_table) / sizeof(agp_amd64_table[0]))
337
338static uint32_t
339agp_amd64_get_aperture(struct agp_softc *sc)
340{
341	struct agp_amd64_softc *asc = sc->as_chipc;
342	uint32_t i;
343
344	i = (pci_conf_read(sc->as_pc, asc->mctrl_tag[0], AGP_AMD64_APCTRL) &
345		AGP_AMD64_APCTRL_SIZE_MASK) >> 1;
346
347	if (i >= AGP_AMD64_TABLE_SIZE)
348		return 0;
349
350	return agp_amd64_table[i];
351}
352
353static int
354agp_amd64_set_aperture(struct agp_softc *sc, uint32_t aperture)
355{
356	struct agp_amd64_softc *asc = sc->as_chipc;
357	uint32_t i;
358	pcireg_t apctrl;
359	int j;
360
361	for (i = 0; i < AGP_AMD64_TABLE_SIZE; i++)
362		if (agp_amd64_table[i] == aperture)
363			break;
364	if (i >= AGP_AMD64_TABLE_SIZE)
365		return EINVAL;
366
367	for (j = 0; j < asc->n_mctrl; j++) {
368		apctrl = pci_conf_read(sc->as_pc, asc->mctrl_tag[0],
369		    AGP_AMD64_APCTRL);
370		pci_conf_write(sc->as_pc, asc->mctrl_tag[0], AGP_AMD64_APCTRL,
371		    (apctrl & ~(AGP_AMD64_APCTRL_SIZE_MASK)) | (i << 1));
372	}
373
374	switch (PCI_VENDOR(sc->as_id)) {
375	case PCI_VENDOR_ALI:
376		return agp_amd64_uli_set_aperture(sc, aperture);
377		break;
378
379	case PCI_VENDOR_NVIDIA:
380		return agp_amd64_nvidia_set_aperture(sc, aperture);
381		break;
382
383	case PCI_VENDOR_VIATECH:
384		if (asc->via_agp)
385			return agp_amd64_via_set_aperture(sc, aperture);
386		break;
387	}
388
389	return 0;
390}
391
392static int
393agp_amd64_bind_page(struct agp_softc *sc, off_t offset, bus_addr_t physical)
394{
395	struct agp_amd64_softc *asc = sc->as_chipc;
396
397	if (offset < 0 || offset >= (asc->gatt->ag_entries << AGP_PAGE_SHIFT))
398		return EINVAL;
399
400	asc->gatt->ag_virtual[offset >> AGP_PAGE_SHIFT] =
401	    (physical & 0xfffff000) | ((physical >> 28) & 0x00000ff0) | 3;
402
403	return 0;
404}
405
406static int
407agp_amd64_unbind_page(struct agp_softc *sc, off_t offset)
408{
409	struct agp_amd64_softc *asc = sc->as_chipc;
410
411	if (offset < 0 || offset >= (asc->gatt->ag_entries << AGP_PAGE_SHIFT))
412		return EINVAL;
413
414	asc->gatt->ag_virtual[offset >> AGP_PAGE_SHIFT] = 0;
415
416	return 0;
417}
418
419static void
420agp_amd64_flush_tlb(struct agp_softc *sc)
421{
422	struct agp_amd64_softc *asc = sc->as_chipc;
423	pcireg_t cachectrl;
424	int i;
425
426	for (i = 0; i < asc->n_mctrl; i++) {
427		cachectrl = pci_conf_read(sc->as_pc, asc->mctrl_tag[i],
428		    AGP_AMD64_CACHECTRL);
429		pci_conf_write(sc->as_pc, asc->mctrl_tag[i],
430		    AGP_AMD64_CACHECTRL,
431		    cachectrl | AGP_AMD64_CACHECTRL_INVGART);
432	}
433}
434
435static void
436agp_amd64_apbase_fixup(struct agp_softc *sc)
437{
438	struct agp_amd64_softc *asc = sc->as_chipc;
439	uint32_t apbase;
440	int i;
441
442	apbase = pci_conf_read(sc->as_pc, sc->as_tag, AGP_APBASE);
443	asc->apbase = PCI_MAPREG_MEM_ADDR(apbase);
444	apbase = (asc->apbase >> 25) & AGP_AMD64_APBASE_MASK;
445	for (i = 0; i < asc->n_mctrl; i++)
446		pci_conf_write(sc->as_pc, asc->mctrl_tag[i], AGP_AMD64_APBASE,
447		    apbase);
448}
449
450static void
451agp_amd64_uli_init(struct agp_softc *sc)
452{
453	struct agp_amd64_softc *asc = sc->as_chipc;
454	pcireg_t apbase;
455
456	agp_amd64_apbase_fixup(sc);
457	apbase = pci_conf_read(sc->as_pc, sc->as_tag, AGP_AMD64_ULI_APBASE);
458	pci_conf_write(sc->as_pc, sc->as_tag, AGP_AMD64_ULI_APBASE,
459	    (apbase & 0x0000000f) | asc->apbase);
460	pci_conf_write(sc->as_pc, sc->as_tag, AGP_AMD64_ULI_HTT_FEATURE,
461	    asc->apbase);
462}
463
464static int
465agp_amd64_uli_set_aperture(struct agp_softc *sc, uint32_t aperture)
466{
467	struct agp_amd64_softc *asc = sc->as_chipc;
468
469	switch (aperture) {
470	case 0x02000000:	/*  32 MB */
471	case 0x04000000:	/*  64 MB */
472	case 0x08000000:	/* 128 MB */
473	case 0x10000000:	/* 256 MB */
474		break;
475	default:
476		return EINVAL;
477	}
478
479	pci_conf_write(sc->as_pc, sc->as_tag, AGP_AMD64_ULI_ENU_SCR,
480	    asc->apbase + aperture - 1);
481
482	return 0;
483}
484
485static void
486agp_amd64_nvidia_init(struct agp_softc *sc)
487{
488	struct agp_amd64_softc *asc = sc->as_chipc;
489	pcireg_t apbase;
490
491	agp_amd64_apbase_fixup(sc);
492	apbase =
493	    pci_conf_read(sc->as_pc, sc->as_tag, AGP_AMD64_NVIDIA_0_APBASE);
494	pci_conf_write(sc->as_pc, sc->as_tag, AGP_AMD64_NVIDIA_0_APBASE,
495	    (apbase & 0x0000000f) | asc->apbase);
496	pci_conf_write(sc->as_pc, asc->ctrl_tag, AGP_AMD64_NVIDIA_1_APBASE1,
497	    asc->apbase);
498	pci_conf_write(sc->as_pc, asc->ctrl_tag, AGP_AMD64_NVIDIA_1_APBASE2,
499	    asc->apbase);
500}
501
502static int
503agp_amd64_nvidia_set_aperture(struct agp_softc *sc, uint32_t aperture)
504{
505	struct agp_amd64_softc *asc = sc->as_chipc;
506	uint32_t apsize;
507
508	switch (aperture) {
509	case 0x02000000:	apsize = 0x0f;	break;	/*  32 MB */
510	case 0x04000000:	apsize = 0x0e;	break;	/*  64 MB */
511	case 0x08000000:	apsize = 0x0c;	break;	/* 128 MB */
512	case 0x10000000:	apsize = 0x08;	break;	/* 256 MB */
513	case 0x20000000:	apsize = 0x00;	break;	/* 512 MB */
514	default:
515		return EINVAL;
516	}
517
518	pci_conf_write(sc->as_pc, asc->ctrl_tag, AGP_AMD64_NVIDIA_1_APSIZE,
519	    (pci_conf_read(sc->as_pc, asc->ctrl_tag,
520	    AGP_AMD64_NVIDIA_1_APSIZE) & 0xfffffff0) | apsize);
521	pci_conf_write(sc->as_pc, asc->ctrl_tag, AGP_AMD64_NVIDIA_1_APLIMIT1,
522	    asc->apbase + aperture - 1);
523	pci_conf_write(sc->as_pc, asc->ctrl_tag, AGP_AMD64_NVIDIA_1_APLIMIT2,
524	    asc->apbase + aperture - 1);
525
526	return 0;
527}
528
529static void
530agp_amd64_via_init(struct agp_softc *sc)
531{
532	struct agp_amd64_softc *asc = sc->as_chipc;
533
534	agp_amd64_apbase_fixup(sc);
535	pci_conf_write(sc->as_pc, asc->ctrl_tag, AGP3_VIA_ATTBASE,
536	    asc->gatt->ag_physical);
537	pci_conf_write(sc->as_pc, asc->ctrl_tag, AGP3_VIA_GARTCTRL,
538	    pci_conf_read(sc->as_pc, asc->ctrl_tag, AGP3_VIA_ATTBASE) | 0x180);
539}
540
541static int
542agp_amd64_via_set_aperture(struct agp_softc *sc, uint32_t aperture)
543{
544	struct agp_amd64_softc *asc = sc->as_chipc;
545	uint32_t apsize;
546
547	apsize = ((aperture - 1) >> 20) ^ 0xff;
548	if ((((apsize ^ 0xff) << 20) | ((1 << 20) - 1)) + 1 != aperture)
549		return EINVAL;
550	pci_conf_write(sc->as_pc, asc->ctrl_tag, AGP3_VIA_APSIZE,
551	    (pci_conf_read(sc->as_pc, asc->ctrl_tag, AGP3_VIA_APSIZE) & ~0xff) |
552	    apsize);
553
554	return 0;
555}
556