On some systems reading the whole qspi can take longer than default timeout. Signed-off-by: Michal Simek <michal.simek@xilinx.com>
271 lines
8.8 KiB
Python
271 lines
8.8 KiB
Python
# Copyright (c) 2016, Xilinx Inc. Michal Simek
|
|
#
|
|
# SPDX-License-Identifier: GPL-2.0
|
|
|
|
import pytest
|
|
import re
|
|
import random
|
|
import u_boot_utils
|
|
|
|
import test_net
|
|
|
|
"""
|
|
Note: This test relies on boardenv_* containing configuration values to define
|
|
qspi minimum and maximum frequnecies at which the flash part can operate on and
|
|
these tests run at 5 different qspi frequnecy randomised values in the range.
|
|
with out this, this test runs with only one frequnecy value that is 0.
|
|
|
|
Example:
|
|
env__qspi_freq = {
|
|
"min_freq": 10000000,
|
|
"max_freq": 100000000,
|
|
}
|
|
|
|
"""
|
|
page_size = 0
|
|
erase_size = 0
|
|
total_size = 0
|
|
|
|
# Find out qspi memory parameters
|
|
def qspi_pre_commands(u_boot_console, freq):
|
|
|
|
output = u_boot_console.run_command('sf probe 0 %d 0' % (freq))
|
|
if not "SF: Detected" in output:
|
|
pytest.skip('No QSPI device available')
|
|
|
|
m = re.search('page size (.+?) Bytes', output)
|
|
if m:
|
|
try:
|
|
global page_size
|
|
page_size = int(m.group(1))
|
|
except ValueError:
|
|
pytest.fail("QSPI page size not recognized")
|
|
|
|
print 'Page size is: ' + str(page_size) + " B"
|
|
|
|
m = re.search('erase size (.+?) KiB', output)
|
|
if m:
|
|
try:
|
|
global erase_size
|
|
erase_size = int(m.group(1))
|
|
except ValueError:
|
|
pytest.fail("QSPI erase size not recognized")
|
|
|
|
erase_size *= 1024
|
|
print 'Erase size is: ' + str(erase_size) + " B"
|
|
|
|
m = re.search('total (.+?) MiB', output)
|
|
if m:
|
|
try:
|
|
global total_size
|
|
total_size = int(m.group(1))
|
|
except ValueError:
|
|
pytest.fail("QSPI total size not recognized")
|
|
|
|
total_size *= 1024 * 1024
|
|
print 'Total size is: ' + str(total_size) + " B"
|
|
|
|
# Find out minimum and maximum frequnecies that device can operate
|
|
def qspi_find_freq_range(u_boot_console):
|
|
f = u_boot_console.config.env.get('env__qspi_freq', None)
|
|
global min_f
|
|
global max_f
|
|
global loop
|
|
|
|
if not f:
|
|
min_f = 0
|
|
max_f = 0
|
|
loop = 1
|
|
return
|
|
|
|
min_f = f.get('min_freq', None)
|
|
if not min_f:
|
|
min_f = 0
|
|
max_f = f.get('max_freq', None)
|
|
if not max_f:
|
|
max_f = 0
|
|
|
|
if max_f < min_f:
|
|
max_f = min_f
|
|
|
|
if min_f == 0 and max_f == 0:
|
|
loop = 1
|
|
return
|
|
|
|
loop = 5
|
|
|
|
# Read the whole QSPI flash twice, random_size till full flash size, random till page size
|
|
def qspi_read_twice(u_boot_console):
|
|
|
|
expected_read = "Read: OK"
|
|
timeout = 10000000
|
|
|
|
# TODO maybe add alignment and different start for pages
|
|
for size in random.randint(4, page_size), random.randint(4, total_size), total_size:
|
|
addr = u_boot_utils.find_ram_base(u_boot_console)
|
|
size = size & ~3
|
|
# FIXME using 0 is failing for me
|
|
with u_boot_console.temporary_timeout(timeout):
|
|
output = u_boot_console.run_command('sf read %x 0 %x' % (addr + total_size, size))
|
|
assert expected_read in output
|
|
output = u_boot_console.run_command('crc32 %x %x' % (addr + total_size, size))
|
|
m = re.search('==> (.+?)$', output)
|
|
if not m:
|
|
pytest.fail("CRC32 failed")
|
|
expected_crc32 = m.group(1)
|
|
with u_boot_console.temporary_timeout(timeout):
|
|
output = u_boot_console.run_command('sf read %x 0 %x' % (addr + total_size + 10, size))
|
|
assert expected_read in output
|
|
output = u_boot_console.run_command('crc32 %x %x' % (addr + total_size + 10, size))
|
|
assert expected_crc32 in output
|
|
|
|
@pytest.mark.buildconfigspec("cmd_sf")
|
|
@pytest.mark.buildconfigspec("cmd_bdi")
|
|
@pytest.mark.buildconfigspec("cmd_memory")
|
|
def test_qspi_read_twice(u_boot_console):
|
|
qspi_find_freq_range(u_boot_console)
|
|
i = 0
|
|
while i < loop:
|
|
qspi_pre_commands(u_boot_console, random.randint(min_f, max_f))
|
|
qspi_read_twice(u_boot_console)
|
|
i = i + 1
|
|
|
|
# This test check crossing boundary for dual/parralel configurations
|
|
def qspi_erase_block(u_boot_console):
|
|
|
|
expected_erase = "Erased: OK"
|
|
for start in range(0, total_size, erase_size):
|
|
output = u_boot_console.run_command('sf erase %x %x' % (start, erase_size))
|
|
assert expected_erase in output
|
|
|
|
@pytest.mark.buildconfigspec('cmd_sf')
|
|
def test_qspi_erase_block(u_boot_console):
|
|
qspi_find_freq_range(u_boot_console)
|
|
i = 0
|
|
while i < loop:
|
|
qspi_pre_commands(u_boot_console, random.randint(min_f, max_f))
|
|
qspi_erase_block(u_boot_console)
|
|
i = i + 1
|
|
|
|
# Random write till page size, random till size and full size
|
|
def qspi_write_twice(u_boot_console):
|
|
|
|
addr = u_boot_utils.find_ram_base(u_boot_console)
|
|
expected_write = "Written: OK"
|
|
expected_read = "Read: OK"
|
|
expected_erase = "Erased: OK"
|
|
|
|
old_size = 0
|
|
# TODO maybe add alignment and different start for pages
|
|
for size in random.randint(4, page_size), random.randint(page_size, total_size), total_size:
|
|
offset = random.randint(4, page_size)
|
|
offset = offset & ~3
|
|
size = size & ~3
|
|
size = size - old_size
|
|
output = u_boot_console.run_command('crc32 %x %x' % (addr + total_size, size))
|
|
m = re.search('==> (.+?)$', output)
|
|
if not m:
|
|
pytest.fail("CRC32 failed")
|
|
|
|
expected_crc32 = m.group(1)
|
|
# print expected_crc32
|
|
if old_size % page_size:
|
|
old_size /= page_size
|
|
old_size *= page_size
|
|
|
|
if size % erase_size:
|
|
erasesize = size/erase_size + 1
|
|
erasesize *= erase_size
|
|
|
|
eraseoffset = old_size/erase_size
|
|
eraseoffset *= erase_size
|
|
|
|
timeout = 100000000
|
|
start = 0
|
|
with u_boot_console.temporary_timeout(timeout):
|
|
output = u_boot_console.run_command('sf erase %x %x' % (eraseoffset, erasesize))
|
|
assert expected_erase in output
|
|
|
|
with u_boot_console.temporary_timeout(timeout):
|
|
output = u_boot_console.run_command('sf write %x %x %x' % (addr + total_size, old_size, size))
|
|
assert expected_write in output
|
|
with u_boot_console.temporary_timeout(timeout):
|
|
output = u_boot_console.run_command('sf read %x %x %x' % (addr + total_size + offset, old_size, size))
|
|
assert expected_read in output
|
|
output = u_boot_console.run_command('crc32 %x %x' % (addr + total_size + offset, size))
|
|
assert expected_crc32 in output
|
|
old_size = size
|
|
|
|
@pytest.mark.buildconfigspec('cmd_bdi')
|
|
@pytest.mark.buildconfigspec('cmd_sf')
|
|
@pytest.mark.buildconfigspec('cmd_memory')
|
|
def test_qspi_write_twice(u_boot_console):
|
|
qspi_find_freq_range(u_boot_console)
|
|
i = 0
|
|
while i < loop:
|
|
qspi_pre_commands(u_boot_console, random.randint(min_f, max_f))
|
|
qspi_write_twice(u_boot_console)
|
|
i = i + 1
|
|
|
|
def qspi_write_continues(u_boot_console):
|
|
|
|
qspi_erase_block(u_boot_console)
|
|
expected_write = "Written: OK"
|
|
expected_read = "Read: OK"
|
|
addr = u_boot_utils.find_ram_base(u_boot_console)
|
|
|
|
output = u_boot_console.run_command('crc32 %x %x' % (addr + 0x10000, total_size))
|
|
m = re.search('==> (.+?)$', output)
|
|
if not m:
|
|
pytest.fail("CRC32 failed")
|
|
expected_crc32 = m.group(1)
|
|
# print expected_crc32
|
|
|
|
timeout = 10000000
|
|
old_size = 0
|
|
for size in random.randint(4, page_size), random.randint(page_size, total_size), total_size:
|
|
size = size & ~3
|
|
size = size - old_size
|
|
with u_boot_console.temporary_timeout(timeout):
|
|
output = u_boot_console.run_command('sf write %x %x %x' % (addr + 0x10000 + old_size, old_size, size))
|
|
assert expected_write in output
|
|
old_size = size
|
|
|
|
with u_boot_console.temporary_timeout(timeout):
|
|
output = u_boot_console.run_command('sf read %x %x %x' % (addr + 0x10000 + total_size, 0, total_size))
|
|
assert expected_read in output
|
|
|
|
#u_boot_console.run_command('md %x' % (addr + 0x10000 + total_size))
|
|
|
|
output = u_boot_console.run_command('crc32 %x %x' % (addr + 0x10000 + total_size, total_size))
|
|
assert expected_crc32 in output
|
|
|
|
@pytest.mark.buildconfigspec('cmd_bdi')
|
|
@pytest.mark.buildconfigspec('cmd_sf')
|
|
@pytest.mark.buildconfigspec('cmd_memory')
|
|
def test_qspi_write_continues(u_boot_console):
|
|
qspi_find_freq_range(u_boot_console)
|
|
i = 0
|
|
while i < loop:
|
|
qspi_pre_commands(u_boot_console, random.randint(min_f, max_f))
|
|
qspi_write_continues(u_boot_console)
|
|
i = i + 1
|
|
|
|
def qspi_erase_all(u_boot_console):
|
|
timeout = 10000000
|
|
|
|
expected_erase = "Erased: OK"
|
|
start = 0
|
|
with u_boot_console.temporary_timeout(timeout):
|
|
output = u_boot_console.run_command('sf erase 0 ' + str(hex(total_size)))
|
|
assert expected_erase in output
|
|
|
|
@pytest.mark.buildconfigspec("cmd_sf")
|
|
def test_qspi_erase_all(u_boot_console):
|
|
qspi_find_freq_range(u_boot_console)
|
|
i = 0
|
|
while i < loop:
|
|
qspi_pre_commands(u_boot_console, random.randint(min_f, max_f))
|
|
qspi_erase_all(u_boot_console)
|
|
i = i + 1
|