Files
2026-08-24 10:03:24 +08:00

270 lines
7.0 KiB
C

/*
* Copyright (c) 2021-2022 Amlogic, Inc. All rights reserved.
*
* SPDX-License-Identifier: MIT
*/
#ifndef __SPI_H__
#define __SPI_H__
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "FreeRTOS.h"
#include "riscv_bits.h"
#include "register.h"
#include "common.h"
#include "task.h"
#include "list.h"
#include "queue.h"
#include "portmacro.h"
#include "semphr.h"
#include "interrupt.h"
#include <mailbox-api.h>
#include "gpio.h"
#ifdef __cplusplus
extern "C" {
#endif
struct xSpiController;
#define SPI_SILENT 1
#ifndef SPI_SILENT
#define SPI_DEBUG(s, ...) printf("[SPI:%s-%d]"#s"\n", __func__, __LINE__, ##__VA_ARGS__)
#else
#define SPI_DEBUG(s, ...)
#endif
#define SPI_CHECK(a, str, ret_val) SPI_RETURN_ON_FALSE(a, ret_val, str)
#define SPI_RETURN_ON_FALSE(a, err_code, str) do {\
if (unlikely(!(a))) { \
printf("SPI:%s-%d:%s\n", __func__, __LINE__, str); \
return err_code; \
} \
} while (0)
#define DIV_ROUND_DOWN(n, d) ((n) / (d))
#define SPI_CPHA BIT(0) /* clock phase */
#define SPI_CPOL BIT(1) /* clock polarity */
#define SPI_MODE_0 (0 | 0) /* (original MicroWire) */
#define SPI_MODE_1 (0 | SPI_CPHA)
#define SPI_MODE_2 (SPI_CPOL | 0)
#define SPI_MODE_3 (SPI_CPOL | SPI_CPHA)
#define SPI_LINE_MASK GENMASK(7, 4)
#define SPI_TX_MASK (SPI_TX_DUAL | SPI_TX_QUAD)
#define SPI_RX_MASK (SPI_RX_DUAL | SPI_RX_QUAD)
#define SPI_3WIRE BIT(2) /* SI/SO signals shared */
#define SPI_NO_CS BIT(3) /* 1 dev/bus, no chipselect */
#define SPI_TX_DUAL BIT(4) /* transmit with 2 wires */
#define SPI_TX_QUAD BIT(5) /* transmit with 4 wires */
#define SPI_RX_DUAL BIT(6) /* receive with 2 wires */
#define SPI_RX_QUAD BIT(7) /* receive with 4 wires */
#define SPI_LITTLE_ENDIAN BIT(8) /* Endian 0:BIG 1:LITTLE */
#define SPI_MODE_MASK (BIT(9) - 1)
#define SPI_DEFAULT_MODE (SPI_MODE_0 | SPI_LITTLE_ENDIAN)
#define SPI_OP_WR 2
#define SPI_OP_RD 3
#define SPI_DEFAULT_OPMODE SPI_OP_WR
#define SPI_MAX_CS_NUM 3
#define SPI_NAME_SIZE 4
#define SPI_DEFAULT_SCLK (10000000)
#define SPI_DEFAULT_BITSWIDTH 8
#define SPIReadl(addr) REG32(addr)
#define SPIWritel(val, addr) (REG32(addr) = val)
#define SPISetBit(addr, bits) REG32_SET_BITS(addr, bits)
#define SPIClrBit(addr, bits) REG32_CLR_BITS(addr, bits)
#define SPIUpdateBits(addr, mask, val) REG32_UPDATE_BITS(addr, mask, val)
#define SPIReadBits(mask, addr) FIELD_GET(mask, REG32(addr))
#define SPI0_BASE_ADDR SPICC0_CFG_READY
#define SPI1_BASE_ADDR SPICC1_CFG_READY
/* Pin Selected by Default */
#define SPI0_PIN_WP_DQ2 GPIOT_11
#define SPI0_PIN_HOLD_DQ3 GPIOT_12
#define SPI0_PIN_CLK GPIOT_13
#define SPI0_PIN_MOSI_DQ0 GPIOT_14
#define SPI0_PIN_MISO_DQ1 GPIOT_15
#define SPI0_PIN_CS GPIOT_16
#define SPI0_PIN_CS1 GPIOT_17
#define SPI0_PIN_CS2 GPIOT_18
#define SPI1_PIN_WP_DQ2 GPIOD_6
#define SPI1_PIN_HOLD_DQ3 GPIOD_7
#define SPI1_PIN_CLK GPIOT_5
#define SPI1_PIN_MOSI_DQ0 GPIOT_6
#define SPI1_PIN_MISO_DQ1 GPIOT_7
#define SPI1_PIN_CS GPIOT_8
#define SPI1_PIN_CS1 GPIOT_9
#define SPI1_PIN_CS2 GPIOT_10
/* Irq source Num */
#define SPI0_IRQ_NUM 183
#define SPI1_IRQ_NUM 184
#define SPI_IRQ_PRIORITY 6
#define SPI_IRQ_MASK GENMASK(11, 0)
/**
* Enum with the spi master ID
*/
typedef enum {
SPI0 = 0,
SPI1,
SPI_BUS_MAX,
} xSpiMaster_t;
typedef struct {
xSpiMaster_t xBusNum;
uint32_t uISpeedHz;
uint32_t uIMode;
uint8_t ucChipSelect;
uint8_t ucBitsPerWord;
void *pvControllerData;
} xSpiBoardInfo_t;
typedef struct xSpiDevice {
ListItem_t xListItem;
char cName[SPI_NAME_SIZE];
struct xSpiController *pxController;
uint32_t uIMaxSpeedHz;
uint32_t uIMode;
uint8_t ucChipSelect;
uint8_t ucBitsPerWord;
void *pvControllerData;
} xSpiDevice_t;
typedef struct xSpiMessage {
List_t xTransferList;
xSpiDevice_t *pxSpiDev;
uint32_t uIActualLength;
} xSpiMessage_t;
typedef struct xSpiTransfer {
ListItem_t xListItem;
const void *pvTxBuf;
void *pvRxBuf;
uint32_t uILen;
uint32_t uImode;
uint32_t uISpeedHz;
uint8_t ucBitsPerWord;
uint8_t ucDisableDma;
/*
* @uIOperaMode
* 0:WR_CMD - write n bytes(DC)
* 1:RD_STS - write 1 byte and read more(DC)
* 2:WR - Single/Dual/Quad WR
* 3:RD - Single/Dual/Quad RD
*/
uint32_t uIOperaMode:2;
#define SPI_DC_MODE_MASK GENMASK(1, 0)
/* DATA or CMD*/
uint32_t uIDC:1;
/* PIN or 9BITS */
uint32_t uIDcMode:1;
uint32_t uIKeepSs:1;
uint32_t uIReadTurnAround:2;
uint32_t uIDummyClk:2;//not use
uint32_t uINull:1;
uint32_t uIHalfDuplex:1;
uint32_t uILane:2;
uint32_t uIGapSs2Clk:2;
uint32_t ucTxAdj:4;
uint32_t ucRxAdj:4;
uint32_t ucCmdLen:3;
uint32_t uIRsv:5;
} xSpiTransfer_t;
typedef struct xSpiController {
List_t xSlaveList;
ListItem_t xListItem;
QueueHandle_t xIoMuex;
SemaphoreHandle_t xSemaphore;
xSpiMaster_t ucBusNum;
uint8_t ucChipSelectMask;
uint32_t uIMinSpeedHz;
uint32_t uIMaxSpeedHz;
BaseType_t xIsSlave;
void *pvDevData;
void (*setup)(xSpiDevice_t *pSpiDev);
uint32_t (*transfer)(xSpiDevice_t *pSpiDev, xSpiMessage_t *mesg);
BaseType_t (*transfer_one_message)(xSpiDevice_t *pSpiDev,
xSpiMessage_t *mesg);
uint32_t (*transfer_one)(xSpiDevice_t *pSpiDev,
xSpiTransfer_t *pxTransfer);
} xSpiController_t;
/**
* @description: SPI Controller Initial
* @return {pdPASS - Success, pdFAIL -Failed}
* @param {xSpiMaster_t} master_id spi master ID
*/
BaseType_t xSpiBusInitialize(xSpiMaster_t xMasterId, BaseType_t xIsSlave);
/**
* @description: add a spi slave
* @return {*}
* @param {xSpiBoardInfo_t} slave board info
*/
xSpiDevice_t *xSpiAddDevice(xSpiBoardInfo_t pxSlaveInfo);
/**
* @description: Remove a spi slave
* @return {*}
* @param {xSpiDevice_t} spi device handle
*/
BaseType_t vSpiRemoveDevice(xSpiDevice_t *xSpiDev);
/**
* @description:init msg queue
* @return {*}
* @param {xSpiDevice_t} spi device handle
* @param {xSpiMessage_t} msg
*/
void xSpiMessageInit(xSpiDevice_t *pxSpiDev, xSpiMessage_t *pxSpiMsg);
/**
* @description:add spi xfer to msg queue
* @return {*}
* @param {xSpiMessage_t} spi msg
* @param {xSpiTransfer_t} spi xfer
*/
void xSpiMessageAddTail(xSpiMessage_t *pxSpiMsg, xSpiTransfer_t *pxSpiXfer);
/**
* @description: SPI Controller Transmit msg
* @return {pdTRUE - Success, pdFALSE - Failed}
* @param {xSpiDevice_t} spi device handle
* @param {xSpiMessage_t} spi msg
*/
BaseType_t xSpiTransmit(xSpiDevice_t *pxSpiDevice, xSpiMessage_t *pMsg);
/**
* @description: unregister SPI Controller
* @return {pdTRUE - Success, pdFALSE - Failed}
* @param {xSpiController_t} master_id spi master ID
*/
BaseType_t xSpiUnRegisterMaster(xSpiController_t *xMaster);
/**
* @description: unregister SPI Device
* @return {pdTRUE - Success, pdFALSE - Failed}
* @param {xSpiDevice_t} spi device handle
*/
BaseType_t xSpiUnRegisterSlave(xSpiDevice_t *xDevice);
/**
* @description: Find SPI Controller In SPI BUS
* @return {Null - Failed}
* @param {xSpiMaster_t} xMasterId spi master ID
*/
xSpiController_t *pxSpiFindMaster(xSpiMaster_t xMasterId);
#ifdef __cplusplus
}
#endif
#endif