|
|
|
/* vim: set ts=4 sw=4 et fdm=marker: */
|
|
|
|
#include <vxWorks.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <logLib.h>
|
|
|
|
#include <vxBusLib.h>
|
|
|
|
#include <semLib.h>
|
|
|
|
#include <taskLib.h>
|
|
|
|
#include <sysLib.h>
|
|
|
|
#include <tickLib.h>
|
|
|
|
#include <iosLib.h>
|
|
|
|
#include <selectLib.h>
|
|
|
|
#include <errnoLib.h>
|
|
|
|
#include <hwif/vxbus/vxBus.h>
|
|
|
|
#include <hwif/vxbus/hwConf.h>
|
|
|
|
#include <hwif/vxbus/vxbPlbLib.h>
|
|
|
|
#include <hwif/util/hwMemLib.h>
|
|
|
|
#include <hwif/util/vxbParamSys.h>
|
|
|
|
|
|
|
|
#include <hwif/vxbus/vxbSpiLib.h>
|
|
|
|
#include "vxbSm2130SpiDev.h"
|
|
|
|
#include <usrLib.h>
|
|
|
|
|
|
|
|
#define SPI_DEV_MUTEX_OPT (SEM_Q_PRIORITY | SEM_DELETE_SAFE | SEM_INVERSION_SAFE)
|
|
|
|
|
|
|
|
typedef struct _Sm2310_DEV_HANDLE {
|
|
|
|
DEV_HDR devHdr;
|
|
|
|
|
|
|
|
SEL_WAKEUP_LIST selList;
|
|
|
|
|
|
|
|
SM2130_SPI_DEV *pDevCtrl;
|
|
|
|
} SM2310_DEV_HANDLE;
|
|
|
|
|
|
|
|
/* locals */
|
|
|
|
LOCAL void sm2130SpiDevShow(VXB_DEVICE_ID pDev, int verbose);
|
|
|
|
LOCAL INT32 sm2130BusDevRead(VXB_DEVICE_ID pDev, UINT8 cmd);
|
|
|
|
LOCAL STATUS sm2130BusDevWrite(VXB_DEVICE_ID pDev, UINT8 cmd, UINT16 var);
|
|
|
|
|
|
|
|
/* VxBus methods */
|
|
|
|
LOCAL void sm2130SpiDevInstInit(VXB_DEVICE_ID pDev);
|
|
|
|
LOCAL void sm2130SpiDevInstInit2(VXB_DEVICE_ID pDev);
|
|
|
|
LOCAL void sm2130SpiDevInstConnect(VXB_DEVICE_ID pDev);
|
|
|
|
LOCAL STATUS sm2130SpiDevInstUnlink(VXB_DEVICE_ID pDev, void *unused);
|
|
|
|
|
|
|
|
/* Structs */
|
|
|
|
|
|
|
|
LOCAL struct drvBusFuncs sm2130SpiDevFuncs = {
|
|
|
|
sm2130SpiDevInstInit, /* devInstanceInit */
|
|
|
|
sm2130SpiDevInstInit2, /* devInstanceInit2 */
|
|
|
|
sm2130SpiDevInstConnect /* devConnect */
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Publish the methods for the resources controlled with this file */
|
|
|
|
/* clang-format off */
|
|
|
|
LOCAL struct vxbDeviceMethod sm2130SpiDevMethods[] = {
|
|
|
|
DEVMETHOD(busDevShow , sm2130SpiDevShow),
|
|
|
|
DEVMETHOD(vxbDrvUnlink, sm2130SpiDevInstUnlink),
|
|
|
|
{ 0, 0 }
|
|
|
|
};
|
|
|
|
|
|
|
|
LOCAL struct vxbSpiRegister sm2130SpiDevRegister = {
|
|
|
|
{
|
|
|
|
NULL, /* pNext */
|
|
|
|
VXB_DEVID_DEVICE, /* devID */
|
|
|
|
VXB_BUSID_SPI, /* busID = SPI */
|
|
|
|
VXB_VER_4_0_0, /* vxbVersion */
|
|
|
|
SPI_DEV_SM2130, /* drvName */
|
|
|
|
&sm2130SpiDevFuncs, /* pDrvBusFuncs */
|
|
|
|
sm2130SpiDevMethods, /* pMethods */
|
|
|
|
NULL, /* devProbe */
|
|
|
|
NULL, /* pParamDefaults */
|
|
|
|
},
|
|
|
|
};
|
|
|
|
/* clang-format on */
|
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
* vxbSm2130SpiDevRegister - register with the VxBus subsystem
|
|
|
|
*
|
|
|
|
* This routine registers the driver to VxBus Systems.
|
|
|
|
*
|
|
|
|
* RETURNS: N/A
|
|
|
|
*
|
|
|
|
* ERRNO: N/A
|
|
|
|
*
|
|
|
|
* \NOMANUAL
|
|
|
|
*/
|
|
|
|
void vxbSm2130SpiDevRegister(void)
|
|
|
|
{
|
|
|
|
(void)vxbDevRegister((struct vxbDevRegInfo *)&sm2130SpiDevRegister);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
* sm2130SpiDevInstInit - first level initialization routine of spi flash device
|
|
|
|
*
|
|
|
|
* RETURNS: N/A
|
|
|
|
*
|
|
|
|
* ERRNO: N/A
|
|
|
|
*/
|
|
|
|
LOCAL void sm2130SpiDevInstInit(VXB_DEVICE_ID pDev)
|
|
|
|
{
|
|
|
|
SM2130_SPI_DEV *pDrvCtrl;
|
|
|
|
struct hcfDevice *pHcf;
|
|
|
|
|
|
|
|
/* Check for vaild parameter */
|
|
|
|
VXB_ASSERT_NONNULL_V(pDev);
|
|
|
|
|
|
|
|
pDrvCtrl = (SM2130_SPI_DEV *)hwMemAlloc(sizeof(SM2130_SPI_DEV));
|
|
|
|
if (pDrvCtrl == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
pDrvCtrl->pDev = pDev;
|
|
|
|
pDev->pDrvCtrl = pDrvCtrl;
|
|
|
|
|
|
|
|
pDrvCtrl->drvNode = -1;
|
|
|
|
pDrvCtrl->devHandle = NULL;
|
|
|
|
pDrvCtrl->devName = SM2310_DEV_NAME;
|
|
|
|
pHcf = (struct hcfDevice *)hcfDeviceGet(pDev);
|
|
|
|
if (pHcf) {
|
|
|
|
if (devResourceGet(pHcf, "devName", HCF_RES_STRING, (void *)&pDrvCtrl->devName) != OK) {
|
|
|
|
pDrvCtrl->devName = SM2310_DEV_NAME;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pDrvCtrl->read = sm2130BusDevRead;
|
|
|
|
pDrvCtrl->write = sm2130BusDevWrite;
|
|
|
|
|
|
|
|
vxbNextUnitGet(pDev);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
* sm2130SpiDevInstInit2 - first level initialization routine of spi flash device
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* RETURNS: N/A
|
|
|
|
*
|
|
|
|
* ERRNO: N/A
|
|
|
|
*/
|
|
|
|
LOCAL void sm2130SpiDevInstInit2(VXB_DEVICE_ID pDev)
|
|
|
|
{
|
|
|
|
SM2130_SPI_DEV *pDrvCtrl;
|
|
|
|
FUNCPTR pFunc;
|
|
|
|
|
|
|
|
/* Check for vaild parameter */
|
|
|
|
VXB_ASSERT_NONNULL_V(pDev);
|
|
|
|
|
|
|
|
pDrvCtrl = (SM2130_SPI_DEV *)pDev->pDrvCtrl;
|
|
|
|
|
|
|
|
/* Mutex semaphore is initialized and necessary at this point */
|
|
|
|
pDrvCtrl->muteSem = semMCreate(SPI_DEV_MUTEX_OPT);
|
|
|
|
|
|
|
|
pFunc = vxbDevMethodGet(vxbDevParent(pDev), (VXB_METHOD_ID)vxbSpiSpecialGet_desc);
|
|
|
|
|
|
|
|
/* Retrieve the SPI master special information */
|
|
|
|
if (pFunc != NULL)
|
|
|
|
(*pFunc)(vxbDevParent(pDev), &pDrvCtrl->specialInfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* {{{ device driver api */
|
|
|
|
LOCAL SM2310_DEV_HANDLE *drv1553bOpen(SM2310_DEV_HANDLE *dev, const char *name, int flags, int mode)
|
|
|
|
{
|
|
|
|
SM2130_SPI_DEV *pDrvCtrl = dev->pDevCtrl;
|
|
|
|
|
|
|
|
(void)semTake(pDrvCtrl->muteSem, WAIT_FOREVER);
|
|
|
|
++pDrvCtrl->refcount;
|
|
|
|
(void)semGive(pDrvCtrl->muteSem);
|
|
|
|
printf("open: %p\n", dev);
|
|
|
|
return dev;
|
|
|
|
}
|
|
|
|
|
|
|
|
LOCAL int drv1553bClose(SM2310_DEV_HANDLE *dev)
|
|
|
|
{
|
|
|
|
SM2130_SPI_DEV *pDrvCtrl = dev->pDevCtrl;
|
|
|
|
|
|
|
|
(void)semTake(pDrvCtrl->muteSem, WAIT_FOREVER);
|
|
|
|
--pDrvCtrl->refcount;
|
|
|
|
(void)semGive(pDrvCtrl->muteSem);
|
|
|
|
|
|
|
|
printf("close: %p\n", dev);
|
|
|
|
return (OK);
|
|
|
|
}
|
|
|
|
|
|
|
|
LOCAL int drv1553bIoctl(SM2310_DEV_HANDLE *dev, int cmd, _Vx_ioctl_arg_t arg)
|
|
|
|
{
|
|
|
|
SM2130_XFER *xfer;
|
|
|
|
SM2130_SPI_DEV *pDrvCtrl = dev->pDevCtrl;
|
|
|
|
STATUS ret = OK;
|
|
|
|
|
|
|
|
printf("ioctl: %p\n", dev);
|
|
|
|
|
|
|
|
(void)semTake(pDrvCtrl->muteSem, WAIT_FOREVER);
|
|
|
|
switch (cmd) {
|
|
|
|
case FIOSELECT:
|
|
|
|
ret = selNodeAdd(&dev->selList, (SEL_WAKEUP_NODE *)arg);
|
|
|
|
break;
|
|
|
|
case FIOUNSELECT:
|
|
|
|
ret = selNodeDelete(&dev->selList, (SEL_WAKEUP_NODE *)arg);
|
|
|
|
break;
|
|
|
|
case FIO_XFER:
|
|
|
|
xfer = (SM2130_XFER *)(arg);
|
|
|
|
switch (xfer->type) {
|
|
|
|
case FIO_XFER_TX:
|
|
|
|
pDrvCtrl->write(pDrvCtrl->pDev, xfer->reg, xfer->val);
|
|
|
|
break;
|
|
|
|
case FIO_XFER_RX:
|
|
|
|
xfer->val = pDrvCtrl->read(pDrvCtrl->pDev, xfer->reg);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
errnoSet(EINVAL);
|
|
|
|
ret = ERROR;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
(void)semGive(pDrvCtrl->muteSem);
|
|
|
|
return (ret);
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* sm2130SpiDevInstConnect - third level initialization routine of spi flash
|
|
|
|
*
|
|
|
|
* This function implements the VxBus instConnect handler for a SPI Flash
|
|
|
|
* device instance.
|
|
|
|
*
|
|
|
|
* RETURNS: N/A
|
|
|
|
*
|
|
|
|
* ERRNO: N/A
|
|
|
|
*/
|
|
|
|
LOCAL void sm2130SpiDevInstConnect(VXB_DEVICE_ID pDev)
|
|
|
|
{
|
|
|
|
SM2130_SPI_DEV *pDrvCtrl;
|
|
|
|
SM2310_DEV_HANDLE *dev;
|
|
|
|
/* Check for vaild parameter */
|
|
|
|
VXB_ASSERT_NONNULL_V(pDev);
|
|
|
|
|
|
|
|
pDrvCtrl = (SM2130_SPI_DEV *)pDev->pDrvCtrl;
|
|
|
|
|
|
|
|
(void)semTake(pDrvCtrl->muteSem, WAIT_FOREVER);
|
|
|
|
if (pDrvCtrl->drvNode < 0) {
|
|
|
|
/* clang-format off */
|
|
|
|
pDrvCtrl->drvNode = iosDrvInstall(
|
|
|
|
(DRV_CREATE_PTR)drv1553bOpen ,
|
|
|
|
(DRV_REMOVE_PTR)NULL ,
|
|
|
|
(DRV_OPEN_PTR)drv1553bOpen ,
|
|
|
|
(DRV_CLOSE_PTR)drv1553bClose ,
|
|
|
|
(DRV_READ_PTR)NULL ,
|
|
|
|
(DRV_WRITE_PTR)NULL ,
|
|
|
|
(DRV_IOCTL_PTR)drv1553bIoctl);
|
|
|
|
/* clang-format on */
|
|
|
|
if (pDrvCtrl->drvNode > 0) {
|
|
|
|
dev = (SM2310_DEV_HANDLE *)hwMemAlloc(sizeof(SM2310_DEV_HANDLE));
|
|
|
|
if (dev) {
|
|
|
|
pDrvCtrl->refcount = 0;
|
|
|
|
selWakeupListInit(&dev->selList);
|
|
|
|
if (iosDevAdd(&dev->devHdr, pDrvCtrl->devName, pDrvCtrl->drvNode) == OK) {
|
|
|
|
pDrvCtrl->devHandle = dev;
|
|
|
|
dev->pDevCtrl = pDrvCtrl;
|
|
|
|
} else {
|
|
|
|
#ifndef _VXBUS_BASIC_HWMEMLIB
|
|
|
|
hwMemFree((char *)dev);
|
|
|
|
#endif /* _VXBUS_BASIC_HWMEMLIB */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
(void)semGive(pDrvCtrl->muteSem);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* sm2130SpiDevInstUnlink - VxBus unlink handler
|
|
|
|
*
|
|
|
|
* This function shuts down a SPI Flash device instance in response to an
|
|
|
|
* unlink event from VxBus. This may occur if our VxBus instance has been
|
|
|
|
* terminated, or if the driver has been unloaded.
|
|
|
|
*
|
|
|
|
* RETURNS: OK always.
|
|
|
|
*
|
|
|
|
* ERRNO: N/A
|
|
|
|
*/
|
|
|
|
LOCAL STATUS sm2130SpiDevInstUnlink(VXB_DEVICE_ID pDev, void *unused)
|
|
|
|
{
|
|
|
|
SM2130_SPI_DEV *pDrvCtrl;
|
|
|
|
|
|
|
|
/* Check for vaild parameter */
|
|
|
|
VXB_ASSERT_NONNULL_V(pDev);
|
|
|
|
|
|
|
|
pDrvCtrl = (SM2130_SPI_DEV *)pDev->pDrvCtrl;
|
|
|
|
|
|
|
|
if (pDrvCtrl->muteSem) {
|
|
|
|
(void)semTake(pDrvCtrl->muteSem, WAIT_FOREVER);
|
|
|
|
|
|
|
|
(void)semDelete(pDrvCtrl->muteSem);
|
|
|
|
pDrvCtrl->muteSem = NULL;
|
|
|
|
}
|
|
|
|
#ifndef _VXBUS_BASIC_HWMEMLIB
|
|
|
|
hwMemFree((char *)pDrvCtrl);
|
|
|
|
#endif /* _VXBUS_BASIC_HWMEMLIB */
|
|
|
|
pDev->pDrvCtrl = NULL;
|
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
* sm2130SpiDevShow - show the SPI 1553B info.
|
|
|
|
*
|
|
|
|
* This routine show the SPI flash info by vxBusShow.
|
|
|
|
*
|
|
|
|
* RETURNS: N/A
|
|
|
|
*
|
|
|
|
* ERRNO: N/A
|
|
|
|
*/
|
|
|
|
LOCAL void sm2130SpiDevShow(VXB_DEVICE_ID pDev, int verbose)
|
|
|
|
{
|
|
|
|
SM2130_SPI_DEV *pDrvCtrl = (SM2130_SPI_DEV *)pDev->pDrvCtrl;
|
|
|
|
|
|
|
|
printf(" %s unit %d on %s @ 0x%08x", pDev->pName, pDev->unitNumber, vxbBusTypeString(pDev->busID), pDev);
|
|
|
|
printf(" with busInfo %p\n", pDev->u.pSubordinateBus);
|
|
|
|
|
|
|
|
if (verbose) {
|
|
|
|
printf(" chipSelect: %d\n", pDrvCtrl->cs);
|
|
|
|
printf(" mode: %d\n", pDrvCtrl->mode);
|
|
|
|
printf(" speed: %u\n", pDrvCtrl->freq);
|
|
|
|
printf(" devName: %s\n", pDrvCtrl->devName);
|
|
|
|
printf(" devHandle: %p\n", pDrvCtrl->devHandle);
|
|
|
|
printf(" drvNode: %d\n", pDrvCtrl->drvNode);
|
|
|
|
printf(" refCount: %d\n", pDrvCtrl->refcount);
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* sm2130BusDevWrite - VxBus SPI device write by name support routine
|
|
|
|
*
|
|
|
|
* This routine firstly finds the VXB_DEVICE_ID for a given instance
|
|
|
|
* identified by name and unit number, then call vxbI2cDevWrite() routine to
|
|
|
|
* write the device.
|
|
|
|
*
|
|
|
|
* RETURNS: OK/ERROR
|
|
|
|
*
|
|
|
|
* ERRNO : N/A
|
|
|
|
*/
|
|
|
|
LOCAL STATUS sm2130BusDevWrite(VXB_DEVICE_ID pDev, UINT8 cmd, UINT16 var)
|
|
|
|
{
|
|
|
|
SPI_TRANSFER transInfo = { NULL, NULL, 0, 0, 0 };
|
|
|
|
UINT8 buf[3];
|
|
|
|
|
|
|
|
/* Check if the pDev pointer is valid */
|
|
|
|
VXB_ASSERT(pDev != NULL, ERROR)
|
|
|
|
buf[0] = cmd;
|
|
|
|
buf[1] = var & 0xff;
|
|
|
|
buf[1] = (var >> 8) & 0xff;
|
|
|
|
|
|
|
|
transInfo.txBuf = buf;
|
|
|
|
transInfo.txLen = 3;
|
|
|
|
|
|
|
|
return vxbSpiTransfer(pDev, &transInfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* sm2130BusDevRead - read register routine
|
|
|
|
*
|
|
|
|
* This is the SPI flash status /config register read out routine.
|
|
|
|
*
|
|
|
|
* RETURNS: status register value.
|
|
|
|
*
|
|
|
|
* ERRNO: N/A
|
|
|
|
*/
|
|
|
|
LOCAL INT32 sm2130BusDevRead(VXB_DEVICE_ID pDev, UINT8 cmd)
|
|
|
|
{
|
|
|
|
SPI_TRANSFER transInfo = { NULL, NULL, 0, 0, 0 };
|
|
|
|
UINT16 buffer;
|
|
|
|
UINT8 buf[3] = { 0xff, 0xff, 0xff };
|
|
|
|
|
|
|
|
/* check if the pDev pointer is valid */
|
|
|
|
|
|
|
|
VXB_ASSERT(pDev != NULL, ERROR)
|
|
|
|
|
|
|
|
buf[0] = cmd;
|
|
|
|
|
|
|
|
transInfo.txBuf = buf;
|
|
|
|
transInfo.txLen = 1;
|
|
|
|
transInfo.rxBuf = buf;
|
|
|
|
transInfo.rxLen = 3;
|
|
|
|
|
|
|
|
if (vxbSpiTransfer(pDev, &transInfo) != OK)
|
|
|
|
return ERROR;
|
|
|
|
|
|
|
|
buffer = (buf[2] << 8) | buf[1];
|
|
|
|
return (buffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* {{{ Test Read write */
|
|
|
|
INT32 sm2130Read(UINT8 cmd)
|
|
|
|
{
|
|
|
|
VXB_DEVICE_ID pDev;
|
|
|
|
SM2130_SPI_DEV *pCtrl;
|
|
|
|
|
|
|
|
pDev = vxbInstByNameFind(SPI_DEV_SM2130, 0);
|
|
|
|
if (pDev == NULL) {
|
|
|
|
return ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
pCtrl = pDev->pDrvCtrl;
|
|
|
|
|
|
|
|
/* printf("pDev @ %p, pCtrl %p\n", pDev, pCtrl); */
|
|
|
|
|
|
|
|
return pCtrl->read(pDev, cmd);
|
|
|
|
}
|
|
|
|
|
|
|
|
STATUS sm2130Write(UINT8 cmd, UINT16 var)
|
|
|
|
{
|
|
|
|
VXB_DEVICE_ID pDev;
|
|
|
|
SM2130_SPI_DEV *pCtrl;
|
|
|
|
|
|
|
|
pDev = vxbInstByNameFind(SPI_DEV_SM2130, 0);
|
|
|
|
if (pDev == NULL) {
|
|
|
|
return ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
pCtrl = pDev->pDrvCtrl;
|
|
|
|
|
|
|
|
/* printf("pDev @ %p, pCtrl %p\n", pDev, pCtrl); */
|
|
|
|
|
|
|
|
return pCtrl->write(pDev, cmd, var);
|
|
|
|
}
|
|
|
|
/* }}} */
|