From 223903472252053d7e94223290415326b0c4b25c Mon Sep 17 00:00:00 2001 From: surenyi Date: Wed, 16 Oct 2024 13:14:32 +0800 Subject: [PATCH] add FtSpi driver Signed-off-by: surenyi --- 40vxbFtQspi.cdf | 1 - 40vxbFtSpi.cdf | 26 +++ Makefile | 2 +- config.h | 14 +- ft2000-4.h | 8 + hwconf.c | 104 ++++++---- sysLib.c | 23 ++- vxbFtQspi.h | 2 +- vxbFtSpi.c | 500 ++++++++++++++++++++++++++++++++++++++++++++++++ vxbFtSpi.h | 32 ++++ 10 files changed, 661 insertions(+), 51 deletions(-) create mode 100644 40vxbFtSpi.cdf create mode 100644 vxbFtSpi.c create mode 100644 vxbFtSpi.h diff --git a/40vxbFtQspi.cdf b/40vxbFtQspi.cdf index 2299efd..1ac549b 100644 --- a/40vxbFtQspi.cdf +++ b/40vxbFtQspi.cdf @@ -23,4 +23,3 @@ Component DRV_FTQSPI { INIT_AFTER INCLUDE_PLB_BUS \ INCLUDE_SPI_BUS } - diff --git a/40vxbFtSpi.cdf b/40vxbFtSpi.cdf new file mode 100644 index 0000000..debac82 --- /dev/null +++ b/40vxbFtSpi.cdf @@ -0,0 +1,26 @@ +/* 40vxbFtQspi.cdf - QSPI controller configuration file */ + +/* + * + * This program is OPEN SOURCE software: you can redistribute it and/or modify it; + * This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + */ + + +Component DRV_FTSPI { + NAME FT SPI controller driver + SYNOPSIS FT SPI controller driver + _CHILDREN FOLDER_DRIVERS + CONFIGLETTES + _INIT_ORDER hardWareInterFaceBusInit + INIT_RTN vxbFtSpiRegister(); + PROTOTYPE void vxbFtSpiRegister (void); + REQUIRES INCLUDE_VXBUS \ + INCLUDE_PLB_BUS \ + INCLUDE_SPI_BUS + INIT_AFTER INCLUDE_PLB_BUS \ + INCLUDE_SPI_BUS +} + diff --git a/Makefile b/Makefile index 7d3ef4f..21c58c0 100644 --- a/Makefile +++ b/Makefile @@ -22,7 +22,7 @@ RELEASE += bootrom_uncmp.hex MACH_EXTRA += vxbArmGenIntCtlrV3.o vxbArmv7GenTimer.o vxbArmv7AuxTimer.o \ vxbFtPcie.o vxbAhciStorage.o vxbFtGmacEnd.o vxbFtcan.o vxbPci.o \ vxbFtSdCtrl.o vxbFtI2c.o vxbYt8521Phy.o genericPhy.o vxbFtQspi.o\ - vxbSp25SpiFlash.o vxbFtGpio.o usrStubs.o vxbLfsLib.o + vxbSp25SpiFlash.o vxbFtGpio.o vxbFtSpi.o usrStubs.o vxbLfsLib.o ifneq ($(findstring bootrom,$(MAKECMDGOALS)),bootrom) LIB_EXTRA = lib/libFtX100dcdrv.a diff --git a/config.h b/config.h index 1b1f636..8b022e1 100644 --- a/config.h +++ b/config.h @@ -41,8 +41,9 @@ extern "C" { #undef DRV_FTCAN #undef INCLUDE_FT_SD #undef DRV_FTI2C -#define DRV_FTQSPI #define INCLUDE_SPI_BUS +#define DRV_FTQSPI +#define DRV_FTSPI #define DRV_SPIFLASH_SP25 #define INCLUDE_YT8521PHY #define DRV_FTGPIO @@ -67,10 +68,8 @@ extern "C" { #define INCLUDE_USB_GEN2_STORAGE_INIT #endif -#define INCLUDE_TFFS - #undef INCLUDE_DRV_STORAGE_AHCI -#if defined(INCLUDE_USB) || defined(INCLUDE_TFFS) || \ +#if defined(INCLUDE_USB) || \ defined(INCLUDE_DRV_STORAGE_PIIX) || defined(INCLUDE_DRV_STORAGE_AHCI) #define INCLUDE_DOSFS #define INCLUDE_DOSFS_MAIN @@ -92,9 +91,14 @@ extern "C" { #define INCLUDE_DISK_UTIL #endif +#define INCLUDE_TFFS +#if defined(INCLUDE_TFFS) + +#endif /*#define INCLUDE_HRFS*/ #define DRV_VXBEND_FTGMAC - +# define INCLUDE_HRFS_FORMAT +# define INCLUDE_HRFS_CHKDSK #undef DRV_PCIBUS_FT #ifdef DRV_PCIBUS_FT diff --git a/ft2000-4.h b/ft2000-4.h index 22badf2..cc432c3 100644 --- a/ft2000-4.h +++ b/ft2000-4.h @@ -83,11 +83,19 @@ enum can_bitrate{ #define FTCAN2_IRQ 124 #define FTCAN2_BITRATE FTCAN_BRATE_DEFAULT +#define FTSPI0_BASE 0x2800c000 +#define FTSPI0_IRQ 50 + +#define FTSPI1_BASE 0x28013000 +#define FTSPI1_IRQ 51 + /* pad pin multi-function demux component */ #define PIN_DEMUX_BASE 0x28180000 #define REG200 0x200 #define REG204 0x204 #define REG208 0x208 +#define REG210 0x210 +#define REG214 0x214 #define CAN_TXD_0 (1<<24) #define CAN_RXD_0 (1<<12) #define CAN_TXD_1 (1<<20) diff --git a/hwconf.c b/hwconf.c index 14daeb2..352ae78 100644 --- a/hwconf.c +++ b/hwconf.c @@ -23,6 +23,9 @@ #ifdef DRV_FTQSPI #include "vxbFtQspi.h" #endif +#ifdef DRV_FTSPI +#include "vxbFtSpi.h" +#endif #ifdef DRV_PCIBUS_FT # include #endif @@ -39,38 +42,41 @@ #ifdef DRV_ARM_GICV3 - LOCAL struct intrCtlrInputs gicInputs[] = { /* pin, driver, unit, index */ - { GEN_TIMER_IRQ, "armGenTimer", 0, 0 }, + { GEN_TIMER_IRQ, "armGenTimer", 0, 0 }, #ifdef DRV_ARM_GEN_AUX_TIMER - { AUX_GEN_TIMER_IRQ, "armAuxTimer", 0, 0 }, + { AUX_GEN_TIMER_IRQ, "armAuxTimer", 0, 0 }, +#endif + { INT_VEC_UART0INTR, "primeCellSioDev", 0, 0 }, + { INT_VEC_UART1INTR, "primeCellSioDev", 1, 0 }, + { INT_VEC_UART2INTR, "primeCellSioDev", 2, 0 }, + { INT_VEC_UART3INTR, "primeCellSioDev", 3, 0 }, + { 81, "gmac", 0, 0 }, + { 82, "gmac", 1, 0 }, + { FTCAN0_IRQ, "ftCan", 0, 0 }, + { FTCAN1_IRQ, "ftCan", 1, 0 }, + { FTCAN2_IRQ, "ftCan", 2, 0 }, + { 60, "legacy", 0, 60}, /* Peu0 legacy interrupt number : 60,61,62,63*/ + { 61, "legacy", 0, 61}, + { 62, "legacy", 0, 62}, + { 63, "legacy", 0, 63}, + { 52, "ftSdhci", 0, 0 }, +#ifdef DRV_FTSPI + { FTSPI0_IRQ, FT_SPI_NAME, 0, 0 }, + { FTSPI1_IRQ, FT_SPI_NAME, 1, 0 }, #endif - { INT_VEC_UART0INTR, "primeCellSioDev", 0, 0 }, - { INT_VEC_UART1INTR, "primeCellSioDev", 1, 0 }, - { INT_VEC_UART2INTR, "primeCellSioDev", 2, 0 }, - { INT_VEC_UART3INTR, "primeCellSioDev", 3, 0 }, - { 81, "gmac", 0, 0 }, - { 82, "gmac", 1, 0 }, - { FTCAN0_IRQ, "ftCan", 0, 0 }, - { FTCAN1_IRQ, "ftCan", 1, 0 }, - { FTCAN2_IRQ, "ftCan", 2, 0 }, - { 60, "legacy", 0, 60 }, /* Peu0 legacy interrupt number : 60,61,62,63*/ - { 61, "legacy", 0, 61 }, - { 62, "legacy", 0, 62 }, - { 63, "legacy", 0, 63 }, - { 52, "ftSdhci", 0, 0 }, - { 53, "ftSdhci", 0, 1 }, - { 54, "ftSdhci", 0, 2 }, - { I2C_0_INTR_IRQ, "ftI2c", 0, 0 }, - { I2C_1_INTR_IRQ, "ftI2c", 1, 0 }, - { I2C_2_INTR_IRQ, "ftI2c", 2, 0 }, - { I2C_3_INTR_IRQ, "ftI2c", 3, 0 }, - { INT_VEC_GPIO0INTR, "ftGpio", 0, 0 }, - { INT_VEC_GPIO1INTR, "ftGpio", 1, 0 }, - { INT_VEC_GPIO0INTR, "legacy", 0, INT_VEC_GPIO0INTR }, - { INT_VEC_GPIO1INTR, "legacy", 0, INT_VEC_GPIO1INTR }, + { 53, "ftSdhci", 0, 1 }, + { 54, "ftSdhci", 0, 2 }, + { I2C_0_INTR_IRQ, "ftI2c", 0, 0 }, + { I2C_1_INTR_IRQ, "ftI2c", 1, 0 }, + { I2C_2_INTR_IRQ, "ftI2c", 2, 0 }, + { I2C_3_INTR_IRQ, "ftI2c", 3, 0 }, + { INT_VEC_GPIO0INTR, "ftGpio", 0, 0 }, + { INT_VEC_GPIO1INTR, "ftGpio", 1, 0 }, + { INT_VEC_GPIO0INTR, "legacy", 0, INT_VEC_GPIO0INTR }, + { INT_VEC_GPIO1INTR, "legacy", 0, INT_VEC_GPIO1INTR }, }; LOCAL const struct intrCtlrPriority gicPriority[] = { @@ -224,7 +230,7 @@ struct hcfResource ftCanDev2Resources[] = { #define ftCanDev2Num NELEMENTS(ftCanDev2Resources) #ifdef DRV_FTQSPI -struct vxbSpiDevInfo spiDevTbl[] = { +struct vxbSpiDevInfo qspiDevTbl[] = { /* name cs width freq mode */ #ifdef DRV_SPIFLASH_SP25 { SPI_FLASH_DEVICE_NAME, 0, 8, 30000000, 1}, @@ -237,13 +243,28 @@ struct hcfResource qspiResources[] = { { "clkDiv", HCF_RES_INT, { (void *)(QSPI_SCK_DIV_128) } }, { "transMode", HCF_RES_INT, { (void *)(QSPI_TRANSFER_1_1_1) } }, { "addrMode", HCF_RES_INT, { (void *)(QSPI_ADDR_SEL_4) } }, - { "spiDev", HCF_RES_ADDR, { (void *)&spiDevTbl[0]} }, - { "spiDevNum", HCF_RES_INT, { (void *)NELEMENTS(spiDevTbl)}}, + { "spiDev", HCF_RES_ADDR, { (void *)&qspiDevTbl[0]} }, + { "spiDevNum", HCF_RES_INT, { (void *)NELEMENTS(qspiDevTbl)}}, }; # define qspiNum NELEMENTS(qspiResources) #endif /* DRV_FTQSPI */ +#ifdef DRV_FTSPI +struct vxbSpiDevInfo spiDevTbl1[] = { + /* name cs width freq mode */ + { "SM2130", 0, 8, 500000, 1}, +}; + +struct hcfResource spiResources1[] = { + { "regBase", HCF_RES_INT, { (void *)(FTSPI1_BASE) } }, + { "clkDiv", HCF_RES_INT, { (void *)(2) } }, + { "spiDev", HCF_RES_ADDR, { (void *)&spiDevTbl1[0]} }, + { "spiDevNum", HCF_RES_INT, { (void *)NELEMENTS(spiDevTbl1)}}, +}; +# define spiNum1 NELEMENTS(spiResources1) +#endif /* DRV_FTQSPI */ + #ifdef DRV_FTI2C LOCAL struct i2cDevInputs i2cDev0Input[] = { @@ -438,13 +459,12 @@ LOCAL struct hcfResource ftSdhc0Resources[] = { #ifdef DRV_VXBEND_FTGMAC -#define PHYADDR_OF_GREEN_BOARD 4 /* for reference green board. hardware V1 */ -#define PHYADDR_OF_BLACK_BOARD 3 /* for reference black board. hardware V2 */ -#define PHYADDR_OF_AUTO -1 /* auto probe when start */ +#define PHYADDR_OF_GMAC0 1 +#define PHYADDR_OF_AUTO -1 /* auto probe when start */ struct hcfResource gmac0Resources[] = { { "regBase", HCF_RES_INT, {(void *)0x2820c000} }, - { "phyAddr", HCF_RES_INT, {(void *)PHYADDR_OF_AUTO} }, + { "phyAddr", HCF_RES_INT, {(void *)PHYADDR_OF_GMAC0} }, { "macAddrSet", HCF_RES_ADDR, {(void *)sysGmacAddrSet} }, { "miiIfName", HCF_RES_STRING, {(void *)"gmac"} }, { "miiIfUnit", HCF_RES_INT, {(void *)0} }, @@ -482,8 +502,8 @@ const struct hcfDevice hcfDeviceList[] = { #endif /* DRV_ARM_GIC */ { "primeCellSioDev", 0, VXB_BUSID_PLB, 0, primeCellSioDev0Num , primeCellSioDev0Resources }, { "primeCellSioDev", 1, VXB_BUSID_PLB, 0, primeCellSioDev1Num , primeCellSioDev1Resources }, - { "primeCellSioDev", 2, VXB_BUSID_PLB, 0, primeCellSioDev2Num , primeCellSioDev2Resources }, - { "primeCellSioDev", 3, VXB_BUSID_PLB, 0, primeCellSioDev3Num , primeCellSioDev3Resources }, + /* { "primeCellSioDev", 2, VXB_BUSID_PLB, 0, primeCellSioDev2Num , primeCellSioDev2Resources }, */ /* 1553B SPI */ + /* { "primeCellSioDev", 3, VXB_BUSID_PLB, 0, primeCellSioDev3Num , primeCellSioDev3Resources }, */ #ifdef DRV_VXBEND_FTGMAC { "gmac", 0, VXB_BUSID_PLB, 0, gmac0Num, gmac0Resources}, @@ -504,8 +524,8 @@ const struct hcfDevice hcfDeviceList[] = { #endif /* DRV_PCIBUS_M85XX */ #ifdef DRV_FTCAN -{ "ftCan", 0, VXB_BUSID_PLB, 0, ftCanDev0Num, ftCanDev0Resources }, -{ "ftCan", 1, VXB_BUSID_PLB, 0, ftCanDev1Num, ftCanDev1Resources }, + { "ftCan", 0, VXB_BUSID_PLB, 0, ftCanDev0Num, ftCanDev0Resources }, + { "ftCan", 1, VXB_BUSID_PLB, 0, ftCanDev1Num, ftCanDev1Resources }, /*{ "ftCan", 2, VXB_BUSID_PLB, 0, ftCanDev2Num, ftCanDev2Resources },*/ #endif @@ -526,6 +546,10 @@ const struct hcfDevice hcfDeviceList[] = { { FT_QSPI_NAME, 0, VXB_BUSID_PLB, 0, qspiNum, qspiResources }, #endif +#ifdef DRV_FTSPI +{ FT_SPI_NAME, 1, VXB_BUSID_PLB, 0, spiNum1, spiResources1 }, +#endif + #ifdef DRV_FTGPIO { "ftGpio", 0, VXB_BUSID_PLB, 0, gpioDev0Num, gpioDev0Resources }, { "ftGpio", 1, VXB_BUSID_PLB, 0, gpioDev1Num, gpioDev1Resources }, @@ -535,8 +559,8 @@ const struct hcfDevice hcfDeviceList[] = { const int hcfDeviceNum = NELEMENTS(hcfDeviceList); VXB_INST_PARAM_OVERRIDE sysInstParamTable[] = - { +{ { NULL, 0, NULL, VXB_PARAM_END_OF_LIST, {(void *)0} } - }; +}; diff --git a/sysLib.c b/sysLib.c index c23cef2..4ce69bc 100644 --- a/sysLib.c +++ b/sysLib.c @@ -568,7 +568,7 @@ extern void ftX100DcDevicePciRegister (void); #endif void sysHwInit (void) - { +{ uartf("...............................\r\n"); /* swdo_swj_pad: can_rxd_1 i2c_2_scl @@ -576,8 +576,25 @@ void sysHwInit (void) CAN_1,CAN_2 and I2C_2, only choose ONE. */ - // writeq(readq(PIN_DEMUX_BASE+REG204)|CAN_TXD_0|CAN_RXD_0|CAN_TXD_1|CAN_RXD_1, + // writeq(readq(PIN_DEMUX_BASE+REG204)|CAN_TXD_0|CAN_RXD_0|CAN_TXD_1|CAN_RXD_1, // PIN_DEMUX_BASE+REG204); /* pad pin DeMux. enable CAN */ + + /* pin_mux: + * uart_2_rxd_pad: uart_2_rxd spi1_csn0 gpio0_portb_5 + * uart_2_txd_pad: uart_2_txd spi1_sck hda_sdi1 + * uart_3_rxd_pad: uart_3_rxd spi1_so hda_sdi2 + * uart_3_txd_pad: uart_3_txd spi1_si hda_sdi3 + */ + /* SM2130 1553B SPI1 */ + unsigned int reg = readl(PIN_DEMUX_BASE + REG210); + reg &= ~0x3; + reg |= 0x1; /* spi1_csn0 */ + writel(reg, PIN_DEMUX_BASE + REG210); + reg = readl(PIN_DEMUX_BASE + REG214); + reg &= ~((0x3 << 28) | (0x3 << 24) | (0x3 << 20)); + reg |= (1 << 28) | (1 << 24) | (1 << 20); + writel(reg, PIN_DEMUX_BASE + REG214); + #ifdef DRV_X100DC ftX100DcDevicePciRegister(); #endif @@ -605,7 +622,7 @@ void sysHwInit (void) armGenGetFreq(); #endif/*_WRS_CONFIG_SMP*/ - } +} /******************************************************************************* * diff --git a/vxbFtQspi.h b/vxbFtQspi.h index e3fe772..5a40707 100644 --- a/vxbFtQspi.h +++ b/vxbFtQspi.h @@ -240,7 +240,7 @@ typedef union /* structure holding the instance specific details */ -typedef struct tf_qspi_drv_ctrl +typedef struct ft_qspi_drv_ctrl { VXB_DEVICE_ID pDev; void * regBase; diff --git a/vxbFtSpi.c b/vxbFtSpi.c new file mode 100644 index 0000000..170ad48 --- /dev/null +++ b/vxbFtSpi.c @@ -0,0 +1,500 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include <../src/hwif/h/vxbus/vxbAccess.h> +#include +#include "vxbFtSpi.h" + +/* debug macro */ +#undef SPI_DBG_ON +#ifdef SPI_DBG_ON + +#undef LOCAL +#define LOCAL + +#define SPI_DBG_OFF 0x00000000 +#define SPI_DBG_ISR 0x00000001 +#define SPI_DBG_RW 0x00000002 +#define SPI_DBG_ERR 0x00000004 +#define SPI_DBG_RTN 0x00000008 +#define SPI_DBG_INFO 0x00000010 +#define SPI_DBG_ALL 0xffffffff + +LOCAL UINT32 spiDbgMask = SPI_DBG_ALL; +IMPORT FUNCPTR _func_logMsg; + +#define SPI_DBG(mask, string, X1, X2, X3, X4, X5, X6) \ + if ((spiDbgMask & mask) || (mask == SPI_DBG_ALL)) \ + if (_func_logMsg != NULL) \ + (* _func_logMsg)(string, (int)X1, (int)X2, (int)X3, \ + (int)X4, (int)X5, (int)X6) +#else +#define SPI_DBG(mask, string, X1, X2, X3, X4, X5, X6) +#endif /* SPI_DBG_ON */ + +#if _BYTE_ORDER == _BIG_ENDIAN +# define SPI_REG_HANDLE_SWAP(x) VXB_HANDLE_SWAP(x) +#else +# define SPI_REG_HANDLE_SWAP(x) (x) +#endif /* _BYTE_ORDER == _BIG_ENDIAN */ + +/* VxBus methods */ +LOCAL void vxbFtSpiInstInit (VXB_DEVICE_ID pDev); +LOCAL void vxbFtSpiInstInit2 (VXB_DEVICE_ID pDev); +LOCAL void vxbFtSpiInstConnect (VXB_DEVICE_ID pDev); +LOCAL VXB_SPI_BUS_CTRL * vxbFtSpiCtrlGet (VXB_DEVICE_ID pDev); +LOCAL void vxbFtSpiShow (VXB_DEVICE_ID, int); +LOCAL STATUS vxbFtSpiInstUnlink (VXB_DEVICE_ID pDev, void * unused); + +/* forward declarations */ +LOCAL STATUS vxbFtSpiTransfer (VXB_DEVICE_ID pDev, SPI_HARDWARE * pSpiDev, + SPI_TRANSFER * pPkg); +/* locals */ +LOCAL struct drvBusFuncs vxbFtSpiVxbFuncs = { + vxbFtSpiInstInit, /* devInstanceInit */ + vxbFtSpiInstInit2, /* devInstanceInit2 */ + vxbFtSpiInstConnect /* devConnect */ +}; + +LOCAL device_method_t vxbFtSpiDeviceMethods[] = { + DEVMETHOD (vxbSpiControlGet, vxbFtSpiCtrlGet), + DEVMETHOD (busDevShow, vxbFtSpiShow), + DEVMETHOD (vxbDrvUnlink, vxbFtSpiInstUnlink), + DEVMETHOD_END +}; + +LOCAL struct vxbPlbRegister vxbFtSpiDevRegistration = { + { + NULL, /* pNext */ + VXB_DEVID_DEVICE, /* devID */ + VXB_BUSID_PLB, /* busID = PLB */ + VXB_VER_4_0_0, /* vxbVersion */ + FT_SPI_NAME, /* drvName */ + &vxbFtSpiVxbFuncs, /* pDrvBusFuncs */ + &vxbFtSpiDeviceMethods[0], /* pMethods */ + NULL, /* devProbe */ + NULL, /* pParamDefaults */ + }, +}; + +/* + * + * vxbFtSpiRegister - register with the VxBus subsystem + * + * This routine registers the SPI driver with VxBus Systems. + * + * RETURNS: N/A + * + * ERRNO: N/A + */ +void vxbFtSpiRegister (void) +{ + vxbDevRegister ((struct vxbDevRegInfo *) &vxbFtSpiDevRegistration); +} + +/* + * + * vxbFtSpiInstInit - initialize SPI controller + * + * This function implements the VxBus instInit handler for a SPI controller + * device instance. + * + * Initialize the device by the following: + * + * - retrieve the resource from the hwconf + * - per-device init + * - announce SPI Bus and create device instance + * + * RETURNS: N/A + * + * ERRNO: N/A + */ +LOCAL void vxbFtSpiInstInit(VXB_DEVICE_ID pDev) +{ + FT_SPI_CTRL * pDrvCtrl; + struct hcfDevice *pHcf; + int i; + + /* check for valid parameter */ + VXB_ASSERT_NONNULL_V (pDev); + + /* create controller driver context structure for core */ + pDrvCtrl = (FT_SPI_CTRL *) hwMemAlloc (sizeof (FT_SPI_CTRL)); + if (pDrvCtrl == NULL) { + return; + } + pDev->pDrvCtrl = pDrvCtrl; + pDrvCtrl->pDev = pDev; + + for (i = 0; i < VXB_MAXBARS; i++) { + if (pDev->regBaseFlags[i] == VXB_REG_MEM) { + break; + } + } + if (i == VXB_MAXBARS) { +#ifndef _VXBUS_BASIC_HWMEMLIB + hwMemFree((char *)pDrvCtrl); +#endif + pDev->pDrvCtrl = NULL; + return; + } + pDrvCtrl->regBase = pDev->pRegBase[i]; + vxbRegMap(pDev, i, &pDrvCtrl->regHandle); + pDrvCtrl->regHandle = (void *)SPI_REG_HANDLE_SWAP ((ULONG)pDrvCtrl->regHandle); + pHcf = (struct hcfDevice *) hcfDeviceGet (pDev); + if (pHcf == NULL) { +#ifndef _VXBUS_BASIC_HWMEMLIB + hwMemFree((char *)pDrvCtrl); +#endif + pDev->pDrvCtrl = NULL; + return; + } + + if (devResourceGet (pHcf, "clkDiv", HCF_RES_INT,(void *) &pDrvCtrl->clkDiv) != OK) { + pDrvCtrl->clkDiv = 2; + } + + if (devResourceGet (pHcf, "spiDevNum", HCF_RES_INT, (void *) &pDrvCtrl->spiDevNum) != OK) { + pDrvCtrl->spiDevNum = 0; + } + + pDrvCtrl->vxbSpiCtrl.spiTransfer = (void *)vxbFtSpiTransfer; + + /* announce that there's a SPI bus */ + (void) vxbBusAnnounce (pDev, VXB_BUSID_SPI); + + /* notify the bus subsystem of all devices on SPI */ + (void) spiBusAnnounceDevices (pDev); + + pDrvCtrl->initPhase = 1; +} + +/* + * + * vxbFtSpiInstInit2 - second level initialization routine of SPI controller + * + * This routine performs the second level initialization of the SPI controller. + * + * RETURNS: N/A + * + * ERRNO: N/A + */ +LOCAL void vxbFtSpiInstInit2(VXB_DEVICE_ID pDev) +{ + FT_SPI_CTRL * pDrvCtrl; + + /* check for valid parameter */ + + VXB_ASSERT_NONNULL_V (pDev); + + pDrvCtrl = (FT_SPI_CTRL *) pDev->pDrvCtrl; + + /* used for mutex accessing of the controller */ + pDrvCtrl->muxSem = semMCreate (SEM_Q_PRIORITY); + + if (pDrvCtrl->muxSem == NULL) { + SPI_DBG (SPI_DBG_ERR, "semMCreate failed for muxSem\n", + 0, 0, 0, 0, 0, 0); + return; + } + + pDrvCtrl->initPhase = 2; +} + +/* + * + * vxbFtSpiInstConnect - third level initialization + * + * This routine performs the third level initialization of the QSPI controller + * driver. + * + * RETURNS: N/A + * + * ERRNO : N/A + */ +LOCAL void vxbFtSpiInstConnect(VXB_DEVICE_ID pDev) +{ + FT_SPI_CTRL * pDrvCtrl; + + pDrvCtrl = pDev->pDrvCtrl; + pDrvCtrl->initPhase = 3; +} + +/* + * + * vxbFtSpiCtrlGet - get the SPI controller struct + * + * This routine returns the QSPI controller struct pointer (VXB_SPI_BUS_CTRL *) + * to caller (SPI Lib) by vxbSpiControlGet method. Currently, this struct + * only contain the spiTransfer routine(eg: vxbFtQspiTransfer) for SPI Lib, + * other parameters can be easily added in this struct. + * + * RETURNS: the pointer of SPI controller struct + * + * ERRNO: N/A + */ +LOCAL VXB_SPI_BUS_CTRL * vxbFtSpiCtrlGet(VXB_DEVICE_ID pDev) +{ + FT_SPI_CTRL * pDrvCtrl; + + /* check if the pDev pointer is valid */ + VXB_ASSERT (pDev != NULL, NULL) + + pDrvCtrl = (FT_SPI_CTRL *) pDev->pDrvCtrl; + + SPI_DBG (SPI_DBG_RTN, "vxbFtQspiCtrlGet(0x08%x) called\n", + (_Vx_usr_arg_t)pDev, 2, 3, 4, 5, 6); + + return (&(pDrvCtrl->vxbSpiCtrl)); +} + +/* + * + * vxbFtSpiTransfer - SPI transfer routine + * + * This routine is used to perform one transmission. It is the interface which + * can be called by SPI device driver to send and receive data via the QSPI + * controller. + * + * RETURNS: OK or ERROR + * + * ERRNO: N/A + */ +LOCAL STATUS vxbFtSpiTransfer( + VXB_DEVICE_ID pDev, /* controller pDev */ + SPI_HARDWARE * pSpiDev, /* device info */ + SPI_TRANSFER * pPkg /* transfer data info */ +) +{ + STATUS sts = OK; + UINT32 cmd; + UINT32 alignSize; + FT_SPI_CTRL * pDrvCtrl; + /* check if the pointers are valid */ + + if (pDev == NULL || pSpiDev == NULL || pPkg == NULL || pSpiDev->devInfo == NULL) { + SPI_DBG (SPI_DBG_ERR, "vxbFtQspiTransfer NULL pointer\n", + 1, 2, 3, 4, 5, 6); + return ERROR; + } + + pDrvCtrl = (FT_SPI_CTRL *) pDev->pDrvCtrl; + if (pDrvCtrl == NULL) { + SPI_DBG (SPI_DBG_ERR, "vxbFtQspiTransfer pDrvCtrl is NULL\n", + 1, 2, 3, 4, 5, 6); + return ERROR; + } + + SPI_DBG (SPI_DBG_RTN, "vxbFtQspiTransfer txLen[%d] rxLen[%d]\n", + pPkg->txLen, pPkg->rxLen, 3, 4, 5, 6); + + if (pPkg->txLen == 0 && pPkg->rxLen == 0) { + SPI_DBG (SPI_DBG_ERR, "vxbFtQspiTransfer tx and rx both are 0\n", + 1, 2, 3, 4, 5, 6); + return ERROR; + } + + if ((pPkg->txLen != 0 && pPkg->txBuf == NULL ) || (pPkg->rxLen != 0 && pPkg->rxBuf == NULL)) { + SPI_DBG (SPI_DBG_ERR, + "vxbFtQspiTransfer invalid parameters[%x %x %x %x] \n", + pPkg->txBuf, pPkg->txLen, pPkg->rxLen, pPkg->rxBuf, 5, 6); + + return ERROR; + } + + if (pSpiDev->devInfo->bitWidth <= 8) { /* 4 to 8 bits */ + alignSize = sizeof(char); + } else if (pSpiDev->devInfo->bitWidth <= 16) { /* 9 to 16 bits */ + alignSize = sizeof(UINT16); + } else { /* 17 to 32 bits */ + SPI_DBG (SPI_DBG_ERR, + "vxbFtQspiTransfer: data word length must between 2-16\n", + 1, 2, 3, 4, 5, 6); + return ERROR; + } + + /* check to see if the address is aligned with SPI bit width */ + if ((pPkg->txLen != 0 && + (((UINT32)pPkg->txBuf & (alignSize - 1)) != 0 || + (pPkg->txLen & (alignSize - 1)) != 0)) || + (pPkg->rxLen != 0 && + (((UINT32)pPkg->rxBuf & (alignSize - 1)) != 0 || + (pPkg->rxLen & (alignSize - 1)) != 0))) { + SPI_DBG (SPI_DBG_ERR, + "vxbFtQspiTransfer address or len is not aligned:" + "[tx:%x-%x rx:%x-%x] with %d \n", + pPkg->txBuf, pPkg->txLen, pPkg->rxBuf, pPkg->rxLen, + alignSize, 6); + + return ERROR; + } + + pDrvCtrl->channel = pSpiDev->devInfo->chipSelect; + if (pDrvCtrl->channel >= SPI_MAX_CS_NUM) { + SPI_DBG (SPI_DBG_ERR, + "vxbFtQspiTransfer invalid channel[%x] \n", + pDrvCtrl->channel, 2, 3, 4, 5, 6); + + return ERROR; + } + + /* + * The controller can not be used by multichannel at the same time. + * If the initPhase < 2, there is no multi-task context. So, the + * semTake is not needed. + */ + if (pDrvCtrl->initPhase >= 2) { + (void)semTake (pDrvCtrl->muxSem, WAIT_FOREVER); + } + + pDrvCtrl->txBuf = pPkg->txBuf; + pDrvCtrl->txLen = pPkg->txLen; + pDrvCtrl->rxBuf = pPkg->rxBuf; + pDrvCtrl->rxLen = pPkg->rxLen; + cmd = pDrvCtrl->txBuf[0]; + #if 0 + switch (cmd) { + case QSPI_FLASH_CMD_RDID: + case QSPI_FLASH_CMD_RDSR1: + vxbFtQspiFlashRegGet(pDev); + break; + case QSPI_FLASH_CMD_4BAM: + pDrvCtrl->addrMode = QSPI_ADDR_SEL_4; + /*vxbFtQspiFlashRegSet(pDev);*/ + break; + case QSPI_FLASH_CMD_4BEX: + pDrvCtrl->addrMode = QSPI_ADDR_SEL_3; + /*vxbFtQspiFlashRegSet(pDev);*/ + break; + case QSPI_FLASH_CMD_WREN: + case QSPI_FLASH_CMD_WRDI: + case QSPI_FLASH_CMD_BE: + case QSPI_FLASH_CMD_WRR: + vxbFtQspiFlashRegSet(pDev); + break; + case QSPI_FLASH_CMD_SE: + if(pDrvCtrl->addrMode == QSPI_ADDR_SEL_4) + { + pDrvCtrl->txBuf[0] = QSPI_FLASH_CMD_4SE; + } + vxbFtQspiFlashRegSetWithAddr(pDev); + break; + case QSPI_FLASH_CMD_PP: + if(pDrvCtrl->addrMode == QSPI_ADDR_SEL_4) + { + pDrvCtrl->txBuf[0] = QSPI_FLASH_CMD_4PP; + } + vxbFtQspiFlashPageWrite(pDev); + break; + case QSPI_FLASH_CMD_READ: + if(pDrvCtrl->addrMode == QSPI_ADDR_SEL_4) + { + pDrvCtrl->txBuf[0] = QSPI_FLASH_CMD_4READ; + } + vxbFtQspiFlashRead(pDev); + break; + default: + break; + } +#endif + printf(" xfer :%x\n",cmd); + + if (pPkg->usDelay > 0) { + vxbUsDelay(pPkg->usDelay); + } + + if (pDrvCtrl->initPhase >= 2) { + semGive (pDrvCtrl->muxSem); + } + return sts; +} + +/* + * + * vxbFtSpiShow - show the controller info + * + * This function shows the SPI controller's info. + * + * RETURNS: N/A + * + * ERRNO: N/A + */ +LOCAL void vxbFtSpiShow(VXB_DEVICE_ID pDev,int verbose) +{ + FT_SPI_CTRL * pDrvCtrl; + + /* check for valid parameter */ + VXB_ASSERT_NONNULL_V (pDev); + + pDrvCtrl = (FT_SPI_CTRL *) pDev->pDrvCtrl; + + printf (" %s unit %d on %s @ %p with busInfo %08p\n", + pDev->pName, + pDev->unitNumber, + vxbBusTypeString (pDev->busID), + pDev, + pDev->u.pSubordinateBus); + + if (verbose > 0) { + printf (" BAR0 @ 0x%08x (memory mapped)\n",pDev->pRegBase[0]); + printf (" pDrvCtrl @ 0x%08x\n", pDev->pDrvCtrl); + printf (" initPhase : %u\n", pDrvCtrl->initPhase); + printf (" clkDiv : %u\n", pDrvCtrl->clkDiv); + printf (" spiDevNum : %u\n", pDrvCtrl->spiDevNum); + } +} + +/* + * + * vxbFtSpiInstUnlink - VxBus unlink handler + * + * This function shuts down a SPI controller instance in response to an + * an unlink event from VxBus. This may occur if our VxBus instance has + * been terminated, or if the SPI driver has been unloaded. + * + * RETURNS: OK if device was successfully destroyed, otherwise ERROR + * + * ERRNO: N/A + */ +LOCAL STATUS vxbFtSpiInstUnlink(VXB_DEVICE_ID pDev, void * unused) +{ + FT_SPI_CTRL * pDrvCtrl; + + /* check if the pDev pointer is valid */ + VXB_ASSERT (pDev != NULL, ERROR) + + pDrvCtrl = (FT_SPI_CTRL *) pDev->pDrvCtrl; + + /* + * The semaphore and interrupt resource are released here . The + * semaphore was created at phase 2 and interrupt was installed + * at phase 3. + */ + + if (pDrvCtrl->initPhase >= 2) { + (void)semTake (pDrvCtrl->muxSem, WAIT_FOREVER); + + (void) semDelete (pDrvCtrl->muxSem); + pDrvCtrl->muxSem = NULL; + } + +#ifndef _VXBUS_BASIC_HWMEMLIB + hwMemFree ((char *) pDrvCtrl); +#endif /* _VXBUS_BASIC_HWMEMLIB */ + + pDev->pDrvCtrl = NULL; + pDrvCtrl->initPhase = 0; + + return (OK); +} diff --git a/vxbFtSpi.h b/vxbFtSpi.h new file mode 100644 index 0000000..269c71d --- /dev/null +++ b/vxbFtSpi.h @@ -0,0 +1,32 @@ +#ifndef __VXB_FTSPI_H__ +#define __VXB_FTSPI_H__ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define FT_SPI_NAME "ftSpi" +#define SPI_MAX_CS_NUM 4 +/* structure holding the instance specific details */ +typedef struct _ft_spi_drv_ctrl { + VXB_DEVICE_ID pDev; + void * regBase; + void * regHandle; + UINT32 clkDiv; + UINT32 spiDevNum; + UINT32 channel; + UINT32 initPhase; + UINT8 * txBuf; + UINT32 txLen; + UINT8 * rxBuf; + UINT32 rxLen; + SEM_ID muxSem; + VXB_SPI_BUS_CTRL vxbSpiCtrl; +} FT_SPI_CTRL; + +#endif