blob: ada813b7e5ea39db83e160ea2a75e4686eee3432 [file] [log] [blame]
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +02001/*
Javier Almansa Sobrinod31b6b52019-12-09 13:32:00 +00002 * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +02003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <assert.h>
8#include <debug.h>
9#include <mmio.h>
10#include <string.h>
Javier Almansa Sobrinod31b6b52019-12-09 13:32:00 +000011#include <cdefs.h>
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020012#include "io_vexpress_nor_internal.h"
13#include "norflash.h"
14
15/* Device Id information */
16#define NOR_DEVICE_ID_LOCK_CONFIGURATION 0x02
17#define NOR_DEVICE_ID_BLOCK_LOCKED (1 << 0)
18#define NOR_DEVICE_ID_BLOCK_LOCKED_DOWN (1 << 1)
19
20/* Status Register Bits */
21#define NOR_SR_BIT_WRITE ((1 << 23) | (1 << 7))
22#define NOR_SR_BIT_ERASE ((1 << 21) | (1 << 5))
23#define NOR_SR_BIT_PROGRAM ((1 << 20) | (1 << 4))
24#define NOR_SR_BIT_VPP ((1 << 19) | (1 << 3))
25#define NOR_SR_BIT_BLOCK_LOCKED ((1 << 17) | (1 << 1))
26
27/*
28 * On chip buffer size for buffered programming operations
29 * There are 2 chips, each chip can buffer up to 32 (16-bit)words.
30 * Therefore the total size of the buffer is 2 x 32 x 2 = 128 bytes.
31 */
32#define NOR_MAX_BUFFER_SIZE_IN_BYTES 128
33#define NOR_MAX_BUFFER_SIZE_IN_WORDS (NOR_MAX_BUFFER_SIZE_IN_BYTES / 4)
34
35#define MAX_BUFFERED_PROG_ITERATIONS 1000
36#define LOW_16_BITS 0x0000FFFF
37#define FOLD_32BIT_INTO_16BIT(value) ((value >> 16) | (value & LOW_16_BITS))
38#define BOUNDARY_OF_32_WORDS 0x7F
39
40#define CHECK_VPP_RANGE_ERROR(status_register, address) \
41 do { \
42 if ((status_register) & NOR_SR_BIT_VPP) { \
43 ERROR("%s (address:0x%X): " \
44 "VPP Range Error\n", __func__, address);\
45 err = IO_FAIL; \
46 } \
47 } while (0)
48
49#define CHECK_BLOCK_LOCK_ERROR(status_register, address) \
50 do { \
51 if ((status_register) & NOR_SR_BIT_BLOCK_LOCKED) { \
52 ERROR("%s (address:0x%X): Device Protect " \
53 "Error\n", __func__, address); \
54 err = IO_FAIL; \
55 } \
56 } while (0)
57
58#define CHECK_BLOCK_ERASE_ERROR(status_register, block_offset) \
59 do { \
60 if ((status_register) & NOR_SR_BIT_ERASE) { \
61 ERROR("%s (block_offset=0x%08x: " \
62 "Block Erase Error status_register" \
63 ":0x%x\n", __func__, block_offset, \
64 status_register); \
65 err = IO_FAIL; \
66 } \
67 } while (0)
68
69#define CHECK_SR_BIT_PROGRAM_ERROR(status_register, address) \
70 do { \
71 if ((status_register) & NOR_SR_BIT_PROGRAM) { \
72 ERROR("%s(address:0x%X): Program Error\n", \
73 __func__, address); \
74 err = IO_FAIL; \
75 } \
76 } while (0)
77
78/* Helper macros to access two flash banks in parallel */
79#define NOR_2X16(d) ((d << 16) | (d & 0xffff))
80
81static inline void nor_send_cmd(uintptr_t base_addr, unsigned long cmd)
82{
83 mmio_write_32(base_addr, NOR_2X16(cmd));
84}
85
86static uint32_t flash_read_status(const io_nor_flash_spec_t *device)
87{
88 /* Prepare to read the status register */
89 nor_send_cmd(device->device_address, NOR_CMD_READ_STATUS_REG);
90
91 return mmio_read_32(device->device_address);
92}
93
94static uint32_t flash_wait_until_complete(const io_nor_flash_spec_t *device)
95{
96 uint32_t lock_status;
97
98 /* Wait until the status register gives us the all clear */
99 do {
100 lock_status = flash_read_status(device);
101 } while ((lock_status & NOR_SR_BIT_WRITE) != NOR_SR_BIT_WRITE);
102
103 return lock_status;
104}
105
106static int flash_block_is_locked(uint32_t block_offset)
107{
108 uint32_t lock_status;
109
110 uintptr_t addr = block_offset + (NOR_DEVICE_ID_LOCK_CONFIGURATION << 2);
111
112 /* Send command for reading device id */
113 nor_send_cmd(addr, NOR_CMD_READ_ID_CODE);
114
115 /* Read block lock status */
116 lock_status = mmio_read_32(addr);
117
118 /* Decode block lock status */
119 lock_status = FOLD_32BIT_INTO_16BIT(lock_status);
120
121 if ((lock_status & NOR_DEVICE_ID_BLOCK_LOCKED_DOWN) != 0)
122 WARN("flash_block_is_locked: Block LOCKED DOWN\n");
123
124 return lock_status & NOR_DEVICE_ID_BLOCK_LOCKED;
125}
126
127
128static void flash_perform_lock_operation(const io_nor_flash_spec_t *device,
129 uint32_t block_offset,
130 uint32_t lock_operation)
131{
132 assert ((lock_operation == NOR_UNLOCK_BLOCK) ||
133 (lock_operation == NOR_LOCK_BLOCK));
134
135 /* Request a lock setup */
136 nor_send_cmd(block_offset, NOR_CMD_LOCK_UNLOCK);
137
138 /* Request lock or unlock */
139 nor_send_cmd(block_offset, lock_operation);
140
141 /* Wait until status register shows device is free */
142 flash_wait_until_complete(device);
143
144 /* Put device back into Read Array mode */
145 nor_send_cmd(block_offset, NOR_CMD_READ_ARRAY);
146}
147
148static void flash_unlock_block_if_necessary(const io_nor_flash_spec_t *device,
149 uint32_t block_offset)
150{
151 if (flash_block_is_locked(block_offset) != 0)
152 flash_perform_lock_operation(device, block_offset,
153 NOR_UNLOCK_BLOCK);
154}
155
156
157static int flash_erase_block(const io_nor_flash_spec_t *device,
158 uint32_t block_offset)
159{
160 int err = IO_SUCCESS;
161 uint32_t status_register;
162
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200163 /* Request a block erase and then confirm it */
164 nor_send_cmd(block_offset, NOR_CMD_BLOCK_ERASE);
165 nor_send_cmd(block_offset, NOR_CMD_BLOCK_ERASE_ACK);
166
167 /* Wait for the write to complete and then check for any errors;
168 * i.e. check the Status Register */
169 status_register = flash_wait_until_complete(device);
170
171 CHECK_VPP_RANGE_ERROR(status_register, block_offset);
172
173 if ((status_register & (NOR_SR_BIT_ERASE | NOR_SR_BIT_PROGRAM)) ==
174 (NOR_SR_BIT_ERASE | NOR_SR_BIT_PROGRAM)) {
175 ERROR("%s(block_offset=0x%08x: "
176 "Command Sequence Error\n", __func__, block_offset);
177 err = IO_FAIL;
178 }
179
180 CHECK_BLOCK_ERASE_ERROR(status_register, block_offset);
181
182 CHECK_BLOCK_LOCK_ERROR(status_register, block_offset);
183
184 if (err) {
185 /* Clear the Status Register */
186 nor_send_cmd(device->device_address, NOR_CMD_CLEAR_STATUS_REG);
187 }
188
189 /* Put device back into Read Array mode */
190 nor_send_cmd(device->device_address, NOR_CMD_READ_ARRAY);
191
192 return err;
193}
194
195/*
196 * Writes data to the NOR Flash using the Buffered Programming method.
197 *
198 * The maximum size of the on-chip buffer is 32-words, because of hardware
199 * restrictions. Therefore this function will only handle buffers up to 32
200 * words or 128 bytes. To deal with larger buffers, call this function again.
201 *
202 * This function presumes that both the offset and the offset+BufferSize
203 * fit entirely within the NOR Flash. Therefore these conditions will not
204 * be checked here.
205 *
206 * In buffered programming, if the target address is not at the beginning of a
207 * 32-bit word boundary, then programming time is doubled and power consumption
208 * is increased. Therefore, it is a requirement to align buffer writes to
209 * 32-bit word boundaries.
210 */
211static int flash_write_buffer(const io_nor_flash_spec_t *device,
212 uint32_t offset,
213 const uint32_t *buffer,
214 uint32_t buffer_size)
215{
216 int err = IO_SUCCESS;
217 uint32_t size_in_words;
218 uint32_t count;
219 volatile uint32_t *data;
220 uint32_t timeout;
221 int is_buffer_available = 0;
222 uint32_t status_register;
223
224 timeout = MAX_BUFFERED_PROG_ITERATIONS;
225 is_buffer_available = 0;
226
227 /* Check that the target offset does not cross a 32-word boundary. */
228 if ((offset & BOUNDARY_OF_32_WORDS) != 0)
229 return IO_FAIL;
230
231 /* This implementation requires the buffer to be 32bit aligned. */
232 if (((uintptr_t)buffer & (sizeof(uint32_t) - 1)) != 0)
233 return IO_FAIL;
234
235 /* Check there are some data to program */
236 assert(buffer_size > 0);
237
238 /* Check that the buffer size does not exceed the maximum hardware
239 * buffer size on chip.
240 */
241 assert(buffer_size <= NOR_MAX_BUFFER_SIZE_IN_BYTES);
242
243 /* Check that the buffer size is a multiple of 32-bit words */
244 assert((buffer_size % 4) == 0);
245
246 /* Pre-programming conditions checked, now start the algorithm. */
247
248 /* Prepare the data destination address */
249 data = (uint32_t *)(uintptr_t)offset;
250
251 /* Check the availability of the buffer */
252 do {
253 /* Issue the Buffered Program Setup command */
254 nor_send_cmd(offset, NOR_CMD_BUFFERED_PROGRAM);
255
256 /* Read back the status register bit#7 from the same offset */
257 if (((*data) & NOR_SR_BIT_WRITE) == NOR_SR_BIT_WRITE)
258 is_buffer_available = 1;
259
260 /* Update the loop counter */
261 timeout--;
262 } while ((timeout > 0) && (is_buffer_available == 0));
263
264 /* The buffer was not available for writing */
265 if (timeout == 0) {
266 err = IO_FAIL;
267 goto exit;
268 }
269
270 /* From now on we work in 32-bit words */
271 size_in_words = buffer_size / sizeof(uint32_t);
272
273 /* Write the word count, which is (buffer_size_in_words - 1),
274 * because word count 0 means one word. */
275 nor_send_cmd(offset, size_in_words - 1);
276
277 /* Write the data to the NOR Flash, advancing each address by 4 bytes */
278 for (count = 0; count < size_in_words; count++, data++, buffer++)
279 *data = *buffer;
280
281 /* Issue the Buffered Program Confirm command, to start the programming
282 * operation */
283 nor_send_cmd(device->device_address, NOR_CMD_BUFFERED_PROGRAM_ACK);
284
285 /* Wait for the write to complete and then check for any errors;
286 * i.e. check the Status Register */
287 status_register = flash_wait_until_complete(device);
288
289 /* Perform a full status check:
290 * Mask the relevant bits of Status Register.
291 * Everything should be zero, if not, we have a problem */
292
293 CHECK_VPP_RANGE_ERROR(status_register, offset);
294
295 CHECK_SR_BIT_PROGRAM_ERROR(status_register, offset);
296
297 CHECK_BLOCK_LOCK_ERROR(status_register, offset);
298
299 if (err != IO_SUCCESS) {
300 /* Clear the Status Register */
301 nor_send_cmd(device->device_address,
302 NOR_CMD_CLEAR_STATUS_REG);
303 }
304
305exit:
306 /* Put device back into Read Array mode */
307 nor_send_cmd(device->device_address, NOR_CMD_READ_ARRAY);
308
309 return err;
310}
311
312static int flash_write_single_word(const io_nor_flash_spec_t *device,
313 int32_t offset, uint32_t data)
314{
315 int err = IO_SUCCESS;
316 uint32_t status_register;
317
318 /* NOR Flash Programming: Request a write single word command */
319 nor_send_cmd(offset, NOR_CMD_WORD_PROGRAM);
320
321 /* Store the word into NOR Flash; */
322 mmio_write_32(offset, data);
323
324 /* Wait for the write to complete and then check for any errors;
325 * i.e. check the Status Register */
326 status_register = flash_wait_until_complete(device);
327
328 /* Perform a full status check: */
329 /* Mask the relevant bits of Status Register.
330 * Everything should be zero, if not, we have a problem */
331
332 CHECK_VPP_RANGE_ERROR(status_register, offset);
333
334 CHECK_SR_BIT_PROGRAM_ERROR(status_register, offset);
335
336 CHECK_BLOCK_LOCK_ERROR(status_register, offset);
337
338 if (err != IO_SUCCESS)
339 /* Clear the Status Register */
340 nor_send_cmd(device->device_address,
341 NOR_CMD_CLEAR_STATUS_REG);
342
343 /* Put device back into Read Array mode */
344 nor_send_cmd(device->device_address, NOR_CMD_READ_ARRAY);
345
346 return err;
347}
348
349int flash_block_write(file_state_t *fp, uint32_t offset,
350 const uintptr_t buffer, size_t *written)
351{
352 int ret;
353 uintptr_t buffer_ptr = buffer;
354 uint32_t buffer_size;
355 uint32_t remaining = fp->block_spec->block_size;
356 uint32_t flash_pos = fp->block_spec->region_address + offset;
357 uint32_t block_offset = flash_pos;
358
359 /* address passed should be block aligned */
360 assert(!(offset % fp->block_spec->block_size));
361
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200362 /* Unlock block */
363 flash_unlock_block_if_necessary(fp->block_spec, block_offset);
364
365 /* Erase one block */
366 ret = flash_erase_block(fp->block_spec, flash_pos);
367
368 if (ret != IO_SUCCESS)
369 /* Perform lock operation as we unlocked it */
370 goto lock_block;
371
372 /* Start by using NOR Flash buffer while the buffer size is a multiple
373 * of 32-bit */
374 while ((remaining >= sizeof(uint32_t)) && (ret == IO_SUCCESS)) {
375 if (remaining >= NOR_MAX_BUFFER_SIZE_IN_BYTES)
376 buffer_size = NOR_MAX_BUFFER_SIZE_IN_BYTES;
377 else
378 /* Copy the remaining 32bit words of the buffer */
379 buffer_size = remaining & (sizeof(uint32_t) - 1);
380
381 ret = flash_write_buffer(fp->block_spec, flash_pos,
382 (const uint32_t *)buffer_ptr, buffer_size);
383 flash_pos += buffer_size;
384 remaining -= buffer_size;
385 buffer_ptr += buffer_size;
386
387 }
388
389 /* Write the remaining bytes */
390 while ((remaining > 0) && (ret == IO_SUCCESS)) {
391 ret = flash_write_single_word(fp->block_spec,
392 flash_pos++, buffer_ptr++);
393 remaining--;
394 }
395
396 if (ret == IO_SUCCESS)
397 *written = fp->block_spec->block_size;
398
399lock_block:
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200400 /* Lock the block once done */
401 flash_perform_lock_operation(fp->block_spec,
402 block_offset,
403 NOR_LOCK_BLOCK);
404
405 return ret;
406}
407
408/* In case of partial write we need to save the block into a temporary buffer */
Javier Almansa Sobrinod31b6b52019-12-09 13:32:00 +0000409static char block_buffer[NOR_FLASH_BLOCK_SIZE] __aligned(sizeof(uint32_t));
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200410
411int flash_partial_write(file_state_t *fp, uint32_t offset,
412 const uintptr_t buffer, size_t length, size_t *written)
413{
414 uintptr_t block_start;
415 uint32_t block_size;
416 uint32_t block_offset;
417 int ret;
418
419 assert((fp != NULL) && (fp->block_spec != NULL));
420 assert(written != NULL);
421
422 block_size = fp->block_spec->block_size;
423 /* Start address of the block to write */
424 block_start = (offset / block_size) * block_size;
425
426 /* Ensure 'block_buffer' is big enough to contain a copy of the block.
427 * 'block_buffer' is reserved at build time - so it might not match */
428 assert(sizeof(block_buffer) >= block_size);
429
430 /*
431 * Check the buffer fits inside a single block.
432 * It must not span several blocks
433 */
434 assert((offset / block_size) ==
435 ((offset + length - 1) / block_size));
436
437 /* Make a copy of the block from flash to a temporary buffer */
438 memcpy(block_buffer, (void *)(fp->block_spec->region_address +
439 block_start), block_size);
440
441 /* Calculate the offset of the buffer into the block */
442 block_offset = offset % block_size;
443
444 /* update the content of the block buffer */
445 memcpy(block_buffer + block_offset, (void *)buffer, length);
446
447 /* Write the block buffer back */
448 ret = flash_block_write(fp, block_start,
449 (uintptr_t)block_buffer, written);
450 if (ret == IO_SUCCESS)
451 *written = length;
452
453 return ret;
454}