summaryrefslogtreecommitdiffstats
path: root/sys/mips/nlm/hal/mmu.h
blob: a62072753198742b783a65ede3032d4dd7052b65 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
/*-
 * Copyright 2003-2011 Netlogic Microsystems (Netlogic). All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY Netlogic Microsystems ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 *
 * $FreeBSD$
 * NETLOGIC_BSD */

#ifndef __XLP_MMU_H__
#define __XLP_MMU_H__

#include <mips/nlm/hal/cop0.h>
#include <mips/nlm/hal/mips-extns.h>

#define XLP_MMU_SETUP_REG		0x400
#define XLP_MMU_LFSRSEED_REG		0x401
#define XLP_MMU_HPW_NUM_PAGE_LVL_REG	0x410
#define XLP_MMU_PGWKR_PGDBASE_REG	0x411
#define XLP_MMU_PGWKR_PGDSHFT_REG	0x412
#define XLP_MMU_PGWKR_PGDMASK_REG	0x413
#define XLP_MMU_PGWKR_PUDSHFT_REG	0x414
#define XLP_MMU_PGWKR_PUDMASK_REG	0x415
#define XLP_MMU_PGWKR_PMDSHFT_REG	0x416
#define XLP_MMU_PGWKR_PMDMASK_REG	0x417
#define XLP_MMU_PGWKR_PTESHFT_REG	0x418
#define XLP_MMU_PGWKR_PTEMASK_REG	0x419

typedef struct hw_pagewalker {
	int pgd_present;
	int pud_present;
	int pmd_present;
	int pte_present;
	uint64_t pgd_baseaddr;
	uint32_t pgd_shift;
	uint32_t pgd_mask;
	uint32_t pud_shift;
	uint32_t pud_mask;
	uint32_t pmd_shift;
	uint32_t pmd_mask;
	uint32_t pte_shift;
	uint32_t pte_mask;
} nlm_pagewalker;

/**
 * On power on reset, XLP comes up with 64 TLBs.
 * Large-variable-tlb's (ELVT) and extended TLB is disabled.
 * Enabling large-variable-tlb's sets up the standard
 * TLB size from 64 to 128 TLBs.
 * Enabling fixed TLB (EFT) sets up an additional 2048 tlbs.
 * ELVT + EFT = 128 + 2048 = 2176 TLB entries.
 * threads  64-entry-standard-tlb    128-entry-standard-tlb
 * per      std-tlb-only| std+EFT  | std-tlb-only| std+EFT
 * core                 |          |             |
 * --------------------------------------------------------
 * 1         64           64+2048     128          128+2048
 * 2         64           64+1024      64           64+1024
 * 4         32           32+512       32           32+512
 *
 * 1(G)      64           64+2048     128          128+2048
 * 2(G)      128         128+2048     128          128+2048
 * 4(G)      128         128+2048     128          128+2048
 * (G) = Global mode
 */


/* en = 1 to enable
 * en = 0 to disable
 */
static __inline__ void nlm_large_variable_tlb_en (int en)
{
	unsigned int val;

	val = nlm_read_c0_config6();
	val |= (en << 5);
	nlm_write_c0_config6(val);
	return;
}

/* en = 1 to enable
 * en = 0 to disable
 */
static __inline__ void nlm_pagewalker_en (int en)
{
	unsigned int val;

	val = nlm_read_c0_config6();
	val |= (en << 3);
	nlm_write_c0_config6(val);
	return;
}

/* en = 1 to enable
 * en = 0 to disable
 */
static __inline__ void nlm_extended_tlb_en (int en)
{
	unsigned int val;

	val = nlm_read_c0_config6();
	val |= (en << 2);
	nlm_write_c0_config6(val);
	return;
}

static __inline__ int nlm_get_num_combined_tlbs(void)
{
	return (((nlm_read_c0_config6() >> 16) & 0xffff) + 1);
}

/* get number of variable TLB entries */
static __inline__ int nlm_get_num_vtlbs(void)
{
	return (((nlm_read_c0_config6() >> 6) & 0x3ff) + 1);
}

static __inline__ void nlm_setup_extended_pagemask (int mask)
{
	nlm_write_c0_config7(mask);
}

/* hashindex_en = 1 to enable hash mode, hashindex_en=0 to disable
 * global_mode = 1 to enable global mode, global_mode=0 to disable
 * clk_gating = 0 to enable clock gating, clk_gating=1 to disable
 */
static __inline__ void nlm_mmu_setup(int hashindex_en, int global_mode,
		int clk_gating)
{
	/*uint32_t mmusetup = nlm_mfcr(XLP_MMU_SETUP_REG);*/

	uint32_t mmusetup = 0;
	mmusetup |= (hashindex_en << 13);
	mmusetup |= (clk_gating << 3);
	mmusetup |= (global_mode << 0);
	nlm_mtcr(XLP_MMU_SETUP_REG, mmusetup);
}

static __inline__ void nlm_mmu_lfsr_seed (int thr0_seed, int thr1_seed,
		int thr2_seed, int thr3_seed)
{
	uint32_t seed = nlm_mfcr(XLP_MMU_LFSRSEED_REG);
	seed |= ((thr3_seed & 0x7f) << 23);
	seed |= ((thr2_seed & 0x7f) << 16);
	seed |= ((thr1_seed & 0x7f) << 7);
	seed |= ((thr0_seed & 0x7f) << 0);
	nlm_mtcr(XLP_MMU_LFSRSEED_REG, seed);
}

static __inline__ void nlm_pagewalker_setup (nlm_pagewalker *walker)
{
	uint64_t val;

	if (!walker->pgd_present)
		return;

	val = nlm_mfcr(XLP_MMU_HPW_NUM_PAGE_LVL_REG);

	if (walker->pgd_present)
		val |= (1 << 3);

	if (walker->pud_present)
		val |= (1 << 2);

	if (walker->pmd_present)
		val |= (1 << 1);

	if (walker->pte_present)
		val |= (1 << 0);

	nlm_mtcr(XLP_MMU_HPW_NUM_PAGE_LVL_REG, val);

	nlm_mtcr(XLP_MMU_PGWKR_PGDBASE_REG, walker->pgd_baseaddr);
	nlm_mtcr(XLP_MMU_PGWKR_PGDSHFT_REG, walker->pgd_shift);
	nlm_mtcr(XLP_MMU_PGWKR_PGDMASK_REG, walker->pgd_mask);
	nlm_mtcr(XLP_MMU_PGWKR_PUDSHFT_REG, walker->pud_shift);
	nlm_mtcr(XLP_MMU_PGWKR_PUDMASK_REG, walker->pud_mask);
	nlm_mtcr(XLP_MMU_PGWKR_PMDSHFT_REG, walker->pmd_shift);
	nlm_mtcr(XLP_MMU_PGWKR_PMDMASK_REG, walker->pmd_mask);
	nlm_mtcr(XLP_MMU_PGWKR_PTESHFT_REG, walker->pte_shift);
	nlm_mtcr(XLP_MMU_PGWKR_PTEMASK_REG, walker->pte_mask);
}

#endif
OpenPOWER on IntegriCloud