xref: /openbsd/sys/dev/pci/drm/i915/gt/agp_intel_gtt.c (revision 73471bf0)
1 /*
2  * Copyright (c) 2008-2009 Owain G. Ainsworth <oga@openbsd.org>
3  *
4  * Permission to use, copy, modify, and distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 #include "../i915_drv.h"
18 
19 #include <drm/drm_agpsupport.h>
20 
21 /* MCH IFP BARs */
22 #define I915_IFPADDR	0x60
23 #define I965_IFPADDR	0x70
24 
25 extern struct cfdriver inteldrm_cd;
26 
27 #ifdef __amd64__
28 #define membar_producer_wc()	__asm __volatile("sfence":::"memory")
29 #else
30 #define membar_producer_wc()	__asm __volatile(\
31 				"lock; addl $0,0(%%esp)":::"memory")
32 #endif
33 
34 /*
35  * We're intel IGD, bus 0 function 0 dev 0 should be the GMCH, so it should
36  * be Intel
37  */
38 int
39 inteldrm_gmch_match(struct pci_attach_args *pa)
40 {
41 	if (pa->pa_bus == 0 && pa->pa_device == 0 && pa->pa_function == 0 &&
42 	    PCI_VENDOR(pa->pa_id) == PCI_VENDOR_INTEL &&
43 	    PCI_CLASS(pa->pa_class) == PCI_CLASS_BRIDGE &&
44 	    PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_BRIDGE_HOST)
45 		return (1);
46 	return (0);
47 }
48 
49 void
50 i915_alloc_ifp(struct inteldrm_softc *dev_priv, struct pci_attach_args *bpa)
51 {
52 	bus_addr_t	addr;
53 	u_int32_t	reg;
54 
55 	dev_priv->ifp.i9xx.bst = bpa->pa_memt;
56 
57 	reg = pci_conf_read(bpa->pa_pc, bpa->pa_tag, I915_IFPADDR);
58 	if (reg & 0x1) {
59 		addr = (bus_addr_t)reg;
60 		addr &= ~0x1;
61 		/* XXX extents ... need data on whether bioses alloc or not. */
62 		if (bus_space_map(bpa->pa_memt, addr, PAGE_SIZE, 0,
63 		    &dev_priv->ifp.i9xx.bsh) != 0)
64 			goto nope;
65 		return;
66 	} else if (bpa->pa_memex == NULL ||
67 	    extent_alloc_subregion(bpa->pa_memex, 0x100000, 0xffffffff,
68 	    PAGE_SIZE, PAGE_SIZE, 0, 0, 0, &addr) ||
69 	    bus_space_map(bpa->pa_memt, addr, PAGE_SIZE, 0,
70 	    &dev_priv->ifp.i9xx.bsh))
71 		goto nope;
72 
73 	pci_conf_write(bpa->pa_pc, bpa->pa_tag, I915_IFPADDR, addr | 0x1);
74 
75 	return;
76 
77 nope:
78 	dev_priv->ifp.i9xx.bsh = 0;
79 	printf("%s: no ifp\n", dev_priv->sc_dev.dv_xname);
80 }
81 
82 void
83 i965_alloc_ifp(struct inteldrm_softc *dev_priv, struct pci_attach_args *bpa)
84 {
85 	bus_addr_t	addr;
86 	u_int32_t	lo, hi;
87 
88 	dev_priv->ifp.i9xx.bst = bpa->pa_memt;
89 
90 	hi = pci_conf_read(bpa->pa_pc, bpa->pa_tag, I965_IFPADDR + 4);
91 	lo = pci_conf_read(bpa->pa_pc, bpa->pa_tag, I965_IFPADDR);
92 	if (lo & 0x1) {
93 		addr = (((u_int64_t)hi << 32) | lo);
94 		addr &= ~0x1;
95 		/* XXX extents ... need data on whether bioses alloc or not. */
96 		if (bus_space_map(bpa->pa_memt, addr, PAGE_SIZE, 0,
97 		    &dev_priv->ifp.i9xx.bsh) != 0)
98 			goto nope;
99 		return;
100 	} else if (bpa->pa_memex == NULL ||
101 	    extent_alloc_subregion(bpa->pa_memex, 0x100000, 0xffffffff,
102 	    PAGE_SIZE, PAGE_SIZE, 0, 0, 0, &addr) ||
103 	    bus_space_map(bpa->pa_memt, addr, PAGE_SIZE, 0,
104 	    &dev_priv->ifp.i9xx.bsh))
105 		goto nope;
106 
107 	pci_conf_write(bpa->pa_pc, bpa->pa_tag, I965_IFPADDR + 4,
108 	    upper_32_bits(addr));
109 	pci_conf_write(bpa->pa_pc, bpa->pa_tag, I965_IFPADDR,
110 	    (addr & 0xffffffff) | 0x1);
111 
112 	return;
113 
114 nope:
115 	dev_priv->ifp.i9xx.bsh = 0;
116 	printf("%s: no ifp\n", dev_priv->sc_dev.dv_xname);
117 }
118 
119 void
120 intel_gtt_chipset_setup(struct drm_device *dev)
121 {
122 	struct inteldrm_softc *dev_priv = dev->dev_private;
123 	struct pci_attach_args bpa;
124 
125 	if (INTEL_GEN(dev_priv) >= 6)
126 		return;
127 
128 	if (pci_find_device(&bpa, inteldrm_gmch_match) == 0) {
129 		printf("%s: can't find GMCH\n",
130 		    dev_priv->sc_dev.dv_xname);
131 		return;
132 	}
133 
134 	/* Set up the IFP for chipset flushing */
135 	if (INTEL_GEN(dev_priv) >= 4 || IS_G33(dev_priv)) {
136 		i965_alloc_ifp(dev_priv, &bpa);
137 	} else if (INTEL_GEN(dev_priv) == 3) {
138 		i915_alloc_ifp(dev_priv, &bpa);
139 	} else {
140 		int nsegs;
141 		/*
142 		 * I8XX has no flush page mechanism, we fake it by writing until
143 		 * the cache is empty. allocate a page to scribble on
144 		 */
145 		dev_priv->ifp.i8xx.kva = NULL;
146 		if (bus_dmamem_alloc(dev_priv->dmat, PAGE_SIZE, 0, 0,
147 		    &dev_priv->ifp.i8xx.seg, 1, &nsegs, BUS_DMA_WAITOK) == 0) {
148 			if (bus_dmamem_map(dev_priv->dmat, &dev_priv->ifp.i8xx.seg,
149 			    1, PAGE_SIZE, &dev_priv->ifp.i8xx.kva, 0) != 0) {
150 				bus_dmamem_free(dev_priv->dmat,
151 				    &dev_priv->ifp.i8xx.seg, nsegs);
152 				dev_priv->ifp.i8xx.kva = NULL;
153 			}
154 		}
155 	}
156 }
157 
158 int
159 intel_enable_gtt(void)
160 {
161 	struct inteldrm_softc *dev_priv = (void *)inteldrm_cd.cd_devs[0];
162 
163 	intel_gtt_chipset_setup(&dev_priv->drm);
164 	return 1;
165 }
166 
167 int
168 intel_gmch_probe(struct pci_dev *bridge_dev, struct pci_dev *gpu_pdev,
169     void *bridge)
170 {
171 	return 1;
172 }
173 
174 void
175 intel_gtt_get(u64 *gtt_total,
176     phys_addr_t *mappable_base, resource_size_t *mappable_end)
177 {
178 	struct inteldrm_softc *dev_priv = (void *)inteldrm_cd.cd_devs[0];
179 	struct agp_info *ai = &dev_priv->drm.agp->info;
180 
181 	*gtt_total = ai->ai_aperture_size;
182 	*mappable_base = ai->ai_aperture_base;
183 	*mappable_end = ai->ai_aperture_size;
184 }
185 
186 void
187 intel_gtt_chipset_flush(void)
188 {
189 	struct inteldrm_softc *dev_priv = (void *)inteldrm_cd.cd_devs[0];
190 
191 	/*
192 	 * Write to this flush page flushes the chipset write cache.
193 	 * The write will return when it is done.
194 	 */
195 	if (INTEL_GEN(dev_priv) >= 3) {
196 	    if (dev_priv->ifp.i9xx.bsh != 0)
197 		bus_space_write_4(dev_priv->ifp.i9xx.bst,
198 		    dev_priv->ifp.i9xx.bsh, 0, 1);
199 	} else {
200 		int i;
201 #define I830_HIC        0x70
202 		i915_reg_t hic = _MMIO(I830_HIC);
203 
204 		wbinvd_on_all_cpus();
205 
206 		I915_WRITE(hic, (I915_READ(hic) | (1<<31)));
207 		for (i = 1000; i; i--) {
208 			if (!(I915_READ(hic) & (1<<31)))
209 				break;
210 			delay(100);
211 		}
212 
213 	}
214 }
215 
216 void
217 intel_gmch_remove(void)
218 {
219 }
220 
221 void
222 intel_gtt_insert_sg_entries(struct sg_table *pages, unsigned int pg_start,
223     unsigned int flags)
224 {
225 	struct inteldrm_softc *dev_priv = (void *)inteldrm_cd.cd_devs[0];
226 	struct agp_softc *sc = dev_priv->drm.agp->agpdev;
227 	bus_addr_t addr = sc->sc_apaddr + pg_start * PAGE_SIZE;
228 	struct sg_page_iter sg_iter;
229 
230 	for_each_sg_page(pages->sgl, &sg_iter, pages->nents, 0) {
231 		sc->sc_methods->bind_page(sc->sc_chipc, addr,
232 		    sg_page_iter_dma_address(&sg_iter), flags);
233 		addr += PAGE_SIZE;
234 	}
235 	membar_producer_wc();
236 	intel_gtt_chipset_flush();
237 }
238 
239 void
240 intel_gtt_insert_page(dma_addr_t addr, unsigned int pg,
241     unsigned int flags)
242 {
243 	struct inteldrm_softc *dev_priv = (void *)inteldrm_cd.cd_devs[0];
244 	struct agp_softc *sc = dev_priv->drm.agp->agpdev;
245 	bus_addr_t apaddr = sc->sc_apaddr + (pg * PAGE_SIZE);
246 	sc->sc_methods->bind_page(sc->sc_chipc, apaddr, addr, flags);
247 	intel_gtt_chipset_flush();
248 }
249 
250 void
251 intel_gtt_clear_range(unsigned int first_entry, unsigned int num_entries)
252 {
253 	struct inteldrm_softc *dev_priv = (void *)inteldrm_cd.cd_devs[0];
254 	struct agp_softc *sc = dev_priv->drm.agp->agpdev;
255 	bus_addr_t addr = sc->sc_apaddr + first_entry * PAGE_SIZE;
256 	int i;
257 
258 	for (i = 0; i < num_entries; i++) {
259 		sc->sc_methods->unbind_page(sc->sc_chipc, addr);
260 		addr += PAGE_SIZE;
261 	}
262 	membar_producer_wc();
263 }
264