surenyi
3 weeks ago
10 changed files with 661 additions and 51 deletions
@ -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 |
||||
|
} |
||||
|
|
@ -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); |
||||
|
} |
@ -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…
Reference in new issue