]>
Commit | Line | Data |
---|---|---|
19fbdca4 MS |
1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* | |
3 | * (C) Copyright 2018 | |
4 | * Mario Six, Guntermann & Drunck GmbH, [email protected] | |
5 | */ | |
6 | ||
7 | #include <common.h> | |
8 | #include <bitfield.h> | |
9 | #include <clk.h> | |
10 | #include <cpu.h> | |
11 | #include <dm.h> | |
f7ae49fc | 12 | #include <log.h> |
2189d5f1 | 13 | #include <vsprintf.h> |
19fbdca4 MS |
14 | |
15 | #include "mpc83xx_cpu.h" | |
16 | ||
17 | /** | |
18 | * struct mpc83xx_cpu_priv - Private data for MPC83xx CPUs | |
19 | * @e300_type: The e300 core type of the MPC83xx CPU | |
20 | * @family: The MPC83xx family the CPU belongs to | |
21 | * @type: The MPC83xx type of the CPU | |
22 | * @is_e_processor: Flag indicating whether the CPU is a E processor or not | |
23 | * @is_a_variant: Flag indicating whtther the CPU is a A variant or not | |
24 | * @revid: The revision ID of the CPU | |
25 | * @revid.major: The major part of the CPU's revision ID | |
26 | * @revid.minor: The minor part of the CPU's revision ID | |
27 | */ | |
28 | struct mpc83xx_cpu_priv { | |
29 | enum e300_type e300_type; | |
30 | enum mpc83xx_cpu_family family; | |
31 | enum mpc83xx_cpu_type type; | |
32 | bool is_e_processor; | |
33 | bool is_a_variant; | |
34 | struct { | |
35 | uint major; | |
36 | uint minor; | |
37 | } revid; | |
38 | }; | |
39 | ||
40 | int checkcpu(void) | |
41 | { | |
42 | /* Activate all CPUs from board_f.c */ | |
43 | return cpu_probe_all(); | |
44 | } | |
45 | ||
46 | /** | |
47 | * get_spridr() - Read SPRIDR (System Part and Revision ID Register) of CPU | |
48 | * | |
49 | * Return: The SPRIDR value | |
50 | */ | |
51 | static inline u32 get_spridr(void) | |
52 | { | |
53 | immap_t *immr = (immap_t *)CONFIG_SYS_IMMR; | |
54 | ||
55 | return in_be32(&immr->sysconf.spridr); | |
56 | } | |
57 | ||
58 | /** | |
59 | * determine_type() - Determine CPU family of MPC83xx device | |
60 | * @dev: CPU device from which to read CPU family from | |
61 | */ | |
62 | static inline void determine_family(struct udevice *dev) | |
63 | { | |
64 | struct mpc83xx_cpu_priv *priv = dev_get_priv(dev); | |
65 | /* Upper 12 bits of PARTID field (bits 0-23 in SPRIDR) */ | |
66 | const u32 PARTID_FAMILY_MASK = 0xFFF00000; | |
67 | ||
68 | switch (bitfield_extract_by_mask(get_spridr(), PARTID_FAMILY_MASK)) { | |
69 | case 0x810: | |
70 | case 0x811: | |
71 | priv->family = FAMILY_830X; | |
72 | break; | |
73 | case 0x80B: | |
74 | priv->family = FAMILY_831X; | |
75 | break; | |
76 | case 0x806: | |
77 | priv->family = FAMILY_832X; | |
78 | break; | |
79 | case 0x803: | |
80 | priv->family = FAMILY_834X; | |
81 | break; | |
82 | case 0x804: | |
83 | priv->family = FAMILY_836X; | |
84 | break; | |
85 | case 0x80C: | |
86 | priv->family = FAMILY_837X; | |
87 | break; | |
88 | default: | |
89 | priv->family = FAMILY_UNKNOWN; | |
90 | } | |
91 | } | |
92 | ||
93 | /** | |
94 | * determine_type() - Determine CPU type of MPC83xx device | |
95 | * @dev: CPU device from which to read CPU type from | |
96 | */ | |
97 | static inline void determine_type(struct udevice *dev) | |
98 | { | |
99 | struct mpc83xx_cpu_priv *priv = dev_get_priv(dev); | |
100 | /* Upper 16 bits of PVR (Processor Version Register) */ | |
101 | const u32 PCR_UPPER_MASK = 0xFFFF0000; | |
102 | u32 val; | |
103 | ||
104 | val = bitfield_extract_by_mask(get_spridr(), PCR_UPPER_MASK); | |
105 | ||
106 | /* Mask out E-variant bit */ | |
107 | switch (val & 0xFFFE) { | |
108 | case 0x8100: | |
109 | priv->type = TYPE_8308; | |
110 | break; | |
111 | case 0x8110: | |
112 | priv->type = TYPE_8309; | |
113 | break; | |
114 | case 0x80B2: | |
115 | priv->type = TYPE_8311; | |
116 | break; | |
117 | case 0x80B0: | |
118 | priv->type = TYPE_8313; | |
119 | break; | |
120 | case 0x80B6: | |
121 | priv->type = TYPE_8314; | |
122 | break; | |
123 | case 0x80B4: | |
124 | priv->type = TYPE_8315; | |
125 | break; | |
126 | case 0x8066: | |
127 | priv->type = TYPE_8321; | |
128 | break; | |
129 | case 0x8062: | |
130 | priv->type = TYPE_8323; | |
131 | break; | |
132 | case 0x8036: | |
133 | priv->type = TYPE_8343; | |
134 | break; | |
135 | case 0x8032: | |
136 | priv->type = TYPE_8347_TBGA; | |
137 | break; | |
138 | case 0x8034: | |
139 | priv->type = TYPE_8347_PBGA; | |
140 | break; | |
141 | case 0x8030: | |
142 | priv->type = TYPE_8349; | |
143 | break; | |
144 | case 0x804A: | |
145 | priv->type = TYPE_8358_TBGA; | |
146 | break; | |
147 | case 0x804E: | |
148 | priv->type = TYPE_8358_PBGA; | |
149 | break; | |
150 | case 0x8048: | |
151 | priv->type = TYPE_8360; | |
152 | break; | |
153 | case 0x80C6: | |
154 | priv->type = TYPE_8377; | |
155 | break; | |
156 | case 0x80C4: | |
157 | priv->type = TYPE_8378; | |
158 | break; | |
159 | case 0x80C2: | |
160 | priv->type = TYPE_8379; | |
161 | break; | |
162 | default: | |
163 | priv->type = TYPE_UNKNOWN; | |
164 | } | |
165 | } | |
166 | ||
167 | /** | |
168 | * determine_e300_type() - Determine e300 core type of MPC83xx device | |
169 | * @dev: CPU device from which to read e300 core type from | |
170 | */ | |
171 | static inline void determine_e300_type(struct udevice *dev) | |
172 | { | |
173 | struct mpc83xx_cpu_priv *priv = dev_get_priv(dev); | |
174 | /* Upper 16 bits of PVR (Processor Version Register) */ | |
175 | const u32 PCR_UPPER_MASK = 0xFFFF0000; | |
176 | u32 pvr = get_pvr(); | |
177 | ||
178 | switch ((pvr & PCR_UPPER_MASK) >> 16) { | |
179 | case 0x8083: | |
180 | priv->e300_type = E300C1; | |
181 | break; | |
182 | case 0x8084: | |
183 | priv->e300_type = E300C2; | |
184 | break; | |
185 | case 0x8085: | |
186 | priv->e300_type = E300C3; | |
187 | break; | |
188 | case 0x8086: | |
189 | priv->e300_type = E300C4; | |
190 | break; | |
191 | default: | |
192 | priv->e300_type = E300_UNKNOWN; | |
193 | } | |
194 | } | |
195 | ||
196 | /** | |
197 | * determine_revid() - Determine revision ID of CPU device | |
198 | * @dev: CPU device from which to read revision ID | |
199 | */ | |
200 | static inline void determine_revid(struct udevice *dev) | |
201 | { | |
202 | struct mpc83xx_cpu_priv *priv = dev_get_priv(dev); | |
203 | u32 REVID_MAJOR_MASK; | |
204 | u32 REVID_MINOR_MASK; | |
205 | u32 spridr = get_spridr(); | |
206 | ||
207 | if (priv->family == FAMILY_834X) { | |
208 | REVID_MAJOR_MASK = 0x0000FF00; | |
209 | REVID_MINOR_MASK = 0x000000FF; | |
210 | } else { | |
211 | REVID_MAJOR_MASK = 0x000000F0; | |
212 | REVID_MINOR_MASK = 0x0000000F; | |
213 | } | |
214 | ||
215 | priv->revid.major = bitfield_extract_by_mask(spridr, REVID_MAJOR_MASK); | |
216 | priv->revid.minor = bitfield_extract_by_mask(spridr, REVID_MINOR_MASK); | |
217 | } | |
218 | ||
219 | /** | |
220 | * determine_cpu_data() - Determine CPU information from hardware | |
221 | * @dev: CPU device from which to read information | |
222 | */ | |
223 | static void determine_cpu_data(struct udevice *dev) | |
224 | { | |
225 | struct mpc83xx_cpu_priv *priv = dev_get_priv(dev); | |
226 | const u32 E_FLAG_MASK = 0x00010000; | |
227 | u32 spridr = get_spridr(); | |
228 | ||
229 | determine_family(dev); | |
230 | determine_type(dev); | |
231 | determine_e300_type(dev); | |
232 | determine_revid(dev); | |
233 | ||
234 | if ((priv->family == FAMILY_834X || | |
235 | priv->family == FAMILY_836X) && priv->revid.major >= 2) | |
236 | priv->is_a_variant = true; | |
237 | ||
238 | priv->is_e_processor = !bitfield_extract_by_mask(spridr, E_FLAG_MASK); | |
239 | } | |
240 | ||
241 | static int mpc83xx_cpu_get_desc(struct udevice *dev, char *buf, int size) | |
242 | { | |
243 | struct mpc83xx_cpu_priv *priv = dev_get_priv(dev); | |
244 | struct clk core_clk; | |
245 | struct clk csb_clk; | |
246 | char core_freq[32]; | |
247 | char csb_freq[32]; | |
248 | int ret; | |
249 | ||
250 | ret = clk_get_by_index(dev, 0, &core_clk); | |
251 | if (ret) { | |
252 | debug("%s: Failed to get core clock (err = %d)\n", | |
253 | dev->name, ret); | |
254 | return ret; | |
255 | } | |
256 | ||
257 | ret = clk_get_by_index(dev, 1, &csb_clk); | |
258 | if (ret) { | |
259 | debug("%s: Failed to get CSB clock (err = %d)\n", | |
260 | dev->name, ret); | |
261 | return ret; | |
262 | } | |
263 | ||
264 | determine_cpu_data(dev); | |
265 | ||
266 | snprintf(buf, size, | |
6fe8abcc | 267 | "%s, MPC%s%s%s, Rev: %d.%d at %s MHz, CSB: %s MHz", |
19fbdca4 MS |
268 | e300_names[priv->e300_type], |
269 | cpu_type_names[priv->type], | |
270 | priv->is_e_processor ? "E" : "", | |
271 | priv->is_a_variant ? "A" : "", | |
272 | priv->revid.major, | |
273 | priv->revid.minor, | |
274 | strmhz(core_freq, clk_get_rate(&core_clk)), | |
275 | strmhz(csb_freq, clk_get_rate(&csb_clk))); | |
276 | ||
277 | return 0; | |
278 | } | |
279 | ||
280 | static int mpc83xx_cpu_get_info(struct udevice *dev, struct cpu_info *info) | |
281 | { | |
282 | struct clk clock; | |
283 | int ret; | |
284 | ulong freq; | |
285 | ||
286 | ret = clk_get_by_index(dev, 0, &clock); | |
287 | if (ret) { | |
288 | debug("%s: Failed to get core clock (err = %d)\n", | |
289 | dev->name, ret); | |
290 | return ret; | |
291 | } | |
292 | ||
293 | freq = clk_get_rate(&clock); | |
294 | if (!freq) { | |
295 | debug("%s: Core clock speed is zero\n", dev->name); | |
296 | return -EINVAL; | |
297 | } | |
298 | ||
299 | info->cpu_freq = freq; | |
300 | info->features = BIT(CPU_FEAT_L1_CACHE) | BIT(CPU_FEAT_MMU); | |
301 | ||
302 | return 0; | |
303 | } | |
304 | ||
305 | static int mpc83xx_cpu_get_count(struct udevice *dev) | |
306 | { | |
307 | /* We have one e300cX core */ | |
308 | return 1; | |
309 | } | |
310 | ||
311 | static int mpc83xx_cpu_get_vendor(struct udevice *dev, char *buf, int size) | |
312 | { | |
313 | snprintf(buf, size, "NXP"); | |
314 | ||
315 | return 0; | |
316 | } | |
317 | ||
318 | static const struct cpu_ops mpc83xx_cpu_ops = { | |
319 | .get_desc = mpc83xx_cpu_get_desc, | |
320 | .get_info = mpc83xx_cpu_get_info, | |
321 | .get_count = mpc83xx_cpu_get_count, | |
322 | .get_vendor = mpc83xx_cpu_get_vendor, | |
323 | }; | |
324 | ||
325 | static int mpc83xx_cpu_probe(struct udevice *dev) | |
326 | { | |
327 | return 0; | |
328 | } | |
329 | ||
330 | static const struct udevice_id mpc83xx_cpu_ids[] = { | |
331 | { .compatible = "fsl,mpc83xx", }, | |
332 | { .compatible = "fsl,mpc8308", }, | |
333 | { .compatible = "fsl,mpc8309", }, | |
334 | { .compatible = "fsl,mpc8313", }, | |
335 | { .compatible = "fsl,mpc8315", }, | |
336 | { .compatible = "fsl,mpc832x", }, | |
337 | { .compatible = "fsl,mpc8349", }, | |
338 | { .compatible = "fsl,mpc8360", }, | |
339 | { .compatible = "fsl,mpc8379", }, | |
340 | { /* sentinel */ } | |
341 | }; | |
342 | ||
343 | U_BOOT_DRIVER(mpc83xx_cpu) = { | |
344 | .name = "mpc83xx_cpu", | |
345 | .id = UCLASS_CPU, | |
346 | .of_match = mpc83xx_cpu_ids, | |
347 | .probe = mpc83xx_cpu_probe, | |
348 | .priv_auto_alloc_size = sizeof(struct mpc83xx_cpu_priv), | |
349 | .ops = &mpc83xx_cpu_ops, | |
350 | .flags = DM_FLAG_PRE_RELOC, | |
351 | }; |