rpihw.c
Go to the documentation of this file.
1 /*
2  * rpihw.c
3  *
4  * Copyright (c) 2014 Jeremy Garff <jer @ jers.net>
5  *
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without modification, are permitted
9  * provided that the following conditions are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright notice, this list of
12  * conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright notice, this list
14  * of conditions and the following disclaimer in the documentation and/or other materials
15  * provided with the distribution.
16  * 3. Neither the name of the owner nor the names of its contributors may be used to endorse
17  * or promote products derived from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
24  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  *
28  */
29 
30 
31 #include <stdint.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <stdlib.h>
35 #include <errno.h>
36 #include <byteswap.h>
37 
38 #include "rpihw.h"
39 
40 
41 #define LINE_WIDTH_MAX 80
42 #define HW_VER_STRING "Revision"
43 
44 #define PERIPH_BASE_RPI 0x20000000
45 #define PERIPH_BASE_RPI2 0x3f000000
46 #define PERIPH_BASE_RPI4 0xfe000000
47 
48 #define VIDEOCORE_BASE_RPI 0x40000000
49 #define VIDEOCORE_BASE_RPI2 0xc0000000
50 
51 #define RPI_MANUFACTURER_MASK (0xf << 16)
52 #define RPI_WARRANTY_MASK (0x3 << 24)
53 
54 static const rpi_hw_t rpi_hw_info[] = {
55  //
56  // Raspberry Pi 400
57  //
58  {
59  .hwver = 0xc03130,
60  .type = RPI_HWVER_TYPE_PI4,
61  .periph_base = PERIPH_BASE_RPI4,
62  .videocore_base = VIDEOCORE_BASE_RPI2,
63  .desc = "Pi 400 - 4GB v1.0"
64  },
65  {
66  .hwver = 0xc03131,
67  .type = RPI_HWVER_TYPE_PI4,
68  .periph_base = PERIPH_BASE_RPI4,
69  .videocore_base = VIDEOCORE_BASE_RPI2,
70  .desc = "Pi 400 - 4GB v1.1"
71  },
72  //
73  // Raspberry Pi 4
74  //
75  {
76  .hwver = 0xA03111,
77  .type = RPI_HWVER_TYPE_PI4,
78  .periph_base = PERIPH_BASE_RPI4,
79  .videocore_base = VIDEOCORE_BASE_RPI2,
80  .desc = "Pi 4 Model B - 1GB v1.1"
81  },
82  {
83  .hwver = 0xB03111,
84  .type = RPI_HWVER_TYPE_PI4,
85  .periph_base = PERIPH_BASE_RPI4,
86  .videocore_base = VIDEOCORE_BASE_RPI2,
87  .desc = "Pi 4 Model B - 2GB v.1.1"
88  },
89  {
90  .hwver = 0xC03111,
91  .type = RPI_HWVER_TYPE_PI4,
92  .periph_base = PERIPH_BASE_RPI4,
93  .videocore_base = VIDEOCORE_BASE_RPI2,
94  .desc = "Pi 4 Model B - 4GB v1.1"
95  },
96  {
97  .hwver = 0xA03112,
98  .type = RPI_HWVER_TYPE_PI4,
99  .periph_base = PERIPH_BASE_RPI4,
100  .videocore_base = VIDEOCORE_BASE_RPI2,
101  .desc = "Pi 4 Model B - 1GB v1.2"
102  },
103  {
104  .hwver = 0xB03112,
105  .type = RPI_HWVER_TYPE_PI4,
106  .periph_base = PERIPH_BASE_RPI4,
107  .videocore_base = VIDEOCORE_BASE_RPI2,
108  .desc = "Pi 4 Model B - 2GB v.1.2"
109  },
110  {
111  .hwver = 0xC03112,
112  .type = RPI_HWVER_TYPE_PI4,
113  .periph_base = PERIPH_BASE_RPI4,
114  .videocore_base = VIDEOCORE_BASE_RPI2,
115  .desc = "Pi 4 Model B - 4GB v1.2"
116  },
117  {
118  .hwver = 0xb03114,
119  .type = RPI_HWVER_TYPE_PI4,
120  .periph_base = PERIPH_BASE_RPI4,
121  .videocore_base = VIDEOCORE_BASE_RPI2,
122  .desc = "Pi 4 Model B - 2GB v1.4"
123  },
124  {
125  .hwver = 0xD03114,
126  .type = RPI_HWVER_TYPE_PI4,
127  .periph_base = PERIPH_BASE_RPI4,
128  .videocore_base = VIDEOCORE_BASE_RPI2,
129  .desc = "Pi 4 Model B - 8GB v1.4"
130  },
131  {
132  .hwver = 0xc03114,
133  .type = RPI_HWVER_TYPE_PI4,
134  .periph_base = PERIPH_BASE_RPI4,
135  .videocore_base = VIDEOCORE_BASE_RPI2,
136  .desc = "Pi 4 Model B - 4GB v1.4"
137  },
138  {
139  .hwver = 0xa03115,
140  .type = RPI_HWVER_TYPE_PI4,
141  .periph_base = PERIPH_BASE_RPI4,
142  .videocore_base = VIDEOCORE_BASE_RPI2,
143  .desc = "Pi 4 Model B - 1GB v1.5"
144  },
145  {
146  .hwver = 0xb03115,
147  .type = RPI_HWVER_TYPE_PI4,
148  .periph_base = PERIPH_BASE_RPI4,
149  .videocore_base = VIDEOCORE_BASE_RPI2,
150  .desc = "Pi 4 Model B - 2GB v1.5"
151  },
152  {
153  .hwver = 0xc03115,
154  .type = RPI_HWVER_TYPE_PI4,
155  .periph_base = PERIPH_BASE_RPI4,
156  .videocore_base = VIDEOCORE_BASE_RPI2,
157  .desc = "Pi 4 Model B - 4GB v1.5"
158  },
159  {
160  .hwver = 0xd03115,
161  .type = RPI_HWVER_TYPE_PI4,
162  .periph_base = PERIPH_BASE_RPI4,
163  .videocore_base = VIDEOCORE_BASE_RPI2,
164  .desc = "Pi 4 Model B - 8GB v1.5"
165  },
166  //
167  // Compute Module 4
168  //
169  {
170  .hwver = 0xa03140,
171  .type = RPI_HWVER_TYPE_PI4,
172  .periph_base = PERIPH_BASE_RPI4,
173  .videocore_base = VIDEOCORE_BASE_RPI2,
174  .desc = "Compute Module 4 v1.0 eMMC"
175  },
176  {
177  .hwver = 0xb03140,
178  .type = RPI_HWVER_TYPE_PI4,
179  .periph_base = PERIPH_BASE_RPI4,
180  .videocore_base = VIDEOCORE_BASE_RPI2,
181  .desc = "Compute Module 4 v1.0 Lite"
182  },
183  {
184  .hwver = 0xc03140,
185  .type = RPI_HWVER_TYPE_PI4,
186  .periph_base = PERIPH_BASE_RPI4,
187  .videocore_base = VIDEOCORE_BASE_RPI2,
188  .desc = "Compute Module 4 v1.0 WiFi"
189  },
190  {
191  .hwver = 0xd03140,
192  .type = RPI_HWVER_TYPE_PI4,
193  .periph_base = PERIPH_BASE_RPI4,
194  .videocore_base = VIDEOCORE_BASE_RPI2,
195  .desc = "Compute Module 4 v1.0 WiFi 8GB"
196  },
197  //
198  // Model B Rev 1.0
199  //
200  {
201  .hwver = 0x02,
202  .type = RPI_HWVER_TYPE_PI1,
203  .periph_base = PERIPH_BASE_RPI,
204  .videocore_base = VIDEOCORE_BASE_RPI,
205  .desc = "Model B",
206  },
207  {
208  .hwver = 0x03,
209  .type = RPI_HWVER_TYPE_PI1,
210  .periph_base = PERIPH_BASE_RPI,
211  .videocore_base = VIDEOCORE_BASE_RPI,
212  .desc = "Model B",
213  },
214 
215  //
216  // Model B Rev 2.0
217  //
218  {
219  .hwver = 0x04,
220  .type = RPI_HWVER_TYPE_PI1,
221  .periph_base = PERIPH_BASE_RPI,
222  .videocore_base = VIDEOCORE_BASE_RPI,
223  .desc = "Model B",
224  },
225  {
226  .hwver = 0x05,
227  .type = RPI_HWVER_TYPE_PI1,
228  .periph_base = PERIPH_BASE_RPI,
229  .videocore_base = VIDEOCORE_BASE_RPI,
230  .desc = "Model B",
231  },
232  {
233  .hwver = 0x06,
234  .type = RPI_HWVER_TYPE_PI1,
235  .periph_base = PERIPH_BASE_RPI,
236  .videocore_base = VIDEOCORE_BASE_RPI,
237  .desc = "Model B",
238  },
239 
240  //
241  // Model A
242  //
243  {
244  .hwver = 0x07,
245  .type = RPI_HWVER_TYPE_PI1,
246  .periph_base = PERIPH_BASE_RPI,
247  .videocore_base = VIDEOCORE_BASE_RPI,
248  .desc = "Model A",
249  },
250  {
251  .hwver = 0x08,
252  .type = RPI_HWVER_TYPE_PI1,
253  .periph_base = PERIPH_BASE_RPI,
254  .videocore_base = VIDEOCORE_BASE_RPI,
255  .desc = "Model A",
256  },
257  {
258  .hwver = 0x09,
259  .type = RPI_HWVER_TYPE_PI1,
260  .periph_base = PERIPH_BASE_RPI,
261  .videocore_base = VIDEOCORE_BASE_RPI,
262  .desc = "Model A",
263  },
264 
265  //
266  // Model B
267  //
268  {
269  .hwver = 0x0d,
270  .type = RPI_HWVER_TYPE_PI1,
271  .periph_base = PERIPH_BASE_RPI,
272  .videocore_base = VIDEOCORE_BASE_RPI,
273  .desc = "Model B",
274  },
275  {
276  .hwver = 0x0e,
277  .type = RPI_HWVER_TYPE_PI1,
278  .periph_base = PERIPH_BASE_RPI,
279  .videocore_base = VIDEOCORE_BASE_RPI,
280  .desc = "Model B",
281  },
282  {
283  .hwver = 0x0f,
284  .type = RPI_HWVER_TYPE_PI1,
285  .periph_base = PERIPH_BASE_RPI,
286  .videocore_base = VIDEOCORE_BASE_RPI,
287  .desc = "Model B",
288  },
289 
290  //
291  // Model B+
292  //
293  {
294  .hwver = 0x10,
295  .type = RPI_HWVER_TYPE_PI1,
296  .periph_base = PERIPH_BASE_RPI,
297  .videocore_base = VIDEOCORE_BASE_RPI,
298  .desc = "Model B+",
299  },
300  {
301  .hwver = 0x13,
302  .type = RPI_HWVER_TYPE_PI1,
303  .periph_base = PERIPH_BASE_RPI,
304  .videocore_base = VIDEOCORE_BASE_RPI,
305  .desc = "Model B+",
306  },
307  {
308  .hwver = 0x900032,
309  .type = RPI_HWVER_TYPE_PI1,
310  .periph_base = PERIPH_BASE_RPI,
311  .videocore_base = VIDEOCORE_BASE_RPI,
312  .desc = "Model B+",
313  },
314 
315  //
316  // Compute Module
317  //
318  {
319  .hwver = 0x11,
320  .type = RPI_HWVER_TYPE_PI1,
321  .periph_base = PERIPH_BASE_RPI,
322  .videocore_base = VIDEOCORE_BASE_RPI,
323  .desc = "Compute Module 1",
324  },
325  {
326  .hwver = 0x14,
327  .type = RPI_HWVER_TYPE_PI1,
328  .periph_base = PERIPH_BASE_RPI,
329  .videocore_base = VIDEOCORE_BASE_RPI,
330  .desc = "Compute Module 1",
331  },
332 
333  //
334  // Pi Zero
335  //
336  {
337  .hwver = 0x900092,
338  .type = RPI_HWVER_TYPE_PI1,
339  .periph_base = PERIPH_BASE_RPI,
340  .videocore_base = VIDEOCORE_BASE_RPI,
341  .desc = "Pi Zero v1.2",
342  },
343  {
344  .hwver = 0x900093,
345  .type = RPI_HWVER_TYPE_PI1,
346  .periph_base = PERIPH_BASE_RPI,
347  .videocore_base = VIDEOCORE_BASE_RPI,
348  .desc = "Pi Zero v1.3",
349  },
350  {
351  .hwver = 0x920093,
352  .type = RPI_HWVER_TYPE_PI1,
353  .periph_base = PERIPH_BASE_RPI,
354  .videocore_base = VIDEOCORE_BASE_RPI,
355  .desc = "Pi Zero v1.3",
356  },
357  {
358  .hwver = 0x9200c1,
359  .type = RPI_HWVER_TYPE_PI1,
360  .periph_base = PERIPH_BASE_RPI,
361  .videocore_base = VIDEOCORE_BASE_RPI,
362  .desc = "Pi Zero W v1.1",
363  },
364  {
365  .hwver = 0x9000c1,
366  .type = RPI_HWVER_TYPE_PI1,
367  .periph_base = PERIPH_BASE_RPI,
368  .videocore_base = VIDEOCORE_BASE_RPI,
369  .desc = "Pi Zero W v1.1",
370  },
371 
372  //
373  // Model Zero 2 W
374  //
375  {
376  .hwver = 0x902120,
377  .type = RPI_HWVER_TYPE_PI2,
378  .periph_base = PERIPH_BASE_RPI2,
379  .videocore_base = VIDEOCORE_BASE_RPI2,
380  .desc = "Pi Zero 2 W v1.0",
381  },
382 
383  //
384  // Model A+
385  //
386  {
387  .hwver = 0x12,
388  .type = RPI_HWVER_TYPE_PI1,
389  .periph_base = PERIPH_BASE_RPI,
390  .videocore_base = VIDEOCORE_BASE_RPI,
391  .desc = "Model A+",
392  },
393  {
394  .hwver = 0x15,
395  .type = RPI_HWVER_TYPE_PI1,
396  .periph_base = PERIPH_BASE_RPI,
397  .videocore_base = VIDEOCORE_BASE_RPI,
398  .desc = "Model A+",
399  },
400  {
401  .hwver = 0x900021,
402  .type = RPI_HWVER_TYPE_PI1,
403  .periph_base = PERIPH_BASE_RPI,
404  .videocore_base = VIDEOCORE_BASE_RPI,
405  .desc = "Model A+",
406  },
407 
408  //
409  // Pi 2 Model B
410  //
411  {
412  .hwver = 0xa01041,
413  .type = RPI_HWVER_TYPE_PI2,
414  .periph_base = PERIPH_BASE_RPI2,
415  .videocore_base = VIDEOCORE_BASE_RPI2,
416  .desc = "Pi 2",
417  },
418  {
419  .hwver = 0xa01040,
420  .type = RPI_HWVER_TYPE_PI2,
421  .periph_base = PERIPH_BASE_RPI2,
422  .videocore_base = VIDEOCORE_BASE_RPI2,
423  .desc = "Pi 2",
424  },
425  {
426  .hwver = 0xa21041,
427  .type = RPI_HWVER_TYPE_PI2,
428  .periph_base = PERIPH_BASE_RPI2,
429  .videocore_base = VIDEOCORE_BASE_RPI2,
430  .desc = "Pi 2",
431  },
432  //
433  // Pi 2 with BCM2837
434  //
435  {
436  .hwver = 0xa22042,
437  .type = RPI_HWVER_TYPE_PI2,
438  .periph_base = PERIPH_BASE_RPI2,
439  .videocore_base = VIDEOCORE_BASE_RPI2,
440  .desc = "Pi 2",
441  },
442  //
443  // Pi 3 Model B
444  //
445  {
446  .hwver = 0xa020d3,
447  .type = RPI_HWVER_TYPE_PI2,
448  .periph_base = PERIPH_BASE_RPI2,
449  .videocore_base = VIDEOCORE_BASE_RPI2,
450  .desc = "Pi 3 B+",
451  },
452  {
453  .hwver = 0xa02082,
454  .type = RPI_HWVER_TYPE_PI2,
455  .periph_base = PERIPH_BASE_RPI2,
456  .videocore_base = VIDEOCORE_BASE_RPI2,
457  .desc = "Pi 3",
458  },
459  {
460  .hwver = 0xa02083,
461  .type = RPI_HWVER_TYPE_PI2,
462  .periph_base = PERIPH_BASE_RPI2,
463  .videocore_base = VIDEOCORE_BASE_RPI2,
464  .desc = "Pi 3",
465  },
466  {
467  .hwver = 0xa22082,
468  .type = RPI_HWVER_TYPE_PI2,
469  .periph_base = PERIPH_BASE_RPI2,
470  .videocore_base = VIDEOCORE_BASE_RPI2,
471  .desc = "Pi 3",
472  },
473  {
474  .hwver = 0xa22083,
475  .type = RPI_HWVER_TYPE_PI2,
476  .periph_base = PERIPH_BASE_RPI2,
477  .videocore_base = VIDEOCORE_BASE_RPI2,
478  .desc = "Pi 3",
479  },
480  {
481  .hwver = 0x9020e0,
482  .type = RPI_HWVER_TYPE_PI2,
483  .periph_base = PERIPH_BASE_RPI2,
484  .videocore_base = VIDEOCORE_BASE_RPI2,
485  .desc = "Model 3 A+",
486  },
487 
488  //
489  // Pi Compute Module 3
490  //
491  {
492  .hwver = 0xa020a0,
493  .type = RPI_HWVER_TYPE_PI2,
494  .periph_base = PERIPH_BASE_RPI2,
495  .videocore_base = VIDEOCORE_BASE_RPI2,
496  .desc = "Compute Module 3/L3",
497  },
498  //
499  // Pi Compute Module 3+
500  //
501  {
502  .hwver = 0xa02100,
503  .type = RPI_HWVER_TYPE_PI2,
504  .periph_base = PERIPH_BASE_RPI2,
505  .videocore_base = VIDEOCORE_BASE_RPI2,
506  .desc = "Compute Module 3+",
507  },
508 
509 
510 };
511 
512 
514 {
515  const rpi_hw_t *result = NULL;
516  uint32_t rev;
517  unsigned i;
518 
519 #ifdef __aarch64__
520  // On ARM64, read revision from /proc/device-tree as it is not shown in
521  // /proc/cpuinfo
522  FILE *f = fopen("/proc/device-tree/system/linux,revision", "r");
523  if (!f)
524  {
525  return NULL;
526  }
527  size_t read = fread(&rev, 1, sizeof(uint32_t), f);
528  if (read != sizeof(uint32_t))
529  goto done;
530  #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
531  rev = bswap_32(rev); // linux,revision appears to be in big endian
532  #endif
533 
534  for (i = 0; i < (sizeof(rpi_hw_info) / sizeof(rpi_hw_info[0])); i++)
535  {
536  uint32_t hwver = rpi_hw_info[i].hwver;
537  if (rev == hwver)
538  {
539  result = &rpi_hw_info[i];
540 
541  goto done;
542  }
543  }
544 #else
545  FILE *f = fopen("/proc/cpuinfo", "r");
546  char line[LINE_WIDTH_MAX];
547 
548  if (!f)
549  {
550  return NULL;
551  }
552 
553  while (fgets(line, LINE_WIDTH_MAX - 1, f))
554  {
555  if (strstr(line, HW_VER_STRING))
556  {
557  char *substr;
558 
559  substr = strstr(line, ": ");
560  if (!substr)
561  {
562  continue;
563  }
564 
565  errno = 0;
566  rev = strtoul(&substr[1], NULL, 16); // Base 16
567  if (errno)
568  {
569  continue;
570  }
571 
572  for (i = 0; i < (sizeof(rpi_hw_info) / sizeof(rpi_hw_info[0])); i++)
573  {
574  uint32_t hwver = rpi_hw_info[i].hwver;
575 
576  // Take out warranty and manufacturer bits
579 
580  if (rev == hwver)
581  {
582  result = &rpi_hw_info[i];
583 
584  goto done;
585  }
586  }
587  }
588  }
589 #endif
590 done:
591  fclose(f);
592 
593  return result;
594 }
595 
VIDEOCORE_BASE_RPI
#define VIDEOCORE_BASE_RPI
Definition: rpihw.c:48
VIDEOCORE_BASE_RPI2
#define VIDEOCORE_BASE_RPI2
Definition: rpihw.c:49
LINE_WIDTH_MAX
#define LINE_WIDTH_MAX
Definition: rpihw.c:41
f
f
rpi_hw_info
static const rpi_hw_t rpi_hw_info[]
Definition: rpihw.c:54
RPI_HWVER_TYPE_PI1
#define RPI_HWVER_TYPE_PI1
Definition: rpihw.h:39
RPI_WARRANTY_MASK
#define RPI_WARRANTY_MASK
Definition: rpihw.c:52
PERIPH_BASE_RPI4
#define PERIPH_BASE_RPI4
Definition: rpihw.c:46
rpi_hw_detect
const rpi_hw_t * rpi_hw_detect(void)
Definition: rpihw.c:513
HW_VER_STRING
#define HW_VER_STRING
Definition: rpihw.c:42
RPI_MANUFACTURER_MASK
#define RPI_MANUFACTURER_MASK
Definition: rpihw.c:51
PERIPH_BASE_RPI
#define PERIPH_BASE_RPI
Definition: rpihw.c:44
PERIPH_BASE_RPI2
#define PERIPH_BASE_RPI2
Definition: rpihw.c:45
rpi_hw_t
Definition: rpihw.h:36
RPI_HWVER_TYPE_PI2
#define RPI_HWVER_TYPE_PI2
Definition: rpihw.h:40
rpihw.h
rpi_hw_t::hwver
uint32_t hwver
Definition: rpihw.h:42
RPI_HWVER_TYPE_PI4
#define RPI_HWVER_TYPE_PI4
Definition: rpihw.h:41


ws281x
Author(s): Alexey Rogachevskiy , Oleg Kalachev
autogenerated on Wed Jun 15 2022 02:21:36