blob: 07b9ed1471b7024d4259a9a2bcd84b61176debe5 [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
Daniel Vetterc03c6ce2014-03-22 21:34:29 +010044#include "intel_io.h"
Daniel Vetter71ac5de2014-08-26 15:13:06 +020045#include "igt_core.h"
Daniel Vetter3cd45de2015-02-10 17:46:43 +010046#include "igt_gt.h"
Daniel Vetter6cfcd712014-03-22 20:07:35 +010047#include "intel_chipset.h"
Chris Wilson95374222010-04-08 11:56:57 +010048
Daniel Vetter95e89f02014-03-22 22:41:28 +010049/**
50 * SECTION:intel_io
Damien Lespiau4dca31b2015-06-27 11:16:52 +010051 * @short_description: Register access and sideband I/O library
Damien Lespiau6ebd8c22015-06-26 14:28:41 +010052 * @title: I/O
Thomas Woodf0381d12015-09-07 09:26:01 +010053 * @include: igt.h
Thomas Wood5d808722015-06-29 11:03:39 +010054 * @section_id: intel-gpu-tools-IO
Daniel Vetter95e89f02014-03-22 22:41:28 +010055 *
56 * This library provides register I/O helpers in both a basic version and a more
Thomas Wood519f3772014-09-26 14:24:52 +010057 * fancy version which also handles forcewake and can optionally check registers
Daniel Vetter95e89f02014-03-22 22:41:28 +010058 * against a white-list. All register function are compatible. Hence the same
59 * code can be used to decode registers with either of them, or also from a dump
60 * file using intel_mmio_use_dump_file().
61 *
Thomas Wood519f3772014-09-26 14:24:52 +010062 * Furthermore this library also provides helper functions for accessing the
Daniel Vetter95e89f02014-03-22 22:41:28 +010063 * various sideband interfaces found on Valleyview/Baytrail based platforms.
64 */
65
Ben Widawsky8904d292013-02-21 22:05:33 -080066#define FAKEKEY 0x2468ace0
67
Daniel Vetter95e89f02014-03-22 22:41:28 +010068/**
Jani Nikulaa734ac22015-04-28 13:31:30 +030069 * igt_global_mmio:
Daniel Vetter95e89f02014-03-22 22:41:28 +010070 *
Jani Nikulaa734ac22015-04-28 13:31:30 +030071 * Pointer to the register range, initialized using intel_register_access_init()
72 * or intel_mmio_use_dump_file(). It is not recommended to use this directly.
Daniel Vetter95e89f02014-03-22 22:41:28 +010073 */
Jani Nikulaa734ac22015-04-28 13:31:30 +030074void *igt_global_mmio;
Chris Wilson95374222010-04-08 11:56:57 +010075
Ben Widawskycac8f8b2011-07-28 13:40:19 -070076static struct _mmio_data {
77 int inited;
78 bool safe;
Ben Widawskycac8f8b2011-07-28 13:40:19 -070079 uint32_t i915_devid;
Ben Widawskyabd70382011-07-28 13:42:45 -070080 struct intel_register_map map;
Ben Widawskycac8f8b2011-07-28 13:40:19 -070081 int key;
82} mmio_data;
83
Daniel Vetter95e89f02014-03-22 22:41:28 +010084/**
85 * intel_mmio_use_dump_file:
86 * @file: name of the register dump file to open
87 *
Jani Nikulaa734ac22015-04-28 13:31:30 +030088 * Sets up #igt_global_mmio to point at the data contained in @file. This allows
89 * the same code to get reused for dumping and decoding from running hardware as
90 * from register dumps.
Daniel Vetter95e89f02014-03-22 22:41:28 +010091 */
Chris Wilson95374222010-04-08 11:56:57 +010092void
Daniel Vetter2d4656f2014-03-22 22:23:04 +010093intel_mmio_use_dump_file(char *file)
Chris Wilson95374222010-04-08 11:56:57 +010094{
95 int fd;
96 struct stat st;
97
98 fd = open(file, O_RDWR);
Daniel Vetter71ac5de2014-08-26 15:13:06 +020099 igt_fail_on_f(fd == -1,
100 "Couldn't open %s\n", file);
101
Chris Wilson95374222010-04-08 11:56:57 +0100102 fstat(fd, &st);
Jani Nikulaa734ac22015-04-28 13:31:30 +0300103 igt_global_mmio = mmap(NULL, st.st_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
104 igt_fail_on_f(igt_global_mmio == MAP_FAILED,
Daniel Vetter71ac5de2014-08-26 15:13:06 +0200105 "Couldn't mmap %s\n", file);
Chris Wilson95374222010-04-08 11:56:57 +0100106 close(fd);
107}
108
Daniel Vetter95e89f02014-03-22 22:41:28 +0100109/**
110 * intel_mmio_use_pci_bar:
111 * @pci_dev: intel gracphis pci device
112 *
Jani Nikulaa734ac22015-04-28 13:31:30 +0300113 * Sets up #igt_global_mmio to point at the mmio bar.
Daniel Vetter95e89f02014-03-22 22:41:28 +0100114 *
115 * @pci_dev can be obtained from intel_get_pci_device().
116 */
Chris Wilson95374222010-04-08 11:56:57 +0100117void
Daniel Vetter2d4656f2014-03-22 22:23:04 +0100118intel_mmio_use_pci_bar(struct pci_device *pci_dev)
Chris Wilson95374222010-04-08 11:56:57 +0100119{
Chris Wilson7a02aa42012-08-26 21:22:15 +0100120 uint32_t devid, gen;
121 int mmio_bar, mmio_size;
Daniel Vetter1be3fd72012-01-09 23:42:19 +0100122 int error;
Chris Wilson95374222010-04-08 11:56:57 +0100123
124 devid = pci_dev->device_id;
Chris Wilson41570d92011-02-14 15:56:14 +0000125 if (IS_GEN2(devid))
Chris Wilson95374222010-04-08 11:56:57 +0100126 mmio_bar = 1;
Chris Wilson41570d92011-02-14 15:56:14 +0000127 else
128 mmio_bar = 0;
Chris Wilson95374222010-04-08 11:56:57 +0100129
Chris Wilson7a02aa42012-08-26 21:22:15 +0100130 gen = intel_gen(devid);
131 if (gen < 3)
Daniel Vetter50d46752012-10-12 10:45:52 +0200132 mmio_size = 512*1024;
Chris Wilson7a02aa42012-08-26 21:22:15 +0100133 else if (gen < 5)
134 mmio_size = 512*1024;
135 else
136 mmio_size = 2*1024*1024;
137
Daniel Vetter1be3fd72012-01-09 23:42:19 +0100138 error = pci_device_map_range (pci_dev,
Chris Wilson7a02aa42012-08-26 21:22:15 +0100139 pci_dev->regions[mmio_bar].base_addr,
140 mmio_size,
141 PCI_DEV_MAP_FLAG_WRITABLE,
Jani Nikulaa734ac22015-04-28 13:31:30 +0300142 &igt_global_mmio);
Chris Wilson95374222010-04-08 11:56:57 +0100143
Daniel Vetter71ac5de2014-08-26 15:13:06 +0200144 igt_fail_on_f(error != 0,
145 "Couldn't map MMIO region\n");
Chris Wilson95374222010-04-08 11:56:57 +0100146}
147
Ben Widawskycac8f8b2011-07-28 13:40:19 -0700148static void
149release_forcewake_lock(int fd)
150{
151 close(fd);
152}
153
Daniel Vetter95e89f02014-03-22 22:41:28 +0100154/**
155 * intel_register_access_init:
Thomas Woodd01ebbd2015-06-29 16:47:14 +0100156 * @pci_dev: intel graphics pci device
Ben Widawskycac8f8b2011-07-28 13:40:19 -0700157 * @safe: use safe register access tables
Daniel Vetter95e89f02014-03-22 22:41:28 +0100158 *
159 * This initializes the new register access library, which supports forcewake
160 * handling and also allows register access to be checked with an explicit
161 * whitelist.
162 *
Jani Nikulaa734ac22015-04-28 13:31:30 +0300163 * It also initializes #igt_global_mmio like intel_mmio_use_pci_bar().
Daniel Vetter95e89f02014-03-22 22:41:28 +0100164 *
165 * @pci_dev can be obtained from intel_get_pci_device().
Ben Widawskycac8f8b2011-07-28 13:40:19 -0700166 */
167int
Chris Wilson83884e92017-03-21 17:16:03 +0000168intel_register_access_init(struct pci_device *pci_dev, int safe, int fd)
Ben Widawskycac8f8b2011-07-28 13:40:19 -0700169{
170 int ret;
171
172 /* after old API is deprecated, remove this */
Jani Nikulaa734ac22015-04-28 13:31:30 +0300173 if (igt_global_mmio == NULL)
Daniel Vetter2d4656f2014-03-22 22:23:04 +0100174 intel_mmio_use_pci_bar(pci_dev);
Ben Widawskycac8f8b2011-07-28 13:40:19 -0700175
Jani Nikulaa734ac22015-04-28 13:31:30 +0300176 igt_assert(igt_global_mmio != NULL);
Ben Widawskycac8f8b2011-07-28 13:40:19 -0700177
178 if (mmio_data.inited)
179 return -1;
180
Ben Widawskya8554892013-07-27 15:30:41 -0700181 mmio_data.safe = (safe != 0 &&
182 intel_gen(pci_dev->device_id) >= 4) ? true : false;
Ben Widawsky4c205252012-01-25 21:04:16 -0800183 mmio_data.i915_devid = pci_dev->device_id;
Ben Widawsky57bc7632013-05-23 11:09:55 -0700184 if (mmio_data.safe)
Ben Widawsky4c205252012-01-25 21:04:16 -0800185 mmio_data.map = intel_get_register_map(mmio_data.i915_devid);
186
Ben Widawsky57bc7632013-05-23 11:09:55 -0700187 /* Find where the forcewake lock is. Forcewake doesn't exist
188 * gen < 6, but the debugfs should do the right things for us.
189 */
Chris Wilson83884e92017-03-21 17:16:03 +0000190 ret = igt_open_forcewake_handle(fd);
Daniel Vetterea18fc12014-03-14 16:00:22 +0100191 if (ret == -1)
Ben Widawsky8904d292013-02-21 22:05:33 -0800192 mmio_data.key = FAKEKEY;
Daniel Vetterea18fc12014-03-14 16:00:22 +0100193 else
194 mmio_data.key = ret;
Ben Widawsky4c205252012-01-25 21:04:16 -0800195
Ben Widawskycac8f8b2011-07-28 13:40:19 -0700196 mmio_data.inited++;
197 return 0;
198}
Daniel Vetter95e89f02014-03-22 22:41:28 +0100199
Ben Widawskyc7b6ec52013-04-24 19:05:18 -0700200static int
201intel_register_access_needs_wake(void)
202{
203 return mmio_data.key != FAKEKEY;
204}
Ben Widawskycac8f8b2011-07-28 13:40:19 -0700205
Daniel Vetter95e89f02014-03-22 22:41:28 +0100206/**
207 * intel_register_access_needs_fakewake:
208 *
209 * Returns:
210 * Non-zero when forcewake initialization failed.
211 */
Ben Widawsky8be812b2013-04-26 14:26:48 -0700212int intel_register_access_needs_fakewake(void)
213{
214 return mmio_data.key == FAKEKEY;
215}
216
Daniel Vetter95e89f02014-03-22 22:41:28 +0100217/**
218 * intel_register_access_fini:
219 *
220 * Clean up the register access helper initialized with
221 * intel_register_access_init().
222 */
Ben Widawskycac8f8b2011-07-28 13:40:19 -0700223void
224intel_register_access_fini(void)
225{
Ben Widawskyc7b6ec52013-04-24 19:05:18 -0700226 if (mmio_data.key && intel_register_access_needs_wake())
Ben Widawsky4c205252012-01-25 21:04:16 -0800227 release_forcewake_lock(mmio_data.key);
Ben Widawskycac8f8b2011-07-28 13:40:19 -0700228 mmio_data.inited--;
229}
230
Daniel Vetter95e89f02014-03-22 22:41:28 +0100231/**
232 * intel_register_read:
233 * @reg: register offset
234 *
235 * 32-bit read of the register at @offset. This function only works when the new
236 * register access helper is initialized with intel_register_access_init().
237 *
238 * Compared to INREG() it can do optional checking with the register access
239 * white lists.
240 *
241 * Returns:
242 * The value read from the register.
243 */
Ben Widawskycac8f8b2011-07-28 13:40:19 -0700244uint32_t
245intel_register_read(uint32_t reg)
246{
247 struct intel_register_range *range;
248 uint32_t ret;
249
Daniel Vetter71ac5de2014-08-26 15:13:06 +0200250 igt_assert(mmio_data.inited);
Ben Widawskycac8f8b2011-07-28 13:40:19 -0700251
Daniel Vetter137f4d42012-01-24 09:37:51 +0100252 if (intel_gen(mmio_data.i915_devid) >= 6)
Daniel Vetter71ac5de2014-08-26 15:13:06 +0200253 igt_assert(mmio_data.key != -1);
Ben Widawskyabd70382011-07-28 13:42:45 -0700254
255 if (!mmio_data.safe)
256 goto read_out;
257
258 range = intel_get_register_range(mmio_data.map,
259 reg,
260 INTEL_RANGE_READ);
261
262 if(!range) {
Daniel Vetter71ac5de2014-08-26 15:13:06 +0200263 igt_warn("Register read blocked for safety ""(*0x%08x)\n", reg);
Ben Widawskyabd70382011-07-28 13:42:45 -0700264 ret = 0xffffffff;
265 goto out;
266 }
267
268read_out:
Jani Nikulaa734ac22015-04-28 13:31:30 +0300269 ret = *(volatile uint32_t *)((volatile char *)igt_global_mmio + reg);
Ben Widawskyabd70382011-07-28 13:42:45 -0700270out:
271 return ret;
Ben Widawskycac8f8b2011-07-28 13:40:19 -0700272}
273
Daniel Vetter95e89f02014-03-22 22:41:28 +0100274/**
275 * intel_register_write:
276 * @reg: register offset
277 * @val: value to write
278 *
279 * 32-bit write to the register at @offset. This function only works when the new
280 * register access helper is initialized with intel_register_access_init().
281 *
Daniel Vetteraa720ff2015-05-06 11:38:06 +0200282 * Compared to OUTREG() it can do optional checking with the register access
Daniel Vetter95e89f02014-03-22 22:41:28 +0100283 * white lists.
284 */
Ben Widawskycac8f8b2011-07-28 13:40:19 -0700285void
286intel_register_write(uint32_t reg, uint32_t val)
287{
288 struct intel_register_range *range;
289
Daniel Vetter71ac5de2014-08-26 15:13:06 +0200290 igt_assert(mmio_data.inited);
Ben Widawskycac8f8b2011-07-28 13:40:19 -0700291
Daniel Vetter137f4d42012-01-24 09:37:51 +0100292 if (intel_gen(mmio_data.i915_devid) >= 6)
Daniel Vetter71ac5de2014-08-26 15:13:06 +0200293 igt_assert(mmio_data.key != -1);
Ben Widawskycac8f8b2011-07-28 13:40:19 -0700294
Ben Widawskyabd70382011-07-28 13:42:45 -0700295 if (!mmio_data.safe)
296 goto write_out;
297
298 range = intel_get_register_range(mmio_data.map,
299 reg,
300 INTEL_RANGE_WRITE);
301
Daniel Vetter71ac5de2014-08-26 15:13:06 +0200302 igt_warn_on_f(!range,
303 "Register write blocked for safety ""(*0x%08x = 0x%x)\n", reg, val);
Ben Widawskyabd70382011-07-28 13:42:45 -0700304
305write_out:
Jani Nikulaa734ac22015-04-28 13:31:30 +0300306 *(volatile uint32_t *)((volatile char *)igt_global_mmio + reg) = val;
Ben Widawskycac8f8b2011-07-28 13:40:19 -0700307}
Daniel Vetter95e89f02014-03-22 22:41:28 +0100308
309
310/**
311 * INREG:
312 * @reg: register offset
313 *
Jani Nikula23b7f082015-04-28 11:52:42 +0300314 * 32-bit read of the register at offset @reg. This function only works when the
315 * new register access helper is initialized with intel_register_access_init().
Daniel Vetter95e89f02014-03-22 22:41:28 +0100316 *
Jani Nikulaa734ac22015-04-28 13:31:30 +0300317 * This function directly accesses the #igt_global_mmio without safety checks.
Daniel Vetter95e89f02014-03-22 22:41:28 +0100318 *
319 * Returns:
320 * The value read from the register.
321 */
322uint32_t INREG(uint32_t reg)
323{
Jani Nikulaa734ac22015-04-28 13:31:30 +0300324 return *(volatile uint32_t *)((volatile char *)igt_global_mmio + reg);
Daniel Vetter95e89f02014-03-22 22:41:28 +0100325}
326
327/**
Jani Nikula23b7f082015-04-28 11:52:42 +0300328 * INREG16:
329 * @reg: register offset
330 *
331 * 16-bit read of the register at offset @reg. This function only works when the
332 * new register access helper is initialized with intel_register_access_init().
333 *
Jani Nikulaa734ac22015-04-28 13:31:30 +0300334 * This function directly accesses the #igt_global_mmio without safety checks.
Jani Nikula23b7f082015-04-28 11:52:42 +0300335 *
336 * Returns:
337 * The value read from the register.
338 */
339uint16_t INREG16(uint32_t reg)
340{
Jani Nikulaa734ac22015-04-28 13:31:30 +0300341 return *(volatile uint16_t *)((volatile char *)igt_global_mmio + reg);
Jani Nikula23b7f082015-04-28 11:52:42 +0300342}
343
344/**
345 * INREG8:
346 * @reg: register offset
347 *
348 * 8-bit read of the register at offset @reg. This function only works when the
349 * new register access helper is initialized with intel_register_access_init().
350 *
Jani Nikulaa734ac22015-04-28 13:31:30 +0300351 * This function directly accesses the #igt_global_mmio without safety checks.
Jani Nikula23b7f082015-04-28 11:52:42 +0300352 *
353 * Returns:
354 * The value read from the register.
355 */
356uint8_t INREG8(uint32_t reg)
357{
Jani Nikulaa734ac22015-04-28 13:31:30 +0300358 return *((volatile uint8_t *)igt_global_mmio + reg);
Jani Nikula23b7f082015-04-28 11:52:42 +0300359}
360
361/**
362 * OUTREG:
Daniel Vetter95e89f02014-03-22 22:41:28 +0100363 * @reg: register offset
364 * @val: value to write
365 *
Jani Nikula23b7f082015-04-28 11:52:42 +0300366 * 32-bit write of @val to the register at offset @reg. This function only works
367 * when the new register access helper is initialized with
368 * intel_register_access_init().
Daniel Vetter95e89f02014-03-22 22:41:28 +0100369 *
Jani Nikulaa734ac22015-04-28 13:31:30 +0300370 * This function directly accesses the #igt_global_mmio without safety checks.
Daniel Vetter95e89f02014-03-22 22:41:28 +0100371 */
372void OUTREG(uint32_t reg, uint32_t val)
373{
Jani Nikulaa734ac22015-04-28 13:31:30 +0300374 *(volatile uint32_t *)((volatile char *)igt_global_mmio + reg) = val;
Daniel Vetter95e89f02014-03-22 22:41:28 +0100375}
Jani Nikula23b7f082015-04-28 11:52:42 +0300376
377/**
378 * OUTREG16:
379 * @reg: register offset
380 * @val: value to write
381 *
382 * 16-bit write of @val to the register at offset @reg. This function only works
383 * when the new register access helper is initialized with
384 * intel_register_access_init().
385 *
Jani Nikulaa734ac22015-04-28 13:31:30 +0300386 * This function directly accesses the #igt_global_mmio without safety checks.
Jani Nikula23b7f082015-04-28 11:52:42 +0300387 */
388void OUTREG16(uint32_t reg, uint16_t val)
389{
Jani Nikulaa734ac22015-04-28 13:31:30 +0300390 *(volatile uint16_t *)((volatile char *)igt_global_mmio + reg) = val;
Jani Nikula23b7f082015-04-28 11:52:42 +0300391}
392
393/**
394 * OUTREG8:
395 * @reg: register offset
396 * @val: value to write
397 *
398 * 8-bit write of @val to the register at offset @reg. This function only works
399 * when the new register access helper is initialized with
400 * intel_register_access_init().
401 *
Jani Nikulaa734ac22015-04-28 13:31:30 +0300402 * This function directly accesses the #igt_global_mmio without safety checks.
Jani Nikula23b7f082015-04-28 11:52:42 +0300403 */
404void OUTREG8(uint32_t reg, uint8_t val)
405{
Jani Nikulaa734ac22015-04-28 13:31:30 +0300406 *((volatile uint8_t *)igt_global_mmio + reg) = val;
Jani Nikula23b7f082015-04-28 11:52:42 +0300407}