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