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