From caa486d56bb0e44531732ba15d2f268a827b017f Mon Sep 17 00:00:00 2001 From: surenyi Date: Fri, 25 Oct 2024 10:51:13 +0800 Subject: [PATCH] improv sm2130 chip driver Signed-off-by: surenyi --- bspApi.h | 37 +++--- bspStubs.c | 49 ++++++-- hwconf.c | 68 ++++++----- vxbSm2130SpiDev.c | 299 ++++++++++++++++++++++++++++++++-------------- vxbSm2130SpiDev.h | 37 +++--- 5 files changed, 321 insertions(+), 169 deletions(-) diff --git a/bspApi.h b/bspApi.h index 395f12e..7e381e8 100644 --- a/bspApi.h +++ b/bspApi.h @@ -15,13 +15,16 @@ extern "C" { #define FIOC_SM2130_WR (__SM2130__IOC_MAGIC | XFER_TYPE_WR) #define FIOC_SM2130_RD (__SM2130__IOC_MAGIC | XFER_TYPE_RD) -#define FIOC_SM2130_READY (__SM2130__IOC_MAGIC | 0x10) +#define FIOC_SM2130_READY (__SM2130__IOC_MAGIC | 0x10) +#define FIOC_SM2130_ACKIRQ (__SM2130__IOC_MAGIC | 0x11) +#define FIOC_SM2130_RST (__SM2130__IOC_MAGIC | 0x12) +#define FIOC_SM2130_REQISR (__SM2130__IOC_MAGIC | 0x13) -#define FIOC_SM2130_REGRD (__SM2130__IOC_MAGIC | 0x21) -#define FIOC_SM2130_REGWR (__SM2130__IOC_MAGIC | 0x22) +#define FIOC_SM2130_REGRD (__SM2130__IOC_MAGIC | 0x21) +#define FIOC_SM2130_REGWR (__SM2130__IOC_MAGIC | 0x22) #define FIOC_SM2130_SMADDR (__SM2130__IOC_MAGIC | 0x23) -#define FIOC_SM2130_RDMEM (__SM2130__IOC_MAGIC | 0x24) -#define FIOC_SM2130_WRMEM (__SM2130__IOC_MAGIC | 0x25) +#define FIOC_SM2130_RDMEM (__SM2130__IOC_MAGIC | 0x24) +#define FIOC_SM2130_WRMEM (__SM2130__IOC_MAGIC | 0x25) struct sm2130_xfer { UINT8 reg; @@ -29,9 +32,11 @@ struct sm2130_xfer { }; typedef struct sm2130_xfer SM2130_XFER; +#define SMX_MAX_WORDS (64) + struct sm2130_xfer_mem { - int count; - UINT8 reg; + int count; + UINT8 reg; UINT16 address; UINT16 *membuf; }; @@ -39,23 +44,23 @@ typedef struct sm2130_xfer_mem SM2130_MEM_XFER; /* }}} */ /* {{{ spidev FIO_SPIXFER msgs */ -#define FIO_XFER_TX (1 << 0) -#define FIO_XFER_RX (1 << 1) +#define FIO_XFER_TX (1 << 0) +#define FIO_XFER_RX (1 << 1) #define FIO_XFER_DUPLEX ((FIO_XFER_TX) | (FIO_XFER_RX)) /* ioctl */ -#define FIO_SPIXFER (('P' << 16) | 0x1001) +#define FIO_SPIXFER (('P' << 16) | 0x1001) struct spi_xfer { - int len; - int xferDir; - UINT8 *txbuf; - UINT8 *rxbuf; + int len; + int xferDir; + UINT8 *txbuf; + UINT8 *rxbuf; }; struct spi_xfer_msg { - int count; - struct spi_xfer *xfer; + int count; + struct spi_xfer *xfer; }; /* }}} */ diff --git a/bspStubs.c b/bspStubs.c index 6957d0f..b6e2e67 100644 --- a/bspStubs.c +++ b/bspStubs.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include "config.h" @@ -30,6 +31,7 @@ IMPORT int uenvInit(); IMPORT void lfsDevRegister(void); IMPORT void vxbSpiRawDevRegister(void); IMPORT void sysMsDelay(UINT delay); +IMPORT void sysUsDelay(int us); /* bsp glue functions */ void bspPinMuxInitialize(void) @@ -109,27 +111,39 @@ void bspDriverRegiser(void) } /* {{{ 1553B IO */ -/* GPIO1_A4 */ -int bspSm1553bIrqConnect(void *data, void (*isr)(void *data)) + +/* MR: GPIO1_B7 (reset) */ +void bspSm1553bReset(BOOL value) { VXB_DEVICE_ID pDev; FT_GPIO_DRVCTRL * pCtrl; - + pDev = vxbInstByNameFind("ftGpio", 1); if (pDev == NULL) { - printf("Can't find ftGpio1\r\n"); - return ERROR; + logMsg("Can't find ftGpio1\r\n", 1, 2, 3, 4, 5, 6); + return; } pCtrl = pDev->pDrvCtrl; /* MR: GPIO1_B7 (reset) */ - pCtrl->gpioOutput(pDev, 1, 7, 0); - sysMsDelay(10); - pCtrl->gpioOutput(pDev, 1, 7, 1); + pCtrl->gpioOutput(pDev, 1, 7, value); +} + +/* GPIO1_A4 */ +void bspSm1553bIrqConnect(void *data, void (*isr)(void *data)) +{ + VXB_DEVICE_ID pDev; + FT_GPIO_DRVCTRL * pCtrl; + + pDev = vxbInstByNameFind("ftGpio", 1); + if (pDev == NULL) { + logMsg("Can't find ftGpio1\r\n", 1, 2, 3, 4, 5, 6); + return; + } + pCtrl = pDev->pDrvCtrl; /* GPIO1_A4 (irq) */ pCtrl->gpioISRSet(pDev, 4, isr, data); - return OK; } /* GPIO0_B7: SM2130_READY */ @@ -140,7 +154,7 @@ int bspSm1553bChipReady(void) pDev = vxbInstByNameFind("ftGpio", 0); if (pDev == NULL) { - printf("Can't find ftGpio0\r\n"); + logMsg("Can't find ftGpio0\r\n", 1, 2, 3, 4, 5, 6); return 0; } pCtrl = pDev->pDrvCtrl; @@ -148,9 +162,20 @@ int bspSm1553bChipReady(void) return pCtrl->gpioInput(pDev, 1, 7); } -void bspSm1553bAckIrq(void) +/* GPIO0_B6: M2130_ACKIRQ */ +void bspSm1553bAckIrq(BOOL value) { - logMsg("Sm1553b Irq\r\n", 1, 2, 3, 4, 5, 6); + VXB_DEVICE_ID pDev; + FT_GPIO_DRVCTRL * pCtrl; + + pDev = vxbInstByNameFind("ftGpio", 0); + if (pDev == NULL) { + return; + } + pCtrl = pDev->pDrvCtrl; + + pCtrl->gpioOutput(pDev, 1, 6, value); + logMsg("ackirq Sm1553b Irq\r\n", 1, 2, 3, 4, 5, 6); } /* }}} */ diff --git a/hwconf.c b/hwconf.c index 7a67dee..c702dfc 100644 --- a/hwconf.c +++ b/hwconf.c @@ -150,7 +150,7 @@ LOCAL const struct intrCtlrTrigger gicTrigger[] = { /* pin, sensitivity */ { INT_VEC_GPIO0INTR, VXB_INTR_TRIG_RISING_EDGE }, - { INT_VEC_GPIO1INTR, VXB_INTR_TRIG_RISING_EDGE }, + { INT_VEC_GPIO1INTR, VXB_INTR_TRIG_FALLING_EDGE }, }; @@ -382,12 +382,12 @@ LOCAL UINT8 gpio0PortBModeTable[] = { 0, 0, 0, 0, 0, 0, 2, 1 /* GPIO0_B6: SM2130_ACKIRQ; GPIO0_B7: SM2130_READY */ }; struct hcfResource gpioDev0Resources[] = { - { "regBase", HCF_RES_INT, { (void *)GPIO_0_BASE_ADR } }, - { "portAModeTable", HCF_RES_ADDR, { (void *)&gpio0PortAModeTable[0] } }, + { "regBase", HCF_RES_INT, { (void *)GPIO_0_BASE_ADR } }, + { "portAModeTable", HCF_RES_ADDR, { (void *)&gpio0PortAModeTable[0] } }, { "portAModeTableNum", HCF_RES_INT, { (void *)NELEMENTS(gpio0PortAModeTable)} }, - { "portBModeTable", HCF_RES_ADDR, { (void *)&gpio0PortBModeTable[0] } }, + { "portBModeTable", HCF_RES_ADDR, { (void *)&gpio0PortBModeTable[0] } }, { "portBModeTableNum", HCF_RES_INT, { (void *)NELEMENTS(gpio0PortBModeTable)} }, - { "trigger", HCF_RES_INT, { (void *)VXB_INTR_TRIG_RISING_EDGE} }, + { "trigger", HCF_RES_INT, { (void *)VXB_INTR_TRIG_RISING_EDGE } }, }; #define gpioDev0Num NELEMENTS(gpioDev0Resources) @@ -401,21 +401,21 @@ LOCAL UINT8 gpio1PortBModeTable[] = { 0, 0, 0, 0, 0, 0, 0, 2 /* GPIO1_B7: SM2130_MR */ }; struct hcfResource gpioDev1Resources[] = { - { "regBase", HCF_RES_INT, { (void *)GPIO_1_BASE_ADR } }, - { "portAModeTable", HCF_RES_ADDR, { (void *)&gpio1PortAModeTable[0] } }, + { "regBase", HCF_RES_INT, { (void *)GPIO_1_BASE_ADR } }, + { "portAModeTable", HCF_RES_ADDR, { (void *)&gpio1PortAModeTable[0] } }, { "portAModeTableNum", HCF_RES_INT, { (void *)NELEMENTS(gpio1PortAModeTable)} }, - { "portBModeTable", HCF_RES_ADDR, { (void *)&gpio1PortBModeTable[0] } }, + { "portBModeTable", HCF_RES_ADDR, { (void *)&gpio1PortBModeTable[0] } }, { "portBModeTableNum", HCF_RES_INT, { (void *)NELEMENTS(gpio1PortBModeTable)} }, - { "trigger", HCF_RES_INT, { (void *)VXB_INTR_TRIG_RISING_EDGE} }, + { "trigger", HCF_RES_INT, { (void *)VXB_INTR_TRIG_FALLING_EDGE } }, }; #define gpioDev1Num NELEMENTS(gpioDev1Resources) #endif #ifdef DRV_ARM_GEN_SYS_TIMER struct hcfResource armGenSysTimerResources[] = { - { "regBase", HCF_RES_INT, {(void *)0xeeee0000} }, - { "irq", HCF_RES_INT, {(void *)GEN_TIMER_IRQ} }, - { "clkFreq", HCF_RES_INT, {(void *)SYS_CLK_FREQ} }, + { "regBase", HCF_RES_INT, {(void *)0xeeee0000 } }, + { "irq", HCF_RES_INT, {(void *)GEN_TIMER_IRQ } }, + { "clkFreq", HCF_RES_INT, {(void *)SYS_CLK_FREQ } }, { "minClkRate", HCF_RES_INT, {(void *)SYS_CLK_RATE_MIN} }, { "maxClkRate", HCF_RES_INT, {(void *)SYS_CLK_RATE_MAX} }, }; @@ -424,9 +424,9 @@ struct hcfResource armGenSysTimerResources[] = { #ifdef DRV_ARM_GEN_AUX_TIMER struct hcfResource armAuxGenTimerResources[] = { - { "regBase", HCF_RES_INT, {(void *)AUX_CLK_REG_BASE} }, - { "irq", HCF_RES_INT, {(void *)AUX_GEN_TIMER_IRQ} }, - { "clkFreq", HCF_RES_INT, {(void *)AUX_CLK_FREQ} }, + { "regBase", HCF_RES_INT, {(void *)AUX_CLK_REG_BASE } }, + { "irq", HCF_RES_INT, {(void *)AUX_GEN_TIMER_IRQ } }, + { "clkFreq", HCF_RES_INT, {(void *)AUX_CLK_FREQ } }, { "minClkRate", HCF_RES_INT, {(void *)SYS_CLK_RATE_MIN} }, { "maxClkRate", HCF_RES_INT, {(void *)SYS_CLK_RATE_MAX} }, }; @@ -444,31 +444,31 @@ const struct hcfResource ftPci0Resources[] = { { "io32Addr", HCF_RES_ADDR, { (void *)0x50000000 } }, { "io32Size", HCF_RES_INT, { (void *)0x08000000 } }, - { "io16Addr", HCF_RES_ADDR, { (void *)0x1000 } }, + { "io16Addr", HCF_RES_ADDR, { (void *)0x1000 } }, { "io16Size", HCF_RES_INT, { (void *)0x0ffff000 } }, - { "ioStart", HCF_RES_ADDR, { (void *)0x50000000 } }, + { "ioStart", HCF_RES_ADDR, { (void *)0x50000000} }, - { "fbbEnable", HCF_RES_INT, { (void *)TRUE } }, - { "cacheSize", HCF_RES_INT, { (void *)(8) } }, - { "maxLatAllSet", HCF_RES_INT, { (void *)0x40 } }, - { "autoIntRouteSet", HCF_RES_INT, { (void *)FALSE } }, + { "fbbEnable", HCF_RES_INT, { (void *)TRUE } }, + { "cacheSize", HCF_RES_INT, { (void *)(8) } }, + { "maxLatAllSet", HCF_RES_INT, { (void *)0x40 } }, + { "autoIntRouteSet", HCF_RES_INT, { (void *)FALSE } }, { "includeFuncSet", HCF_RES_ADDR, { (void *)sysPciExAutoconfigInclude } }, { "intAssignFuncSet", HCF_RES_ADDR, { (void *)sysPciExAutoconfigIntrAssign } }, { "funcPirqEnable", HCF_RES_ADDR, { (void *)sysPciPirqEnable}}, - { "maxBusSet", HCF_RES_INT, { (void *)32 } }, + { "maxBusSet", HCF_RES_INT, { (void *)32 } }, /* Window Attributes - Defaults to 8540 type if none given */ - { "autoConfig", HCF_RES_INT, { (void *)(FALSE)} }, + { "autoConfig", HCF_RES_INT, { (void *)(FALSE) } }, #ifdef INCLUDE_INTCTLR_DYNAMIC_LIB - { "msiEnable", HCF_RES_INT, { (void *)(TRUE)} }, - { "dynamicInterrupts", HCF_RES_INT, { (void *)(TRUE)} } + { "msiEnable", HCF_RES_INT, { (void *)(TRUE) } }, + { "dynamicInterrupts", HCF_RES_INT, { (void *)(TRUE) } } #else - { "msiEnable", HCF_RES_INT, { (void *)(FALSE)} }, - { "dynamicInterrupts", HCF_RES_INT, { (void *)(FALSE)} } + { "msiEnable", HCF_RES_INT, { (void *)(FALSE) } }, + { "dynamicInterrupts", HCF_RES_INT, { (void *)(FALSE) } } #endif /* INCLUDE_INTCTLR_DYNAMIC_LIB */ }; #define ftPci0Num NELEMENTS(ftPci0Resources) @@ -530,15 +530,17 @@ struct hcfResource lfsResources[] = { #define lfsResNum NELEMENTS(lfsResources) #endif -IMPORT int bspSm1553bIrqConnect(void *data, void (*isr)(void *data)); +IMPORT void bspSm1553bIrqConnect(void *data, void (*isr)(void *data)); IMPORT int bspSm1553bChipReady(void); -IMPORT void bspSm1553bAckIrq(void); +IMPORT void bspSm1553bAckIrq(BOOL); +IMPORT void bspSm1553bReset(BOOL); struct hcfResource sm2130Resources[] = { - { "devName" , HCF_RES_STRING, {(void *)"/sm1553b"}}, - { "reqIsr" , HCF_RES_ADDR, {(void *)bspSm1553bIrqConnect}}, - { "isReady" , HCF_RES_ADDR, {(void *)bspSm1553bChipReady}}, - { "ackIrq" , HCF_RES_ADDR, {(void *)bspSm1553bAckIrq}}, + { "devName" , HCF_RES_STRING, {(void *)"/sm1553b" } }, + { "funcReqIsr" , HCF_RES_ADDR, {(void *)bspSm1553bIrqConnect } }, + { "funcIsReady" , HCF_RES_ADDR, {(void *)bspSm1553bChipReady } }, + { "funcAckIrq" , HCF_RES_ADDR, {(void *)bspSm1553bAckIrq } }, + { "funcReset" , HCF_RES_ADDR, {(void *)bspSm1553bReset } }, }; #define sm2130ResNum NELEMENTS(sm2130Resources) diff --git a/vxbSm2130SpiDev.c b/vxbSm2130SpiDev.c index af48e1f..3bf91c1 100644 --- a/vxbSm2130SpiDev.c +++ b/vxbSm2130SpiDev.c @@ -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, "funcIsReady", HCF_RES_ADDR, (void *)&pDrvCtrl->funcIsReady) != OK) { + pDrvCtrl->funcIsReady = NULL; } - if (devResourceGet(pHcf, "isReady", HCF_RES_ADDR, (void *)&pDrvCtrl->isReady) != OK) { - pDrvCtrl->isReady = NULL; + if (devResourceGet(pHcf, "funcAckIrq", HCF_RES_ADDR, (void *)&pDrvCtrl->funcAckIrq) != OK) { + pDrvCtrl->funcAckIrq = NULL; } - if (devResourceGet(pHcf, "ackIrq", HCF_RES_ADDR, (void *)&pDrvCtrl->ackIrq) != OK) { - pDrvCtrl->ackIrq = NULL; + + if (devResourceGet(pHcf, "funcReset", HCF_RES_ADDR, (void *)&pDrvCtrl->funcReset) != OK) { + pDrvCtrl->funcReset = NULL; } } @@ -146,10 +155,15 @@ LOCAL void sm2130SpiDevInstInit(VXB_DEVICE_ID pDev) 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); + + 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; - - if (xfer->reg <= 15) { - cmd = (xfer->reg << 2); - } else { - cmd = xfer->reg & 0xff; - } - - xfer->val = pDrvCtrl->read(pDrvCtrl->pDev, cmd); - return 0; + UINT8 cmd; + + if (xfer->reg <= 15) { + cmd = (xfer->reg << 2); + } else { + cmd = xfer->reg & 0xff; + } + + xfer->val = pDrvCtrl->read(pDrvCtrl->pDev, cmd); + return 0; } LOCAL int writeReg(SM2130_SPI_DEV *pDrvCtrl, SM2130_XFER *xfer) { - UINT8 cmd; - - if (xfer->reg <= 63) { - cmd = 0x80 | (xfer->reg & 0x3f); - } else { - cmd = xfer->reg & 0xff; - } - - pDrvCtrl->write(pDrvCtrl->pDev, cmd, xfer->val); - - return 0; + UINT8 cmd; + + if (xfer->reg <= 63) { + cmd = 0x80 | (xfer->reg & 0x3f); + } else { + cmd = xfer->reg & 0xff; + } + + pDrvCtrl->write(pDrvCtrl->pDev, cmd, xfer->val); + + 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); } @@ -214,22 +228,22 @@ LOCAL int readMemory(SM2130_SPI_DEV *pDrvCtrl, SM2130_MEM_XFER *mxfr) SPI_TRANSFER transInfo = { NULL, NULL, 0, 0, 0 }; 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; - + vxbSpiTransfer(pDrvCtrl->pDev, &transInfo); - + pDrvCtrl->write(pDrvCtrl->pDev, 0x80 | mxfr->reg, mxfr->address); - } - + } + cmd = 0x40; ptr = (UINT8 *)pDrvCtrl->regmem; transInfo.txBuf = &cmd; @@ -238,8 +252,8 @@ LOCAL int readMemory(SM2130_SPI_DEV *pDrvCtrl, SM2130_MEM_XFER *mxfr) transInfo.rxLen = 1 + mxfr->count * 2; vxbSpiTransfer(pDrvCtrl->pDev, &transInfo); - - memcpy(mxfr->membuf, ptr + 1, mxfr->count * 2); + + memcpy(mxfr->membuf, ptr + 1, mxfr->count * 2); return OK; } @@ -248,33 +262,85 @@ LOCAL int writeMemory(SM2130_SPI_DEV *pDrvCtrl, SM2130_MEM_XFER *mxfr) SPI_TRANSFER transInfo = { NULL, NULL, 0, 0, 0 }; 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; - + vxbSpiTransfer(pDrvCtrl->pDev, &transInfo); - + pDrvCtrl->write(pDrvCtrl->pDev, 0x80 | mxfr->reg, mxfr->address); - } - + } + 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; - + vxbSpiTransfer(pDrvCtrl->pDev, &transInfo); - + 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->isReady()) { - return "Ready"; - } - - return "Not Ready"; + if (!pDrvCtrl->funcIsReady) { + return "Unknown"; + } + + if (pDrvCtrl->funcIsReady()) { + return "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)); } diff --git a/vxbSm2130SpiDev.h b/vxbSm2130SpiDev.h index 47e6de8..9e64953 100644 --- a/vxbSm2130SpiDev.h +++ b/vxbSm2130SpiDev.h @@ -10,10 +10,13 @@ #define XFER_TYPE_WR (1) #define XFER_TYPE_RD (2) -#define FIOC_SM2130_WR (__SM2130__IOC_MAGIC | XFER_TYPE_WR) -#define FIOC_SM2130_RD (__SM2130__IOC_MAGIC | XFER_TYPE_RD) +#define FIOC_SM2130_WR (__SM2130__IOC_MAGIC | XFER_TYPE_WR) +#define FIOC_SM2130_RD (__SM2130__IOC_MAGIC | XFER_TYPE_RD) #define FIOC_SM2130_READY (__SM2130__IOC_MAGIC | 0x10) +#define FIOC_SM2130_ACKIRQ (__SM2130__IOC_MAGIC | 0x11) +#define FIOC_SM2130_RST (__SM2130__IOC_MAGIC | 0x12) +#define FIOC_SM2130_REQISR (__SM2130__IOC_MAGIC | 0x13) #define FIOC_SM2130_REGRD (__SM2130__IOC_MAGIC | 0x21) #define FIOC_SM2130_REGWR (__SM2130__IOC_MAGIC | 0x22) @@ -22,14 +25,15 @@ #define FIOC_SM2130_WRMEM (__SM2130__IOC_MAGIC | 0x25) struct sm2130_xfer { - UINT8 reg; - UINT16 val; + UINT8 reg; + UINT16 val; }; typedef struct sm2130_xfer SM2130_XFER; +#define SMX_MAX_WORDS (64) struct sm2130_xfer_mem { - int count; - UINT8 reg; + int count; + UINT8 reg; UINT16 address; UINT16 *membuf; }; @@ -42,21 +46,22 @@ typedef struct _spi_1553b_drv_ctrl { const char *devName; - int refcount; - - int irqStage; - + volatile int refcount; + + volatile UINT32 irqCount; + void *devHandle; - int (*reqIsr)(void *data, void (*isr)(void *data)); - - int (*isReady)(); - void (*ackIrq)(); + int (*funcReqIsr)(void *data, void (*isr)(void *data)); + int (*funcIsReady)(); + void (*funcAckIrq)(BOOL); + void (*funcReset)(BOOL); + INT32 (*read)(VXB_DEVICE_ID pDev, UINT8 cmd); STATUS (*write)(VXB_DEVICE_ID pDev, UINT8 cmd, UINT16 var); - UINT16 regmem[64]; - + UINT16 regmem[SMX_MAX_WORDS+1]; /* add 1 dummy slot */ + SEM_ID muteSem; /* operation semaphore */ VXB_SPI_MAST_SPEC *specialInfo; } SM2130_SPI_DEV;