xref: /linux/arch/csky/kernel/setup.c (revision 23b0f90ba871f096474e1c27c3d14f455189d2d9)
1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
3 
4 #include <linux/console.h>
5 #include <linux/memblock.h>
6 #include <linux/initrd.h>
7 #include <linux/of.h>
8 #include <linux/of_fdt.h>
9 #include <linux/start_kernel.h>
10 #include <linux/dma-map-ops.h>
11 #include <asm/sections.h>
12 #include <asm/mmu_context.h>
13 #include <asm/pgalloc.h>
14 
15 #ifdef CONFIG_BLK_DEV_INITRD
16 static void __init setup_initrd(void)
17 {
18 	unsigned long size;
19 
20 	if (initrd_start >= initrd_end) {
21 		pr_err("initrd not found or empty");
22 		goto disable;
23 	}
24 
25 	if (__pa(initrd_end) > PFN_PHYS(max_low_pfn)) {
26 		pr_err("initrd extends beyond end of memory");
27 		goto disable;
28 	}
29 
30 	size = initrd_end - initrd_start;
31 
32 	if (memblock_is_region_reserved(__pa(initrd_start), size)) {
33 		pr_err("INITRD: 0x%08lx+0x%08lx overlaps in-use memory region",
34 		       __pa(initrd_start), size);
35 		goto disable;
36 	}
37 
38 	memblock_reserve(__pa(initrd_start), size);
39 
40 	pr_info("Initial ramdisk at: 0x%p (%lu bytes)\n",
41 		(void *)(initrd_start), size);
42 
43 	initrd_below_start_ok = 1;
44 
45 	return;
46 
47 disable:
48 	initrd_start = initrd_end = 0;
49 
50 	pr_err(" - disabling initrd\n");
51 }
52 #endif
53 
54 void __init arch_zone_limits_init(unsigned long *max_zone_pfns)
55 {
56 	max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
57 #ifdef CONFIG_HIGHMEM
58 	max_zone_pfns[ZONE_HIGHMEM] = max_pfn;
59 #endif
60 }
61 
62 static void __init csky_memblock_init(void)
63 {
64 	unsigned long lowmem_size = PFN_DOWN(LOWMEM_LIMIT - PHYS_OFFSET_OFFSET);
65 	unsigned long sseg_size = PFN_DOWN(SSEG_SIZE - PHYS_OFFSET_OFFSET);
66 	signed long size;
67 
68 	memblock_reserve(__pa(_start), _end - _start);
69 
70 	early_init_fdt_reserve_self();
71 	early_init_fdt_scan_reserved_mem();
72 
73 	memblock_dump_all();
74 
75 	min_low_pfn = PFN_UP(memblock_start_of_DRAM());
76 	max_low_pfn = max_pfn = PFN_DOWN(memblock_end_of_DRAM());
77 
78 	size = max_pfn - min_low_pfn;
79 
80 	if (size >= lowmem_size) {
81 		max_low_pfn = min_low_pfn + lowmem_size;
82 #ifdef CONFIG_PAGE_OFFSET_80000000
83 		write_mmu_msa1(read_mmu_msa0() + SSEG_SIZE);
84 #endif
85 	} else if (size > sseg_size) {
86 		max_low_pfn = min_low_pfn + sseg_size;
87 	}
88 
89 #ifdef CONFIG_BLK_DEV_INITRD
90 	setup_initrd();
91 #endif
92 
93 	mmu_init(min_low_pfn, max_low_pfn);
94 
95 #ifdef CONFIG_HIGHMEM
96 
97 	highstart_pfn = max_low_pfn;
98 	highend_pfn   = max_pfn;
99 #endif
100 	memblock_set_current_limit(PFN_PHYS(max_low_pfn));
101 
102 	dma_contiguous_reserve(0);
103 }
104 
105 void __init setup_arch(char **cmdline_p)
106 {
107 	*cmdline_p = boot_command_line;
108 
109 	console_verbose();
110 
111 	pr_info("Phys. mem: %ldMB\n",
112 		(unsigned long) memblock_phys_mem_size()/1024/1024);
113 
114 	setup_initial_init_mm(_start, _etext, _edata, _end);
115 
116 	parse_early_param();
117 
118 	csky_memblock_init();
119 
120 	unflatten_and_copy_device_tree();
121 
122 #ifdef CONFIG_SMP
123 	setup_smp();
124 #endif
125 
126 	fixaddr_init();
127 
128 #ifdef CONFIG_HIGHMEM
129 	kmap_init();
130 #endif
131 }
132 
133 unsigned long va_pa_offset;
134 EXPORT_SYMBOL(va_pa_offset);
135 
136 static inline unsigned long read_mmu_msa(void)
137 {
138 #ifdef CONFIG_PAGE_OFFSET_80000000
139 	return read_mmu_msa0();
140 #endif
141 
142 #ifdef CONFIG_PAGE_OFFSET_A0000000
143 	return read_mmu_msa1();
144 #endif
145 }
146 
147 asmlinkage __visible void __init csky_start(unsigned int unused,
148 					    void *dtb_start)
149 {
150 	/* Clean up bss section */
151 	memset(__bss_start, 0, __bss_stop - __bss_start);
152 
153 	va_pa_offset = read_mmu_msa() & ~(SSEG_SIZE - 1);
154 
155 	pre_trap_init();
156 
157 	if (dtb_start == NULL)
158 		early_init_dt_scan(__dtb_start, __pa(dtb_start));
159 	else
160 		early_init_dt_scan(dtb_start, __pa(dtb_start));
161 
162 	start_kernel();
163 
164 	asm volatile("br .\n");
165 }
166