Skip to content

Commit 374ace1

Browse files
committed
WIP
1 parent 7dbc0be commit 374ace1

File tree

7 files changed

+335
-0
lines changed

7 files changed

+335
-0
lines changed

boards/nvidia/jetson-xavier.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import boards
2+
from linux import sysfs
3+
4+
class Board(boards.Board):
5+
__compatible__ = 'nvidia,p2972-0000'
6+
name = 'NVIDIA Jetson Xavier Development Kit'
7+
8+
devices = [
9+
# platform bus
10+
sysfs.Device('platform', '2200000.gpio', 'tegra186-gpio'),
11+
sysfs.Device('platform', '2490000.ethernet', 'dwc-eth-dwmac'),
12+
sysfs.Device('platform', '3110000.serial', 'of_serial'),
13+
sysfs.Device('platform', '31c0000.i2c', 'tegra-i2c'),
14+
sysfs.Device('platform', '3400000.sdhci', 'sdhci-tegra'),
15+
sysfs.Device('platform', '3460000.sdhci', 'sdhci-tegra'),
16+
sysfs.Device('platform', '3c00000.hsp', 'tegra-hsp'),
17+
sysfs.Device('platform', 'c150000.hsp', 'tegra-hsp'),
18+
sysfs.Device('platform', 'c340000.pwm', 'tegra-pwm'),
19+
sysfs.Device('platform', 'c360000.pmc', 'tegra-pmc'),
20+
sysfs.Device('platform', '13e00000.host1x', 'tegra-host1x'),
21+
sysfs.Device('platform', 'bpmp', 'tegra-bpmp'),
22+
sysfs.Device('platform', 'bpmp:i2c', 'tegra-bpmp-i2c'),
23+
sysfs.Device('platform', 'bpmp:thermal', 'tegra-bpmp-thermal'),
24+
sysfs.Device('platform', 'fan', 'pwm-fan'),
25+
sysfs.Device('platform', 'gpio-keys', 'gpio-keys'),
26+
# I2C bus
27+
sysfs.Device('i2c', '0-003c', 'max77620'),
28+
]
29+
30+
whitelist = [
31+
r'OF: fdt: Reserved memory: unsupported node format, ignoring',
32+
r'EINJ: ACPI disabled.',
33+
r'cacheinfo: Unable to detect cache hierarchy for CPU 0',
34+
r'dwc-eth-dwmac 2490000.ethernet: Cannot get CSR clock',
35+
r'mmc0: Unknown controller version \(5\). You may experience problems.',
36+
r'mmc1: Unknown controller version \(5\). You may experience problems.',
37+
r'tegra-dpaux 155e0000.dpaux: 155e0000.dpaux supply vdd not found, using dummy regulator',
38+
r'\[drm\] parse error at position 6 in video mode \'tegrafb\'',
39+
]

linux/system.py

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import ctypes
44
import os
5+
import platform
56
import sys
67
import time
78

@@ -173,6 +174,75 @@ def set_alarm_relative(self, alarm):
173174
with self.sysfs.open('wakealarm', 'w') as file:
174175
file.write('%u' % alarm)
175176

