-
Notifications
You must be signed in to change notification settings - Fork 264
Expand file tree
/
Copy pathchip.py
More file actions
502 lines (420 loc) · 18.6 KB
/
chip.py
File metadata and controls
502 lines (420 loc) · 18.6 KB
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
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
# SPDX-FileCopyrightText: 2021 Melissa LeBlanc-Williams for Adafruit Industries
#
# SPDX-License-Identifier: MIT
"""
`adafruit_platformdetect.chip`
================================================================================
Attempt detection of current chip / CPU
* Author(s): Melissa LeBlanc-Williams
Implementation Notes
--------------------
**Software and Dependencies:**
* Linux and Python 3.7 or Higher
"""
import os
import sys
try:
from typing import Optional
except ImportError:
pass
from adafruit_platformdetect.constants import chips
__version__ = "0.0.0+auto.0"
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_PlatformDetect.git"
class Chip:
"""Attempt detection of current chip / CPU."""
def __init__(self, detector) -> None:
self.detector = detector
self._chip_id = None
# pylint: disable=invalid-name,too-many-branches,too-many-return-statements
@property
def id(
self,
) -> Optional[str]:
"""Return a unique id for the detected chip, if any."""
# There are some times we want to trick the platform detection
# say if a raspberry pi doesn't have the right ID, or for testing
# Caching
if self._chip_id:
return self._chip_id
if getattr(os, "environ", None) is not None:
try:
return os.environ["BLINKA_FORCECHIP"]
except KeyError: # no forced chip, continue with testing!
pass
# Special cases controlled by environment var
if os.environ.get("BLINKA_FT232H"):
from pyftdi.usbtools import UsbTools
# look for it based on PID/VID
count = len(UsbTools.find_all([(0x0403, 0x6014)]))
if count == 0:
raise RuntimeError(
"BLINKA_FT232H environment variable "
+ "set, but no FT232H device found"
)
self._chip_id = chips.FT232H
return self._chip_id
if os.environ.get("BLINKA_FT2232H"):
from pyftdi.usbtools import UsbTools
# look for it based on PID/VID
count = len(UsbTools.find_all([(0x0403, 0x6010)]))
if count == 0:
raise RuntimeError(
"BLINKA_FT2232H environment variable "
+ "set, but no FT2232H device found"
)
self._chip_id = chips.FT2232H
return self._chip_id
if os.environ.get("BLINKA_FT4232H"):
from pyftdi.usbtools import UsbTools
# look for it based on PID/VID
count = len(UsbTools.find_all([(0x0403, 0x6011)]))
if count == 0:
raise RuntimeError(
"BLINKA_FT4232H environment variable "
+ "set, but no FT4232H device found"
)
self._chip_id = chips.FT4232H
return self._chip_id
if os.environ.get("BLINKA_MCP2221"):
import hid
# look for it based on PID/VID
for dev in hid.enumerate():
if dev["vendor_id"] == 0x04D8 and dev["product_id"] == 0x00DD:
self._chip_id = chips.MCP2221
return self._chip_id
raise RuntimeError(
"BLINKA_MCP2221 environment variable "
+ "set, but no MCP2221 device found"
)
if os.environ.get("BLINKA_SPIDRIVER"):
self._chip_id = chips.SPIDRIVER
return self._chip_id
if os.environ.get("BLINKA_OS_AGNOSTIC"):
# we don't need to look for this chip, it's just a flag
self._chip_id = chips.OS_AGNOSTIC
return self._chip_id
if os.environ.get("BLINKA_U2IF"):
import hid
# look for it based on PID/VID
for dev in hid.enumerate():
vendor = dev["vendor_id"]
product = dev["product_id"]
# NOTE: If any products are added here, they need added
# to _rp2040_u2if_id() in board.py as well.
# pylint: disable=too-many-boolean-expressions
if (
(
# Raspberry Pi Pico
# Radxa X4
vendor in (0xCAFE, 0xCAFF)
and product == 0x4005
)
or (
# Waveshare RP2040 One
vendor == 0x2E8A
and product == 0x103A
)
or (
# Feather RP2040
# Itsy Bitsy RP2040
# QT Py RP2040
# QT2040 Trinkey
# MacroPad RP2040
# Feather RP2040 ThinkInk
# Feather RP2040 RFM
# Feather RP2040 CAN Bus
vendor == 0x239A
and product
in (
0x00F1,
0x00FD,
0x00F7,
0x0109,
0x0107,
0x812C,
0x812E,
0x8130,
0x0105,
)
)
):
self._chip_id = chips.RP2040_U2IF
return self._chip_id
raise RuntimeError(
"BLINKA_U2IF environment variable "
+ "set, but no compatible device found"
)
if os.environ.get("BLINKA_GREATFET"):
import usb
if usb.core.find(idVendor=0x1D50, idProduct=0x60E6) is not None:
self._chip_id = chips.LPC4330
return self._chip_id
raise RuntimeError(
"BLINKA_GREATFET environment variable "
+ "set, but no GreatFET device found"
)
if os.environ.get("BLINKA_NOVA"):
self._chip_id = chips.BINHO
return self._chip_id
platform = sys.platform
if platform in ("linux", "linux2"):
self._chip_id = self._linux_id()
return self._chip_id
if platform == "esp8266":
self._chip_id = chips.ESP8266
return self._chip_id
if platform == "samd21":
self._chip_id = chips.SAMD21
return self._chip_id
if platform == "pyboard":
self._chip_id = chips.STM32F405
return self._chip_id
if platform == "rp2":
self._chip_id = chips.RP2040
return self._chip_id
# nothing found!
return None
# pylint: enable=invalid-name
def _linux_id(self) -> Optional[str]:
# pylint: disable=too-many-branches,too-many-statements
# pylint: disable=too-many-return-statements
"""Attempt to detect the CPU on a computer running the Linux kernel."""
if self.detector.check_dt_compatible_value("beagle,am67a-beagley-ai"):
return chips.AM67A
if self.detector.check_dt_compatible_value("beagle,am62-pocketbeagle2ti,am625"):
return chips.AM625X
if self.detector.check_dt_compatible_value("ti,am625"):
return chips.AM625X
if self.detector.check_dt_compatible_value("ti,am654"):
return chips.AM65XX
if self.detector.check_dt_compatible_value("ti,am652"):
return chips.AM65XX
if self.detector.check_dt_compatible_value("sun4i-a10"):
return chips.A10
if self.detector.check_dt_compatible_value("sun7i-a20"):
return chips.A20
if self.detector.check_dt_compatible_value("amlogic,g12a"):
return chips.S905Y2
if self.detector.check_dt_compatible_value("amlogic, g12a"):
return chips.S905X3
if self.detector.check_dt_compatible_value("sun8i-h3"):
return chips.H3
if self.detector.check_dt_compatible_value("qcom,apq8016"):
return chips.APQ8016
if self.detector.check_dt_compatible_value("fu500"):
return chips.HFU540
if self.detector.check_dt_compatible_value("sun20iw1p1"):
return chips.C906
# Older Builds
if self.detector.check_dt_compatible_value("sifive"):
return chips.JH71X0
# Newer Builds
if self.detector.check_dt_compatible_value("jh7100"):
return chips.JH71X0
if self.detector.check_dt_compatible_value("jh7110"):
return chips.JH7110
if self.detector.check_dt_compatible_value("sun8i-a33"):
return chips.A33
if self.detector.check_dt_compatible_value("rockchip,rk3308"):
return chips.RK3308
if self.detector.check_dt_compatible_value("radxa,rock-4c-plus"):
return chips.RK3399_T
if self.detector.check_dt_compatible_value("rockchip,rk3399pro"):
return chips.RK3399PRO
if self.detector.check_dt_compatible_value("rockchip,rk3399"):
return chips.RK3399
if self.detector.check_dt_compatible_value("rockchip,rk3288"):
return chips.RK3288
if self.detector.check_dt_compatible_value("rockchip,rk3328"):
return chips.RK3328
if self.detector.check_dt_compatible_value("rockchip,rk3566"):
return chips.RK3566
if self.detector.check_dt_compatible_value("rockchip,rk3568"):
return chips.RK3568
if self.detector.check_dt_compatible_value("rockchip,rk3588s"):
return chips.RK3588S
if self.detector.check_dt_compatible_value("rockchip,rk3588"):
return chips.RK3588
if self.detector.check_dt_compatible_value("rockchip,rv1106"):
return chips.RV1106
if self.detector.check_dt_compatible_value("rockchip,rv1103"):
return chips.RV1103
if self.detector.check_dt_compatible_value("amlogic,a311d"):
return chips.A311D
if self.detector.check_dt_compatible_value("st,stm32mp157"):
return chips.STM32MP157
if self.detector.check_dt_compatible_value("st,stm32mp153"):
return chips.STM32MP157DAA1
if self.detector.check_dt_compatible_value("sun50i-a64"):
return chips.A64
if self.detector.check_dt_compatible_value("sun50i-h5"):
return chips.H5
if self.detector.check_dt_compatible_value("sun50i-h618"):
return chips.H618
if self.detector.check_dt_compatible_value("sun50i-h616"):
return chips.H616
if self.detector.check_dt_compatible_value("sun50iw9"):
return chips.H616
if self.detector.check_dt_compatible_value("sun50i-h6"):
return chips.H6
if self.detector.check_dt_compatible_value("sun55iw3"):
return chips.T527
if self.detector.check_dt_compatible_value("spacemit,k1-x"):
return chips.K1
if self.detector.check_dt_compatible_value("renesas,r9a09g056"):
return chips.RZV2N
if self.detector.check_dt_compatible_value("renesas,r9a09g057"):
return chips.RZV2H
if self.detector.check_dt_compatible_value("mediatek,mt8167"):
return chips.MT8167
if self.detector.check_dt_compatible_value("imx6ull"):
return chips.IMX6ULL
if self.detector.check_dt_compatible_value("ti,j721e"):
return chips.TDA4VM
if self.detector.check_dt_compatible_value("sun20i-d1"):
return chips.D1_RISCV
if self.detector.check_dt_compatible_value("imx8mp"):
return chips.IMX8MP
if self.detector.check_dt_compatible_value("libretech,aml-s905x-cc"):
return chips.S905X
if self.detector.check_dt_compatible_value("light-lpi4a"):
return chips.TH1520
if self.detector.check_dt_compatible_value("hobot,x3"):
return chips.SUNRISE_X3
if self.detector.check_dt_compatible_value("Horizon, x5"):
return chips.SUNRISE_X5
if self.detector.check_dt_compatible_value("particle,tachyon"):
return chips.QCM6490
linux_id = None
hardware = self.detector.get_cpuinfo_field("Hardware")
if hardware is None:
vendor_id = self.detector.get_cpuinfo_field("vendor_id")
if vendor_id == "AuthenticAMD":
model_name = self.detector.get_cpuinfo_field("model name").upper()
if "RYZEN EMBEDDED V1202B" in model_name:
linux_id = chips.RYZEN_V1202B
if "RYZEN EMBEDDED V1605B" in model_name:
linux_id = chips.RYZEN_V1605B
else:
linux_id = chips.GENERIC_X86
## print("linux_id = ", linux_id)
elif vendor_id == "GenuineIntel":
model_name = self.detector.get_cpuinfo_field("model name").upper()
## print('model_name =', model_name)
if "N3710" in model_name:
linux_id = chips.PENTIUM_N3710
if "N5105" in model_name:
linux_id = chips.CELERON_N5105
elif "X5-Z8350" in model_name:
linux_id = chips.ATOM_X5_Z8350
elif "J4105" in model_name:
linux_id = chips.ATOM_J4105
else:
linux_id = chips.GENERIC_X86
## print("linux_id = ", linux_id)
compatible = self.detector.get_device_compatible()
if compatible and "tegra" in compatible:
compats = compatible.split("\x00")
if "nvidia,tegra210" in compats:
linux_id = chips.T210
elif "nvidia,tegra186" in compats:
linux_id = chips.T186
elif "nvidia,tegra194" in compats:
linux_id = chips.T194
elif "nvidia,tegra234" in compats:
linux_id = chips.T234
elif "nvidia,tegra264" in compats:
linux_id = chips.T264
if compatible and "imx8m" in compatible:
linux_id = chips.IMX8MX
if compatible and "odroid-c2" in compatible:
linux_id = chips.S905
if compatible and "amlogic" in compatible:
compatible_list = (
compatible.replace("\x00", ",").replace(" ", "").split(",")
)
if "g12a" in compatible_list:
# 'sm1' is correct for S905X3, but some kernels use 'g12a'
return chips.S905X3
if "g12b" in compatible_list:
return chips.S922X
if "sm1" in compatible_list:
return chips.S905X3
if "vim3amlogic" in compatible_list:
return chips.A311D
if compatible and "sun50i-a64" in compatible:
linux_id = chips.A64
if compatible and "sun50i-h6" in compatible:
linux_id = chips.H6
if compatible and "sun50i-h5" in compatible:
linux_id = chips.H5
if compatible and "odroid-xu4" in compatible:
linux_id = chips.EXYNOS5422
if compatible and "cvitek,cv180x" in compatible:
linux_id = chips.CV1800B
if compatible and "xlnx,zynqmp" in compatible:
linux_id = chips.ZYNQMP
cpu_model = self.detector.get_cpuinfo_field("cpu model")
if cpu_model is not None:
if "MIPS 24Kc" in cpu_model:
linux_id = chips.MIPS24KC
elif "MIPS 24KEc" in cpu_model:
linux_id = chips.MIPS24KEC
# we still haven't identified the hardware, so
# convert it to a list and let the remaining
# conditions attempt.
if not linux_id:
hardware = [
entry.replace("\x00", "") for entry in compatible.split(",")
]
if not linux_id:
if "AM33XX" in hardware:
linux_id = chips.AM33XX
elif "DRA74X" in hardware:
linux_id = chips.DRA74X
elif "sun4i" in hardware:
linux_id = chips.A10
elif "sun7i" in hardware:
linux_id = chips.A20
elif "sun8i" in hardware:
linux_id = chips.SUN8I
elif "ODROIDC" in hardware:
linux_id = chips.S805
elif "ODROID-C2" in hardware:
linux_id = chips.S905
elif "ODROID-N2" in hardware:
linux_id = chips.S922X
elif "ODROID-C4" in hardware:
linux_id = chips.S905X3
elif "ODROID-XU4" in hardware:
linux_id = chips.EXYNOS5422
elif "KHADAS-VIM3" in hardware:
linux_id = chips.A311D
elif "SAMA5" in hardware:
linux_id = chips.SAMA5
elif "Pinebook" in hardware:
linux_id = chips.A64
elif "ASUS_TINKER_BOARD" in hardware:
linux_id = chips.RK3288
elif "Xilinx Zynq" in hardware:
compatible = self.detector.get_device_compatible()
if compatible and "xlnx,zynq-7000" in compatible:
linux_id = chips.ZYNQ7000
else:
if isinstance(hardware, str):
if hardware.upper() in chips.BCM_RANGE:
linux_id = chips.BCM2XXX
elif isinstance(hardware, list):
if {model.upper() for model in hardware} & chips.BCM_RANGE:
linux_id = chips.BCM2XXX
return linux_id
def __getattr__(self, attr: str) -> bool:
"""
Detect whether the given attribute is the currently-detected chip. See
list of constants at the top of this module for available options.
"""
if attr == "id":
raise AttributeError() # Avoid infinite recursion
if self.id == attr:
return True
return False