1  /*
2  * Copyright (C) 2017-2024 Alibaba Group Holding Limited
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 
19 /******************************************************************************
20  * @file     drv/spi.h
21  * @brief    Header File for SPI Driver
22  * @version  V1.0
23  * @date     08. Apr 2020
24  * @model    spi
25  ******************************************************************************/
26 
27 #ifndef _DRV_SPI_H_
28 #define _DRV_SPI_H_
29 
30 #include <stdint.h>
31 #include <drv/common.h>
32 #include <drv/gpio.h>
33 #include <drv/dma.h>
34 
35 #ifdef __cplusplus
36 extern "C" {
37 #endif
38 
39 /**
40  *  \enum    csi_spi_mode_t
41  *  \brief   Function mode of spi
42  */
43 typedef enum {
44     SPI_MASTER,             ///< SPI Master (Output on MOSI, Input on MISO); arg = Bus Speed in bps
45     SPI_SLAVE,              ///< SPI Slave  (Output on MISO, Input on MOSI)
46 } csi_spi_mode_t;
47 
48 /**
49  *  \enum     csi_spi_frame_len_t
50  *  \brief    SPI data width (4bit ~ 16bit)
51  */
52 typedef enum {
53     SPI_FRAME_LEN_4  = 4,
54     SPI_FRAME_LEN_5,
55     SPI_FRAME_LEN_6,
56     SPI_FRAME_LEN_7,
57     SPI_FRAME_LEN_8,
58     SPI_FRAME_LEN_9,
59     SPI_FRAME_LEN_10,
60     SPI_FRAME_LEN_11,
61     SPI_FRAME_LEN_12,
62     SPI_FRAME_LEN_13,
63     SPI_FRAME_LEN_14,
64     SPI_FRAME_LEN_15,
65     SPI_FRAME_LEN_16
66 } csi_spi_frame_len_t;
67 
68 /**
69  *  \enum     csi_spi_format_t
70  *  \brief    Timing format of spi
71  */
72 typedef enum {
73     SPI_FORMAT_CPOL0_CPHA0 = 0,  ///< Clock Polarity 0, Clock Phase 0
74     SPI_FORMAT_CPOL0_CPHA1,      ///< Clock Polarity 0, Clock Phase 1
75     SPI_FORMAT_CPOL1_CPHA0,      ///< Clock Polarity 1, Clock Phase 0
76     SPI_FORMAT_CPOL1_CPHA1,      ///< Clock Polarity 1, Clock Phase 1
77 } csi_spi_cp_format_t;
78 
79 /**
80  *  \enum     csi_spi_event_t
81  *  \brief    Signaled event for user by driver
82  */
83 typedef enum {
84     SPI_EVENT_SEND_COMPLETE,           ///< Data Send completed. Occurs after call to csi_spi_send_async to indicate that all the data has been send over
85     SPI_EVENT_RECEIVE_COMPLETE,        ///< Data Receive completed. Occurs after call to csi_spi_receive_async to indicate that all the data has been received
86     SPI_EVENT_SEND_RECEIVE_COMPLETE,   ///< Data Send_receive completed. Occurs after call to csi_spi_send_receive_async to indicate that all the data has been send_received
87     SPI_EVENT_ERROR_OVERFLOW,          ///< Data overflow: Receive overflow
88     SPI_EVENT_ERROR_UNDERFLOW,         ///< Data underflow: Transmit underflow
89     SPI_EVENT_ERROR                    ///< Master Mode Fault (SS deactivated when Master).Occurs in master mode when Slave Select is deactivated and indicates Master Mode Fault
90 } csi_spi_event_t;
91 
92 /**
93  *  \struct     csi_spi_t
94  *  \brief      Ctrl block of spi instance
95  */
96 typedef struct csi_spi csi_spi_t;
97 struct csi_spi {
98     csi_dev_t            dev;          ///< Hw-device info
99     void (*callback)(csi_spi_t *spi, csi_spi_event_t event, void *arg); ///< User callback ,signaled by driver event
100     void                *arg;          ///< User private param ,passed to user callback
101     uint8_t             *tx_data;      ///< Output data buf
102     uint32_t             tx_size;      ///< Output data size specified by user
103     uint8_t             *rx_data;      ///< Input  data buf
104     uint32_t             rx_size;      ///< Input  data size specified by user
105     csi_error_t (*send)(csi_spi_t *spi, const void *data, uint32_t size); ///< The send_async func
106     csi_error_t (*receive)(csi_spi_t *spi, void *data, uint32_t size);    ///< The receive_async func
107     csi_error_t (*send_receive)(csi_spi_t *spi, const void *data_out, void *data_in, uint32_t size); ///< The send_receive_async func
108     csi_state_t          state;        ///< Peripheral state
109     csi_dma_ch_t        *tx_dma;
110     csi_dma_ch_t        *rx_dma;
111     void                *priv;
112 };
113 
114 /**
115   \brief       Initialize SPI Interface
116                Initialize the resources needed for the SPI instance
117   \param[in]   spi    SPI handle
118   \param[in]   idx    SPI instance index
119   \return      Error code
120 */
121 csi_error_t csi_spi_init(csi_spi_t *spi, uint32_t idx);
122 
123 /**
124   \brief       De-initialize SPI Interface
125                stops Operation and releases the software resources used by the spi instance
126   \param[in]   spi    Handle
127   \return      None
128 */
129 void    csi_spi_uninit(csi_spi_t *spi);
130 
131 /**
132   \brief       Attach the callback handler to SPI
133   \param[in]   spi    Operate handle
134   \param[in]   callback    Callback function
135   \param[in]   arg         User can define it by himself as callback's param
136   \return      Error code
137 */
138 csi_error_t csi_spi_attach_callback(csi_spi_t *spi, void *callback, void *arg);
139 
140 /**
141   \brief       Detach the callback handler
142   \param[in]   spi    Operate handle
143   \return      None
144 */
145 void        csi_spi_detach_callback(csi_spi_t *spi);
146 
147 /**
148   \brief       Config spi mode (master or slave)
149   \param[in]   spi     SPI handle
150   \param[in]   mode    The mode of spi (master or slave)
151   \return      Error code
152 */
153 csi_error_t csi_spi_mode(csi_spi_t *spi, csi_spi_mode_t mode);
154 
155 /**
156   \brief       Config spi cp format
157   \param[in]   spi       SPI handle
158   \param[in]   format    SPI cp format
159   \return      Error code
160 */
161 csi_error_t csi_spi_cp_format(csi_spi_t *spi, csi_spi_cp_format_t format);
162 
163 /**
164   \brief       Config spi frame len
165   \param[in]   spi       SPI handle
166   \param[in]   length    SPI frame len
167   \return      Error code
168 */
169 csi_error_t csi_spi_frame_len(csi_spi_t *spi, csi_spi_frame_len_t length);
170 
171 /**
172   \brief       Config spi work frequence
173   \param[in]   spi     SPI handle
174   \param[in]   baud    SPI work baud
175   \return      the actual config frequency
176 */
177 uint32_t csi_spi_baud(csi_spi_t *spi, uint32_t baud);
178 
179 /**
180   \brief       Sending data to SPI transmitter,(received data is ignored)
181                blocking mode ,return unti all data has been sent or err happened
182   \param[in]   spi        Handle to operate
183   \param[in]   data       Pointer to buffer with data to send to SPI transmitter
184   \param[in]   size       Number of data to send(byte)
185   \param[in]   timeout    Unit in mini-second
186   \return      If send successful, this function shall return the num of data witch is sent successful
187                otherwise, the function shall return Error code
188 */
189 int32_t csi_spi_send(csi_spi_t *spi, const void *data, uint32_t size, uint32_t timeout);
190 
191 /**
192   \brief       Sending data to SPI transmitter,(received data is ignored)
193                non-blocking mode,transfer done event will be signaled by driver
194   \param[in]   spi     Handle to operate
195   \param[in]   data    Pointer to buffer with data to send to SPI transmitter
196   \param[in]   size    Number of data items to send(byte)
197   \return      Error code
198 */
199 csi_error_t csi_spi_send_async(csi_spi_t *spi, const void *data, uint32_t size);
200 
201 /**
202   \brief       Receiving data from SPI receiver
203                blocking mode, return untill curtain data items are readed
204   \param[in]   spi        Handle to operate
205   \param[out]  data       Pointer to buffer for data to receive from SPI receiver
206   \param[in]   size       Number of data items to receive(byte)
207   \param[in]   timeout    Unit in mini-second
208   \return      If receive successful, this function shall return the num of data witch is  received successful
209                otherwise, the function shall return Error code
210 */
211 int32_t csi_spi_receive(csi_spi_t *spi, void *data, uint32_t size, uint32_t timeout);
212 
213 /**
214   \brief       Receiving data from SPI receiver
215                not-blocking mode, event will be signaled when receive done or err happend
216   \param[in]   spi     Handle to operate
217   \param[out]  data    Pointer to buffer for data to receive from SPI receiver
218   \param[in]   size    Number of data items to receive(byte)
219   \return      Error code
220 */
221 csi_error_t csi_spi_receive_async(csi_spi_t *spi, void *data, uint32_t size);
222 
223 /**
224   \brief       Dulplex,sending and receiving data at the same time
225                \ref csi_spi_event_t is signaled when operation completes or error happens
226                \ref csi_spi_get_state can get operation status
227                blocking mode, this function returns after operation completes or error happens
228   \param[in]   spi         SPI handle to operate
229   \param[in]   data_out    Pointer to buffer with data to send to SPI transmitter
230   \param[out]  data_in     Pointer to buffer for data to receive from SPI receiver
231   \param[in]   size        Data size(byte)
232   \return      If transfer successful, this function shall return the num of data witch is transfer successful,
233                otherwise, the function shall return Error code
234 */
235 int32_t csi_spi_send_receive(csi_spi_t *spi, const void *data_out, void *data_in, uint32_t size, uint32_t timeout);
236 
237 /**
238   \brief       Transmit first then receive ,receive will begin after transmit is done
239                if non-blocking mode, this function only starts the transfer,
240                \ref csi_spi_event_t is signaled when operation completes or error happens
241                \ref csi_spi_get_state can get operation status
242   \param[in]   spi         SPI handle to operate
243   \param[in]   data_out    Pointer to buffer with data to send to SPI transmitter
244   \param[out]  data_in     Pointer to buffer for data to receive from SPI receiver
245   \param[in]   size        Data size(byte)
246   \return      Error code
247 */
248 csi_error_t csi_spi_send_receive_async(csi_spi_t *spi, const void *data_out, void *data_in, uint32_t size);
249 
250 /*
251   \brief       Set slave select num. Only valid for master
252   \param[in]   handle       SPI handle to operate
253   \param[in]   slave_num    SPI slave num
254   \return      None
255  */
256 void csi_spi_select_slave(csi_spi_t *spi, uint32_t slave_num);
257 
258 /**
259   \brief       Link DMA channel to spi device
260   \param[in]   spi       SPI handle to operate
261   \param[in]   tx_dma    The DMA channel handle for send, when it is NULL means to unlink the channel
262   \param[in]   rx_dma    The DMA channel handle for receive, when it is NULL means to unlink the channel
263   \return      Error code
264 */
265 csi_error_t csi_spi_link_dma(csi_spi_t *spi, csi_dma_ch_t *tx_dma, csi_dma_ch_t *rx_dma);
266 
267 /**
268   \brief       Get the state of spi device
269   \param[in]   spi      SPI handle to operate
270   \param[out]  state    The state of spi device
271   \return      Error code
272 */
273 csi_error_t csi_spi_get_state(csi_spi_t *spi, csi_state_t *state);
274 
275 /**
276   \brief       Enable spi power manage
277   \param[in]   spi  SPI handle to operate
278   \return      Error code
279 */
280 csi_error_t csi_spi_enable_pm(csi_spi_t *spi);
281 
282 /**
283   \brief       Disable spi power manage
284   \param[in]   spi    SPI handle to operate
285   \return      Error code
286 */
287 void csi_spi_disable_pm(csi_spi_t *spi);
288 
289 #ifdef __cplusplus
290 }
291 #endif
292 
293 #endif /* _DRV_SPI_H_ */
294