Browse Source

add FtSpi driver

Signed-off-by: surenyi <surenyi82@163.com>
master
surenyi 3 weeks ago
parent
commit
2239034722
  1. 1
      40vxbFtQspi.cdf
  2. 26
      40vxbFtSpi.cdf
  3. 2
      Makefile
  4. 14
      config.h
  5. 8
      ft2000-4.h
  6. 104
      hwconf.c
  7. 23
      sysLib.c
  8. 2
      vxbFtQspi.h
  9. 500
      vxbFtSpi.c
  10. 32
      vxbFtSpi.h

1
40vxbFtQspi.cdf

@ -23,4 +23,3 @@ Component DRV_FTQSPI {
INIT_AFTER INCLUDE_PLB_BUS \
INCLUDE_SPI_BUS
}

26
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
}

2
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

14
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

8
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)

104
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 <drv/pci/pciAutoConfigLib.h>
#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} }
};
};

23
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*/
}
}
/*******************************************************************************
*

2
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;

500
vxbFtSpi.c

@ -0,0 +1,500 @@
#include <vxWorks.h>
#include <vsbConfig.h>
#include <intLib.h>
#include <stdlib.h>
#include <string.h>
#include <semLib.h>
#include <taskLib.h>
#include <stdio.h>
#include <vxbTimerLib.h>
#include <cacheLib.h>
#include <hwif/util/hwMemLib.h>
#include <hwif/util/vxbParamSys.h>
#include <hwif/vxbus/vxBus.h>
#include <hwif/vxbus/vxbPlbLib.h>
#include <../src/hwif/h/vxbus/vxbAccess.h>
#include <hwif/vxbus/vxbSpiLib.h>
#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);
}

32
vxbFtSpi.h

@ -0,0 +1,32 @@
#ifndef __VXB_FTSPI_H__
#define __VXB_FTSPI_H__
#include <vxWorks.h>
#include <config.h>
#include <sysLib.h>
#include <vxBusLib.h>
#include <string.h>
#include <memLib.h>
#include <stdlib.h>
#include <semLibCommon.h>
#include <hwif/vxbus/vxbSpiLib.h>
#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
Loading…
Cancel
Save