177+
class Kernel:
178+
class Version:
179+
def __init__(self, release = None):
180+
if not release:
181+
self.release = platform.release()
182+
else:
183+
self.release = release
184+
185+
try:
186+
self.version, self.extra = self.release.split('-', maxsplit = 1)
187+
except:
188+
self.version = self.release
189+
self.extra = None
190+
191+
try:
192+
major, minor, patch = self.version.split('.')
193+
except:
194+
major, minor = self.version.split('.')
195+
patch = 0
196+
197+
self.major = int(major)
198+
self.minor = int(minor)
199+
self.patch = int(patch)
200+
201+
def numerical(self):
202+
return self.major << 16 | self.minor << 8 | self.patch
203+
204+
def __lt__(self, other):
205+
if isinstance(other, str):
206+
other = Version(other)
207+
208+
return self.numerical() < other.numerical()
209+
210+
def __le__(self, other):
211+
if isinstance(other, str):
212+
other = Version(other)
213+
214+
return self.numerical() <= other.numerical()
215+
216+
def __eq__(self, other):
217+
if isinstance(other, str):
218+
other = Version(other)
219+
220+
return self.numerical() == other.numerical()
221+
222+
def __gt__(self, other):
223+
if isinstance(other, str):
224+
other = Version(other)
225+
226+
return self.numerical() > other.numerical()
227+
228+
def __ge__(self, other):
229+
if isinstance(other, str):
230+
other = Version(other)
231+
232+
return self.numerical() >= other.numerical()
233+
234+
def __repr__(self):
235+
return '%u.%u.%u' % (self.major, self.minor, self.patch)
236+
237+
def __str__(self):
238+
if self.extra:
239+
return '%u.%u.%u-%s' % (self.major, self.minor, self.patch, self.extra)
240+
else:
241+
return repr(self)
242+
243+
def __init__(self):
244+
self.version = Kernel.Version()
245+
176246
'''
177247
Provides access to the system and system wide controls.
178248
'''

linux/util.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#!/usr/bin/python3
2+
3+
import re
4+
5+
class WhiteList():
6+
def __init__(self, patterns):
7+
self.patterns = [ re.compile(pattern) for pattern in patterns ]
8+
9+
def __contains__(self, item):
10+
for pattern in self.patterns:
11+
if pattern.match(item.message):
12+
return True
13+
14+
return False

tegra/tegra194.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import tegra
2+
3+
class SoC(tegra.SoC):
4+
compatible = 'nvidia,tegra194'
5+
name = 'NVIDIA Tegra194'
6+
7+
def __init__(self):
8+
self.num_cpus = 8

tests/boot.py

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
#!/usr/bin/python3
2+
3+
import os.path, sys
4+
import runner
5+
6+
module = sys.modules[__name__]
7+
module.name = 'boot'
8+
9+
class devices(runner.Test):
10+
def __call__(self, log, *args, **kwargs):
11+
import boards
12+
13+
board = boards.detect()
14+
failed = False
15+
16+
log.debug('board:', board.name)
17+
18+
for device in board.devices:
19+
path = os.path.join('/sys', 'bus', device.bus, 'devices', device.name)
20+
21+
log.debug(' device: %s ... ' % path, end = '', flush = True)
22+
23+
if os.path.exists(path):
24+
log.cont('exists')
25+
else:
26+
log.cont('failed')
27+
failed = True
28+
continue
29+
30+
path = os.path.join(path, 'driver')
31+
32+
if os.path.exists(path):
33+
path = os.path.realpath(path)
34+
driver = os.path.basename(path)
35+
36+
log.debug(' bound: %s ... ' % driver, end = '', flush = True)
37+
38+
if driver != device.driver:
39+
log.cont('failed')
40+
failed = True
41+
else:
42+
log.cont('done')
43+
else:
44+
log.debug('unbound')
45+
46+
if device.driver:
47+
failed = True
48+
49+
if failed:
50+
raise runner.Error()
51+
52+
class logs(runner.Test):
53+
def __call__(self, log, *args, **kwargs):
54+
from linux import kmsg, system, util
55+
import boards
56+
57+
board = boards.detect()
58+
kernel = system.Kernel()
59+
whitelist = util.WhiteList(board.whitelist)
60+
count = 0
61+
62+
with kmsg.open('/dev/kmsg') as dmesg:
63+
for entry in dmesg:
64+
if entry.header.facility == kmsg.LOG_KERN and \
65+
entry.header.level <= kmsg.LOG_WARNING:
66+
if entry not in whitelist:
67+
log.debug(entry)
68+
count += 1
69+
70+
if count > 0:
71+
andor = 'and/or' if count > 1 else 'or'
72+
plural = 's' if count > 1 else ''
73+
74+
raise runner.Error('%u warning%s %s error%s found in the kernel log' % (count, plural, andor, plural))
75+
76+
tests = [
77+
devices,
78+
logs,
79+
]
80+
81+
if __name__ == '__main__':
82+
runner.standalone(sys.modules[__name__])

