|
|
@ -28,11 +28,16 @@ typedef struct _Sm2310_DEV_HANDLE { |
|
|
|
|
|
|
|
SEL_WAKEUP_LIST selList; |
|
|
|
|
|
|
|
void (*usrIsr)(); |
|
|
|
|
|
|
|
SM2130_SPI_DEV *pDevCtrl; |
|
|
|
} SM2310_DEV_HANDLE; |
|
|
|
|
|
|
|
LOCAL int sm2130_driver_node = -1; |
|
|
|
|
|
|
|
/* Declare */ |
|
|
|
IMPORT void sysUsDelay(UINT32 us); |
|
|
|
|
|
|
|
/* locals */ |
|
|
|
LOCAL void sm2130SpiDevShow(VXB_DEVICE_ID pDev, int verbose); |
|
|
|
LOCAL INT32 sm2130BusDevRead(VXB_DEVICE_ID pDev, UINT8 cmd); |
|
|
@ -118,21 +123,25 @@ LOCAL void sm2130SpiDevInstInit(VXB_DEVICE_ID pDev) |
|
|
|
|
|
|
|
pDrvCtrl->devHandle = NULL; |
|
|
|
|
|
|
|
snprintf(pDrvCtrl->name, sizeof (pDrvCtrl->name), "%s/%d", SM2130_DEV_NAME, pDev->unitNumber); |
|
|
|
snprintf(pDrvCtrl->name, sizeof(pDrvCtrl->name), "%s/%d", SM2130_DEV_NAME, pDev->unitNumber); |
|
|
|
pDrvCtrl->devName = pDrvCtrl->name; |
|
|
|
pHcf = (struct hcfDevice *)hcfDeviceGet(pDev); |
|
|
|
if (pHcf) { |
|
|
|
if (devResourceGet(pHcf, "devName", HCF_RES_STRING, (void *)&pDrvCtrl->devName) != OK) { |
|
|
|
pDrvCtrl->devName = pDrvCtrl->name; |
|
|
|
} |
|
|
|
if (devResourceGet(pHcf, "reqIsr", HCF_RES_ADDR, (void *)&pDrvCtrl->reqIsr) != OK) { |
|
|
|
pDrvCtrl->reqIsr = NULL; |
|
|
|
if (devResourceGet(pHcf, "funcReqIsr", HCF_RES_ADDR, (void *)&pDrvCtrl->funcReqIsr) != OK) { |
|
|
|
pDrvCtrl->funcReqIsr = NULL; |
|
|
|
} |
|
|
|
if (devResourceGet(pHcf, "isReady", HCF_RES_ADDR, (void *)&pDrvCtrl->isReady) != OK) { |
|
|
|
pDrvCtrl->isReady = NULL; |
|
|
|
if (devResourceGet(pHcf, "funcIsReady", HCF_RES_ADDR, (void *)&pDrvCtrl->funcIsReady) != OK) { |
|
|
|
pDrvCtrl->funcIsReady = NULL; |
|
|
|
} |
|
|
|
if (devResourceGet(pHcf, "ackIrq", HCF_RES_ADDR, (void *)&pDrvCtrl->ackIrq) != OK) { |
|
|
|
pDrvCtrl->ackIrq = NULL; |
|
|
|
if (devResourceGet(pHcf, "funcAckIrq", HCF_RES_ADDR, (void *)&pDrvCtrl->funcAckIrq) != OK) { |
|
|
|
pDrvCtrl->funcAckIrq = NULL; |
|
|
|
} |
|
|
|
|
|
|
|
if (devResourceGet(pHcf, "funcReset", HCF_RES_ADDR, (void *)&pDrvCtrl->funcReset) != OK) { |
|
|
|
pDrvCtrl->funcReset = NULL; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@ -147,9 +156,14 @@ LOCAL SM2310_DEV_HANDLE *drv1553bOpen(SM2310_DEV_HANDLE *dev, const char *name, |
|
|
|
{ |
|
|
|
SM2130_SPI_DEV *pDrvCtrl = dev->pDevCtrl; |
|
|
|
|
|
|
|
(void)semTake(pDrvCtrl->muteSem, WAIT_FOREVER); |
|
|
|
if (pDrvCtrl->refcount > 0) { |
|
|
|
errnoSet(EBUSY); |
|
|
|
return (void *)ERROR; |
|
|
|
} |
|
|
|
|
|
|
|
semTake(pDrvCtrl->muteSem, WAIT_FOREVER); |
|
|
|
++pDrvCtrl->refcount; |
|
|
|
(void)semGive(pDrvCtrl->muteSem); |
|
|
|
semGive(pDrvCtrl->muteSem); |
|
|
|
return dev; |
|
|
|
} |
|
|
|
|
|
|
@ -157,39 +171,39 @@ LOCAL int drv1553bClose(SM2310_DEV_HANDLE *dev) |
|
|
|
{ |
|
|
|
SM2130_SPI_DEV *pDrvCtrl = dev->pDevCtrl; |
|
|
|
|
|
|
|
(void)semTake(pDrvCtrl->muteSem, WAIT_FOREVER); |
|
|
|
semTake(pDrvCtrl->muteSem, WAIT_FOREVER); |
|
|
|
--pDrvCtrl->refcount; |
|
|
|
(void)semGive(pDrvCtrl->muteSem); |
|
|
|
semGive(pDrvCtrl->muteSem); |
|
|
|
return (OK); |
|
|
|
} |
|
|
|
|
|
|
|
LOCAL int readReg(SM2130_SPI_DEV *pDrvCtrl, SM2130_XFER *xfer) |
|
|
|
{ |
|
|
|
UINT8 cmd; |
|
|
|
UINT8 cmd; |
|
|
|
|
|
|
|
if (xfer->reg <= 15) { |
|
|
|
cmd = (xfer->reg << 2); |
|
|
|
} else { |
|
|
|
cmd = xfer->reg & 0xff; |
|
|
|
} |
|
|
|
if (xfer->reg <= 15) { |
|
|
|
cmd = (xfer->reg << 2); |
|
|
|
} else { |
|
|
|
cmd = xfer->reg & 0xff; |
|
|
|
} |
|
|
|
|
|
|
|
xfer->val = pDrvCtrl->read(pDrvCtrl->pDev, cmd); |
|
|
|
return 0; |
|
|
|
xfer->val = pDrvCtrl->read(pDrvCtrl->pDev, cmd); |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
LOCAL int writeReg(SM2130_SPI_DEV *pDrvCtrl, SM2130_XFER *xfer) |
|
|
|
{ |
|
|
|
UINT8 cmd; |
|
|
|
UINT8 cmd; |
|
|
|
|
|
|
|
if (xfer->reg <= 63) { |
|
|
|
cmd = 0x80 | (xfer->reg & 0x3f); |
|
|
|
} else { |
|
|
|
cmd = xfer->reg & 0xff; |
|
|
|
} |
|
|
|
if (xfer->reg <= 63) { |
|
|
|
cmd = 0x80 | (xfer->reg & 0x3f); |
|
|
|
} else { |
|
|
|
cmd = xfer->reg & 0xff; |
|
|
|
} |
|
|
|
|
|
|
|
pDrvCtrl->write(pDrvCtrl->pDev, cmd, xfer->val); |
|
|
|
pDrvCtrl->write(pDrvCtrl->pDev, cmd, xfer->val); |
|
|
|
|
|
|
|
return 0; |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
LOCAL int setMemAddress(SM2130_SPI_DEV *pDrvCtrl, SM2130_XFER *xfer) |
|
|
@ -200,7 +214,7 @@ LOCAL int setMemAddress(SM2130_SPI_DEV *pDrvCtrl, SM2130_XFER *xfer) |
|
|
|
transInfo.txLen = 1; |
|
|
|
|
|
|
|
if (xfer->reg >= 0xb && xfer->reg <= 0xE) { |
|
|
|
cmd =(xfer->reg - 0xB) + 0xD8; |
|
|
|
cmd = (xfer->reg - 0xB) + 0xD8; |
|
|
|
vxbSpiTransfer(pDrvCtrl->pDev, &transInfo); |
|
|
|
return pDrvCtrl->write(pDrvCtrl->pDev, 0x80 | xfer->reg, xfer->val); |
|
|
|
} |
|
|
@ -215,13 +229,13 @@ LOCAL int readMemory(SM2130_SPI_DEV *pDrvCtrl, SM2130_MEM_XFER *mxfr) |
|
|
|
UINT8 *ptr; |
|
|
|
UINT8 cmd; |
|
|
|
|
|
|
|
if ((mxfr->count <= 0) || (mxfr->count >= (sizeof (pDrvCtrl->regmem) / sizeof (pDrvCtrl->regmem[0])))) { |
|
|
|
if ((mxfr->count <= 0) || (mxfr->count > SMX_MAX_WORDS)) { |
|
|
|
errnoSet(EINVAL); |
|
|
|
return ERROR; |
|
|
|
} |
|
|
|
|
|
|
|
if (mxfr->reg >= 0xb && mxfr->reg <= 0xE) { |
|
|
|
cmd =(mxfr->reg - 0xB) + 0xD8; |
|
|
|
cmd = (mxfr->reg - 0xB) + 0xD8; |
|
|
|
transInfo.txBuf = &cmd; |
|
|
|
transInfo.txLen = 1; |
|
|
|
|
|
|
@ -239,7 +253,7 @@ LOCAL int readMemory(SM2130_SPI_DEV *pDrvCtrl, SM2130_MEM_XFER *mxfr) |
|
|
|
|
|
|
|
vxbSpiTransfer(pDrvCtrl->pDev, &transInfo); |
|
|
|
|
|
|
|
memcpy(mxfr->membuf, ptr + 1, mxfr->count * 2); |
|
|
|
memcpy(mxfr->membuf, ptr + 1, mxfr->count * 2); |
|
|
|
return OK; |
|
|
|
} |
|
|
|
|
|
|
@ -249,13 +263,13 @@ LOCAL int writeMemory(SM2130_SPI_DEV *pDrvCtrl, SM2130_MEM_XFER *mxfr) |
|
|
|
UINT8 *ptr; |
|
|
|
UINT8 cmd; |
|
|
|
|
|
|
|
if ((mxfr->count <= 0) || (mxfr->count >= (sizeof (pDrvCtrl->regmem) / sizeof (pDrvCtrl->regmem[0])))) { |
|
|
|
if ((mxfr->count <= 0) || (mxfr->count > SMX_MAX_WORDS)) { |
|
|
|
errnoSet(EINVAL); |
|
|
|
return ERROR; |
|
|
|
} |
|
|
|
|
|
|
|
if (mxfr->reg >= 0xb && mxfr->reg <= 0xE) { |
|
|
|
cmd =(mxfr->reg - 0xB) + 0xD8; |
|
|
|
cmd = (mxfr->reg - 0xB) + 0xD8; |
|
|
|
transInfo.txBuf = &cmd; |
|
|
|
transInfo.txLen = 1; |
|
|
|
|
|
|
@ -266,7 +280,7 @@ LOCAL int writeMemory(SM2130_SPI_DEV *pDrvCtrl, SM2130_MEM_XFER *mxfr) |
|
|
|
|
|
|
|
ptr = (UINT8 *)pDrvCtrl->regmem; |
|
|
|
ptr[0] = 0xC0; |
|
|
|
memcpy(ptr + 1, (UINT8*)mxfr->membuf, mxfr->count * 2); |
|
|
|
memcpy(ptr + 1, (UINT8 *)mxfr->membuf, mxfr->count * 2); |
|
|
|
transInfo.txBuf = ptr; |
|
|
|
transInfo.txLen = 1 + mxfr->count * 2; |
|
|
|
|
|
|
@ -275,6 +289,58 @@ LOCAL int writeMemory(SM2130_SPI_DEV *pDrvCtrl, SM2130_MEM_XFER *mxfr) |
|
|
|
return OK; |
|
|
|
} |
|
|
|
|
|
|
|
LOCAL ssize_t drv1553bRead(SM2310_DEV_HANDLE *dev, char *buffer, size_t maxbytes) |
|
|
|
{ |
|
|
|
SM2130_SPI_DEV *pDrvCtrl = dev->pDevCtrl; |
|
|
|
int max_words = maxbytes / 2; |
|
|
|
SM2130_MEM_XFER smx = { 0, 0, 0, NULL }; |
|
|
|
STATUS error; |
|
|
|
|
|
|
|
if (max_words > SMX_MAX_WORDS) { |
|
|
|
max_words = SMX_MAX_WORDS; |
|
|
|
} |
|
|
|
|
|
|
|
smx.count = max_words; |
|
|
|
smx.membuf = (UINT16 *)buffer; |
|
|
|
|
|
|
|
semTake(pDrvCtrl->muteSem, WAIT_FOREVER); |
|
|
|
error = readMemory(pDrvCtrl, &smx); |
|
|
|
semGive(pDrvCtrl->muteSem); |
|
|
|
|
|
|
|
if (error != OK) { |
|
|
|
errnoSet(EIO); |
|
|
|
return -1; |
|
|
|
} |
|
|
|
|
|
|
|
return max_words * 2; |
|
|
|
} |
|
|
|
|
|
|
|
LOCAL ssize_t drv1553bWrite(SM2310_DEV_HANDLE *dev, char *buffer, size_t nbytes) |
|
|
|
{ |
|
|
|
SM2130_SPI_DEV *pDrvCtrl = dev->pDevCtrl; |
|
|
|
int max_words = nbytes / 2; |
|
|
|
SM2130_MEM_XFER smx = { 0, 0, 0, NULL }; |
|
|
|
STATUS error; |
|
|
|
|
|
|
|
if (max_words > SMX_MAX_WORDS) { |
|
|
|
max_words = SMX_MAX_WORDS; |
|
|
|
} |
|
|
|
|
|
|
|
smx.count = max_words; |
|
|
|
smx.membuf = (UINT16 *)buffer; |
|
|
|
|
|
|
|
semTake(pDrvCtrl->muteSem, WAIT_FOREVER); |
|
|
|
error = writeMemory(pDrvCtrl, &smx); |
|
|
|
semGive(pDrvCtrl->muteSem); |
|
|
|
|
|
|
|
if (error != OK) { |
|
|
|
errnoSet(EIO); |
|
|
|
return -1; |
|
|
|
} |
|
|
|
|
|
|
|
return max_words * 2; |
|
|
|
} |
|
|
|
|
|
|
|
LOCAL int drv1553bIoctl(SM2310_DEV_HANDLE *dev, int cmd, _Vx_ioctl_arg_t arg) |
|
|
|
{ |
|
|
|
SM2130_XFER *xfer; |
|
|
@ -290,27 +356,64 @@ LOCAL int drv1553bIoctl(SM2310_DEV_HANDLE *dev, int cmd, _Vx_ioctl_arg_t arg) |
|
|
|
ret = selNodeDelete(&dev->selList, (SEL_WAKEUP_NODE *)arg); |
|
|
|
break; |
|
|
|
case FIOC_SM2130_WR: |
|
|
|
xfer = (SM2130_XFER *)(arg); |
|
|
|
pDrvCtrl->write(pDrvCtrl->pDev, xfer->reg, xfer->val); |
|
|
|
break; |
|
|
|
xfer = (SM2130_XFER *)(arg); |
|
|
|
pDrvCtrl->write(pDrvCtrl->pDev, xfer->reg, xfer->val); |
|
|
|
break; |
|
|
|
case FIOC_SM2130_RD: |
|
|
|
xfer = (SM2130_XFER *)(arg); |
|
|
|
xfer->val = pDrvCtrl->read(pDrvCtrl->pDev, xfer->reg); |
|
|
|
break; |
|
|
|
xfer = (SM2130_XFER *)(arg); |
|
|
|
xfer->val = pDrvCtrl->read(pDrvCtrl->pDev, xfer->reg); |
|
|
|
break; |
|
|
|
case FIOC_SM2130_RST: |
|
|
|
if (pDrvCtrl->funcReset) { |
|
|
|
UINT32 us = (UINT32)arg; |
|
|
|
|
|
|
|
if (us == 0) { |
|
|
|
us = 10000; |
|
|
|
} |
|
|
|
pDrvCtrl->funcReset(TRUE); |
|
|
|
sysUsDelay(us); |
|
|
|
pDrvCtrl->funcReset(FALSE); |
|
|
|
} else { |
|
|
|
errnoSet(ENOTSUP); |
|
|
|
ret = ERROR; |
|
|
|
} |
|
|
|
break; |
|
|
|
|
|
|
|
case FIOC_SM2130_REQISR: |
|
|
|
dev->usrIsr = (void *)(arg); |
|
|
|
break; |
|
|
|
|
|
|
|
case FIOC_SM2130_ACKIRQ: |
|
|
|
if (pDrvCtrl->funcAckIrq) { |
|
|
|
if (pDrvCtrl->irqCount > 0) { |
|
|
|
UINT32 us = (UINT32)arg; |
|
|
|
if (us == 0) { |
|
|
|
us = 100; |
|
|
|
} |
|
|
|
pDrvCtrl->funcAckIrq(TRUE); |
|
|
|
sysUsDelay(us); |
|
|
|
pDrvCtrl->funcAckIrq(FALSE); |
|
|
|
} |
|
|
|
} else { |
|
|
|
errnoSet(ENOTSUP); |
|
|
|
ret = ERROR; |
|
|
|
} |
|
|
|
pDrvCtrl->irqCount = 0; |
|
|
|
break; |
|
|
|
case FIOC_SM2130_READY: |
|
|
|
if (pDrvCtrl->isReady) { |
|
|
|
*(int *)(arg) = pDrvCtrl->isReady(); |
|
|
|
} else { |
|
|
|
errnoSet(EIO); |
|
|
|
ret = ERROR; |
|
|
|
} |
|
|
|
break; |
|
|
|
if (pDrvCtrl->funcIsReady) { |
|
|
|
*(int *)(arg) = pDrvCtrl->funcIsReady(); |
|
|
|
} else { |
|
|
|
errnoSet(EIO); |
|
|
|
ret = ERROR; |
|
|
|
} |
|
|
|
break; |
|
|
|
case FIOC_SM2130_REGRD: |
|
|
|
ret = readReg(pDrvCtrl, (SM2130_XFER *)(arg)); |
|
|
|
break; |
|
|
|
ret = readReg(pDrvCtrl, (SM2130_XFER *)(arg)); |
|
|
|
break; |
|
|
|
case FIOC_SM2130_REGWR: |
|
|
|
ret = writeReg(pDrvCtrl, (SM2130_XFER *)(arg)); |
|
|
|
break; |
|
|
|
ret = writeReg(pDrvCtrl, (SM2130_XFER *)(arg)); |
|
|
|
break; |
|
|
|
case FIOC_SM2130_SMADDR: |
|
|
|
ret = setMemAddress(pDrvCtrl, (SM2130_XFER *)(arg)); |
|
|
|
break; |
|
|
@ -358,7 +461,6 @@ LOCAL void sm2130SpiDevInstInit2(VXB_DEVICE_ID pDev) |
|
|
|
/* Retrieve the SPI master special information */ |
|
|
|
if (pFunc != NULL) |
|
|
|
(*pFunc)(vxbDevParent(pDev), &pDrvCtrl->specialInfo); |
|
|
|
pDrvCtrl->irqStage = -128; |
|
|
|
} |
|
|
|
|
|
|
|
LOCAL void sm1553isr(void *data) |
|
|
@ -366,11 +468,13 @@ LOCAL void sm1553isr(void *data) |
|
|
|
SM2310_DEV_HANDLE *dev = data; |
|
|
|
SM2130_SPI_DEV *pDrvCtrl = dev->pDevCtrl; |
|
|
|
|
|
|
|
if (pDrvCtrl->ackIrq) { |
|
|
|
pDrvCtrl->ackIrq(); |
|
|
|
++pDrvCtrl->irqCount; |
|
|
|
|
|
|
|
//logMsg("sm1553isr interrupt", 1, 2, 3, 4, 5, 6);
|
|
|
|
if (dev->usrIsr) { |
|
|
|
dev->usrIsr(); |
|
|
|
} |
|
|
|
|
|
|
|
logMsg("sm1553isr interrupt", 1, 2, 3, 4, 5, 6); |
|
|
|
selWakeupAll(&dev->selList, SELREAD); |
|
|
|
} |
|
|
|
|
|
|
@ -400,23 +504,34 @@ LOCAL void sm2130SpiDevInstConnect(VXB_DEVICE_ID pDev) |
|
|
|
(DRV_REMOVE_PTR)NULL , |
|
|
|
(DRV_OPEN_PTR)drv1553bOpen , |
|
|
|
(DRV_CLOSE_PTR)drv1553bClose , |
|
|
|
(DRV_READ_PTR)NULL , |
|
|
|
(DRV_WRITE_PTR)NULL , |
|
|
|
(DRV_READ_PTR)drv1553bRead , |
|
|
|
(DRV_WRITE_PTR)drv1553bWrite , |
|
|
|
(DRV_IOCTL_PTR)drv1553bIoctl); |
|
|
|
/* clang-format on */ |
|
|
|
} |
|
|
|
|
|
|
|
if (pDrvCtrl->funcAckIrq) { |
|
|
|
pDrvCtrl->funcAckIrq(FALSE); |
|
|
|
} |
|
|
|
|
|
|
|
if (pDrvCtrl->funcReset) { |
|
|
|
pDrvCtrl->funcReset(FALSE); |
|
|
|
sysUsDelay(10000); |
|
|
|
pDrvCtrl->funcReset(TRUE); |
|
|
|
} |
|
|
|
|
|
|
|
semTake(pDrvCtrl->muteSem, WAIT_FOREVER); |
|
|
|
if (sm2130_driver_node > 0) { |
|
|
|
dev = (SM2310_DEV_HANDLE *)hwMemAlloc(sizeof(SM2310_DEV_HANDLE)); |
|
|
|
if (dev) { |
|
|
|
pDrvCtrl->refcount = 0; |
|
|
|
dev->usrIsr = NULL; |
|
|
|
selWakeupListInit(&dev->selList); |
|
|
|
if (iosDevAdd(&dev->devHdr, pDrvCtrl->devName, sm2130_driver_node) == OK) { |
|
|
|
pDrvCtrl->devHandle = dev; |
|
|
|
dev->pDevCtrl = pDrvCtrl; |
|
|
|
if (pDrvCtrl->reqIsr) { |
|
|
|
pDrvCtrl->irqStage = pDrvCtrl->reqIsr(dev, sm1553isr); |
|
|
|
if (pDrvCtrl->funcReqIsr) { |
|
|
|
pDrvCtrl->funcReqIsr(dev, sm1553isr); |
|
|
|
} |
|
|
|
} else { |
|
|
|
#ifndef _VXBUS_BASIC_HWMEMLIB |
|
|
@ -473,15 +588,15 @@ LOCAL STATUS sm2130SpiDevInstUnlink(VXB_DEVICE_ID pDev, void *unused) |
|
|
|
*/ |
|
|
|
LOCAL const char *checkReady(SM2130_SPI_DEV *pDrvCtrl) |
|
|
|
{ |
|
|
|
if (!pDrvCtrl->isReady()) { |
|
|
|
return "Unknown"; |
|
|
|
} |
|
|
|
if (!pDrvCtrl->funcIsReady) { |
|
|
|
return "Unknown"; |
|
|
|
} |
|
|
|
|
|
|
|
if (pDrvCtrl->isReady()) { |
|
|
|
return "Ready"; |
|
|
|
} |
|
|
|
if (pDrvCtrl->funcIsReady()) { |
|
|
|
return "Ready"; |
|
|
|
} |
|
|
|
|
|
|
|
return "Not Ready"; |
|
|
|
return "Not Ready"; |
|
|
|
} |
|
|
|
|
|
|
|
LOCAL void sm2130SpiDevShow(VXB_DEVICE_ID pDev, int verbose) |
|
|
@ -495,8 +610,8 @@ LOCAL void sm2130SpiDevShow(VXB_DEVICE_ID pDev, int verbose) |
|
|
|
printf(" devName: %s\n", pDrvCtrl->devName); |
|
|
|
printf(" devHandle: %p\n", pDrvCtrl->devHandle); |
|
|
|
printf(" refCount: %d\n", pDrvCtrl->refcount); |
|
|
|
printf(" reqIsr: %p\n", pDrvCtrl->reqIsr); |
|
|
|
printf(" irqStatus: %d\n", pDrvCtrl->irqStage); |
|
|
|
printf(" funcReqIsr: %p\n", pDrvCtrl->funcReqIsr); |
|
|
|
printf(" irqCount: %u\n", pDrvCtrl->irqCount); |
|
|
|
printf(" isReady: %s\n", checkReady(pDrvCtrl)); |
|
|
|
} |
|
|
|
|
|
|
|