270 lines
7.0 KiB
C
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
|