1 /*
2 * Arm SCP/MCP Software
3 * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 #include "nor/device_nor_mx25.h"
9 #include "qspi_api.h"
10
11 #include <fwk_id.h>
12 #include <fwk_module.h>
13 #include <fwk_status.h>
14
15 #include <stdbool.h>
16 #include <stdint.h>
17
18 /*
19 * local functions
20 */
set_read_command(fwk_id_t id,const struct qspi_api * qspi_api,struct qspi_command command)21 static int set_read_command(
22 fwk_id_t id,
23 const struct qspi_api *qspi_api,
24 struct qspi_command command)
25 {
26 if (IS_QSPI_COMMAND_EMPTY(command)) {
27 return FWK_E_SUPPORT;
28 }
29
30 return qspi_api->set_read_command(id, &command);
31 }
32
set_write_command(fwk_id_t id,const struct qspi_api * qspi_api,struct qspi_command command)33 static int set_write_command(
34 fwk_id_t id,
35 const struct qspi_api *qspi_api,
36 struct qspi_command command)
37 {
38 if (IS_QSPI_COMMAND_EMPTY(command)) {
39 return FWK_E_SUPPORT;
40 }
41
42 return qspi_api->set_write_command(id, &command);
43 }
44
mx25_read_status_reg(fwk_id_t id,const struct qspi_api * qspi_api,uint8_t * buf)45 static int mx25_read_status_reg(
46 fwk_id_t id,
47 const struct qspi_api *qspi_api,
48 uint8_t *buf)
49 {
50 int status;
51
52 status = set_read_command(id, qspi_api, COMMAND_READ_STATUS_REG);
53 if (status != FWK_SUCCESS) {
54 return status;
55 }
56
57 return qspi_api->read(id, 0, buf, sizeof(buf[0]));
58 }
59
mx25_write_status_reg(fwk_id_t id,const struct qspi_api * qspi_api,uint8_t buf)60 static int mx25_write_status_reg(
61 fwk_id_t id,
62 const struct qspi_api *qspi_api,
63 uint8_t buf)
64 {
65 int status;
66
67 status = set_write_command(id, qspi_api, COMMAND_WRITE_STATUS_REG);
68 if (status != FWK_SUCCESS) {
69 return status;
70 }
71
72 return qspi_api->write(id, 0, &buf, sizeof(buf));
73 }
74
mx25_read_security_reg(fwk_id_t id,const struct qspi_api * qspi_api,uint8_t * buf)75 static int mx25_read_security_reg(
76 fwk_id_t id,
77 const struct qspi_api *qspi_api,
78 uint8_t *buf)
79 {
80 int status;
81
82 status = set_read_command(id, qspi_api, MX25_COMMAND_READ_SECURITY_REG);
83 if (status != FWK_SUCCESS) {
84 return status;
85 }
86
87 return qspi_api->read(id, 0, buf, sizeof(buf[0]));
88 }
89
90 /*
91 * User APIs
92 */
mx25_nor_set_io_protocol(fwk_id_t id,const struct qspi_api * qspi_api,void * arg)93 int mx25_nor_set_io_protocol(
94 fwk_id_t id,
95 const struct qspi_api *qspi_api,
96 void *arg)
97 {
98 uint8_t io_num = *(uint8_t *)arg;
99 uint8_t buf;
100 bool req_quad;
101 int status;
102
103 if (io_num != 1 && io_num != 2 && io_num != 4) {
104 return FWK_E_PARAM;
105 }
106
107 req_quad = (io_num == 4);
108
109 status = mx25_read_status_reg(id, qspi_api, &buf);
110 if (status != FWK_SUCCESS) {
111 return status;
112 }
113
114 if (!req_quad || MX25_IS_QUAD_ENABLE(buf)) {
115 return FWK_SUCCESS;
116 }
117
118 if (!MX25_IS_WEL_ENABLE(buf)) {
119 return FWK_E_ACCESS;
120 }
121
122 /* At here, quad transfer is requested but not yet enabled. */
123 MX25_QUAD_ENABLE(buf);
124
125 status = mx25_write_status_reg(id, qspi_api, buf);
126 if (status != FWK_SUCCESS) {
127 return status;
128 }
129
130 return FWK_SUCCESS;
131 }
132
mx25_nor_set_4byte_addr_mode(fwk_id_t id,const struct qspi_api * qspi_api,void * arg)133 int mx25_nor_set_4byte_addr_mode(
134 fwk_id_t id,
135 const struct qspi_api *qspi_api,
136 void *arg)
137 {
138 bool enable = *(bool *)arg;
139 struct qspi_command command;
140
141 if (enable) {
142 command = MX25_COMMAND_ENTER_4BYTE;
143 } else {
144 command = MX25_COMMAND_EXIT_4BYTE;
145 }
146
147 return set_write_command(id, qspi_api, command);
148 }
149
mx25_nor_get_program_result(fwk_id_t id,const struct qspi_api * qspi_api,void * arg)150 int mx25_nor_get_program_result(
151 fwk_id_t id,
152 const struct qspi_api *qspi_api,
153 void *arg)
154 {
155 uint8_t buf;
156 bool *is_fail = (bool *)arg;
157 int status;
158
159 status = mx25_read_security_reg(id, qspi_api, &buf);
160 if (status != FWK_SUCCESS) {
161 return status;
162 }
163
164 if (MX25_IS_PROGRAM_FAIL(buf)) {
165 *is_fail = true;
166 } else {
167 *is_fail = false;
168 }
169
170 return FWK_SUCCESS;
171 }
172
mx25_nor_get_erase_result(fwk_id_t id,const struct qspi_api * qspi_api,void * arg)173 int mx25_nor_get_erase_result(
174 fwk_id_t id,
175 const struct qspi_api *qspi_api,
176 void *arg)
177 {
178 uint8_t buf;
179 bool *is_fail = (bool *)arg;
180 int status;
181
182 status = mx25_read_security_reg(id, qspi_api, &buf);
183 if (status != FWK_SUCCESS) {
184 return status;
185 }
186
187 if (MX25_IS_ERASE_FAIL(buf)) {
188 *is_fail = true;
189 } else {
190 *is_fail = false;
191 }
192
193 return FWK_SUCCESS;
194 }
195