]> git.saurik.com Git - apple/xnu.git/blob - pexpert/ppc/pe_identify_machine.c
d5c21b71294bf2bfc9eb0b60b578ba7287c6af49
[apple/xnu.git] / pexpert / ppc / pe_identify_machine.c
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_OSREFERENCE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
14 * agreement.
15 *
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
18 * file.
19 *
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
27 *
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
29 */
30 #include <pexpert/protos.h>
31 #include <pexpert/pexpert.h>
32 #include <pexpert/ppc/powermac.h>
33 #include <pexpert/device_tree.h>
34 #include <vm/pmap.h>
35
36 /* pe_identify_machine:
37 *
38 * Sets up platform parameters.
39 * Returns: nothing
40 */
41 void pe_identify_machine(void)
42 {
43 DTEntry cpu, root;
44 unsigned long *value;
45 int size;
46
47 // Clear the gPEClockFrequencyInfo struct
48 bzero((void *)&gPEClockFrequencyInfo, sizeof(clock_frequency_info_t));
49
50 // Start with default values.
51 gPEClockFrequencyInfo.timebase_frequency_hz = 25000000;
52 gPEClockFrequencyInfo.bus_clock_rate_hz = 100000000;
53 gPEClockFrequencyInfo.cpu_clock_rate_hz = 300000000;
54
55 // Try to get the values from the device tree.
56 if (DTFindEntry("device_type", "cpu", &cpu) == kSuccess) {
57 // Find the time base frequency first.
58 if (DTGetProperty(cpu, "timebase-frequency", (void **)&value, &size) == kSuccess) {
59 // timebase_frequency_hz is only 32 bits, and the device tree should never provide 64 bits
60 // so this if should never be taken.
61 if (size == 8) gPEClockFrequencyInfo.timebase_frequency_hz = *(unsigned long long *)value;
62 else gPEClockFrequencyInfo.timebase_frequency_hz = *value;
63 }
64 gPEClockFrequencyInfo.dec_clock_rate_hz = gPEClockFrequencyInfo.timebase_frequency_hz;
65
66 // Find the bus frequency next. Try the cpu node, then the root.
67 if (DTGetProperty(cpu, "bus-frequency", (void **)&value, &size) == kSuccess) {
68 if (size == 8) gPEClockFrequencyInfo.bus_frequency_hz = *(unsigned long long *)value;
69 else gPEClockFrequencyInfo.bus_frequency_hz = *value;
70 } else {
71 if (DTLookupEntry(0, "/", &root) == kSuccess) {
72 if (DTGetProperty(root, "clock-frequency", (void **)&value, &size) == kSuccess) {
73 if (size == 8) gPEClockFrequencyInfo.bus_frequency_hz = *(unsigned long long *)value;
74 else gPEClockFrequencyInfo.bus_frequency_hz = *value;
75 }
76 }
77 }
78
79 gPEClockFrequencyInfo.bus_frequency_min_hz = gPEClockFrequencyInfo.bus_frequency_hz;
80 gPEClockFrequencyInfo.bus_frequency_max_hz = gPEClockFrequencyInfo.bus_frequency_hz;
81
82 if (gPEClockFrequencyInfo.bus_frequency_hz < 0x100000000ULL)
83 gPEClockFrequencyInfo.bus_clock_rate_hz = gPEClockFrequencyInfo.bus_frequency_hz;
84 else
85 gPEClockFrequencyInfo.bus_clock_rate_hz = 0xFFFFFFFF;
86
87 // Find the cpu frequency last.
88 if (DTGetProperty(cpu, "clock-frequency", (void **)&value, &size) == kSuccess) {
89 if (size == 8) gPEClockFrequencyInfo.cpu_frequency_hz = *(unsigned long long *)value;
90 else gPEClockFrequencyInfo.cpu_frequency_hz = *value;
91 }
92
93 gPEClockFrequencyInfo.cpu_frequency_min_hz = gPEClockFrequencyInfo.cpu_frequency_hz;
94 gPEClockFrequencyInfo.cpu_frequency_max_hz = gPEClockFrequencyInfo.cpu_frequency_hz;
95
96 if (gPEClockFrequencyInfo.cpu_frequency_hz < 0x100000000ULL)
97 gPEClockFrequencyInfo.cpu_clock_rate_hz = gPEClockFrequencyInfo.cpu_frequency_hz;
98 else
99 gPEClockFrequencyInfo.cpu_clock_rate_hz = 0xFFFFFFFF;
100 }
101
102 // Set the num / den pairs form the hz values.
103 gPEClockFrequencyInfo.timebase_frequency_num = gPEClockFrequencyInfo.timebase_frequency_hz;
104 gPEClockFrequencyInfo.timebase_frequency_den = 1;
105
106 gPEClockFrequencyInfo.bus_clock_rate_num = gPEClockFrequencyInfo.bus_clock_rate_hz;
107 gPEClockFrequencyInfo.bus_clock_rate_den = 1;
108
109 gPEClockFrequencyInfo.bus_to_cpu_rate_num =
110 (2 * gPEClockFrequencyInfo.cpu_clock_rate_hz) / gPEClockFrequencyInfo.bus_clock_rate_hz;
111 gPEClockFrequencyInfo.bus_to_cpu_rate_den = 2;
112
113 gPEClockFrequencyInfo.bus_to_dec_rate_num = 1;
114 gPEClockFrequencyInfo.bus_to_dec_rate_den =
115 gPEClockFrequencyInfo.bus_clock_rate_hz / gPEClockFrequencyInfo.dec_clock_rate_hz;
116 }
117
118 /* get_io_base_addr():
119 *
120 * Get the base address of the io controller.
121 */
122 vm_offset_t get_io_base_addr(void)
123 {
124 DTEntry entryP;
125 vm_offset_t *address;
126 int size;
127
128 if ((DTFindEntry("device_type", "dbdma", &entryP) == kSuccess)
129 || (DTFindEntry("device_type", "mac-io", &entryP) == kSuccess))
130 {
131 if (DTGetProperty(entryP, "AAPL,address", (void **)&address, &size) == kSuccess)
132 return *address;
133
134 if (DTGetProperty(entryP, "assigned-addresses", (void **)&address, &size) == kSuccess)
135 // address calculation not correct
136 return *(address+2);
137 }
138
139 panic("Can't find this machine's io base address\n");
140 return 0;
141 }
142
143 vm_offset_t PE_find_scc(void)
144 {
145 vm_offset_t io, sccadd;
146 DTEntry entryP;
147 vm_offset_t *sccregs;
148 unsigned int sccrsize;
149
150 if(!(io = get_io_base_addr())) { /* Get the I/O controller base address */
151 return (vm_offset_t)0; /* Hmmm, no I/O??? What gives??? How'd we even boot? */
152 }
153
154
155 /* Note: if we find a escc-legacy, we need to kind of hack because it can be either an offset
156 into the iobase or the actual address itself. ORint the two should provide the correct
157 for either */
158
159 sccadd = 0; /* Assume none for now */
160
161 if(DTFindEntry("name", "escc-legacy", &entryP) == kSuccess) { /* Find the old fashioned serial port */
162 if (DTGetProperty(entryP, "reg", (void **)&sccregs, &sccrsize) == kSuccess) { /* Do we have some registers? */
163 sccadd = ((vm_offset_t)*sccregs | io); /* Get the address */
164 }
165 }
166
167 if(DTFindEntry("name", "escc", &entryP) == kSuccess) { /* Well, see if we just have the new fangled one */
168 sccadd = io + 0x12000; /* Yeah, but still return the oldie goldie... */
169 }
170
171 return sccadd; /* Return it if you found it */
172 }
173
174 unsigned int PE_init_taproot(vm_offset_t *taddr)
175 {
176 DTEntry entryP;
177 vm_offset_t *tappdata;
178 unsigned int tappsize;
179
180
181 if(DTFindEntry("name", "memory-map", &entryP) != kSuccess) return 0; /* no memory map */
182
183 if (DTGetProperty(entryP, "TapRoot", (void **)&tappdata, &tappsize) != kSuccess) return 0; /* No TapRoot */
184
185 tappdata[1] = (tappdata[1] + 4095 ) & -4096; /* Make sure this is a whole page */
186
187 *taddr = io_map_spec(tappdata[0], tappdata[1], VM_WIMG_IO); /* Map it in and return the address */
188 tappdata[0] = *taddr; /* Also change property */
189 return tappdata[1]; /* And the size */
190 }