embox

Форк
0
/
etnaviv_iommu_v2.c 
137 строк · 3.8 Кб
1
/*
2
 * Copyright (C) 2016 Etnaviv Project
3
  *
4
 * This program is free software; you can redistribute it and/or modify it
5
 * under the terms of the GNU General Public License version 2 as published by
6
 * the Free Software Foundation.
7
 *
8
 * This program is distributed in the hope that it will be useful, but WITHOUT
9
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
11
 * more details.
12
 *
13
 * You should have received a copy of the GNU General Public License along with
14
 * this program.  If not, see <http://www.gnu.org/licenses/>.
15
 */
16

17
#include <asm-generic/dma-mapping.h>
18

19
#include "etnaviv_compat.h"
20
#include "etnaviv_cmdbuf.h"
21
#include "etnaviv_gpu.h"
22
#include "etnaviv_mmu.h"
23
#include "etnaviv_drv.h"
24
#include "etnaviv_iommu.h"
25

26
#include <etnaviv_xml/state.xml.h>
27
#include <etnaviv_xml/state_hi.xml.h>
28

29
#define MMUv2_PTE_PRESENT		BIT(0)
30
#define MMUv2_PTE_EXCEPTION		BIT(1)
31
#define MMUv2_PTE_WRITEABLE		BIT(2)
32

33
#define MMUv2_MTLB_MASK			0xffc00000
34
#define MMUv2_MTLB_SHIFT		22
35
#define MMUv2_STLB_MASK			0x003ff000
36
#define MMUv2_STLB_SHIFT		12
37

38
#define MMUv2_MAX_STLB_ENTRIES		1024
39

40
static int etnaviv_iommuv2_init(struct etnaviv_gpu *gpu) {
41
	uint32_t *p;
42
	int ret, i, j;
43

44
	struct etnaviv_iommuv2_domain *etnaviv_domain = (void*) gpu->mmu.domain;
45
	/* allocate scratch page */
46
	etnaviv_domain->bad_page_cpu = dma_alloc_coherent(etnaviv_domain->dev,
47
						  SZ_4K,
48
						  &etnaviv_domain->bad_page_dma,
49
						  GFP_KERNEL);
50
	if (!etnaviv_domain->bad_page_cpu) {
51
		ret = -ENOMEM;
52
		goto fail_mem;
53
	}
54
	p = etnaviv_domain->bad_page_cpu;
55
	for (i = 0; i < SZ_4K / 4; i++)
56
		*p++ = 0xdead55aa;
57

58
	etnaviv_domain->mtlb_cpu = dma_alloc_coherent(etnaviv_domain->dev,
59
						  SZ_4K,
60
						  &etnaviv_domain->mtlb_dma,
61
						  GFP_KERNEL);
62
	if (!etnaviv_domain->mtlb_cpu) {
63
		ret = -ENOMEM;
64
		goto fail_mem;
65
	}
66

67
	/* pre-populate STLB pages (may want to switch to on-demand later) */
68
	for (i = 0; i < MMUv2_MAX_STLB_ENTRIES; i++) {
69
		etnaviv_domain->stlb_cpu[i] =
70
				dma_alloc_coherent(etnaviv_domain->dev,
71
						   SZ_4K,
72
						   &etnaviv_domain->stlb_dma[i],
73
						   GFP_KERNEL);
74
		if (!etnaviv_domain->stlb_cpu[i]) {
75
			ret = -ENOMEM;
76
			goto fail_mem;
77
		}
78
		p = etnaviv_domain->stlb_cpu[i];
79
		for (j = 0; j < SZ_4K / 4; j++)
80
			*p++ = MMUv2_PTE_EXCEPTION;
81

82
		etnaviv_domain->mtlb_cpu[i] = etnaviv_domain->stlb_dma[i] |
83
					      MMUv2_PTE_PRESENT;
84
	}
85

86
	return 0;
87

88
fail_mem:
89
	if (etnaviv_domain->bad_page_cpu)
90
		dma_free_coherent(etnaviv_domain->dev, SZ_4K,
91
				  etnaviv_domain->bad_page_cpu,
92
				  etnaviv_domain->bad_page_dma);
93

94
	if (etnaviv_domain->mtlb_cpu)
95
		dma_free_coherent(etnaviv_domain->dev, SZ_4K,
96
				  etnaviv_domain->mtlb_cpu,
97
				  etnaviv_domain->mtlb_dma);
98

99
	for (i = 0; i < MMUv2_MAX_STLB_ENTRIES; i++) {
100
		if (etnaviv_domain->stlb_cpu[i])
101
			dma_free_coherent(etnaviv_domain->dev, SZ_4K,
102
					  etnaviv_domain->stlb_cpu[i],
103
					  etnaviv_domain->stlb_dma[i]);
104
	}
105

106
	return ret;
107
}
108

109
void etnaviv_iommuv2_restore(struct etnaviv_gpu *gpu) {
110
	struct etnaviv_iommuv2_domain *etnaviv_domain = (void *) gpu->mmu.domain;
111
	uint16_t prefetch;
112

113
	/* If the MMU is already enabled the state is still there. */
114
	if (gpu_read(gpu, VIVS_MMUv2_CONTROL) & VIVS_MMUv2_CONTROL_ENABLE)
115
		return;
116

117
	prefetch = etnaviv_buffer_config_mmuv2(gpu,
118
				(uint32_t)etnaviv_domain->mtlb_dma,
119
				(uint32_t)etnaviv_domain->bad_page_dma);
120
	etnaviv_gpu_start_fe(gpu, (uint32_t)etnaviv_cmdbuf_get_pa(gpu->buffer),
121
			     prefetch);
122
	etnaviv_gpu_wait_idle(gpu, 100);
123

124
	gpu_write(gpu, VIVS_MMUv2_CONTROL, VIVS_MMUv2_CONTROL_ENABLE);
125
}
126

127
int etnaviv_iommuv2_domain_init(struct etnaviv_gpu *gpu) {
128
	gpu->mmu.start_addr = 0;
129
	gpu->mmu.end_addr = 4096 - 1;
130

131
	memset(gpu->mmu.domain, 0, sizeof(struct etnaviv_iommuv2_domain));
132
	if (etnaviv_iommuv2_init(gpu)) {
133
		return -1;
134
	}
135

136
	return 0;
137
}
138

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.