tests/drm.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#!/usr/bin/python3
22

3+
import boards
34
import os
45
import sys
56
import unittest
@@ -43,3 +44,9 @@ def test_list_devices(self):
4344
version.minor,
4445
version.patch,
4546
version.date))
47+
48+
def test_modeset(self):
49+
board = boards.detect()
50+
51+
for mode in board.modes:
52+
print('mode: %s, CRC: %s' % (mode.name, mode.crc))

tests/runner.py

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
#!/usr/bin/python3
2+
3+
import argparse, builtins, io, os.path, sys
4+
5+
class Log:
6+
def __init__(self, module, output):
7+
self.module = module
8+
self.output = output
9+
self.verbose = False
10+
self.test = None
11+
12+
def print(self, *args, **kwargs):
13+
if self.output:
14+
kwargs['file'] = self.output
15+
16+
builtins.print(*args, **kwargs)
17+
18+
def info(self, *args, **kwargs):
19+
if self.test:
20+
args = [ '%s:' % type(self.test).__name__, *args ]
21+
22+
args = [ '%s:' % self.module.name, *args ]
23+
24+
self.print(*args, **kwargs)
25+
self.next = self.print
26+
27+
def debug(self, *args, **kwargs):
28+
if self.verbose:
29+
self.info(*args, **kwargs)
30+
self.next = self.print
31+
else:
32+
self.next = None
33+
34+
def cont(self, *args, **kwargs):
35+
if self.next:
36+
kwargs['file'] = self.output
37+
38+
self.next(*args, **kwargs)
39+
40+
class Test:
41+
pass
42+
43+
class Error(Exception):
44+
pass
45+
46+
def setup():
47+
path = os.path.dirname(sys.argv[0])
48+
path = os.path.join(path, '..')
49+
path = os.path.abspath(path)
50+
51+
sys.path.append(path)
52+
53+
def standalone(module):
54+
output = sys.stdout
55+
56+
parser = argparse.ArgumentParser('')
57+
parser.add_argument('--quiet', '-q', action = 'store_true')
58+
parser.add_argument('--summary', '-s', action = 'store_true')
59+
parser.add_argument('--verbose', '-v', action = 'store_true')
60+
args = parser.parse_args(sys.argv[1:])
61+
62+
if args.quiet:
63+
output = io.StringIO()
64+
65+
log = Log(module, output)
66+
67+
if args.verbose or args.quiet:
68+
log.verbose = True
69+
70+
okay = 0
71+
fail = 0
72+
skip = 0
73+
74+
setup()
75+
76+
for test in module.tests:
77+
log.test = test()
78+
79+
try:
80+
log.test(log = log)
81+
82+
if args.summary:
83+
log.info('OKAY')
84+
85+
okay += 1
86+
except Error as e:
87+
log.info(e)
88+
89+
if args.summary:
90+
log.info('FAIL')
91+
92+
fail += 1
93+
except Exception as e:
94+
raise
95+
96+
log.test = None
97+
98+
if args.summary:
99+
log.info('Tests:', okay + fail + skip)
100+
log.info(' okay:', okay)
101+
log.info(' fail:', fail)
102+
log.info(' skip:', skip)
103+
104+
if fail > 0:
105+
log.info('FAIL')
106+
107+
if args.quiet:
108+
output.seek(0, io.SEEK_SET)
109+
message = output.read()
110+
print(message, file = sys.stderr, end = '')
111+
112+
sys.exit(1)
113+
else:
114+
log.info('OKAY')
115+
sys.exit(0)

0 commit comments

Comments
 (0)