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