Merge branch 'master' of git://git.denx.de/u-boot-spi
[oweals/u-boot.git] / test / py / tests / test_sf.py
1 # SPDX-License-Identifier: GPL-2.0
2 # Copyright (c) 2016, Xilinx Inc. Michal Simek
3 # Copyright (c) 2017, Xiphos Systems Corp. All rights reserved.
4
5 import re
6 import pytest
7 import random
8 import u_boot_utils
9
10 """
11 Note: This test relies on boardenv_* containing configuration values to define
12 which SPI Flash areas are available for testing.  Without this, this test will
13 be automatically skipped.
14 For example:
15
16 # A list of sections of Flash memory to be tested.
17 env__sf_configs = (
18     {
19         # Where in SPI Flash should the test operate.
20         'offset': 0x00000000,
21         # This value is optional.
22         #   If present, specifies the [[bus:]cs] argument used in `sf probe`
23         #   If missing, defaults to 0.
24         'id': '0:1',
25         # This value is optional.
26         #   If set as a number, specifies the speed of the SPI Flash.
27         #   If set as an array of 2, specifies a range for a random speed.
28         #   If missing, defaults to 0.
29         'speed': 1000000,
30         # This value is optional.
31         #   If present, specifies the size to use for read/write operations.
32         #   If missing, the SPI Flash page size is used as a default (based on
33         #   the `sf probe` output).
34         'len': 0x10000,
35         # This value is optional.
36         #   If present, specifies if the test can write to Flash offset
37         #   If missing, defaults to False.
38         'writeable': False,
39         # This value is optional.
40         #   If present, specifies the expected CRC32 value of the flash area.
41         #   If missing, extra check is ignored.
42         'crc32': 0xCAFECAFE,
43     },
44 )
45 """
46
47 def sf_prepare(u_boot_console, env__sf_config):
48     """Check global state of the SPI Flash before running any test.
49
50    Args:
51         u_boot_console: A U-Boot console connection.
52         env__sf_config: The single SPI Flash device configuration on which to
53             run the tests.
54
55     Returns:
56         sf_params: a dictionary of SPI Flash parameters.
57     """
58
59     sf_params = {}
60     sf_params['ram_base'] = u_boot_utils.find_ram_base(u_boot_console)
61
62     probe_id = env__sf_config.get('id', 0)
63     speed = env__sf_config.get('speed', 0)
64     if isinstance(speed, int):
65         sf_params['speed'] = speed
66     else:
67         assert len(speed) == 2, "If speed is a list, it must have 2 entries"
68         sf_params['speed'] = random.randint(speed[0], speed[1])
69
70     cmd = 'sf probe %d %d' % (probe_id, sf_params['speed'])
71
72     output = u_boot_console.run_command(cmd)
73     assert 'SF: Detected' in output, 'No Flash device available'
74
75     m = re.search('page size (.+?) Bytes', output)
76     assert m, 'SPI Flash page size not recognized'
77     sf_params['page_size'] = int(m.group(1))
78
79     m = re.search('erase size (.+?) KiB', output)
80     assert m, 'SPI Flash erase size not recognized'
81     sf_params['erase_size'] = int(m.group(1))
82     sf_params['erase_size'] *= 1024
83
84     m = re.search('total (.+?) MiB', output)
85     assert m, 'SPI Flash total size not recognized'
86     sf_params['total_size'] = int(m.group(1))
87     sf_params['total_size'] *= 1024 * 1024
88
89     assert 'offset' in env__sf_config, \
90         '\'offset\' is required for this test.'
91     sf_params['len'] = env__sf_config.get('len', sf_params['erase_size'])
92
93     assert not env__sf_config['offset'] % sf_params['erase_size'], \
94         'offset not multiple of erase size.'
95     assert not sf_params['len'] % sf_params['erase_size'], \
96         'erase length not multiple of erase size.'
97
98     assert not (env__sf_config.get('writeable', False) and
99                 'crc32' in env__sf_config), \
100         'Cannot check crc32 on writeable sections'
101
102     return sf_params
103
104 def sf_read(u_boot_console, env__sf_config, sf_params):
105     """Helper function used to read and compute the CRC32 value of a section of
106     SPI Flash memory.
107
108     Args:
109         u_boot_console: A U-Boot console connection.
110         env__sf_config: The single SPI Flash device configuration on which to
111             run the tests.
112         sf_params: SPI Flash parameters.
113
114     Returns:
115         CRC32 value of SPI Flash section
116     """
117
118     addr = sf_params['ram_base']
119     offset = env__sf_config['offset']
120     count = sf_params['len']
121     pattern = random.randint(0, 0xFF)
122     crc_expected = env__sf_config.get('crc32', None)
123
124     cmd = 'mw.b %08x %02x %x' % (addr, pattern, count)
125     u_boot_console.run_command(cmd)
126     crc_pattern = u_boot_utils.crc32(u_boot_console, addr, count)
127     if crc_expected:
128         assert crc_pattern != crc_expected
129
130     cmd = 'sf read %08x %08x %x' % (addr, offset, count)
131     response = u_boot_console.run_command(cmd)
132     assert 'Read: OK' in response, 'Read operation failed'
133     crc_readback = u_boot_utils.crc32(u_boot_console, addr, count)
134     assert crc_pattern != crc_readback, 'sf read did not update RAM content.'
135     if crc_expected:
136         assert crc_readback == crc_expected
137
138     return crc_readback
139
140 def sf_update(u_boot_console, env__sf_config, sf_params):
141     """Helper function used to update a section of SPI Flash memory.
142
143    Args:
144         u_boot_console: A U-Boot console connection.
145         env__sf_config: The single SPI Flash device configuration on which to
146            run the tests.
147
148     Returns:
149         CRC32 value of SPI Flash section
150     """
151
152     addr = sf_params['ram_base']
153     offset = env__sf_config['offset']
154     count = sf_params['len']
155     pattern = int(random.random() * 0xFF)
156
157     cmd = 'mw.b %08x %02x %x' % (addr, pattern, count)
158     u_boot_console.run_command(cmd)
159     crc_pattern = u_boot_utils.crc32(u_boot_console, addr, count)
160
161     cmd = 'sf update %08x %08x %x' % (addr, offset, count)
162     u_boot_console.run_command(cmd)
163     crc_readback = sf_read(u_boot_console, env__sf_config, sf_params)
164
165     assert crc_readback == crc_pattern
166
167 @pytest.mark.buildconfigspec('cmd_sf')
168 @pytest.mark.buildconfigspec('cmd_crc32')
169 @pytest.mark.buildconfigspec('cmd_memory')
170 def test_sf_read(u_boot_console, env__sf_config):
171     sf_params = sf_prepare(u_boot_console, env__sf_config)
172     sf_read(u_boot_console, env__sf_config, sf_params)
173
174 @pytest.mark.buildconfigspec('cmd_sf')
175 @pytest.mark.buildconfigspec('cmd_crc32')
176 @pytest.mark.buildconfigspec('cmd_memory')
177 def test_sf_read_twice(u_boot_console, env__sf_config):
178     sf_params = sf_prepare(u_boot_console, env__sf_config)
179
180     crc1 = sf_read(u_boot_console, env__sf_config, sf_params)
181     sf_params['ram_base'] += 0x100
182     crc2 = sf_read(u_boot_console, env__sf_config, sf_params)
183
184     assert crc1 == crc2, 'CRC32 of two successive read operation do not match'
185
186 @pytest.mark.buildconfigspec('cmd_sf')
187 @pytest.mark.buildconfigspec('cmd_crc32')
188 @pytest.mark.buildconfigspec('cmd_memory')
189 def test_sf_erase(u_boot_console, env__sf_config):
190     if not env__sf_config.get('writeable', False):
191         pytest.skip('Flash config is tagged as not writeable')
192
193     sf_params = sf_prepare(u_boot_console, env__sf_config)
194     addr = sf_params['ram_base']
195     offset = env__sf_config['offset']
196     count = sf_params['len']
197
198     cmd = 'sf erase %08x %x' % (offset, count)
199     output = u_boot_console.run_command(cmd)
200     assert 'Erased: OK' in output, 'Erase operation failed'
201
202     cmd = 'mw.b %08x ff %x' % (addr, count)
203     u_boot_console.run_command(cmd)
204     crc_ffs = u_boot_utils.crc32(u_boot_console, addr, count)
205
206     crc_read = sf_read(u_boot_console, env__sf_config, sf_params)
207     assert crc_ffs == crc_read, 'Unexpected CRC32 after erase operation.'
208
209 @pytest.mark.buildconfigspec('cmd_sf')
210 @pytest.mark.buildconfigspec('cmd_crc32')
211 @pytest.mark.buildconfigspec('cmd_memory')
212 def test_sf_update(u_boot_console, env__sf_config):
213     if not env__sf_config.get('writeable', False):
214         pytest.skip('Flash config is tagged as not writeable')
215
216     sf_params = sf_prepare(u_boot_console, env__sf_config)
217     sf_update(u_boot_console, env__sf_config, sf_params)