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 #ifndef QSPI_API_H
9 #define QSPI_API_H
10 
11 #include <fwk_id.h>
12 
13 #include <stdbool.h>
14 #include <stdint.h>
15 
16 /*
17  * \brief qspi command structure
18  */
19 struct qspi_command {
20     uint8_t code;
21     struct len {
22         uint8_t code_byte;
23         uint8_t addr_byte;
24         uint8_t alt_byte;
25         uint8_t dummy_cycle;
26         uint8_t data_byte;
27     } len;
28     struct alt {
29         uint8_t data[4];
30         bool is_nibble;
31     } alt;
32     struct io {
33         uint8_t code_bit;
34         uint8_t addr_bit;
35         uint8_t data_bit;
36     } io;
37 };
38 
39 /*
40  * \brief qspi command generator macro definitions
41  */
42 #define QSPI_GEN_COMMAND( \
43     CODE, \
44     CODE_BYTE, \
45     ADDR_BYTE, \
46     ALT_BYTE, \
47     DUMMY, \
48     DATA_BYTE, \
49     ALT_0, \
50     ALT_1, \
51     ALT_2, \
52     ALT_3, \
53     NIBBLE, \
54     IO_CODE, \
55     IO_ADDR, \
56     IO_DATA) \
57     { \
58         .code = CODE,                 \
59         .len = {                      \
60             .code_byte = CODE_BYTE,   \
61             .addr_byte = ADDR_BYTE,   \
62             .alt_byte = ALT_BYTE,     \
63             .dummy_cycle = DUMMY,     \
64             .data_byte = DATA_BYTE,   \
65         },                            \
66         .alt = {                      \
67             .data = {                 \
68                 ALT_0,                \
69                 ALT_1,                \
70                 ALT_2,                \
71                 ALT_3                 \
72             },                        \
73             .is_nibble = NIBBLE,      \
74         },                            \
75         .io = {                       \
76             .code_bit = IO_CODE,      \
77             .addr_bit = IO_ADDR,      \
78             .data_bit = IO_DATA,      \
79         }, \
80     }
81 #define QSPI_COMMAND_EMPTY \
82     ((struct qspi_command) \
83         QSPI_GEN_COMMAND(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, false, 0, 0, 0))
84 #define QSPI_COMMAND_TYPE_CODE(CODE) \
85     ((struct qspi_command) \
86         QSPI_GEN_COMMAND(CODE, 1, 0, 0, 0, 0, 0, 0, 0, 0, false, 1, 0, 1))
87 #define QSPI_COMMAND_TYPE_CODE_DATA(CODE) \
88     ((struct qspi_command) \
89         QSPI_GEN_COMMAND(CODE, 1, 0, 0, 0, 1, 0, 0, 0, 0, false, 1, 0, 1))
90 
91 #define QSPI_COMMAND_TYPE_READ(CODE, ADDR, DUMMY, IO_CODE, IO_ADDR, IO_DATA) \
92     ((struct qspi_command) QSPI_GEN_COMMAND( \
93         CODE, \
94         1, \
95         ADDR, \
96         0, \
97         DUMMY, \
98         1, \
99         0, \
100         0, \
101         0, \
102         0, \
103         false, \
104         IO_CODE, \
105         IO_ADDR, \
106         IO_DATA))
107 #define QSPI_COMMAND_TYPE_WRITE(CODE, ADDR, IO_CODE, IO_ADDR, IO_DATA) \
108     ((struct qspi_command) QSPI_GEN_COMMAND( \
109         CODE, 1, ADDR, 0, 0, 1, 0, 0, 0, 0, false, IO_CODE, IO_ADDR, IO_DATA))
110 #define QSPI_COMMAND_TYPE_WRITE_ADDR(CODE, ADDR, IO_CODE, IO_ADDR, IO_DATA) \
111     ((struct qspi_command) QSPI_GEN_COMMAND( \
112         CODE, 1, ADDR, 0, 0, 0, 0, 0, 0, 0, false, IO_CODE, IO_ADDR, IO_DATA))
113 #define QSPI_COMMAND_TYPE_READ_WITH_ALT_00( \
114     CODE, ADDR, ALT, DUMMY, IO_CODE, IO_ADDR, IO_DATA) \
115     ((struct qspi_command) QSPI_GEN_COMMAND( \
116         CODE, \
117         1, \
118         ADDR, \
119         ALT, \
120         DUMMY, \
121         1, \
122         0, \
123         0, \
124         0, \
125         0, \
126         false, \
127         IO_CODE, \
128         IO_ADDR, \
129         IO_DATA))
130 #define QSPI_COMMAND_TYPE_READ_WITH_ALT_FF( \
131     CODE, ADDR, ALT, DUMMY, IO_CODE, IO_ADDR, IO_DATA) \
132     ((struct qspi_command) QSPI_GEN_COMMAND( \
133         CODE, \
134         1, \
135         ADDR, \
136         ALT, \
137         DUMMY, \
138         1, \
139         0xFF, \
140         0xFF, \
141         0xFF, \
142         0xFF, \
143         false, \
144         IO_CODE, \
145         IO_ADDR, \
146         IO_DATA))
147 
148 #define IS_QSPI_COMMAND_EMPTY(cmd) \
149     (cmd.code == 0 && cmd.len.code_byte == 0 && cmd.len.addr_byte == 0 && \
150      cmd.len.alt_byte == 0 && cmd.len.dummy_cycle == 0 && \
151      cmd.len.data_byte == 0)
152 
153 /*
154  * \brief QSPI API indices
155  */
156 enum qspi_api_type {
157     QSPI_API_TYPE_DEFAULT = 0,
158     QSPI_API_TYPE_COUNT,
159 };
160 
161 /*!
162  * \brief APIs to access the descriptors in the flash memory.
163  */
164 struct qspi_api {
165     /*!
166      * \brief set read command to spi flash memory
167      *
168      * \param id The qspi device identifier.
169      * \param command Read command to send spi flash memofy.
170      *
171      * \retval ::FWK_SUCCESS The operation succeeded.
172      * \retval ::FWK_E_PARAM An invalid command was encountered.
173      * \retval ::FWK_E_STATE The qspi module isn't started yet.
174      * \return One of the other specific error codes.
175      */
176     int (*set_read_command)(fwk_id_t id, struct qspi_command *command);
177 
178     /*!
179      * \brief set write command to spi flash memory
180      *
181      * \param id The qspi device identifier.
182      * \param command Write command to send spi flash memofy.
183      *
184      * \retval ::FWK_SUCCESS The operation succeeded.
185      * \retval ::FWK_E_PARAM An invalid command was encountered.
186      * \retval ::FWK_E_STATE The qspi module isn't started yet.
187      * \return One of the other specific error codes.
188      */
189     int (*set_write_command)(fwk_id_t id, struct qspi_command *command);
190 
191     /*!
192      * \brief read data from spi flash memory
193      *
194      * \param id The qspi device identifier.
195      * \param offset Offset address of spi flash memory to read.
196      * \param buf The pointer address to store the data.
197      * \param len Number of data to read.
198      *
199      * \retval ::FWK_SUCCESS The operation succeeded.
200      * \retval ::FWK_E_PARAM An invalid parameter was encountered.
201      * \retval ::FWK_E_STATE The qspi module isn't started yet.
202      * \return One of the other specific error codes.
203      */
204     int (*read)(fwk_id_t id, uint32_t offset, void *buf, uint32_t len);
205 
206     /*!
207      * \brief write data to spi flash memory
208      *
209      * \param id The qspi device identifier.
210      * \param offset Offset address of spi flash memory to write.
211      * \param buf The pointer address to store the data.
212      * \param len Number of data to write.
213      *
214      * \retval ::FWK_SUCCESS The operation succeeded.
215      * \retval ::FWK_E_PARAM An invalid parameter was encountered.
216      * \retval ::FWK_E_STATE The qspi module isn't started yet.
217      * \return One of the other specific error codes.
218      */
219     int (*write)(fwk_id_t id, uint32_t offset, void *buf, uint32_t len);
220 
221     /*!
222      * \brief erase data on the spi flash memory
223      *
224      * \param id The qspi device identifier.
225      * \param offset Offset address of spi flash memory to write.
226      *
227      * \retval ::FWK_SUCCESS The operation succeeded.
228      * \retval ::FWK_E_STATE The qspi module isn't started yet.
229      * \return One of the other specific error codes.
230      */
231     int (*erase)(fwk_id_t id, uint32_t offset);
232 
233     /*!
234      * \brief reset the device and set hsspi controller to the command sequence
235      * mode
236      *
237      * \param id The qspi device identifier.
238      *
239      * \return never return.
240      */
241     int (*init_csmode)(fwk_id_t id);
242 };
243 
244 /*
245  * \brief function pointer for command operation
246  */
247 typedef int (*qspi_ope_func_t)(fwk_id_t, const struct qspi_api *, void *);
248 
249 #endif /* QSPI_API_H */
250