blob: f9e13f619e89b6582fc6a23441b316772ffde2e6 [file] [log] [blame]
Chris Wilson95374222010-04-08 11:56:57 +01001/*
2 * Copyright © 2008 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 *
23 * Authors:
24 * Eric Anholt <eric@anholt.net>
Ben Widawskycac8f8b2011-07-28 13:40:19 -070025 * Ben Widawsky <ben@bwidawsk.net>
Chris Wilson95374222010-04-08 11:56:57 +010026 *
27 */
28
29#include <unistd.h>
Alan Coopersmith4e3c85f2012-01-06 14:37:20 -080030#include <fcntl.h>
Chris Wilson95374222010-04-08 11:56:57 +010031#include <stdio.h>
Ben Widawskycac8f8b2011-07-28 13:40:19 -070032#include <stdarg.h>
33#include <stdlib.h>
34#include <stdint.h>
35#include <stdbool.h>
Chris Wilson95374222010-04-08 11:56:57 +010036#include <string.h>
37#include <errno.h>
38#include <err.h>
39#include <assert.h>
40#include <sys/ioctl.h>
Chris Wilson95374222010-04-08 11:56:57 +010041#include <sys/stat.h>
42#include <sys/mman.h>
43
44#include "intel_gpu_tools.h"
45
Ben Widawsky8904d292013-02-21 22:05:33 -080046#define FAKEKEY 0x2468ace0
47
Chris Wilson95374222010-04-08 11:56:57 +010048void *mmio;
49
Ben Widawskycac8f8b2011-07-28 13:40:19 -070050static struct _mmio_data {
51 int inited;
52 bool safe;
53 char debugfs_path[FILENAME_MAX];
54 char debugfs_forcewake_path[FILENAME_MAX];
55 uint32_t i915_devid;
Ben Widawskyabd70382011-07-28 13:42:45 -070056 struct intel_register_map map;
Ben Widawskycac8f8b2011-07-28 13:40:19 -070057 int key;
58} mmio_data;
59
Chris Wilson95374222010-04-08 11:56:57 +010060void
61intel_map_file(char *file)
62{
63 int fd;
64 struct stat st;
65
66 fd = open(file, O_RDWR);
67 if (fd == -1) {
68 fprintf(stderr, "Couldn't open %s: %s\n", file,
69 strerror(errno));
70 exit(1);
71 }
72 fstat(fd, &st);
73 mmio = mmap(NULL, st.st_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
74 if (mmio == MAP_FAILED) {
75 fprintf(stderr, "Couldn't mmap %s: %s\n", file,
76 strerror(errno));
77 exit(1);
78 }
79 close(fd);
80}
81
82void
83intel_get_mmio(struct pci_device *pci_dev)
84{
Chris Wilson7a02aa42012-08-26 21:22:15 +010085 uint32_t devid, gen;
86 int mmio_bar, mmio_size;
Daniel Vetter1be3fd72012-01-09 23:42:19 +010087 int error;
Chris Wilson95374222010-04-08 11:56:57 +010088
89 devid = pci_dev->device_id;
Chris Wilson41570d92011-02-14 15:56:14 +000090 if (IS_GEN2(devid))
Chris Wilson95374222010-04-08 11:56:57 +010091 mmio_bar = 1;
Chris Wilson41570d92011-02-14 15:56:14 +000092 else
93 mmio_bar = 0;
Chris Wilson95374222010-04-08 11:56:57 +010094
Chris Wilson7a02aa42012-08-26 21:22:15 +010095 gen = intel_gen(devid);
96 if (gen < 3)
Daniel Vetter50d46752012-10-12 10:45:52 +020097 mmio_size = 512*1024;
Chris Wilson7a02aa42012-08-26 21:22:15 +010098 else if (gen < 5)
99 mmio_size = 512*1024;
100 else
101 mmio_size = 2*1024*1024;
102
Daniel Vetter1be3fd72012-01-09 23:42:19 +0100103 error = pci_device_map_range (pci_dev,
Chris Wilson7a02aa42012-08-26 21:22:15 +0100104 pci_dev->regions[mmio_bar].base_addr,
105 mmio_size,
106 PCI_DEV_MAP_FLAG_WRITABLE,
107 &mmio);
Chris Wilson95374222010-04-08 11:56:57 +0100108
Daniel Vetter1be3fd72012-01-09 23:42:19 +0100109 if (error != 0) {
Chris Wilson95374222010-04-08 11:56:57 +0100110 fprintf(stderr, "Couldn't map MMIO region: %s\n",
Daniel Vetter1be3fd72012-01-09 23:42:19 +0100111 strerror(error));
Chris Wilson95374222010-04-08 11:56:57 +0100112 exit(1);
113 }
114}
115
Ben Widawskycac8f8b2011-07-28 13:40:19 -0700116/*
117 * If successful, i915_debugfs_path and i915_debugfs_forcewake_path are both
118 * updated with the correct path.
119 */
120static int
Daniel Vetter1be3fd72012-01-09 23:42:19 +0100121find_debugfs_path(const char *dri_base)
Ben Widawskycac8f8b2011-07-28 13:40:19 -0700122{
123 char buf[FILENAME_MAX];
124 struct stat sb;
125 int i, ret;
126
127 for (i = 0; i < 16; i++) {
128 snprintf(buf, FILENAME_MAX, "%s/%i/name", dri_base, i);
129
130 snprintf(mmio_data.debugfs_path, FILENAME_MAX,
131 "%s/%i/", dri_base, i);
132 snprintf(mmio_data.debugfs_forcewake_path, FILENAME_MAX,
133 "%s/%i/i915_forcewake_user", dri_base, i);
134
135 ret = stat(mmio_data.debugfs_forcewake_path, &sb);
136 if (ret) {
137 mmio_data.debugfs_path[0] = 0;
138 mmio_data.debugfs_forcewake_path[0] = 0;
139 } else
140 return 0;
141 }
142
143 return -1;
144}
145
146static int
147get_forcewake_lock(void)
148{
149 return open(mmio_data.debugfs_forcewake_path, 0);
150}
151
152static void
153release_forcewake_lock(int fd)
154{
155 close(fd);
156}
157
Ben Widawsky8904d292013-02-21 22:05:33 -0800158/* Dumb check to see if i915 was loaded */
159static bool
160i915_loaded(void)
161{
162 struct stat sb;
163 int ret;
164
165 ret = stat("/sys/module/i915/", &sb);
166 if (ret) {
167 return false;
168 }
169
170 assert(S_ISDIR(sb.st_mode));
171 return true;
172}
173
Ben Widawskycac8f8b2011-07-28 13:40:19 -0700174/*
175 * Initialize register access library.
176 *
177 * @pci_dev: pci device we're mucking with
178 * @safe: use safe register access tables
179 */
180int
Ben Widawskyabd70382011-07-28 13:42:45 -0700181intel_register_access_init(struct pci_device *pci_dev, int safe)
Ben Widawskycac8f8b2011-07-28 13:40:19 -0700182{
183 int ret;
184
185 /* after old API is deprecated, remove this */
186 if (mmio == NULL)
187 intel_get_mmio(pci_dev);
188
189 assert(mmio != NULL);
190
191 if (mmio_data.inited)
192 return -1;
193
Daniel Vetter16e44f52013-04-03 00:22:41 +0200194 if (intel_gen(pci_dev->device_id) >= 6)
195 goto done;
196
Ben Widawskyabd70382011-07-28 13:42:45 -0700197 mmio_data.safe = safe != 0 ? true : false;
Ben Widawsky4c205252012-01-25 21:04:16 -0800198 mmio_data.i915_devid = pci_dev->device_id;
Daniel Vetter16e44f52013-04-03 00:22:41 +0200199 if (mmio_data.safe && intel_gen(pci_dev->device_id) >= 4)
Ben Widawsky4c205252012-01-25 21:04:16 -0800200 mmio_data.map = intel_get_register_map(mmio_data.i915_devid);
201
Daniel Vetter16e44f52013-04-03 00:22:41 +0200202 if (intel_gen(pci_dev->device_id) >= 6)
Ben Widawsky4c205252012-01-25 21:04:16 -0800203 goto done;
Ben Widawskyabd70382011-07-28 13:42:45 -0700204
Ben Widawskycac8f8b2011-07-28 13:40:19 -0700205 /* Find where the forcewake lock is */
206 ret = find_debugfs_path("/sys/kernel/debug/dri");
207 if (ret) {
208 ret = find_debugfs_path("/debug/dri");
209 if (ret) {
210 fprintf(stderr, "Couldn't find path to dri/debugfs entry\n");
Ben Widawsky8904d292013-02-21 22:05:33 -0800211 if (i915_loaded()) {
212 fprintf(stderr, "i915 loaded; not proceeding.\n");
213 return ret;
214 }
Ben Widawskycac8f8b2011-07-28 13:40:19 -0700215 }
Ben Widawsky8904d292013-02-21 22:05:33 -0800216 mmio_data.key = FAKEKEY;
217 } else
218 mmio_data.key = get_forcewake_lock();
Ben Widawsky4c205252012-01-25 21:04:16 -0800219
220done:
Ben Widawskycac8f8b2011-07-28 13:40:19 -0700221 mmio_data.inited++;
222 return 0;
223}
Ben Widawskyc7b6ec52013-04-24 19:05:18 -0700224static int
225intel_register_access_needs_wake(void)
226{
227 return mmio_data.key != FAKEKEY;
228}
Ben Widawskycac8f8b2011-07-28 13:40:19 -0700229
230void
231intel_register_access_fini(void)
232{
Ben Widawskyc7b6ec52013-04-24 19:05:18 -0700233 if (mmio_data.key && intel_register_access_needs_wake())
Ben Widawsky4c205252012-01-25 21:04:16 -0800234 release_forcewake_lock(mmio_data.key);
Ben Widawskycac8f8b2011-07-28 13:40:19 -0700235 mmio_data.inited--;
236}
237
238uint32_t
239intel_register_read(uint32_t reg)
240{
241 struct intel_register_range *range;
242 uint32_t ret;
243
244 assert(mmio_data.inited);
245
Daniel Vetter137f4d42012-01-24 09:37:51 +0100246 if (intel_gen(mmio_data.i915_devid) >= 6)
Ben Widawskycac8f8b2011-07-28 13:40:19 -0700247 assert(mmio_data.key != -1);
Ben Widawskyabd70382011-07-28 13:42:45 -0700248
249 if (!mmio_data.safe)
250 goto read_out;
251
252 range = intel_get_register_range(mmio_data.map,
253 reg,
254 INTEL_RANGE_READ);
255
256 if(!range) {
257 fprintf(stderr, "Register read blocked for safety "
258 "(*0x%08x)\n", reg);
259 ret = 0xffffffff;
260 goto out;
261 }
262
263read_out:
264 ret = *(volatile uint32_t *)((volatile char *)mmio + reg);
265out:
266 return ret;
Ben Widawskycac8f8b2011-07-28 13:40:19 -0700267}
268
269void
270intel_register_write(uint32_t reg, uint32_t val)
271{
272 struct intel_register_range *range;
273
274 assert(mmio_data.inited);
275
Daniel Vetter137f4d42012-01-24 09:37:51 +0100276 if (intel_gen(mmio_data.i915_devid) >= 6)
Ben Widawskycac8f8b2011-07-28 13:40:19 -0700277 assert(mmio_data.key != -1);
278
Ben Widawskyabd70382011-07-28 13:42:45 -0700279 if (!mmio_data.safe)
280 goto write_out;
281
282 range = intel_get_register_range(mmio_data.map,
283 reg,
284 INTEL_RANGE_WRITE);
285
286 if (!range) {
287 fprintf(stderr, "Register write blocked for safety "
288 "(*0x%08x = 0x%x)\n", reg, val);
289 }
290
291write_out:
Ben Widawskycac8f8b2011-07-28 13:40:19 -0700292 *(volatile uint32_t *)((volatile char *)mmio + reg) = val;
293}