blob: cc63d758ea2f9bb9c7b39f9428afbc45e4281429 [file] [log] [blame]
Juan Castillofacdd1c2015-08-12 12:53:02 +01001/*
2 * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
3 *
dp-armfa3cf0b2017-05-03 09:38:09 +01004 * SPDX-License-Identifier: BSD-3-Clause
Juan Castillofacdd1c2015-08-12 12:53:02 +01005 */
6
7#include <errno.h>
8#include <mmio.h>
9#include <norflash.h>
10
11/* Helper macros to access two flash banks in parallel */
12#define NOR_2X16(d) ((d << 16) | (d & 0xffff))
13
14/*
15 * DWS ready poll retries. The number of retries in this driver have been
16 * obtained empirically from Juno. FVP implements a zero wait state NOR flash
17 * model
18 */
19#define DWS_WORD_PROGRAM_RETRIES 1000
20
21/*
22 * Poll Write State Machine. Return values:
23 * 0 = WSM ready
24 * -EBUSY = WSM busy after the number of retries
25 */
26static int nor_poll_dws(uintptr_t base_addr, unsigned int retries)
27{
28 uint32_t status;
29 int ret;
30
31 for (;;) {
32 nor_send_cmd(base_addr, NOR_CMD_READ_STATUS_REG);
33 status = mmio_read_32(base_addr);
34 if ((status & NOR_DWS) &&
35 (status & (NOR_DWS << 16))) {
36 ret = 0;
37 break;
38 }
39 if (retries-- == 0) {
40 ret = -EBUSY;
41 break;
42 }
43 }
44
45 return ret;
46}
47
48void nor_send_cmd(uintptr_t base_addr, unsigned long cmd)
49{
50 mmio_write_32(base_addr, NOR_2X16(cmd));
51}
52
53/*
54 * Return values:
55 * 0 = success
56 * -EBUSY = WSM not ready
57 * -EPERM = Device protected or Block locked
58 */
59int nor_word_program(uintptr_t base_addr, unsigned long data)
60{
61 uint32_t status;
62 int ret;
63
64 /* Set the device in write word mode */
65 nor_send_cmd(base_addr, NOR_CMD_WORD_PROGRAM);
66 mmio_write_32(base_addr, data);
67
68 ret = nor_poll_dws(base_addr, DWS_WORD_PROGRAM_RETRIES);
69 if (ret != 0) {
70 goto word_program_end;
71 }
72
73 /* Full status check */
74 nor_send_cmd(base_addr, NOR_CMD_READ_STATUS_REG);
75 status = mmio_read_32(base_addr);
76
77 if (status & (NOR_PS | NOR_BLS)) {
78 nor_send_cmd(base_addr, NOR_CMD_CLEAR_STATUS_REG);
79 ret = -EPERM;
80 }
81
82word_program_end:
83 nor_send_cmd(base_addr, NOR_CMD_READ_ARRAY);
84 return ret;
85}
86
87void nor_lock(uintptr_t base_addr)
88{
89 nor_send_cmd(base_addr, NOR_CMD_LOCK_UNLOCK);
90 mmio_write_32(base_addr, NOR_2X16(NOR_LOCK_BLOCK));
91 nor_send_cmd(base_addr, NOR_CMD_READ_ARRAY);
92}
93
94void nor_unlock(uintptr_t base_addr)
95{
96 nor_send_cmd(base_addr, NOR_CMD_LOCK_UNLOCK);
97 mmio_write_32(base_addr, NOR_2X16(NOR_UNLOCK_BLOCK));
98 nor_send_cmd(base_addr, NOR_CMD_READ_ARRAY);
99}
100