forked from jgarff/rpi_ws281x
-
Notifications
You must be signed in to change notification settings - Fork 4
/
board_info.c
185 lines (150 loc) · 4.33 KB
/
board_info.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
/*
* This needs cleaning up and expanding. The MODEL_* defines shoudl be in
* board_info.h, it currently identifies everything not a B2 as a B, it
* should have an accessor function for the board model and revision, etc.
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include "board_info.h"
// jimbotel: move OSC_FREQ here from ws2811.c as this board-dependent
#define OSC_FREQ 19200000 // crystal frequency
#define OSC_FREQ_2711 54000000 // raspberry Pi 4B uses BCM2711 Crystal 19.2->54M
// jimbotel: add model 4B
enum
{
MODEL_UNKNOWN,
MODEL_A,
MODEL_A_PLUS,
MODEL_B,
MODEL_B_PLUS,
MODEL_B_2,
MODEL_4B,
};
static int board_info_initialised = 0;
static int board_model = MODEL_UNKNOWN;
static int board_revision;
static void
fatal(char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
exit(1);
}
// jimbotel: add get_osc_freq function to obtain osc_freq of the board
uint32_t get_osc_freq(void)
{
uint32_t osc_freq;
board_info_init();
if(board_info_initialised == 0)
return -1;
if(board_model == MODEL_4B)
osc_freq = OSC_FREQ_2711;
else
osc_freq = OSC_FREQ;
return osc_freq;
}
static unsigned get_dt_ranges(const char *filename, unsigned offset)
{
unsigned address = ~0;
FILE *fp = fopen(filename, "rb");
if (fp)
{
unsigned char buf[4];
fseek(fp, offset, SEEK_SET);
if (fread(buf, 1, sizeof buf, fp) == sizeof buf)
address = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3] << 0;
fclose(fp);
}
return address;
}
uint32_t board_info_peripheral_base_addr(void)
{
unsigned address = get_dt_ranges("/proc/device-tree/soc/ranges", 4);
board_info_init();
// jimbotel: in the pi4, the address obtained is 0.
if (address == 0)
{
if (board_model == MODEL_4B)
return 0xFE000000;
}
if (address == (unsigned) ~0)
{
if (board_model == MODEL_B_2)
return 0x3f000000;
// jimbotel: I also added here just in case, however I haven't seen address being all 1s
else if (board_model == MODEL_4B)
return 0xFE000000;
else
return 0x20000000;
}
else
{
return address;
}
}
uint32_t board_info_sdram_address(void)
{
unsigned address = get_dt_ranges("/proc/device-tree/axi/vc_mem/reg", 8);
board_info_init();
if (address == (unsigned)~0)
{
// jimbotel: Pi4 shares the same sdram address as previous generation
if (board_model == MODEL_B_2 || board_model == MODEL_4B)
return 0xc0000000;
else
return 0x40000000;
}
else
{
return address;
}
}
int board_info_init(void)
{
char buf[128], revstr[128], modelstr[128];
char *ptr, *end, *res;
FILE *fp;
if (board_info_initialised)
return 0;
revstr[0] = modelstr[0] = '\0';
fp = fopen("/proc/cpuinfo", "r");
if (!fp)
fatal("Unable to open /proc/cpuinfo: %m\n");
while ((res = fgets(buf, 128, fp))) {
if (!strncasecmp("model name", buf, 8))
memcpy(modelstr, buf, 128);
else if (!strncasecmp(buf, "revision", 8))
memcpy(revstr, buf, 128);
}
fclose(fp);
if (modelstr[0] == '\0')
fatal("No 'Model name' record in /proc/cpuinfo\n");
if (revstr[0] == '\0')
fatal("No 'Revision' record in /proc/cpuinfo\n");
if (strstr(modelstr, "ARMv6"))
board_model = MODEL_B;
else if (strstr(modelstr, "ARMv7"))
board_model = MODEL_B_2;
else
fatal("Cannot parse the model name string\n");
ptr = revstr + strlen(revstr) - 3;
board_revision = strtol(ptr, &end, 16);
// jimbotel: according to https://www.raspberrypi.org/documentation/hardware/raspberrypi/revision-codes/README.md , last two digits of revision = 17 (hex 11) for Pi4
// jimbotel: board_revision will become 2 a few lines below. Not sure why board_revision is finally set to either 1 or 2, I just didn't want to change previous behavior.
if (board_revision == 17)
board_model = MODEL_4B;
if (end != ptr + 2)
fatal("Failed to parse Revision string\n");
if (board_revision < 1)
fatal("Invalid board Revision\n");
else if (board_revision < 4)
board_revision = 1;
else
board_revision = 2;
board_info_initialised = 1;
return 0;
}