blob: dd767528dbfbb72918deb92bb48e0fe8d3c36942 [file] [log] [blame]
Love Kumareb8eb902024-07-31 14:54:12 +05301# SPDX-License-Identifier: GPL-2.0
2# (C) Copyright 2024, Advanced Micro Devices, Inc.
3
4"""
5Note: This test relies on boardenv_* containing configuration values to define
6spi minimum and maximum frequencies at which the flash part can operate on and
7these tests run at different spi frequency randomised values in the range
8multiple times based on the user defined iteration value.
9It also defines the SPI bus number containing the SPI-flash chip, SPI
10chip-select, SPI mode, SPI flash part name and timeout parameters. If minimum
11and maximum frequency is not defined, it will run on freq 0 by default.
12
13Without the boardenv_* configuration, this test will be automatically skipped.
14
15It also relies on configuration values for supported flashes for lock and
16unlock cases for SPI family flash. It will run lock-unlock cases only for the
17supported flash parts.
18
19For Example:
20
21# Details of SPI device test parameters required for SPI device testing:
22
23# bus - SPI bus number to init the flash device
24# chip_select - SPI chip select number to init the flash device
25# min_freq - Minimum frequency in hz at which the flash part can operate, set 0
26# or None for default frequency
27# max_freq - Maximum frequency in hz at which the flash part can operate, set 0
28# or None for default frequency
29# mode - SPI mode to init the flash device
30# part_name - SPI flash part name to be detected
31# timeout - Default timeout to run the sf commands
32# iteration - No of iteration to run SPI flash test
33
34env__spi_device_test = {
35 'bus': 0,
36 'chip_select': 0,
37 'min_freq': 10000000,
38 'max_freq': 100000000,
39 'mode': 0,
40 'part_name': 'n25q00a',
41 'timeout': 100000,
42 'iteration': 5,
43}
44
45# supported_flash - Flash parts name which support lock-unlock functionality
46env__spi_lock_unlock = {
47 'supported_flash': 'mt25qu512a, n25q00a, n25q512ax3',
48}
49"""
50
51import random
52import re
53import pytest
Simon Glassfb916372025-02-09 09:07:15 -070054import utils
Love Kumareb8eb902024-07-31 14:54:12 +053055
56SPI_DATA = {}
57EXPECTED_ERASE = 'Erased: OK'
58EXPECTED_WRITE = 'Written: OK'
59EXPECTED_READ = 'Read: OK'
60EXPECTED_ERASE_ERRORS = [
61 'Erase operation failed',
62 'Attempted to modify a protected sector',
63 'Erased: ERROR',
64 'is protected and cannot be erased',
65 'ERROR: flash area is locked',
66]
67EXPECTED_WRITE_ERRORS = [
68 'ERROR: flash area is locked',
69 'Program operation failed',
70 'Attempted to modify a protected sector',
71 'Written: ERROR',
72]
73
Simon Glassddba5202025-02-09 09:07:14 -070074def get_params_spi(ubman):
Love Kumareb8eb902024-07-31 14:54:12 +053075 ''' Get SPI device test parameters from boardenv file '''
Simon Glassddba5202025-02-09 09:07:14 -070076 f = ubman.config.env.get('env__spi_device_test', None)
Love Kumareb8eb902024-07-31 14:54:12 +053077 if not f:
Love Kumar625bc3f2024-11-15 18:38:00 +053078 pytest.skip('No SPI test device configured')
Love Kumareb8eb902024-07-31 14:54:12 +053079
80 bus = f.get('bus', 0)
81 cs = f.get('chip_select', 0)
82 mode = f.get('mode', 0)
83 part_name = f.get('part_name', None)
84 timeout = f.get('timeout', None)
85
86 if not part_name:
Love Kumar625bc3f2024-11-15 18:38:00 +053087 pytest.skip('No SPI test device configured')
Love Kumareb8eb902024-07-31 14:54:12 +053088
89 return bus, cs, mode, part_name, timeout
90
Simon Glassddba5202025-02-09 09:07:14 -070091def spi_find_freq_range(ubman):
Love Kumareb8eb902024-07-31 14:54:12 +053092 '''Find out minimum and maximum frequnecies that SPI device can operate'''
Simon Glassddba5202025-02-09 09:07:14 -070093 f = ubman.config.env.get('env__spi_device_test', None)
Love Kumareb8eb902024-07-31 14:54:12 +053094 if not f:
Love Kumar625bc3f2024-11-15 18:38:00 +053095 pytest.skip('No SPI test device configured')
Love Kumareb8eb902024-07-31 14:54:12 +053096
97 min_f = f.get('min_freq', None)
98 max_f = f.get('max_freq', None)
99 iterations = f.get('iteration', 1)
100
101 if not min_f:
102 min_f = 0
103 if not max_f:
104 max_f = 0
105
106 max_f = max(max_f, min_f)
107
108 return min_f, max_f, iterations
109
Simon Glassddba5202025-02-09 09:07:14 -0700110def spi_pre_commands(ubman, freq):
Love Kumareb8eb902024-07-31 14:54:12 +0530111 ''' Find out SPI family flash memory parameters '''
Simon Glassddba5202025-02-09 09:07:14 -0700112 bus, cs, mode, part_name, timeout = get_params_spi(ubman)
Love Kumareb8eb902024-07-31 14:54:12 +0530113
Simon Glassddba5202025-02-09 09:07:14 -0700114 output = ubman.run_command(f'sf probe {bus}:{cs} {freq} {mode}')
Love Kumareb8eb902024-07-31 14:54:12 +0530115 if not 'SF: Detected' in output:
116 pytest.fail('No SPI device available')
117
118 if not part_name in output:
Love Kumar625bc3f2024-11-15 18:38:00 +0530119 pytest.fail('Not recognized the SPI flash part name')
Love Kumareb8eb902024-07-31 14:54:12 +0530120
121 m = re.search('page size (.+?) Bytes', output)
Tom Rini888a98f2025-02-12 16:24:07 -0600122 assert m
123 try:
124 page_size = int(m.group(1))
125 except ValueError:
126 pytest.fail('Not recognized the SPI page size')
Love Kumareb8eb902024-07-31 14:54:12 +0530127
128 m = re.search('erase size (.+?) KiB', output)
Tom Rini888a98f2025-02-12 16:24:07 -0600129 assert m
130 try:
131 erase_size = int(m.group(1))
Love Kumareb8eb902024-07-31 14:54:12 +0530132 erase_size *= 1024
Tom Rini888a98f2025-02-12 16:24:07 -0600133 except ValueError:
134 pytest.fail('Not recognized the SPI erase size')
Love Kumareb8eb902024-07-31 14:54:12 +0530135
136 m = re.search('total (.+?) MiB', output)
Tom Rini888a98f2025-02-12 16:24:07 -0600137 assert m
138 try:
139 total_size = int(m.group(1))
Love Kumareb8eb902024-07-31 14:54:12 +0530140 total_size *= 1024 * 1024
Tom Rini888a98f2025-02-12 16:24:07 -0600141 except ValueError:
142 pytest.fail('Not recognized the SPI total size')
Love Kumareb8eb902024-07-31 14:54:12 +0530143
144 m = re.search('Detected (.+?) with', output)
Tom Rini888a98f2025-02-12 16:24:07 -0600145 assert m
146 try:
147 flash_part = m.group(1)
148 assert flash_part == part_name
149 except ValueError:
150 pytest.fail('Not recognized the SPI flash part')
Love Kumareb8eb902024-07-31 14:54:12 +0530151
152 global SPI_DATA
153 SPI_DATA = {
154 'page_size': page_size,
155 'erase_size': erase_size,
156 'total_size': total_size,
157 'flash_part': flash_part,
158 'timeout': timeout,
159 }
160
161def get_page_size():
162 ''' Get the SPI page size from spi data '''
163 return SPI_DATA['page_size']
164
165def get_erase_size():
166 ''' Get the SPI erase size from spi data '''
167 return SPI_DATA['erase_size']
168
169def get_total_size():
170 ''' Get the SPI total size from spi data '''
171 return SPI_DATA['total_size']
172
173def get_flash_part():
174 ''' Get the SPI flash part name from spi data '''
175 return SPI_DATA['flash_part']
176
177def get_timeout():
178 ''' Get the SPI timeout from spi data '''
179 return SPI_DATA['timeout']
180
Simon Glassddba5202025-02-09 09:07:14 -0700181def spi_erase_block(ubman, erase_size, total_size):
Love Kumareb8eb902024-07-31 14:54:12 +0530182 ''' Erase SPI flash memory block wise '''
183 for start in range(0, total_size, erase_size):
Simon Glassddba5202025-02-09 09:07:14 -0700184 output = ubman.run_command(f'sf erase {hex(start)} {hex(erase_size)}')
Love Kumareb8eb902024-07-31 14:54:12 +0530185 assert EXPECTED_ERASE in output
186
187@pytest.mark.buildconfigspec('cmd_sf')
Simon Glassddba5202025-02-09 09:07:14 -0700188def test_spi_erase_block(ubman):
Love Kumareb8eb902024-07-31 14:54:12 +0530189 ''' Test case to check SPI erase functionality by erasing memory regions
190 block-wise '''
191
Simon Glassddba5202025-02-09 09:07:14 -0700192 min_f, max_f, loop = spi_find_freq_range(ubman)
Love Kumareb8eb902024-07-31 14:54:12 +0530193 i = 0
194 while i < loop:
Simon Glassddba5202025-02-09 09:07:14 -0700195 spi_pre_commands(ubman, random.randint(min_f, max_f))
196 spi_erase_block(ubman, get_erase_size(), get_total_size())
Love Kumareb8eb902024-07-31 14:54:12 +0530197 i = i + 1
198
Simon Glassddba5202025-02-09 09:07:14 -0700199def spi_write_twice(ubman, page_size, erase_size, total_size, timeout):
Love Kumareb8eb902024-07-31 14:54:12 +0530200 ''' Random write till page size, random till size and full size '''
Simon Glassfb916372025-02-09 09:07:15 -0700201 addr = utils.find_ram_base(ubman)
Love Kumareb8eb902024-07-31 14:54:12 +0530202
203 old_size = 0
204 for size in (
205 random.randint(4, page_size),
206 random.randint(page_size, total_size),
207 total_size,
208 ):
209 offset = random.randint(4, page_size)
210 offset = offset & ~3
211 size = size & ~3
212 size = size - old_size
Simon Glassddba5202025-02-09 09:07:14 -0700213 output = ubman.run_command(f'crc32 {hex(addr + total_size)} {hex(size)}')
Love Kumareb8eb902024-07-31 14:54:12 +0530214 m = re.search('==> (.+?)$', output)
215 if not m:
216 pytest.fail('CRC32 failed')
217
218 expected_crc32 = m.group(1)
219 if old_size % page_size:
220 old_size = int(old_size / page_size)
221 old_size *= page_size
222
223 if size % erase_size:
224 erasesize = int(size / erase_size + 1)
225 erasesize *= erase_size
226
227 eraseoffset = int(old_size / erase_size)
228 eraseoffset *= erase_size
229
230 timeout = 100000000
Simon Glassddba5202025-02-09 09:07:14 -0700231 with ubman.temporary_timeout(timeout):
232 output = ubman.run_command(
Love Kumareb8eb902024-07-31 14:54:12 +0530233 f'sf erase {hex(eraseoffset)} {hex(erasesize)}'
234 )
235 assert EXPECTED_ERASE in output
236
Simon Glassddba5202025-02-09 09:07:14 -0700237 with ubman.temporary_timeout(timeout):
238 output = ubman.run_command(
Love Kumareb8eb902024-07-31 14:54:12 +0530239 f'sf write {hex(addr + total_size)} {hex(old_size)} {hex(size)}'
240 )
241 assert EXPECTED_WRITE in output
Simon Glassddba5202025-02-09 09:07:14 -0700242 with ubman.temporary_timeout(timeout):
243 output = ubman.run_command(
Love Kumareb8eb902024-07-31 14:54:12 +0530244 f'sf read {hex(addr + total_size + offset)} {hex(old_size)} {hex(size)}'
245 )
246 assert EXPECTED_READ in output
Simon Glassddba5202025-02-09 09:07:14 -0700247 output = ubman.run_command(
Love Kumareb8eb902024-07-31 14:54:12 +0530248 f'crc32 {hex(addr + total_size + offset)} {hex(size)}'
249 )
250 assert expected_crc32 in output
251 old_size = size
252
253@pytest.mark.buildconfigspec('cmd_bdi')
254@pytest.mark.buildconfigspec('cmd_sf')
255@pytest.mark.buildconfigspec('cmd_memory')
Simon Glassddba5202025-02-09 09:07:14 -0700256def test_spi_write_twice(ubman):
Love Kumareb8eb902024-07-31 14:54:12 +0530257 ''' Test to write data with random size twice for SPI '''
Simon Glassddba5202025-02-09 09:07:14 -0700258 min_f, max_f, loop = spi_find_freq_range(ubman)
Love Kumareb8eb902024-07-31 14:54:12 +0530259 i = 0
260 while i < loop:
Simon Glassddba5202025-02-09 09:07:14 -0700261 spi_pre_commands(ubman, random.randint(min_f, max_f))
Love Kumareb8eb902024-07-31 14:54:12 +0530262 spi_write_twice(
Simon Glassddba5202025-02-09 09:07:14 -0700263 ubman,
Love Kumareb8eb902024-07-31 14:54:12 +0530264 get_page_size(),
265 get_erase_size(),
266 get_total_size(),
267 get_timeout()
268 )
269 i = i + 1
270
Simon Glassddba5202025-02-09 09:07:14 -0700271def spi_write_continues(ubman, page_size, erase_size, total_size, timeout):
Love Kumareb8eb902024-07-31 14:54:12 +0530272 ''' Write with random size of data to continue SPI write case '''
Simon Glassddba5202025-02-09 09:07:14 -0700273 spi_erase_block(ubman, erase_size, total_size)
Simon Glassfb916372025-02-09 09:07:15 -0700274 addr = utils.find_ram_base(ubman)
Love Kumareb8eb902024-07-31 14:54:12 +0530275
Simon Glassddba5202025-02-09 09:07:14 -0700276 output = ubman.run_command(f'crc32 {hex(addr + 0x10000)} {hex(total_size)}')
Love Kumareb8eb902024-07-31 14:54:12 +0530277 m = re.search('==> (.+?)$', output)
278 if not m:
279 pytest.fail('CRC32 failed')
280 expected_crc32 = m.group(1)
281
282 old_size = 0
283 for size in (
284 random.randint(4, page_size),
285 random.randint(page_size, total_size),
286 total_size,
287 ):
288 size = size & ~3
289 size = size - old_size
Simon Glassddba5202025-02-09 09:07:14 -0700290 with ubman.temporary_timeout(timeout):
291 output = ubman.run_command(
Love Kumareb8eb902024-07-31 14:54:12 +0530292 f'sf write {hex(addr + 0x10000 + old_size)} {hex(old_size)} {hex(size)}'
293 )
294 assert EXPECTED_WRITE in output
295 old_size += size
296
Simon Glassddba5202025-02-09 09:07:14 -0700297 with ubman.temporary_timeout(timeout):
298 output = ubman.run_command(
Love Kumareb8eb902024-07-31 14:54:12 +0530299 f'sf read {hex(addr + 0x10000 + total_size)} 0 {hex(total_size)}'
300 )
301 assert EXPECTED_READ in output
302
Simon Glassddba5202025-02-09 09:07:14 -0700303 output = ubman.run_command(
Love Kumareb8eb902024-07-31 14:54:12 +0530304 f'crc32 {hex(addr + 0x10000 + total_size)} {hex(total_size)}'
305 )
306 assert expected_crc32 in output
307
308@pytest.mark.buildconfigspec('cmd_bdi')
309@pytest.mark.buildconfigspec('cmd_sf')
310@pytest.mark.buildconfigspec('cmd_memory')
Simon Glassddba5202025-02-09 09:07:14 -0700311def test_spi_write_continues(ubman):
Love Kumareb8eb902024-07-31 14:54:12 +0530312 ''' Test to write more random size data for SPI '''
Simon Glassddba5202025-02-09 09:07:14 -0700313 min_f, max_f, loop = spi_find_freq_range(ubman)
Love Kumareb8eb902024-07-31 14:54:12 +0530314 i = 0
315 while i < loop:
Simon Glassddba5202025-02-09 09:07:14 -0700316 spi_pre_commands(ubman, random.randint(min_f, max_f))
Love Kumareb8eb902024-07-31 14:54:12 +0530317 spi_write_twice(
Simon Glassddba5202025-02-09 09:07:14 -0700318 ubman,
Love Kumareb8eb902024-07-31 14:54:12 +0530319 get_page_size(),
320 get_erase_size(),
321 get_total_size(),
322 get_timeout(),
323 )
324 i = i + 1
325
Simon Glassddba5202025-02-09 09:07:14 -0700326def spi_read_twice(ubman, page_size, total_size, timeout):
Love Kumareb8eb902024-07-31 14:54:12 +0530327 ''' Read the whole SPI flash twice, random_size till full flash size,
328 random till page size '''
329 for size in random.randint(4, page_size), random.randint(4, total_size), total_size:
Simon Glassfb916372025-02-09 09:07:15 -0700330 addr = utils.find_ram_base(ubman)
Love Kumareb8eb902024-07-31 14:54:12 +0530331 size = size & ~3
Simon Glassddba5202025-02-09 09:07:14 -0700332 with ubman.temporary_timeout(timeout):
333 output = ubman.run_command(
Love Kumareb8eb902024-07-31 14:54:12 +0530334 f'sf read {hex(addr + total_size)} 0 {hex(size)}'
335 )
336 assert EXPECTED_READ in output
Simon Glassddba5202025-02-09 09:07:14 -0700337 output = ubman.run_command(f'crc32 {hex(addr + total_size)} {hex(size)}')
Love Kumareb8eb902024-07-31 14:54:12 +0530338 m = re.search('==> (.+?)$', output)
339 if not m:
340 pytest.fail('CRC32 failed')
341 expected_crc32 = m.group(1)
Simon Glassddba5202025-02-09 09:07:14 -0700342 with ubman.temporary_timeout(timeout):
343 output = ubman.run_command(
Love Kumareb8eb902024-07-31 14:54:12 +0530344 f'sf read {hex(addr + total_size + 10)} 0 {hex(size)}'
345 )
346 assert EXPECTED_READ in output
Simon Glassddba5202025-02-09 09:07:14 -0700347 output = ubman.run_command(
Love Kumareb8eb902024-07-31 14:54:12 +0530348 f'crc32 {hex(addr + total_size + 10)} {hex(size)}'
349 )
350 assert expected_crc32 in output
351
352@pytest.mark.buildconfigspec('cmd_sf')
353@pytest.mark.buildconfigspec('cmd_bdi')
354@pytest.mark.buildconfigspec('cmd_memory')
Simon Glassddba5202025-02-09 09:07:14 -0700355def test_spi_read_twice(ubman):
Love Kumareb8eb902024-07-31 14:54:12 +0530356 ''' Test to read random data twice from SPI '''
Simon Glassddba5202025-02-09 09:07:14 -0700357 min_f, max_f, loop = spi_find_freq_range(ubman)
Love Kumareb8eb902024-07-31 14:54:12 +0530358 i = 0
359 while i < loop:
Simon Glassddba5202025-02-09 09:07:14 -0700360 spi_pre_commands(ubman, random.randint(min_f, max_f))
361 spi_read_twice(ubman, get_page_size(), get_total_size(), get_timeout())
Love Kumareb8eb902024-07-31 14:54:12 +0530362 i = i + 1
363
Simon Glassddba5202025-02-09 09:07:14 -0700364def spi_erase_all(ubman, total_size, timeout):
Love Kumareb8eb902024-07-31 14:54:12 +0530365 ''' Erase the full chip SPI '''
366 start = 0
Simon Glassddba5202025-02-09 09:07:14 -0700367 with ubman.temporary_timeout(timeout):
368 output = ubman.run_command(f'sf erase {start} {hex(total_size)}')
Love Kumareb8eb902024-07-31 14:54:12 +0530369 assert EXPECTED_ERASE in output
370
371@pytest.mark.buildconfigspec('cmd_sf')
Simon Glassddba5202025-02-09 09:07:14 -0700372def test_spi_erase_all(ubman):
Love Kumareb8eb902024-07-31 14:54:12 +0530373 ''' Test to check full chip erase for SPI '''
Simon Glassddba5202025-02-09 09:07:14 -0700374 min_f, max_f, loop = spi_find_freq_range(ubman)
Love Kumareb8eb902024-07-31 14:54:12 +0530375 i = 0
376 while i < loop:
Simon Glassddba5202025-02-09 09:07:14 -0700377 spi_pre_commands(ubman, random.randint(min_f, max_f))
378 spi_erase_all(ubman, get_total_size(), get_timeout())
Love Kumareb8eb902024-07-31 14:54:12 +0530379 i = i + 1
380
381def flash_ops(
Simon Glassddba5202025-02-09 09:07:14 -0700382 ubman, ops, start, size, offset=0, exp_ret=0, exp_str='', not_exp_str=''
Love Kumareb8eb902024-07-31 14:54:12 +0530383):
384 ''' Flash operations: erase, write and read '''
385
Simon Glassddba5202025-02-09 09:07:14 -0700386 f = ubman.config.env.get('env__spi_device_test', None)
Love Kumareb8eb902024-07-31 14:54:12 +0530387 if not f:
388 timeout = 1000000
389
390 timeout = f.get('timeout', 1000000)
391
392 if ops == 'erase':
Simon Glassddba5202025-02-09 09:07:14 -0700393 with ubman.temporary_timeout(timeout):
394 output = ubman.run_command(f'sf erase {hex(start)} {hex(size)}')
Love Kumareb8eb902024-07-31 14:54:12 +0530395 else:
Simon Glassddba5202025-02-09 09:07:14 -0700396 with ubman.temporary_timeout(timeout):
397 output = ubman.run_command(
Love Kumareb8eb902024-07-31 14:54:12 +0530398 f'sf {ops} {hex(offset)} {hex(start)} {hex(size)}'
399 )
400
401 if exp_str:
402 assert exp_str in output
403 if not_exp_str:
404 assert not_exp_str not in output
405
Simon Glassddba5202025-02-09 09:07:14 -0700406 ret_code = ubman.run_command('echo $?')
Love Kumareb8eb902024-07-31 14:54:12 +0530407 if exp_ret >= 0:
408 assert ret_code.endswith(str(exp_ret))
409
410 return output, ret_code
411
Simon Glassddba5202025-02-09 09:07:14 -0700412def spi_unlock_exit(ubman, addr, size):
Love Kumareb8eb902024-07-31 14:54:12 +0530413 ''' Unlock the flash before making it fail '''
Simon Glassddba5202025-02-09 09:07:14 -0700414 ubman.run_command(f'sf protect unlock {hex(addr)} {hex(size)}')
Love Kumareb8eb902024-07-31 14:54:12 +0530415 assert False, 'FAIL: Flash lock is unable to protect the data!'
416
417def find_prot_region(lock_addr, lock_size):
418 ''' Get the protected and un-protected region of flash '''
419 total_size = get_total_size()
420 erase_size = get_erase_size()
421
422 if lock_addr < (total_size // 2):
423 sect_num = (lock_addr + lock_size) // erase_size
424 x = 1
425 while x < sect_num:
426 x *= 2
427 prot_start = 0
428 prot_size = x * erase_size
429 unprot_start = prot_start + prot_size
430 unprot_size = total_size - unprot_start
431 else:
432 sect_num = (total_size - lock_addr) // erase_size
433 x = 1
434 while x < sect_num:
435 x *= 2
436 prot_start = total_size - (x * erase_size)
437 prot_size = total_size - prot_start
438 unprot_start = 0
439 unprot_size = prot_start
440
441 return prot_start, prot_size, unprot_start, unprot_size
442
Simon Glassddba5202025-02-09 09:07:14 -0700443def protect_ops(ubman, lock_addr, lock_size, ops="unlock"):
Love Kumareb8eb902024-07-31 14:54:12 +0530444 ''' Run the command to lock or Unlock the flash '''
Simon Glassddba5202025-02-09 09:07:14 -0700445 ubman.run_command(f'sf protect {ops} {hex(lock_addr)} {hex(lock_size)}')
446 output = ubman.run_command('echo $?')
Love Kumareb8eb902024-07-31 14:54:12 +0530447 if ops == "lock" and not output.endswith('0'):
Simon Glassddba5202025-02-09 09:07:14 -0700448 ubman.run_command(f'sf protect unlock {hex(lock_addr)} {hex(lock_size)}')
Love Kumareb8eb902024-07-31 14:54:12 +0530449 assert False, "sf protect lock command exits with non-zero return code"
450 assert output.endswith('0')
451
Simon Glassddba5202025-02-09 09:07:14 -0700452def erase_write_ops(ubman, start, size):
Love Kumareb8eb902024-07-31 14:54:12 +0530453 ''' Basic erase and write operation for flash '''
Simon Glassfb916372025-02-09 09:07:15 -0700454 addr = utils.find_ram_base(ubman)
Simon Glassddba5202025-02-09 09:07:14 -0700455 flash_ops(ubman, 'erase', start, size, 0, 0, EXPECTED_ERASE)
456 flash_ops(ubman, 'write', start, size, addr, 0, EXPECTED_WRITE)
Love Kumareb8eb902024-07-31 14:54:12 +0530457
Simon Glassddba5202025-02-09 09:07:14 -0700458def spi_lock_unlock(ubman, lock_addr, lock_size):
Love Kumareb8eb902024-07-31 14:54:12 +0530459 ''' Lock unlock operations for SPI family flash '''
Simon Glassfb916372025-02-09 09:07:15 -0700460 addr = utils.find_ram_base(ubman)
Love Kumareb8eb902024-07-31 14:54:12 +0530461 erase_size = get_erase_size()
462
463 # Find the protected/un-protected region
464 prot_start, prot_size, unprot_start, unprot_size = find_prot_region(lock_addr, lock_size)
465
466 # Check erase/write operation before locking
Simon Glassddba5202025-02-09 09:07:14 -0700467 erase_write_ops(ubman, prot_start, prot_size)
Love Kumareb8eb902024-07-31 14:54:12 +0530468
469 # Locking the flash
Simon Glassddba5202025-02-09 09:07:14 -0700470 protect_ops(ubman, lock_addr, lock_size, 'lock')
Love Kumareb8eb902024-07-31 14:54:12 +0530471
472 # Check erase/write operation after locking
Simon Glassddba5202025-02-09 09:07:14 -0700473 output, ret_code = flash_ops(ubman, 'erase', prot_start, prot_size, 0, -1)
Love Kumareb8eb902024-07-31 14:54:12 +0530474 if not any(error in output for error in EXPECTED_ERASE_ERRORS) or ret_code.endswith(
475 '0'
476 ):
Simon Glassddba5202025-02-09 09:07:14 -0700477 spi_unlock_exit(ubman, lock_addr, lock_size)
Love Kumareb8eb902024-07-31 14:54:12 +0530478
479 output, ret_code = flash_ops(
Simon Glassddba5202025-02-09 09:07:14 -0700480 ubman, 'write', prot_start, prot_size, addr, -1
Love Kumareb8eb902024-07-31 14:54:12 +0530481 )
482 if not any(error in output for error in EXPECTED_WRITE_ERRORS) or ret_code.endswith(
483 '0'
484 ):
Simon Glassddba5202025-02-09 09:07:14 -0700485 spi_unlock_exit(ubman, lock_addr, lock_size)
Love Kumareb8eb902024-07-31 14:54:12 +0530486
487 # Check locked sectors
488 sect_lock_start = random.randrange(prot_start, (prot_start + prot_size), erase_size)
489 if prot_size > erase_size:
490 sect_lock_size = random.randrange(
491 erase_size, (prot_start + prot_size - sect_lock_start), erase_size
492 )
493 else:
494 sect_lock_size = erase_size
495 sect_write_size = random.randint(1, sect_lock_size)
496
497 output, ret_code = flash_ops(
Simon Glassddba5202025-02-09 09:07:14 -0700498 ubman, 'erase', sect_lock_start, sect_lock_size, 0, -1
Love Kumareb8eb902024-07-31 14:54:12 +0530499 )
500 if not any(error in output for error in EXPECTED_ERASE_ERRORS) or ret_code.endswith(
501 '0'
502 ):
Simon Glassddba5202025-02-09 09:07:14 -0700503 spi_unlock_exit(ubman, lock_addr, lock_size)
Love Kumareb8eb902024-07-31 14:54:12 +0530504
505 output, ret_code = flash_ops(
Simon Glassddba5202025-02-09 09:07:14 -0700506 ubman, 'write', sect_lock_start, sect_write_size, addr, -1
Love Kumareb8eb902024-07-31 14:54:12 +0530507 )
508 if not any(error in output for error in EXPECTED_WRITE_ERRORS) or ret_code.endswith(
509 '0'
510 ):
Simon Glassddba5202025-02-09 09:07:14 -0700511 spi_unlock_exit(ubman, lock_addr, lock_size)
Love Kumareb8eb902024-07-31 14:54:12 +0530512
513 # Check unlocked sectors
514 if unprot_size != 0:
515 sect_unlock_start = random.randrange(
516 unprot_start, (unprot_start + unprot_size), erase_size
517 )
518 if unprot_size > erase_size:
519 sect_unlock_size = random.randrange(
520 erase_size, (unprot_start + unprot_size - sect_unlock_start), erase_size
521 )
522 else:
523 sect_unlock_size = erase_size
524 sect_write_size = random.randint(1, sect_unlock_size)
525
526 output, ret_code = flash_ops(
Simon Glassddba5202025-02-09 09:07:14 -0700527 ubman, 'erase', sect_unlock_start, sect_unlock_size, 0, -1
Love Kumareb8eb902024-07-31 14:54:12 +0530528 )
529 if EXPECTED_ERASE not in output or ret_code.endswith('1'):
Simon Glassddba5202025-02-09 09:07:14 -0700530 spi_unlock_exit(ubman, lock_addr, lock_size)
Love Kumareb8eb902024-07-31 14:54:12 +0530531
532 output, ret_code = flash_ops(
Simon Glassddba5202025-02-09 09:07:14 -0700533 ubman, 'write', sect_unlock_start, sect_write_size, addr, -1
Love Kumareb8eb902024-07-31 14:54:12 +0530534 )
535 if EXPECTED_WRITE not in output or ret_code.endswith('1'):
Simon Glassddba5202025-02-09 09:07:14 -0700536 spi_unlock_exit(ubman, lock_addr, lock_size)
Love Kumareb8eb902024-07-31 14:54:12 +0530537
538 # Unlocking the flash
Simon Glassddba5202025-02-09 09:07:14 -0700539 protect_ops(ubman, lock_addr, lock_size, 'unlock')
Love Kumareb8eb902024-07-31 14:54:12 +0530540
541 # Check erase/write operation after un-locking
Simon Glassddba5202025-02-09 09:07:14 -0700542 erase_write_ops(ubman, prot_start, prot_size)
Love Kumareb8eb902024-07-31 14:54:12 +0530543
544 # Check previous locked sectors
545 sect_lock_start = random.randrange(prot_start, (prot_start + prot_size), erase_size)
546 if prot_size > erase_size:
547 sect_lock_size = random.randrange(
548 erase_size, (prot_start + prot_size - sect_lock_start), erase_size
549 )
550 else:
551 sect_lock_size = erase_size
552 sect_write_size = random.randint(1, sect_lock_size)
553
554 flash_ops(
Simon Glassddba5202025-02-09 09:07:14 -0700555 ubman, 'erase', sect_lock_start, sect_lock_size, 0, 0, EXPECTED_ERASE
Love Kumareb8eb902024-07-31 14:54:12 +0530556 )
557 flash_ops(
Simon Glassddba5202025-02-09 09:07:14 -0700558 ubman,
Love Kumareb8eb902024-07-31 14:54:12 +0530559 'write',
560 sect_lock_start,
561 sect_write_size,
562 addr,
563 0,
564 EXPECTED_WRITE,
565 )
566
567@pytest.mark.buildconfigspec('cmd_bdi')
568@pytest.mark.buildconfigspec('cmd_sf')
569@pytest.mark.buildconfigspec('cmd_memory')
Simon Glassddba5202025-02-09 09:07:14 -0700570def test_spi_lock_unlock(ubman):
Love Kumareb8eb902024-07-31 14:54:12 +0530571 ''' Test to check the lock-unlock functionality for SPI family flash '''
Simon Glassddba5202025-02-09 09:07:14 -0700572 min_f, max_f, loop = spi_find_freq_range(ubman)
573 flashes = ubman.config.env.get('env__spi_lock_unlock', False)
Love Kumareb8eb902024-07-31 14:54:12 +0530574 if not flashes:
Love Kumar625bc3f2024-11-15 18:38:00 +0530575 pytest.skip('No SPI test device configured for lock/unlock')
Love Kumareb8eb902024-07-31 14:54:12 +0530576
577 i = 0
578 while i < loop:
Simon Glassddba5202025-02-09 09:07:14 -0700579 spi_pre_commands(ubman, random.randint(min_f, max_f))
Love Kumareb8eb902024-07-31 14:54:12 +0530580 total_size = get_total_size()
581 flash_part = get_flash_part()
582
583 flashes_list = flashes.get('supported_flash', None).split(',')
584 flashes_list = [x.strip() for x in flashes_list]
585 if flash_part not in flashes_list:
586 pytest.skip('Detected flash does not support lock/unlock')
587
588 # For lower half of memory
589 lock_addr = random.randint(0, (total_size // 2) - 1)
590 lock_size = random.randint(1, ((total_size // 2) - lock_addr))
Simon Glassddba5202025-02-09 09:07:14 -0700591 spi_lock_unlock(ubman, lock_addr, lock_size)
Love Kumareb8eb902024-07-31 14:54:12 +0530592
593 # For upper half of memory
594 lock_addr = random.randint((total_size // 2), total_size - 1)
595 lock_size = random.randint(1, (total_size - lock_addr))
Simon Glassddba5202025-02-09 09:07:14 -0700596 spi_lock_unlock(ubman, lock_addr, lock_size)
Love Kumareb8eb902024-07-31 14:54:12 +0530597
598 # For entire flash
599 lock_addr = random.randint(0, total_size - 1)
600 lock_size = random.randint(1, (total_size - lock_addr))
Simon Glassddba5202025-02-09 09:07:14 -0700601 spi_lock_unlock(ubman, lock_addr, lock_size)
Love Kumareb8eb902024-07-31 14:54:12 +0530602
603 i = i + 1
604
605@pytest.mark.buildconfigspec('cmd_bdi')
606@pytest.mark.buildconfigspec('cmd_sf')
607@pytest.mark.buildconfigspec('cmd_memory')
Simon Glassddba5202025-02-09 09:07:14 -0700608def test_spi_negative(ubman):
Love Kumareb8eb902024-07-31 14:54:12 +0530609 ''' Negative tests for SPI '''
Simon Glassddba5202025-02-09 09:07:14 -0700610 min_f, max_f, loop = spi_find_freq_range(ubman)
611 spi_pre_commands(ubman, random.randint(min_f, max_f))
Love Kumareb8eb902024-07-31 14:54:12 +0530612 total_size = get_total_size()
613 erase_size = get_erase_size()
614 page_size = get_page_size()
Simon Glassfb916372025-02-09 09:07:15 -0700615 addr = utils.find_ram_base(ubman)
Love Kumareb8eb902024-07-31 14:54:12 +0530616 i = 0
617 while i < loop:
618 # Erase negative test
619 start = random.randint(0, total_size)
620 esize = erase_size
621
622 # If erasesize is not multiple of flash's erase size
623 while esize % erase_size == 0:
624 esize = random.randint(0, total_size - start)
625
626 error_msg = 'Erased: ERROR'
627 flash_ops(
Simon Glassddba5202025-02-09 09:07:14 -0700628 ubman, 'erase', start, esize, 0, 1, error_msg, EXPECTED_ERASE
Love Kumareb8eb902024-07-31 14:54:12 +0530629 )
630
631 # If eraseoffset exceeds beyond flash size
632 eoffset = random.randint(total_size, (total_size + int(0x1000000)))
633 error_msg = 'Offset exceeds device limit'
634 flash_ops(
Simon Glassddba5202025-02-09 09:07:14 -0700635 ubman, 'erase', eoffset, esize, 0, 1, error_msg, EXPECTED_ERASE
Love Kumareb8eb902024-07-31 14:54:12 +0530636 )
637
638 # If erasesize exceeds beyond flash size
639 esize = random.randint((total_size - start), (total_size + int(0x1000000)))
640 error_msg = 'ERROR: attempting erase past flash size'
641 flash_ops(
Simon Glassddba5202025-02-09 09:07:14 -0700642 ubman, 'erase', start, esize, 0, 1, error_msg, EXPECTED_ERASE
Love Kumareb8eb902024-07-31 14:54:12 +0530643 )
644
645 # If erase size is 0
646 esize = 0
Love Kumar9339e512024-09-03 00:08:17 +0530647 error_msg = None
Love Kumareb8eb902024-07-31 14:54:12 +0530648 flash_ops(
Simon Glassddba5202025-02-09 09:07:14 -0700649 ubman, 'erase', start, esize, 0, 1, error_msg, EXPECTED_ERASE
Love Kumareb8eb902024-07-31 14:54:12 +0530650 )
651
652 # If erasesize is less than flash's page size
653 esize = random.randint(0, page_size)
654 start = random.randint(0, (total_size - page_size))
655 error_msg = 'Erased: ERROR'
656 flash_ops(
Simon Glassddba5202025-02-09 09:07:14 -0700657 ubman, 'erase', start, esize, 0, 1, error_msg, EXPECTED_ERASE
Love Kumareb8eb902024-07-31 14:54:12 +0530658 )
659
660 # Write/Read negative test
661 # if Write/Read size exceeds beyond flash size
662 offset = random.randint(0, total_size)
663 size = random.randint((total_size - offset), (total_size + int(0x1000000)))
664 error_msg = 'Size exceeds partition or device limit'
665 flash_ops(
Simon Glassddba5202025-02-09 09:07:14 -0700666 ubman, 'write', offset, size, addr, 1, error_msg, EXPECTED_WRITE
Love Kumareb8eb902024-07-31 14:54:12 +0530667 )
668 flash_ops(
Simon Glassddba5202025-02-09 09:07:14 -0700669 ubman, 'read', offset, size, addr, 1, error_msg, EXPECTED_READ
Love Kumareb8eb902024-07-31 14:54:12 +0530670 )
671
672 # if Write/Read offset exceeds beyond flash size
673 offset = random.randint(total_size, (total_size + int(0x1000000)))
674 size = random.randint(0, total_size)
675 error_msg = 'Offset exceeds device limit'
676 flash_ops(
Simon Glassddba5202025-02-09 09:07:14 -0700677 ubman, 'write', offset, size, addr, 1, error_msg, EXPECTED_WRITE
Love Kumareb8eb902024-07-31 14:54:12 +0530678 )
679 flash_ops(
Simon Glassddba5202025-02-09 09:07:14 -0700680 ubman, 'read', offset, size, addr, 1, error_msg, EXPECTED_READ
Love Kumareb8eb902024-07-31 14:54:12 +0530681 )
682
683 # if Write/Read size is 0
684 offset = random.randint(0, 2)
685 size = 0
Love Kumar9339e512024-09-03 00:08:17 +0530686 error_msg = None
Love Kumareb8eb902024-07-31 14:54:12 +0530687 flash_ops(
Simon Glassddba5202025-02-09 09:07:14 -0700688 ubman, 'write', offset, size, addr, 1, error_msg, EXPECTED_WRITE
Love Kumareb8eb902024-07-31 14:54:12 +0530689 )
690 flash_ops(
Simon Glassddba5202025-02-09 09:07:14 -0700691 ubman, 'read', offset, size, addr, 1, error_msg, EXPECTED_READ
Love Kumareb8eb902024-07-31 14:54:12 +0530692 )
693
Padmarao Begari276495d2024-10-29 17:17:09 +0530694 # Read to relocation address
Simon Glassddba5202025-02-09 09:07:14 -0700695 output = ubman.run_command('bdinfo')
Simon Glass8be1fe52024-11-12 07:13:25 -0700696 m = re.search(r'relocaddr\s*= (.+)', output)
Padmarao Begari276495d2024-10-29 17:17:09 +0530697 res_area = int(m.group(1), 16)
698
699 start = 0
700 size = 0x2000
701 error_msg = 'ERROR: trying to overwrite reserved memory'
702 flash_ops(
Simon Glassddba5202025-02-09 09:07:14 -0700703 ubman, 'read', start, size, res_area, 1, error_msg, EXPECTED_READ
Padmarao Begari276495d2024-10-29 17:17:09 +0530704 )
705
Love Kumareb8eb902024-07-31 14:54:12 +0530706 i = i + 1