• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Set up paging and the MMU.
4  *
5  * Copyright (C) 2000-2003, Axis Communications AB.
6  *
7  * Authors:   Bjorn Wesen <bjornw@axis.com>
8  *            Tobias Anderberg <tobiasa@axis.com>, CRISv32 port.
9  */
10 #include <linux/mmzone.h>
11 #include <linux/init.h>
12 #include <linux/bootmem.h>
13 #include <linux/mm.h>
14 #include <asm/pgtable.h>
15 #include <asm/page.h>
16 #include <asm/types.h>
17 #include <asm/mmu.h>
18 #include <asm/io.h>
19 #include <asm/mmu_context.h>
20 #include <arch/hwregs/asm/mmu_defs_asm.h>
21 #include <arch/hwregs/supp_reg.h>
22 
23 extern void tlb_init(void);
24 
25 /*
26  * The kernel is already mapped with linear mapping at kseg_c so there's no
27  * need to map it with a page table. However, head.S also temporarily mapped it
28  * at kseg_4 thus the ksegs are set up again. Also clear the TLB and do various
29  * other paging stuff.
30  */
cris_mmu_init(void)31 void __init cris_mmu_init(void)
32 {
33 	unsigned long mmu_config;
34 	unsigned long mmu_kbase_hi;
35 	unsigned long mmu_kbase_lo;
36 	unsigned short mmu_page_id;
37 
38 	/*
39 	 * Make sure the current pgd table points to something sane, even if it
40 	 * is most probably not used until the next switch_mm.
41 	 */
42 	per_cpu(current_pgd, smp_processor_id()) = init_mm.pgd;
43 
44 	/* Initialise the TLB. Function found in tlb.c. */
45 	tlb_init();
46 
47 	/*
48 	 * Enable exceptions and initialize the kernel segments.
49 	 * See head.S for differences between ARTPEC-3 and ETRAX FS.
50 	 */
51 	mmu_config = ( REG_STATE(mmu, rw_mm_cfg, we, on)        |
52 		       REG_STATE(mmu, rw_mm_cfg, acc, on)       |
53 		       REG_STATE(mmu, rw_mm_cfg, ex, on)        |
54 		       REG_STATE(mmu, rw_mm_cfg, inv, on)       |
55 #ifdef CONFIG_CRIS_MACH_ARTPEC3
56 		       REG_STATE(mmu, rw_mm_cfg, seg_f, page)   |
57 		       REG_STATE(mmu, rw_mm_cfg, seg_e, page)   |
58 		       REG_STATE(mmu, rw_mm_cfg, seg_d, linear) |
59 #else
60 		       REG_STATE(mmu, rw_mm_cfg, seg_f, linear) |
61 		       REG_STATE(mmu, rw_mm_cfg, seg_e, linear) |
62 		       REG_STATE(mmu, rw_mm_cfg, seg_d, page)   |
63 #endif
64 		       REG_STATE(mmu, rw_mm_cfg, seg_c, linear) |
65 		       REG_STATE(mmu, rw_mm_cfg, seg_b, linear) |
66                        REG_STATE(mmu, rw_mm_cfg, seg_a, page)   |
67 		       REG_STATE(mmu, rw_mm_cfg, seg_9, page)   |
68 		       REG_STATE(mmu, rw_mm_cfg, seg_8, page)   |
69 		       REG_STATE(mmu, rw_mm_cfg, seg_7, page)   |
70 		       REG_STATE(mmu, rw_mm_cfg, seg_6, page)   |
71 		       REG_STATE(mmu, rw_mm_cfg, seg_5, page)   |
72 		       REG_STATE(mmu, rw_mm_cfg, seg_4, page)   |
73 		       REG_STATE(mmu, rw_mm_cfg, seg_3, page)   |
74 		       REG_STATE(mmu, rw_mm_cfg, seg_2, page)   |
75 		       REG_STATE(mmu, rw_mm_cfg, seg_1, page)   |
76 		       REG_STATE(mmu, rw_mm_cfg, seg_0, page));
77 
78 	/* See head.S for differences between ARTPEC-3 and ETRAX FS. */
79 	mmu_kbase_hi = ( REG_FIELD(mmu, rw_mm_kbase_hi, base_f, 0x0) |
80 #ifdef CONFIG_CRIS_MACH_ARTPEC3
81 			 REG_FIELD(mmu, rw_mm_kbase_hi, base_e, 0x0) |
82 			 REG_FIELD(mmu, rw_mm_kbase_hi, base_d, 0x5) |
83 #else
84 			 REG_FIELD(mmu, rw_mm_kbase_hi, base_e, 0x8) |
85 			 REG_FIELD(mmu, rw_mm_kbase_hi, base_d, 0x0) |
86 #endif
87                          REG_FIELD(mmu, rw_mm_kbase_hi, base_c, 0x4) |
88 			 REG_FIELD(mmu, rw_mm_kbase_hi, base_b, 0xb) |
89 			 REG_FIELD(mmu, rw_mm_kbase_hi, base_a, 0x0) |
90 			 REG_FIELD(mmu, rw_mm_kbase_hi, base_9, 0x0) |
91 			 REG_FIELD(mmu, rw_mm_kbase_hi, base_8, 0x0));
92 
93 	mmu_kbase_lo = ( REG_FIELD(mmu, rw_mm_kbase_lo, base_7, 0x0) |
94 			 REG_FIELD(mmu, rw_mm_kbase_lo, base_6, 0x0) |
95 			 REG_FIELD(mmu, rw_mm_kbase_lo, base_5, 0x0) |
96 			 REG_FIELD(mmu, rw_mm_kbase_lo, base_4, 0x0) |
97 			 REG_FIELD(mmu, rw_mm_kbase_lo, base_3, 0x0) |
98 			 REG_FIELD(mmu, rw_mm_kbase_lo, base_2, 0x0) |
99 			 REG_FIELD(mmu, rw_mm_kbase_lo, base_1, 0x0) |
100 			 REG_FIELD(mmu, rw_mm_kbase_lo, base_0, 0x0));
101 
102 	mmu_page_id = REG_FIELD(mmu, rw_mm_tlb_hi, pid, 0);
103 
104 	/* Update the instruction MMU. */
105 	SUPP_BANK_SEL(BANK_IM);
106 	SUPP_REG_WR(RW_MM_CFG, mmu_config);
107 	SUPP_REG_WR(RW_MM_KBASE_HI, mmu_kbase_hi);
108 	SUPP_REG_WR(RW_MM_KBASE_LO, mmu_kbase_lo);
109 	SUPP_REG_WR(RW_MM_TLB_HI, mmu_page_id);
110 
111 	/* Update the data MMU. */
112 	SUPP_BANK_SEL(BANK_DM);
113 	SUPP_REG_WR(RW_MM_CFG, mmu_config);
114 	SUPP_REG_WR(RW_MM_KBASE_HI, mmu_kbase_hi);
115 	SUPP_REG_WR(RW_MM_KBASE_LO, mmu_kbase_lo);
116 	SUPP_REG_WR(RW_MM_TLB_HI, mmu_page_id);
117 
118 	SPEC_REG_WR(SPEC_REG_PID, 0);
119 
120 	/*
121 	 * The MMU has been enabled ever since head.S but just to make it
122 	 * totally obvious enable it here as well.
123 	 */
124 	SUPP_BANK_SEL(BANK_GC);
125 	SUPP_REG_WR(RW_GC_CFG, 0xf); /* IMMU, DMMU, ICache, DCache on */
126 }
127 
paging_init(void)128 void __init paging_init(void)
129 {
130 	int i;
131 	unsigned long zones_size[MAX_NR_ZONES];
132 
133 	printk("Setting up paging and the MMU.\n");
134 
135 	/* Clear out the init_mm.pgd that will contain the kernel's mappings. */
136 	for(i = 0; i < PTRS_PER_PGD; i++)
137 		swapper_pg_dir[i] = __pgd(0);
138 
139 	cris_mmu_init();
140 
141 	/*
142 	 * Initialize the bad page table and bad page to point to a couple of
143 	 * allocated pages.
144 	 */
145 	empty_zero_page = (unsigned long) alloc_bootmem_pages(PAGE_SIZE);
146 	memset((void *) empty_zero_page, 0, PAGE_SIZE);
147 
148 	/* All pages are DMA'able in Etrax, so put all in the DMA'able zone. */
149 	zones_size[0] = ((unsigned long) high_memory - PAGE_OFFSET) >> PAGE_SHIFT;
150 
151 	for (i = 1; i < MAX_NR_ZONES; i++)
152 		zones_size[i] = 0;
153 
154 	/*
155 	 * Use free_area_init_node instead of free_area_init, because it is
156 	 * designed for systems where the DRAM starts at an address
157 	 * substantially higher than 0, like us (we start at PAGE_OFFSET). This
158 	 * saves space in the mem_map page array.
159 	 */
160 	free_area_init_node(0, zones_size, PAGE_OFFSET >> PAGE_SHIFT, 0);
161 
162 	mem_map = contig_page_data.node_mem_map;
163 }
164