xref: /xnu-10063.121.3/pexpert/arm/pe_identify_machine.c (revision 2c2f96dc2b9a4408a43d3150ae9c105355ca3daa)
1 /*
2  * Copyright (c) 2007-2021 Apple Inc. All rights reserved.
3  * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved.
4  */
5 #include <pexpert/pexpert.h>
6 #include <pexpert/boot.h>
7 #include <pexpert/protos.h>
8 #include <pexpert/device_tree.h>
9 #include <pexpert/arm64/board_config.h>
10 
11 #include <machine/machine_routines.h>
12 
13 #include <kern/clock.h>
14 #include <kern/locks.h>
15 
16 /* Local declarations */
17 void pe_identify_machine(boot_args * bootArgs);
18 
19 /* External declarations */
20 extern void clean_mmu_dcache(void);
21 
22 static char    *gPESoCDeviceType;
23 static char     gPESoCDeviceTypeBuffer[SOC_DEVICE_TYPE_BUFFER_SIZE];
24 static vm_offset_t gPESoCBasePhys;
25 
26 static uint32_t pe_arm_init_timer(void *args);
27 
28 
29 /*
30  * pe_identify_machine:
31  *
32  * Sets up platform parameters. Returns:    nothing
33  */
34 void
pe_identify_machine(boot_args * bootArgs)35 pe_identify_machine(boot_args * bootArgs)
36 {
37 	OpaqueDTEntryIterator iter;
38 	DTEntry         cpus, cpu;
39 	void const     *value;
40 	unsigned int    size;
41 	int             err;
42 
43 	(void)bootArgs;
44 
45 	if (pe_arm_get_soc_base_phys() == 0) {
46 		return;
47 	}
48 
49 	/* Clear the gPEClockFrequencyInfo struct */
50 	bzero((void *)&gPEClockFrequencyInfo, sizeof(clock_frequency_info_t));
51 
52 	/* Start with default values. */
53 	gPEClockFrequencyInfo.timebase_frequency_hz = 24000000;
54 	gPEClockFrequencyInfo.bus_clock_rate_hz = 100000000;
55 	gPEClockFrequencyInfo.cpu_clock_rate_hz = 400000000;
56 
57 	err = SecureDTLookupEntry(NULL, "/cpus", &cpus);
58 	assert(err == kSuccess);
59 
60 	err = SecureDTInitEntryIterator(cpus, &iter);
61 	assert(err == kSuccess);
62 
63 	while (kSuccess == SecureDTIterateEntries(&iter, &cpu)) {
64 		if ((kSuccess != SecureDTGetProperty(cpu, "state", &value, &size)) ||
65 		    (strncmp((char const *)value, "running", size) != 0)) {
66 			continue;
67 		}
68 
69 		/* Find the time base frequency first. */
70 		if (SecureDTGetProperty(cpu, "timebase-frequency", &value, &size) == kSuccess) {
71 			/*
72 			 * timebase_frequency_hz is only 32 bits, and
73 			 * the device tree should never provide 64
74 			 * bits so this if should never be taken.
75 			 */
76 			if (size == 8) {
77 				gPEClockFrequencyInfo.timebase_frequency_hz = *(uint64_t const *)value;
78 			} else {
79 				gPEClockFrequencyInfo.timebase_frequency_hz = *(uint32_t const *)value;
80 			}
81 		}
82 		gPEClockFrequencyInfo.dec_clock_rate_hz = gPEClockFrequencyInfo.timebase_frequency_hz;
83 
84 		/* Find the bus frequency next. */
85 		if (SecureDTGetProperty(cpu, "bus-frequency", &value, &size) == kSuccess) {
86 			if (size == 8) {
87 				gPEClockFrequencyInfo.bus_frequency_hz = *(uint64_t const *)value;
88 			} else {
89 				gPEClockFrequencyInfo.bus_frequency_hz = *(uint32_t const *)value;
90 			}
91 		}
92 		gPEClockFrequencyInfo.bus_frequency_min_hz = gPEClockFrequencyInfo.bus_frequency_hz;
93 		gPEClockFrequencyInfo.bus_frequency_max_hz = gPEClockFrequencyInfo.bus_frequency_hz;
94 
95 		if (gPEClockFrequencyInfo.bus_frequency_hz < 0x100000000ULL) {
96 			gPEClockFrequencyInfo.bus_clock_rate_hz = gPEClockFrequencyInfo.bus_frequency_hz;
97 		} else {
98 			gPEClockFrequencyInfo.bus_clock_rate_hz = 0xFFFFFFFF;
99 		}
100 
101 		/* Find the memory frequency next. */
102 		if (SecureDTGetProperty(cpu, "memory-frequency", &value, &size) == kSuccess) {
103 			if (size == 8) {
104 				gPEClockFrequencyInfo.mem_frequency_hz = *(uint64_t const *)value;
105 			} else {
106 				gPEClockFrequencyInfo.mem_frequency_hz = *(uint32_t const *)value;
107 			}
108 		}
109 		gPEClockFrequencyInfo.mem_frequency_min_hz = gPEClockFrequencyInfo.mem_frequency_hz;
110 		gPEClockFrequencyInfo.mem_frequency_max_hz = gPEClockFrequencyInfo.mem_frequency_hz;
111 
112 		/* Find the peripheral frequency next. */
113 		if (SecureDTGetProperty(cpu, "peripheral-frequency", &value, &size) == kSuccess) {
114 			if (size == 8) {
115 				gPEClockFrequencyInfo.prf_frequency_hz = *(uint64_t const *)value;
116 			} else {
117 				gPEClockFrequencyInfo.prf_frequency_hz = *(uint32_t const *)value;
118 			}
119 		}
120 		gPEClockFrequencyInfo.prf_frequency_min_hz = gPEClockFrequencyInfo.prf_frequency_hz;
121 		gPEClockFrequencyInfo.prf_frequency_max_hz = gPEClockFrequencyInfo.prf_frequency_hz;
122 
123 		/* Find the fixed frequency next. */
124 		if (SecureDTGetProperty(cpu, "fixed-frequency", &value, &size) == kSuccess) {
125 			if (size == 8) {
126 				gPEClockFrequencyInfo.fix_frequency_hz = *(uint64_t const *)value;
127 			} else {
128 				gPEClockFrequencyInfo.fix_frequency_hz = *(uint32_t const *)value;
129 			}
130 		}
131 		/* Find the cpu frequency last. */
132 		if (SecureDTGetProperty(cpu, "clock-frequency", &value, &size) == kSuccess) {
133 			if (size == 8) {
134 				gPEClockFrequencyInfo.cpu_frequency_hz = *(uint64_t const *)value;
135 			} else {
136 				gPEClockFrequencyInfo.cpu_frequency_hz = *(uint32_t const *)value;
137 			}
138 		}
139 		gPEClockFrequencyInfo.cpu_frequency_min_hz = gPEClockFrequencyInfo.cpu_frequency_hz;
140 		gPEClockFrequencyInfo.cpu_frequency_max_hz = gPEClockFrequencyInfo.cpu_frequency_hz;
141 
142 		if (gPEClockFrequencyInfo.cpu_frequency_hz < 0x100000000ULL) {
143 			gPEClockFrequencyInfo.cpu_clock_rate_hz = gPEClockFrequencyInfo.cpu_frequency_hz;
144 		} else {
145 			gPEClockFrequencyInfo.cpu_clock_rate_hz = 0xFFFFFFFF;
146 		}
147 	}
148 
149 	/* Set the num / den pairs form the hz values. */
150 	gPEClockFrequencyInfo.bus_clock_rate_num = gPEClockFrequencyInfo.bus_clock_rate_hz;
151 	gPEClockFrequencyInfo.bus_clock_rate_den = 1;
152 
153 	gPEClockFrequencyInfo.bus_to_cpu_rate_num =
154 	    (2 * gPEClockFrequencyInfo.cpu_clock_rate_hz) / gPEClockFrequencyInfo.bus_clock_rate_hz;
155 	gPEClockFrequencyInfo.bus_to_cpu_rate_den = 2;
156 
157 	gPEClockFrequencyInfo.bus_to_dec_rate_num = 1;
158 	gPEClockFrequencyInfo.bus_to_dec_rate_den =
159 	    gPEClockFrequencyInfo.bus_clock_rate_hz / gPEClockFrequencyInfo.dec_clock_rate_hz;
160 }
161 
162 vm_offset_t
pe_arm_get_soc_base_phys(void)163 pe_arm_get_soc_base_phys(void)
164 {
165 	DTEntry         entryP;
166 	uintptr_t const *ranges_prop;
167 	uint32_t        prop_size;
168 	char const      *tmpStr;
169 
170 	if (SecureDTFindEntry("name", "arm-io", &entryP) == kSuccess) {
171 		if (gPESoCDeviceType == 0) {
172 			SecureDTGetProperty(entryP, "device_type", (void const **)&tmpStr, &prop_size);
173 			strlcpy(gPESoCDeviceTypeBuffer, tmpStr, SOC_DEVICE_TYPE_BUFFER_SIZE);
174 			gPESoCDeviceType = gPESoCDeviceTypeBuffer;
175 
176 			SecureDTGetProperty(entryP, "ranges", (void const **)&ranges_prop, &prop_size);
177 			gPESoCBasePhys = *(ranges_prop + 1);
178 		}
179 		return gPESoCBasePhys;
180 	}
181 	return 0;
182 }
183 
184 extern void     fleh_fiq_generic(void);
185 
186 vm_offset_t     gPicBase;
187 vm_offset_t     gTimerBase;
188 vm_offset_t     gSocPhys;
189 
190 static uint32_t
pe_arm_map_interrupt_controller(void)191 pe_arm_map_interrupt_controller(void)
192 {
193 	DTEntry         entryP;
194 	uintptr_t const *reg_prop;
195 	uint32_t        prop_size;
196 	vm_offset_t     soc_phys = 0;
197 
198 	gSocPhys = pe_arm_get_soc_base_phys();
199 
200 	soc_phys = gSocPhys;
201 	kprintf("pe_arm_map_interrupt_controller: soc_phys:  0x%lx\n", (unsigned long)soc_phys);
202 	if (soc_phys == 0) {
203 		return 0;
204 	}
205 
206 	if (SecureDTFindEntry("interrupt-controller", "master", &entryP) == kSuccess) {
207 		kprintf("pe_arm_map_interrupt_controller: found interrupt-controller\n");
208 		SecureDTGetProperty(entryP, "reg", (void const **)&reg_prop, &prop_size);
209 		gPicBase = ml_io_map(soc_phys + *reg_prop, *(reg_prop + 1));
210 		kprintf("pe_arm_map_interrupt_controller: gPicBase: 0x%lx\n", (unsigned long)gPicBase);
211 	}
212 	if (gPicBase == 0) {
213 		kprintf("pe_arm_map_interrupt_controller: failed to find the interrupt-controller.\n");
214 		return 0;
215 	}
216 
217 	if (SecureDTFindEntry("device_type", "timer", &entryP) == kSuccess) {
218 		kprintf("pe_arm_map_interrupt_controller: found timer\n");
219 		SecureDTGetProperty(entryP, "reg", (void const **)&reg_prop, &prop_size);
220 		gTimerBase = ml_io_map(soc_phys + *reg_prop, *(reg_prop + 1));
221 		kprintf("pe_arm_map_interrupt_controller: gTimerBase: 0x%lx\n", (unsigned long)gTimerBase);
222 	}
223 	if (gTimerBase == 0) {
224 		kprintf("pe_arm_map_interrupt_controller: failed to find the timer.\n");
225 		return 0;
226 	}
227 
228 	return 1;
229 }
230 
231 uint32_t
pe_arm_init_interrupts(void * args)232 pe_arm_init_interrupts(void *args)
233 {
234 	kprintf("pe_arm_init_interrupts: args: %p\n", args);
235 
236 	/* Set up mappings for interrupt controller and possibly timers (if they haven't been set up already) */
237 	if (args != NULL) {
238 		if (!pe_arm_map_interrupt_controller()) {
239 			return 0;
240 		}
241 	}
242 
243 	return pe_arm_init_timer(args);
244 }
245 
246 static uint32_t
pe_arm_init_timer(void * args)247 pe_arm_init_timer(void *args)
248 {
249 	vm_offset_t     pic_base = 0;
250 	vm_offset_t     timer_base = 0;
251 	vm_offset_t     soc_phys;
252 	vm_offset_t     eoi_addr = 0;
253 	uint32_t        eoi_value = 0;
254 	struct tbd_ops  generic_funcs = {&fleh_fiq_generic, NULL, NULL};
255 	struct tbd_ops  empty_funcs __unused = {NULL, NULL, NULL};
256 	tbd_ops_t       tbd_funcs = &generic_funcs;
257 
258 	/* The SoC headers expect to use pic_base, timer_base, etc... */
259 	pic_base = gPicBase;
260 	timer_base = gTimerBase;
261 	soc_phys = gSocPhys;
262 
263 #if defined(__arm64__)
264 	tbd_funcs = &empty_funcs;
265 #else
266 	return 0;
267 #endif
268 
269 	if (args != NULL) {
270 		ml_init_timebase(args, tbd_funcs, eoi_addr, eoi_value);
271 	}
272 
273 	return 1;
274 }
275