1 /*
2  * Copyright (c) 2023 Intel Corporation
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #ifndef _SEDI_DRIVER_SPI_H_
8 #define _SEDI_DRIVER_SPI_H_
9 
10 #ifdef __cplusplus
11 extern "C" {
12 #endif
13 
14 #include "sedi_driver_common.h"
15 
16 /*!
17  * \defgroup sedi_driver_spi SPI
18  * \ingroup sedi_driver
19  */
20 
21 #define SEDI_SPI_API_VERSION SEDI_DRIVER_VERSION_MAJOR_MINOR(0, 1)
22 
23 /*!
24  * \defgroup spi_control_mode  SPI Control
25  * \ingroup sedi_driver_spi
26  * \{
27  */
28 
29 enum sedi_spi_ioctl {
30 
31 	/*!
32 	 * Clock Polarity 0, Clock Phase 0
33 	 */
34 	SEDI_SPI_IOCTL_CPOL0_CPHA0,
35 
36 	/*!
37 	 * Clock Polarity 0, Clock Phase 1
38 	 */
39 	SEDI_SPI_IOCTL_CPOL0_CPHA1,
40 
41 	/*!
42 	 * Clock Polarity 1, Clock Phase 0
43 	 */
44 	SEDI_SPI_IOCTL_CPOL1_CPHA0,
45 
46 	/*!
47 	 * Clock Polarity 1, Clock Phase 1
48 	 */
49 	SEDI_SPI_IOCTL_CPOL1_CPHA1,
50 
51 	/*!
52 	 * Texas Instruments Frame Format
53 	 * No need to input args
54 	 */
55 	SEDI_SPI_IOCTL_TI_SSI,
56 
57 	/*!
58 	 * National Microwire Frame Format
59 	 * Need to input microwire configure pointer
60 	 */
61 	SEDI_SPI_IOCTL_MICROWIRE,
62 
63 	/*!
64 	 * Set the number of bits per SPI frame
65 	 * The parameter range is [1,16]
66 	 * For 4 bits operation, users need to provide an expand buffer, which
67 	 * covert 4-bits data to 8-bits data. The transfer size shall also use
68 	 * the expanded buffer size while do transfer.
69 	 */
70 	SEDI_SPI_IOCTL_DATA_WIDTH,
71 
72 	/*!
73 	 * MSB first send out, default
74 	 */
75 	SEDI_SPI_IOCTL_MSB,
76 
77 	/*!
78 	 * LSB first send out, it should be supported by hardware
79 	 */
80 	SEDI_SPI_IOCTL_LSB,
81 
82 	/*!
83 	 * The SPI will not drive or monitor the CS pin, user drives it with
84 	 * GPIO API before and after transaction, or directly connect the
85 	 * SPI slave's CS pin to a fixed low level.
86 	 */
87 	SEDI_SPI_IOCTL_CS_UNUSED,
88 
89 	/*!
90 	 * The SPI auto active the CS pin before transaction, and deactive it
91 	 * after complete or abort.
92 	 * The parameter is bitmask of CS pin been controlled by SPI
93 	 */
94 	SEDI_SPI_IOCTL_CS_HW,
95 
96 	/*!
97 	 * Get SPI speed in Hz
98 	 */
99 	SEDI_SPI_IOCTL_SPEED_SET,
100 
101 	/*!
102 	 * Set SPI speed in Hz
103 	 */
104 	SEDI_SPI_IOCTL_SPEED_GET,
105 
106 	/*!
107 	 * Set the FIFO depth, set it large for bulk transfer, set it small
108 	 * for few data transfer (register access).
109 	 * For bulk transfer, the data length should be aligned with the FIFO
110 	 * depth.
111 	 */
112 	SEDI_SPI_IOCTL_TX_WATERMARK_SET,
113 
114 	/*!
115 	 * Set the FIFO depth, set it large for bulk transfer, set it small
116 	 * for few data transfer (register access).
117 	 * For bulk transfer, the data length should be aligned with the FIFO
118 	 * depth.
119 	 */
120 	SEDI_SPI_IOCTL_RX_WATERMARK_SET,
121 
122 	/*!
123 	 * Get the FIFO depth
124 	 */
125 	SEDI_SPI_IOCTL_TX_WATERMARK_GET,
126 
127 	/*!
128 	 * Get the FIFO depth
129 	 */
130 	SEDI_SPI_IOCTL_RX_WATERMARK_GET,
131 
132 	/*!
133 	 * Set the dummy data on the bus, for example, master wants to read
134 	 * from slave. It can be 0x00 or 0xFF, which means keep data line low
135 	 * level or high level.
136 	 */
137 	SEDI_SPI_IOCTL_DUMMY_DATA,
138 
139 	/*!
140 	 * Abort the data transfer.
141 	 */
142 	SEDI_SPI_IOCTL_ABORT,
143 
144 	/*!
145 	 * Loopback mode for test
146 	 */
147 	SEDI_SPI_IOCTL_LOOPBACK,
148 
149 	/*!
150 	 * SPI transfer buffer sets, it means in a transfer, the buffer can be
151 	 * not physical continuous. Users need to update buffer while callback
152 	 * event is SEDI_SPI_EVENT_TX_FINISHED or SEDI_SPI_EVENT_RX_FINISHED.
153 	 * Users need to use function sedi_spi_update_tx_buf or
154 	 * sedi_spi_update_rx_buf to update buffers.
155 	 * Input 1 means enable this mode, 0 means disable this mode.
156 	 * Notice: This mode only supported in irq transfer mode.
157 	 */
158 	SEDI_SPI_IOCTL_BUFFER_SETS,
159 
160 	/*!
161 	 * Set SPI line mode, it can be single/dual/quad/octal mode.
162 	 */
163 	SEDI_SPI_IOCTL_LINE_MODE,
164 
165 	/*!
166 	 * Indicates the end of ioctl code
167 	 */
168 	SEDI_SPI_IOCTL_NUM
169 };
170 
171 /*!
172  * \}
173  */
174 
175 /*!
176  * \defgroup spi_quad_mode_t  SPI line mode
177  * \ingroup sedi_driver_spi
178  * \{
179  */
180 
181 typedef enum {
182 	SPI_SINGLE_MODE,
183 	SPI_DUAL_MODE,
184 	SPI_QUAD_MODE,
185 	SPI_OCTAL_MODE
186 } spi_line_mode_t;
187 
188 typedef enum {
189 	SPI_INST_ADDR_NORMAL, /*!< SPI instruction and addr use single line */
190 	SPI_INST_NORMAL_ADDR_ENHANCED, /*!< Instruction use single line,
191 					    address use dual/quad/octal mode */
192 	SPI_INST_ADDR_ENHANCED, /*!< Instruction and address use
193 				     dual/quad/octal mode */
194 } spi_inst_addr_mode_t;
195 
196 /*! Instruction length in SPI enhanced mode*/
197 typedef enum {
198 	SPI_INST_LEN_0_BIT,
199 	SPI_INST_LEN_4_BIT,
200 	SPI_INST_LEN_8_BIT,
201 	SPI_INST_LEN_16_BIT
202 } spi_inst_len_t;
203 
204 /*! Address length in SPI enhanced mode*/
205 typedef enum {
206 	SPI_ADDR_LEN_0_BIT,
207 	SPI_ADDR_LEN_4_BIT,
208 	SPI_ADDR_LEN_8_BIT,
209 	SPI_ADDR_LEN_12_BIT,
210 	SPI_ADDR_LEN_16_BIT,
211 	SPI_ADDR_LEN_20_BIT,
212 	SPI_ADDR_LEN_24_BIT,
213 	SPI_ADDR_LEN_28_BIT,
214 	SPI_ADDR_LEN_32_BIT,
215 	SPI_ADDR_LEN_36_BIT,
216 	SPI_ADDR_LEN_40_BIT,
217 	SPI_ADDR_LEN_44_BIT,
218 	SPI_ADDR_LEN_48_BIT,
219 	SPI_ADDR_LEN_52_BIT,
220 	SPI_ADDR_LEN_56_BIT,
221 	SPI_ADDR_LEN_60_BIT,
222 } spi_addr_len_t;
223 
224 /*!
225  * \}
226  */
227 
228 /*!
229  * \defgroup spi_event SPI Event
230  * \ingroup sedi_driver_spi
231  * \{
232  */
233 
234 /*! transfer complete */
235 #define SEDI_SPI_EVENT_COMPLETE (1UL << 0)
236 
237 /*! data lost happens, for example, tx underflow or rx overflow */
238 #define SEDI_SPI_EVENT_DATA_LOST (1UL << 1)
239 
240 /*!
241  * it will be detected by hardware, master detect the CS pin deactive while
242  * it transfer data, see sedi_spi_capabilities to get if hw support it.
243  */
244 #define SEDI_SPI_EVENT_MODE_FAULT (1UL << 2)
245 
246 #define SEDI_SPI_EVENT_TX_FINISHED (1UL << 3)
247 
248 #define SEDI_SPI_EVENT_RX_FINISHED (1UL << 4)
249 
250 /*!
251  * \}
252  */
253 
254 /*!
255  * \struct sedi_spi_status_t
256  * \brief SPI Status, be used if callback has not been registered
257  * \ingroup sedi_driver_spi
258  */
259 typedef volatile struct {
260 	uint32_t busy : 1;
261 	uint32_t data_lost : 1;
262 	uint32_t mode_fault : 1;
263 	uint32_t is_available : 1; /** 1:available 0:used by host  **/
264 	uint32_t isr : 6; /* ISR status in error, only bit 0-5 is valid */
265 	uint32_t reserved : 22;
266 	uint32_t txflr;
267 	uint32_t rxflr;
268 	uint32_t sr;
269 } sedi_spi_status_t;
270 
271 /*!
272  * \struct sedi_spi_capabilities_t
273  * \brief SPI Capabilities, the hardware feature
274  * \ingroup sedi_driver_spi
275  */
276 typedef struct {
277 	uint32_t ti_ssi : 1;
278 	uint32_t microwire : 1;
279 	uint32_t mode_fault : 1;
280 	uint32_t is_available : 1; /** 1:available 0:used by host  **/
281 	uint32_t reserved : 28;
282 } sedi_spi_capabilities_t;
283 
284 /*!
285  * \struct sedi_spi_microwire_config_t
286  * \brief Microwire configure
287  * \ingroup sedi_driver_spi
288  */
289 typedef struct {
290 	bool microwire_handshake; /*!< If enable microwire handshake  */
291 	bool data_direction_tx;   /*!< True means data to transmit, false means
292 				     data for receive */
293 	bool sequential_mode;     /*!< true means only need one control data for
294 				     data transfer, false means one data needs one
295 				     control data*/
296 } sedi_spi_microwire_config_t;
297 
298 /*!
299  * \struct sedi_spi_enhanced_config_t
300  * \brief Transfer in enhanced mode (dual/quad/octal) configure
301  * \ingroup sedi_driver_spi
302  */
303 typedef struct {
304 	uint8_t *inst_buf;
305 	spi_inst_len_t inst_len;
306 	uint8_t *addr_buf;
307 	spi_addr_len_t addr_len;
308 	uint8_t *tx_buf;
309 	uint8_t *rx_buf;
310 	uint32_t data_len;
311 	uint32_t dummy_cycles;
312 	spi_inst_addr_mode_t mode;
313 } sedi_spi_enhanced_config_t;
314 
315 /*!
316  * \defgroup spi_event_handler SPI Event Handler Callback
317  * \ingroup sedi_driver_spi
318  * \{
319  */
320 
321 /*!
322  * \typedef sedi_spi_event_cb_t
323  * \brief Callback function type for signal spi event.
324  * \param[in] event: event type. see \ref spi_event
325  * \param[inout] param: user parameter
326  * \return    void
327  */
328 typedef void (*sedi_spi_event_cb_t)(IN uint32_t event, INOUT void *param);
329 
330 /*!
331  * \}
332  */
333 
334 /*!
335  * \defgroup spi_function_calls SPI Driver Function Calls
336  * \ingroup sedi_driver_spi
337  * \{
338  */
339 
340 /*!
341  * \brief Get the spi driver's API version.
342  * \return the version of current spi driver's API
343  */
344 sedi_driver_version_t sedi_spi_get_version(void);
345 
346 /*!
347  * \brief Get the device's capabilities.
348  * \param[in] spi_device: spi device id
349  * \param[out] cap: spi device capabilities
350  * \return  \ref return_status
351  */
352 int32_t sedi_spi_get_capabilities(IN sedi_spi_t spi_device,
353 				  OUT sedi_spi_capabilities_t *cap);
354 
355 /*!
356  * \brief Initialize the device
357  * \param[in] spi_device: spi device id
358  * \param[in] cb: the callback function which can receive device's events.
359  * \param[in] param: the callback function's parameter.
360  * \param[in] base: base address of the SPI instance.
361  * \return  \ref return_status
362  */
363 int32_t sedi_spi_init(IN sedi_spi_t spi_device, IN sedi_spi_event_cb_t cb,
364 		      INOUT void *param, IN uint32_t base);
365 
366 /*!
367  * \brief Uninitialize the device
368  * \param[in] spi_device: spi device id
369  * \return  \ref return_status
370  */
371 int32_t sedi_spi_uninit(IN sedi_spi_t spi_device);
372 
373 /*!
374  * \brief Set the device's power
375  * \param[in] spi_device: spi device id
376  * \param[in] state: the power state to be set to the device
377  * \return  \ref return_status
378  */
379 int32_t sedi_spi_set_power(IN sedi_spi_t spi_device,
380 			   IN sedi_power_state_t state);
381 
382 /*!
383  * \brief  Get transferred data count
384  * \param[in] spi_device: spi device id
385  * \return number of data bytes transferred;
386  */
387 int32_t sedi_spi_get_data_count(IN sedi_spi_t spi_device);
388 
389 /*!
390  * \brief  Control the spi device
391  * \note Shall not use it in dma mode, as DMA HW cannot support get transferred
392  * bytes. \param[in] spi_device: spi device id \param[in] control: control
393  * operation code. see \ref spi_control_codes \param[in] arg: argument of
394  * operation (optional) \return  \ref return_status
395  */
396 int32_t sedi_spi_control(IN sedi_spi_t spi_device, IN uint32_t control,
397 			 IN uint32_t arg);
398 
399 /*!
400  * \brief  Get device's status
401  * \param[in] spi_device: spi device id
402  * \param[out] status: spi device status
403  * \return  \ref return_status
404  */
405 int32_t sedi_spi_get_status(IN sedi_spi_t spi_device,
406 			    OUT sedi_spi_status_t *status);
407 
408 /*!
409  * \brief Update tx buffer during a spi irq transfer
410  * This function used to tell spi driver a new tx buffer during a irq transfer.
411  * Typically used in callback function with event SEDI_SPI_EVENT_TX_FINISHED.
412  * Notice, if not call this function in callback, will cause data not send
413  * correct data.
414  * \param[in] spi_device: spi device id
415  * \param[in] *tx_buffer: pointer of the buffer with data
416  *                   which need send to slave
417  * \param[in] len: number of data bytes to transfer
418  * \return  \ref return_status
419  */
420 int32_t sedi_spi_update_tx_buf(IN sedi_spi_t spi_device, IN uint8_t *tx_buf,
421 			       IN uint32_t len);
422 
423 /*!
424  * \brief Update rx buffer during a spi irq transfer
425  * This function used to tell spi driver a new rx buffer during a irq transfer.
426  * Typically used in callback function with event SEDI_SPI_EVENT_RX_FINISHED.
427  * Notice, if not call this function in callback, will cause data not receive
428  * to correct location.
429  * \param[in] spi_device: spi device id
430  * \param[out] *rx_buffer: pointer of the buffer with data
431  *                   which need read from the slave
432  * \param[in] len: number of data bytes to transfer
433  * \return  \ref return_status
434  */
435 int32_t sedi_spi_update_rx_buf(IN sedi_spi_t spi_device, OUT uint8_t *rx_buf,
436 			       IN uint32_t len);
437 
438 /*!
439  * \brief Start transmitting data to spi slave device as master
440  * \param[in] spi_device: spi device id
441  * \param[in] *data_out: pointer of the buffer with data
442  *                   which need write to the slave
443  * \param[out] *data_in: pointer of the buffer with data
444  *                   which need read from the slave
445  * \param[in] num: number of data bytes to transfer
446  * \return  \ref return_status
447  */
448 int32_t sedi_spi_transfer(IN sedi_spi_t spi_device, IN uint8_t *data_out,
449 			  OUT uint8_t *data_in, IN uint32_t num);
450 
451 /*!
452  * \brief Start transmitting data to spi slave device as master in polling mode
453  * \param[in] spi_device: spi device id
454  * \param[in] *data_out: pointer of the buffer with data
455  *                   which need write to the slave
456  * \param[out] *data_in: pointer of the buffer with data
457  *                   which need read from the slave
458  * \param[in] num: number of data bytes to transfer
459  * \return  \ref return_status
460  */
461 int32_t sedi_spi_poll_transfer(IN sedi_spi_t spi_device, IN uint8_t *data_out,
462 			       OUT uint8_t *data_in, IN uint32_t num);
463 
464 /*!
465  * \brief Start transmitting data to spi slave device as master in dma mode
466  * \param[in] spi_device: spi device id
467  * \param[in] tx_dma: dma device id
468  * \param[in] tx_dma_chan: dma channel id
469  * \param[in] *data_out: pointer of the buffer with data
470  *                   which need write to the slave
471  * \param[in] rx_dma: dma device id
472  * \param[in] rx_dma_chan: dma channel id
473  * \param[out] *data_in: pointer of the buffer with data
474  *                   which need read from the slave
475  * \param[in] num: number of data bytes to transfer
476  * \return  \ref return_status
477  */
478 int32_t sedi_spi_dma_transfer(IN sedi_spi_t spi_device, IN uint32_t tx_dma,
479 			      IN uint32_t tx_dma_chan, IN uint8_t *data_out,
480 			      IN uint32_t rx_dma, IN uint32_t rx_dma_chan,
481 			      OUT uint8_t *data_in, IN uint32_t num);
482 
483 /*!
484  * \brief Start transmitting data to spi slave device as master enhanced mode
485  * including dual/quad/octal mode
486  * \param[in] spi_device: spi device id
487  * \param[in] *config: Enhanced SPI mode transfer configure
488  * \return  \ref return_status
489  */
490 int32_t sedi_spi_enhanced_transfer(IN sedi_spi_t spi_device,
491 				   IN sedi_spi_enhanced_config_t *config);
492 
493 /*!
494  * \brief Start transmitting data to spi slave device as master in dma mode
495  * using SPI enhanced mode including dual/quad/octal mode
496  * \param[in] spi_device: spi device id
497  * \param[in] tx_dma: dma device id
498  * \param[in] tx_dma_chan: dma channel id
499  * \param[in] rx_dma: dma device id
500  * \param[in] rx_dma_chan: dma channel id
501  * \param[in] *config: Enhanced SPI mode transfer configure
502  * \return  \ref return_status
503  */
504 int32_t sedi_spi_dma_enhanced_transfer(IN sedi_spi_t spi_device, IN uint32_t tx_dma,
505 			      IN uint32_t tx_dma_chan, IN uint32_t rx_dma,
506 			      IN uint32_t rx_dma_chan,
507 			      IN sedi_spi_enhanced_config_t *config);
508 
509 /*!
510  * \}
511  */
512 
513 #ifdef __cplusplus
514 }
515 #endif
516 
517 #endif /* _SEDI_DRIVER_SPI_H_ */
518