From cd6226fb5455fdfdb40cb3a91637ab8963d81ce9 Mon Sep 17 00:00:00 2001 From: surenyi Date: Thu, 17 Oct 2024 17:16:28 +0800 Subject: [PATCH] add SM2130 driver Signed-off-by: surenyi --- .clang-format | 127 +++++ 40vxbSm2130SpiDev.cdf | 20 + Makefile | 3 +- config.h | 20 +- ft2000-4.h | 1 + hwconf.c | 30 +- vxbFtGpio.c | 66 ++- vxbFtSpi.c | 1135 +++++++++++++++++++++++------------------ vxbFtSpi.h | 13 +- vxbSm2130SpiDev.c | 302 +++++++++++ vxbSm2130SpiDev.h | 23 + 11 files changed, 1204 insertions(+), 536 deletions(-) create mode 100644 .clang-format create mode 100644 40vxbSm2130SpiDev.cdf create mode 100644 vxbSm2130SpiDev.c create mode 100644 vxbSm2130SpiDev.h diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..1f61625 --- /dev/null +++ b/.clang-format @@ -0,0 +1,127 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# clang-format configuration file. Intended for clang-format >= 11. +# +# For more information, see: +# +# Documentation/process/clang-format.rst +# https://clang.llvm.org/docs/ClangFormat.html +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html +# +# :lua vim.lsp.buf.format({timeout=2000}) +--- +AccessModifierOffset: -4 +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlines: Left +AlignOperands: true +AlignTrailingComments: false +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: None +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: false +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterClass: false + AfterControlStatement: false + AfterEnum: false + AfterFunction: true + AfterNamespace: true + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + AfterExternBlock: false + BeforeCatch: false + BeforeElse: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Custom +BreakBeforeInheritanceComma: false +BreakBeforeTernaryOperators: false +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: BeforeComma +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: false +ColumnLimit: 80 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: false +DerivePointerAlignment: false +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: false + +# Taken from: +# git grep -h '^#define [^[:space:]]*for_each[^[:space:]]*(' include/ tools/ \ +# | sed "s,^#define \([^[:space:]]*for_each[^[:space:]]*\)(.*$, - '\1'," \ +# | LC_ALL=C sort -u +ForEachMacros: + - 'list_for_each' + +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '.*' + Priority: 1 +IncludeIsMainRegex: '(Test)?$' +IndentCaseLabels: false +IndentGotoLabels: false +IndentPPDirectives: None +IndentWidth: 4 +IndentWrappedFunctionNames: false +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: false +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBinPackProtocolList: Auto +ObjCBlockIndentWidth: 4 +ObjCSpaceAfterProperty: true +ObjCSpaceBeforeProtocolList: true + +# Taken from git's rules +PenaltyBreakAssignment: 10 +PenaltyBreakBeforeFirstCallParameter: 30 +PenaltyBreakComment: 10 +PenaltyBreakFirstLessLess: 0 +PenaltyBreakString: 10 +PenaltyExcessCharacter: 100 +PenaltyReturnTypeOnItsOwnLine: 60 + +PointerAlignment: Right +ReflowComments: false +SortIncludes: false +SortUsingDeclarations: false +SpaceAfterCStyleCast: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatementsExceptForEachMacros +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInContainerLiterals: false +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Cpp03 +TabWidth: 4 +UseTab: Never +... diff --git a/40vxbSm2130SpiDev.cdf b/40vxbSm2130SpiDev.cdf new file mode 100644 index 0000000..d5ef074 --- /dev/null +++ b/40vxbSm2130SpiDev.cdf @@ -0,0 +1,20 @@ +/* 40vxbSm2310SpiDev.cdf - Component configuration file */ + +/* + * modification history + * -------------------- + * 2024-10-16: surenyi written. + */ + +Component DRV_SPIDEV_SM2130 { + NAME State Micro SM2130 SPI 1553B vxBus Driver + SYNOPSIS This enables access to SM2310 1553B protocol chip + INIT_RTN vxbSm2130SpiDevRegister(); + PROTOTYPE void vxbSm2130SpiDevRegister (void); + _INIT_ORDER hardWareInterFaceBusInit + INIT_AFTER INCLUDE_SPI_BUS + REQUIRES INCLUDE_VXBUS \ + INCLUDE_PLB_BUS \ + INCLUDE_SPI_BUS + _CHILDREN FOLDER_DRIVERS +} diff --git a/Makefile b/Makefile index 21c58c0..3f490ad 100644 --- a/Makefile +++ b/Makefile @@ -22,7 +22,8 @@ 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 vxbFtSpi.o usrStubs.o vxbLfsLib.o + vxbSp25SpiFlash.o vxbFtGpio.o vxbFtSpi.o vxbSm2130SpiDev.o \ + usrStubs.o vxbLfsLib.o ifneq ($(findstring bootrom,$(MAKECMDGOALS)),bootrom) LIB_EXTRA = lib/libFtX100dcdrv.a diff --git a/config.h b/config.h index 8b022e1..048d24a 100644 --- a/config.h +++ b/config.h @@ -45,8 +45,10 @@ extern "C" { #define DRV_FTQSPI #define DRV_FTSPI #define DRV_SPIFLASH_SP25 -#define INCLUDE_YT8521PHY +#define DRV_SPIDEV_SM2130 +#undef INCLUDE_YT8521PHY #define DRV_FTGPIO + #if defined(INCLUDE_PC_CONSOLE)||defined(INCLUDE_WINDML) #define DRV_X100DC #endif @@ -68,6 +70,8 @@ extern "C" { #define INCLUDE_USB_GEN2_STORAGE_INIT #endif +#define INCLUDE_TFFS + #undef INCLUDE_DRV_STORAGE_AHCI #if defined(INCLUDE_USB) || \ defined(INCLUDE_DRV_STORAGE_PIIX) || defined(INCLUDE_DRV_STORAGE_AHCI) @@ -79,6 +83,12 @@ extern "C" { #define INCLUDE_DOSFS_SHOW #define INCLUDE_DOSFS_DIR_VFAT #define INCLUDE_DOSFS_DIR_FIXED +#endif + +#if defined(INCLUDE_USB) || \ + defined(INCLUDE_DRV_STORAGE_PIIX) || defined(INCLUDE_TFFS) || defined(INCLUDE_DRV_STORAGE_AHCI) + #define INCLUDE_HRFS_FORMAT + #define INCLUDE_HRFS_CHKDSK #define INCLUDE_FS_MONITOR #define INCLUDE_FS_EVENT_UTIL #define INCLUDE_ERF @@ -91,14 +101,9 @@ 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 @@ -276,6 +281,7 @@ extern "C" { #endif /* _WRS_CONFIG_SMP */ #define INCLUDE_SHELL + #define INCLUDE_SYM_TBL #define INCLUDE_SYM_TBL_INIT /*#define INCLUDE_STANDALONE_SYM_TBL*/ diff --git a/ft2000-4.h b/ft2000-4.h index cc432c3..3ff3eeb 100644 --- a/ft2000-4.h +++ b/ft2000-4.h @@ -83,6 +83,7 @@ enum can_bitrate{ #define FTCAN2_IRQ 124 #define FTCAN2_BITRATE FTCAN_BRATE_DEFAULT +#define FT2000_SPI_CLK (48000000) /* SPI clock */ #define FTSPI0_BASE 0x2800c000 #define FTSPI0_IRQ 50 diff --git a/hwconf.c b/hwconf.c index 352ae78..597320f 100644 --- a/hwconf.c +++ b/hwconf.c @@ -62,11 +62,11 @@ LOCAL struct intrCtlrInputs gicInputs[] = { { 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 + { 52, "ftSdhci", 0, 0 }, { 53, "ftSdhci", 0, 1 }, { 54, "ftSdhci", 0, 2 }, { I2C_0_INTR_IRQ, "ftI2c", 0, 0 }, @@ -99,6 +99,10 @@ LOCAL const struct intrCtlrPriority gicPriority[] = { { 61, 0x10 }, { 62, 0x10 }, { 63, 0x10 }, +#ifdef DRV_FTSPI + { FTSPI0_IRQ, 0x10}, + { FTSPI1_IRQ, 0x10}, +#endif { 52, 0x20 }, /*ftSdhci interrupt number : 52,53,54*/ { 53, 0x20 }, { 54, 0x20 }, @@ -126,6 +130,10 @@ struct intrCtlrCpu gicCpu[] = { { 61, 0 }, { 62, 0 }, { 63, 0 }, +#ifdef DRV_FTSPI + { FTSPI0_IRQ, 0}, + { FTSPI1_IRQ, 0}, +#endif { 52, 0 }, /*ftSdhci interrupt number : 52,53,54*/ { 53, 0 }, { 54, 0 }, @@ -253,13 +261,15 @@ struct hcfResource qspiResources[] = { #ifdef DRV_FTSPI struct vxbSpiDevInfo spiDevTbl1[] = { /* name cs width freq mode */ - { "SM2130", 0, 8, 500000, 1}, + { "SM2130", 0, 8, 5000000, 3}, }; struct hcfResource spiResources1[] = { - { "regBase", HCF_RES_INT, { (void *)(FTSPI1_BASE) } }, - { "clkDiv", HCF_RES_INT, { (void *)(2) } }, - { "spiDev", HCF_RES_ADDR, { (void *)&spiDevTbl1[0]} }, + { "regBase", HCF_RES_INT, { (void *)(FTSPI1_BASE) } }, + { "clkFreq", HCF_RES_INT, { (void *)(FT2000_SPI_CLK) } }, + { "speed", HCF_RES_INT, { (void *)(4000000) } }, + { "mode", HCF_RES_INT, { (void *)3} }, + { "spiDev", HCF_RES_ADDR, { (void *)&spiDevTbl1[0]} }, { "spiDevNum", HCF_RES_INT, { (void *)NELEMENTS(spiDevTbl1)}}, }; # define spiNum1 NELEMENTS(spiResources1) @@ -348,14 +358,14 @@ struct hcfResource i2cDev3Resources[] = { LOCAL UINT8 gpio0PortAModeTable[] = { /*pin of portA can be used as interrupt mode*/ /*portA-pinX: 0 1 2 3 4 5 6 7 */ - 3, 2, 1, 0, 0, 0, 0, 0 /* 0:GPIO_MODE_NOT_USED 1:GPIO_MODE_IN + 0, 2, 0, 0, 0, 0, 0, 0 /* 0:GPIO_MODE_NOT_USED 1:GPIO_MODE_IN 2:GPIO_MODE_OUT 3:GPIO_MODE_INT*/ }; /*This table is used to set the default pin mode of portB*/ LOCAL UINT8 gpio0PortBModeTable[] = { /*pin of portB can not be used as interrupt mode*/ /*portB-pinX: 0 1 2 3 4 5 6 7 */ - 1, 2, 1, 0, 0, 0, 0, 0 + 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 } }, @@ -369,12 +379,12 @@ struct hcfResource gpioDev0Resources[] = { LOCAL UINT8 gpio1PortAModeTable[] = { /*portA-pinX: 0 1 2 3 4 5 6 7 */ - 0, 0, 0, 0, 0, 0, 0, 0 /* 0:GPIO_MODE_NOT_USED 1:GPIO_MODE_IN - 2:GPIO_MODE_OUT 3:GPIO_MODE_INT*/ + 0, 0, 0, 0, 3, 0, 0, 0 /* 0:GPIO_MODE_NOT_USED 1:GPIO_MODE_IN + 2:GPIO_MODE_OUT 3:GPIO_MODE_INT*/ /* GPIO1_A4: SM2130_IRQ */ }; LOCAL UINT8 gpio1PortBModeTable[] = { /*portB-pinX: 0 1 2 3 4 5 6 7 */ - 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 2 /* GPIO1_B7: SM2130_MR */ }; struct hcfResource gpioDev1Resources[] = { { "regBase", HCF_RES_INT, { (void *)GPIO_1_BASE_ADR } }, diff --git a/vxbFtGpio.c b/vxbFtGpio.c index 42318d2..4b48ecb 100644 --- a/vxbFtGpio.c +++ b/vxbFtGpio.c @@ -47,6 +47,7 @@ IMPORT FUNCPTR _func_logMsg; LOCAL void vxbFtGpioInstInit(VXB_DEVICE_ID pInst); LOCAL void vxbFtGpioInstInit2(VXB_DEVICE_ID pInst); LOCAL void vxbFtGpioInstConnect(VXB_DEVICE_ID pInst); +LOCAL void vxbFtGpioShow (VXB_DEVICE_ID pDev, int verbose); LOCAL STATUS vxbFtGpioPinModeSet (VXB_DEVICE_ID pDev, UINT32 port, UINT32 pin,UINT32 mode); LOCAL UINT32 vxbFtGpioPinInput (VXB_DEVICE_ID pDev, UINT32 port, UINT32 pin); @@ -65,6 +66,7 @@ LOCAL struct drvBusFuncs vxbFtGpioDrvFuncs = LOCAL device_method_t vxbFtGpioDrv_methods[] = { + DEVMETHOD (busDevShow, vxbFtGpioShow), DEVMETHOD_END }; @@ -154,8 +156,8 @@ LOCAL void vxbFtGpioInstInit2 FT_GPIO_DRVCTRL * pDrvCtrl; UINT32 port = 0, pin = 0; HCF_DEVICE * pHcf; - UINT32 ** ppPortModeTable[GPIO_PORT_MUM]; - UINT32 *pPortModeTable[GPIO_PORT_MUM]; + UINT8 ** ppPortModeTable[GPIO_PORT_MUM]; + UINT8 *pPortModeTable[GPIO_PORT_MUM]; pDrvCtrl = (FT_GPIO_DRVCTRL *)hwMemAlloc(sizeof (FT_GPIO_DRVCTRL)); @@ -397,7 +399,7 @@ LOCAL STATUS vxbFtGpioPinModeSet FT_GPIO_DRVCTRL * pDrvCtrl = pDev->pDrvCtrl; STATUS st = OK; UINT32 level = 0, polar = 0; - + if ((port > GPIO_PORT_B) || (pin >= FT_GPIO_PORT_WIDTH) || (mode > GPIO_MODE_INT)) { GPIO_DBG(GPIO_DBG_ERR, "Parameter is out of range : GPIO port %d, pin %d, mode %d\r\n", port, pin, mode,4,5,6); @@ -410,14 +412,14 @@ LOCAL STATUS vxbFtGpioPinModeSet GPIO_DBG(GPIO_DBG_ERR, "Only port A support interrupt \r\n", 1,2,3,4,5,6); return ERROR; } - + switch(mode) { case GPIO_MODE_NOT_USED: case GPIO_MODE_IN: if (port == GPIO_PORT_A) { - st |= vxbFtGpioPinIntDisable(pDev, pin); + /* st |= */vxbFtGpioPinIntDisable(pDev, pin); st |= vxbFtGpioBitSet(pDrvCtrl, GPIO_SW_DDR_A, pin, GPIO_DIR_IN); st |= vxbFtGpioBitSet(pDrvCtrl, GPIO_INTMASK_A, pin, GPIO_INT_MASK); st |= vxbFtGpioBitSet(pDrvCtrl, GPIO_INTEN_A, pin, GPIO_INT_DIS); @@ -430,7 +432,7 @@ LOCAL STATUS vxbFtGpioPinModeSet case GPIO_MODE_OUT: if (port == GPIO_PORT_A) { - st |= vxbFtGpioPinIntDisable(pDev, pin); + /* st |= */vxbFtGpioPinIntDisable(pDev, pin); st |= vxbFtGpioBitSet(pDrvCtrl, GPIO_SW_DDR_A, pin, GPIO_DIR_OUT); st |= vxbFtGpioBitSet(pDrvCtrl, GPIO_INTMASK_A, pin, GPIO_INT_MASK); st |= vxbFtGpioBitSet(pDrvCtrl, GPIO_INTEN_A, pin, GPIO_INT_DIS); @@ -466,7 +468,7 @@ LOCAL STATUS vxbFtGpioPinModeSet GPIO_DBG(GPIO_DBG_ERR, "Mode set error of port %d pin %d: trigger mode error \r\n", port, pin,3,4,5,6); return ERROR; } - st |= vxbFtGpioPinIntEnable(pDev, pin); + /* st |= */vxbFtGpioPinIntEnable(pDev, pin); st |= vxbFtGpioBitSet(pDrvCtrl, GPIO_SW_DDR_A, pin, GPIO_DIR_IN); st |= vxbFtGpioBitSet(pDrvCtrl, GPIO_INTMASK_A, pin, GPIO_INT_NOT_MASK); st |= vxbFtGpioBitSet(pDrvCtrl, GPIO_INTTYPE_LEVEL_A, pin, level); @@ -477,7 +479,6 @@ LOCAL STATUS vxbFtGpioPinModeSet default: return ERROR; } - if (OK != st) { pDrvCtrl->pinMode[port][pin] = GPIO_MODE_NOT_USED; @@ -679,6 +680,35 @@ exit: return; } +LOCAL void vxbFtGpioShow (VXB_DEVICE_ID pDev, int verbose) +{ + FT_GPIO_DRVCTRL * pDrvCtrl; + + /* check for valid parameter */ + VXB_ASSERT_NONNULL_V (pDev); + + pDrvCtrl = (FT_GPIO_DRVCTRL *) 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) { + int i, j; + printf (" BAR0 @ 0x%08x (memory mapped)\n",pDev->pRegBase[0]); + for (i = 0; i < GPIO_PORT_MUM; ++i) { + printf(" port %c:", i == 0 ? 'A' : 'B'); + for (j = 0; j < FT_GPIO_PORT_WIDTH; ++j) { + printf(" %d", pDrvCtrl->pinMode[i][j]); + } + printf("\n"); + } + } +} + #define FT_GPIO_DEBUD #ifdef FT_GPIO_DEBUD void gpioModeShow(UINT32 gpio) @@ -688,6 +718,9 @@ void gpioModeShow(UINT32 gpio) FT_GPIO_DRVCTRL * pCtrl; pDev = vxbInstByNameFind("ftGpio", gpio); + if (pDev == NULL) { + return; + } pCtrl = pDev->pDrvCtrl; for(i = 0; i < GPIO_PORT_MUM; i++) @@ -706,7 +739,9 @@ void gpioModeSetTest (UINT32 gpio, UINT32 port, UINT32 pin, UINT32 mode) FT_GPIO_DRVCTRL * pCtrl; pDev = vxbInstByNameFind("ftGpio", gpio); - + if (pDev == NULL) { + return; + } pCtrl = pDev->pDrvCtrl; pCtrl->gpioModeSet(pDev, port, pin, mode); @@ -719,7 +754,10 @@ void gpioOutTest (UINT32 gpio, UINT32 port, UINT32 pin, UINT32 val) FT_GPIO_DRVCTRL * pCtrl; pDev = vxbInstByNameFind("ftGpio", gpio); - + if (pDev == NULL) { + return; + } + pCtrl = pDev->pDrvCtrl; pCtrl->gpioOutput(pDev, port, pin, val); @@ -731,7 +769,9 @@ void gpioInTest (UINT32 gpio, UINT32 port, UINT32 pin) FT_GPIO_DRVCTRL * pCtrl; pDev = vxbInstByNameFind("ftGpio", gpio); - + if (pDev == NULL) { + return; + } pCtrl = pDev->pDrvCtrl; printf("input val %d\n", pCtrl->gpioInput(pDev, port, pin)); @@ -752,7 +792,9 @@ void gpioIsrSetTest (UINT32 gpio, UINT32 pin) FT_GPIO_DRVCTRL * pCtrl; pDev = vxbInstByNameFind("ftGpio", gpio); - + if (pDev == NULL) { + return; + } pCtrl = pDev->pDrvCtrl; isrArgTest = pin; diff --git a/vxbFtSpi.c b/vxbFtSpi.c index 170ad48..ada5e1b 100644 --- a/vxbFtSpi.c +++ b/vxbFtSpi.c @@ -1,500 +1,635 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include <../src/hwif/h/vxbus/vxbAccess.h> -#include -#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); -} +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include <../src/hwif/h/vxbus/vxbAccess.h> +#include +#include "vxbFtSpi.h" +#include "ft2000-4.h" + +#define CTRLR0 0x0 +#define CTRLR1 0x4 +#define SSIENR 0x8 +#define MWCR 0xc +#define SER 0x10 +#define BAUDR 0x14 +#define TXFTLR 0x18 +#define RXFTLR 0x1c +#define TXFLR 0x20 +#define RXFLR 0x24 +#define SR 0x28 +#define IMR 0x2c +#define ISR 0x30 +#define DMACR 0x4c +#define DR 0x60 +#define RX_SAMPLE_DLY 0xfc +/* 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 */ + +/* read write macros */ +#define VXB_FT_SPI_REG(pChan, reg) \ + (UINT32 *)((UINT32) ((pChan)->regBase) + (reg)) + +#define VXB_FT_SPI_REG16(pChan, reg) \ + (UINT16 *)((UINT32) ((pChan)->regBase) + (reg)) + +#define VXB_FT_SPI_REG8(pChan, reg) \ + (UINT8 *)((UINT32) ((pChan)->regBase) + (reg)) + +#define VXB_FT_SPI_REG_READ(pChan, reg, result) \ + (result) = vxbRead32 ((pChan)->regHandle, VXB_FT_SPI_REG(pChan, reg)) + +#define VXB_FT_SPI_REG_WRITE(pChan, reg, data) \ + vxbWrite32 ((pChan)->regHandle, VXB_FT_SPI_REG(pChan, reg), (data)) + +#define VXB_FT_SPI_REG_BIT_SET(pChan, reg, data) \ + VXB_FT_SPI_REG_WRITE (pChan, reg, \ + vxbRead32 ((pChan)->regHandle, VXB_FT_SPI_REG(pChan, reg)) | (data)) + +#define VXB_FT_SPI_REG_BIT_CLR(pChan, reg, data) \ + VXB_FT_SPI_REG_WRITE (pChan, reg, \ + vxbRead32 ((pChan)->regHandle, VXB_FT_SPI_REG(pChan, reg)) & (~(data))) + +/* 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 void vxbFtSpiCtrlInit (VXB_DEVICE_ID pDev); + +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, "clkFreq", HCF_RES_INT,(void *) &pDrvCtrl->clkFreq) != OK) { + pDrvCtrl->clkFreq = FT2000_SPI_CLK; + } + + if (devResourceGet (pHcf, "speed", HCF_RES_INT,(void *) &pDrvCtrl->speed) != OK) { + pDrvCtrl->speed = 1000000; + } + + if (devResourceGet (pHcf, "mode", HCF_RES_INT,(void *) &pDrvCtrl->mode) != OK) { + pDrvCtrl->mode = 0; + } + + if (devResourceGet (pHcf, "dataWidth", HCF_RES_INT,(void *) &pDrvCtrl->dataWidth) != OK) { + pDrvCtrl->dataWidth = 8; + } + + if (devResourceGet (pHcf, "spiDevNum", HCF_RES_INT, (void *) &pDrvCtrl->spiDevNum) != OK) { + pDrvCtrl->spiDevNum = 0; + } + pDrvCtrl->cs = 0; + + vxbFtSpiCtrlInit(pDev); + + 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)); +} + +/* + * vxbFtSpiCtrlInit - SPI controller initialization + * + * This routine performs the SPI controller initialization. + * + * RETURNS: N/A + * + * ERRNO: N/A + */ +LOCAL void vxbFtSpiCtrlInit(VXB_DEVICE_ID pDev) +{ + FT_SPI_CTRL *pDrvCtrl; + UINT32 regval, clkDiv; + + pDrvCtrl = (FT_SPI_CTRL *) pDev->pDrvCtrl; + + /* disable the controller */ + VXB_FT_SPI_REG_WRITE(pDrvCtrl, SSIENR, 0x0); + + /* CTRLR0 */ + VXB_FT_SPI_REG_READ(pDrvCtrl, CTRLR0, regval); + + /* normal mode */ + regval &= ~(1 << 11); + + /* data width */ + regval &= ~(0xf); + regval |= (pDrvCtrl->dataWidth - 1) & 0xf; + + /* + * spi mode mapping: + * + * CPOL CPHA + * 0 0 mode 0 + * 0 1 mode 1 + * 1 0 mode 2 + * 1 1 mode 3 + */ + if (pDrvCtrl->mode & 0x1) { + regval |= (1 << 6); /* CPHA */ + } else { + regval &= ~(1 << 6); + } + if (pDrvCtrl->mode & 0x2) { + regval |= (1 << 7); + } else { + regval &= ~(1 << 7); + } + /* rx & tx */ + regval &= ~(0x3 << 8); + + /* slv_oe = 1 (slave disable) */ + regval &= ~(1 << 10); + + VXB_FT_SPI_REG_WRITE(pDrvCtrl, CTRLR0, regval); + + VXB_FT_SPI_REG_WRITE(pDrvCtrl, CTRLR1, 0); + + /* disable DMA */ + VXB_FT_SPI_REG_WRITE(pDrvCtrl, DMACR, 0); + + /* baudrate */ + clkDiv = pDrvCtrl->clkFreq / pDrvCtrl->speed; + if (clkDiv < 2) { + clkDiv = 2; + } + + if (clkDiv > 65534) { + clkDiv = 65534; + } + + VXB_FT_SPI_REG_WRITE(pDrvCtrl, BAUDR, clkDiv); + + VXB_FT_SPI_REG_WRITE(pDrvCtrl, RX_SAMPLE_DLY, 0); + + VXB_FT_SPI_REG_WRITE(pDrvCtrl, RXFTLR, 0); + VXB_FT_SPI_REG_WRITE(pDrvCtrl, TXFTLR, 0); + + VXB_FT_SPI_REG_BIT_CLR(pDrvCtrl, IMR, 0x1f); /* disable all interrupts */ + regval = (1 << pDrvCtrl->cs); + VXB_FT_SPI_REG_BIT_SET(pDrvCtrl, SER, regval); +} + +/* + * 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 alignSize; + FT_SPI_CTRL * pDrvCtrl; + int i, len; + UINT8 dummy8; + UINT16 dummy16, *dptr; + /* 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; + } + + if ( pSpiDev->devInfo->chipSelect >= 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); + } + + if ((pSpiDev->devInfo->devFreq != pDrvCtrl->speed) || (pSpiDev->devInfo->bitWidth != pDrvCtrl->dataWidth) + || (pSpiDev->devInfo->mode != pDrvCtrl->mode) || (pSpiDev->devInfo->chipSelect != pDrvCtrl->cs)) { + pDrvCtrl->mode = pSpiDev->devInfo->mode; + pDrvCtrl->speed = pSpiDev->devInfo->devFreq; + pDrvCtrl->dataWidth = pSpiDev->devInfo->bitWidth; + pDrvCtrl->cs = pSpiDev->devInfo->chipSelect; + vxbFtSpiCtrlInit(pDev); + } + + VXB_FT_SPI_REG_WRITE(pDrvCtrl, SSIENR, 0x1); + if (pPkg->txLen > 0) { + if (alignSize == 1) { + for (i = 0;i < pPkg->txLen; ++i) { + vxbWrite8(pDrvCtrl->regHandle, VXB_FT_SPI_REG8(pDrvCtrl, DR), pPkg->txBuf[i]); + dummy8 = vxbRead8(pDrvCtrl->regHandle, VXB_FT_SPI_REG8(pDrvCtrl, DR)); + (void)dummy8; + } + } else { + dptr = (UINT16 *)(pPkg->txBuf); + len = pPkg->txLen >> 1; + for (i = 0; i < len; ++i) { + vxbWrite16(pDrvCtrl->regHandle, VXB_FT_SPI_REG16(pDrvCtrl, DR), dptr[i]); + dummy16 = vxbRead16(pDrvCtrl->regHandle, VXB_FT_SPI_REG16(pDrvCtrl, DR)); + (void)dummy16; + } + } + } + + if (pPkg->rxLen > 0) { + if (alignSize == 1) { + dummy8 = 0x0; + for (i = 0;i < pPkg->rxLen; ++i) { + vxbWrite8(pDrvCtrl->regHandle, VXB_FT_SPI_REG8(pDrvCtrl, DR), dummy8); + pPkg->rxBuf[i] = vxbRead8(pDrvCtrl->regHandle, VXB_FT_SPI_REG8(pDrvCtrl, DR)); + } + } else { + dummy16 = 0; + dptr = (UINT16 *)(pPkg->rxBuf); + len = pPkg->rxLen >> 1; + for (i = 0; i < len; ++i) { + vxbWrite16(pDrvCtrl->regHandle, VXB_FT_SPI_REG16(pDrvCtrl, DR), dummy16); + dptr[i] = vxbRead16(pDrvCtrl->regHandle, VXB_FT_SPI_REG16(pDrvCtrl, DR)); + } + } + + } + VXB_FT_SPI_REG_WRITE(pDrvCtrl, SSIENR, 0x0); + + printf(" xfer : tx %d bytes, rx %d bytes\n",pPkg->txLen, pPkg->rxLen); + + 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 (" clkFreq : %u\n", pDrvCtrl->clkFreq); + printf (" speed : %u\n", pDrvCtrl->speed); + printf (" bitWidth : %u\n", pDrvCtrl->dataWidth); + printf (" mode : %u\n", pDrvCtrl->mode); + 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); +} diff --git a/vxbFtSpi.h b/vxbFtSpi.h index 269c71d..0980ae5 100644 --- a/vxbFtSpi.h +++ b/vxbFtSpi.h @@ -12,19 +12,20 @@ #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 clkFreq; + UINT32 speed; + int mode; + int dataWidth; + int cs; + UINT32 length; 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; diff --git a/vxbSm2130SpiDev.c b/vxbSm2130SpiDev.c new file mode 100644 index 0000000..c1ab7b2 --- /dev/null +++ b/vxbSm2130SpiDev.c @@ -0,0 +1,302 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "vxbSm2130SpiDev.h" +#include + +/* locals */ +LOCAL void sm2130SpiDevShow(VXB_DEVICE_ID pDev, int verbose); +LOCAL INT32 spiDevRead(VXB_DEVICE_ID pDev, UINT8 cmd); +LOCAL STATUS spiDevWrite(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 */ + +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, //sm2130Probe, /* devProbe */ + NULL, /* pParamDefaults */ + }, +}; +/* + * + * 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; + + /* 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->read = spiDevRead; + pDrvCtrl->write = spiDevWrite; + + 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); +} + +/* + * 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; + + /* Check for vaild parameter */ + VXB_ASSERT_NONNULL_V(pDev); + + pDrvCtrl = (SM2130_SPI_DEV *)pDev->pDrvCtrl; +} + +/* + * 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) +{ + 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) { + + } + + return; +} + +/* + * spiDevWrite - 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 spiDevWrite(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)); +} + +/* + * spiDevRead - read register routine + * + * This is the SPI flash status /config register read out routine. + * + * RETURNS: status register value. + * + * ERRNO: N/A + */ +LOCAL INT32 spiDevRead(VXB_DEVICE_ID pDev, UINT8 cmd) +{ + SPI_TRANSFER transInfo = {NULL, NULL, 0, 0, 0}; + UINT16 buffer = 0xffff; + + /* check if the pDev pointer is valid */ + + VXB_ASSERT(pDev != NULL, ERROR) + + transInfo.txBuf = &cmd; + transInfo.txLen = 1; + transInfo.rxBuf = (UINT8 *)&buffer; + transInfo.rxLen = 2; + + if (vxbSpiTransfer(pDev, &transInfo) != OK) + return ERROR; + else + return (buffer); +} + + +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); +} diff --git a/vxbSm2130SpiDev.h b/vxbSm2130SpiDev.h new file mode 100644 index 0000000..ca55ee5 --- /dev/null +++ b/vxbSm2130SpiDev.h @@ -0,0 +1,23 @@ +#ifndef __VXB_SM2130_SPI_DEV_H +#define __VXB_SM2130_SPI_DEV_H + +#define SPI_DEV_SM2130 "SM2130" + +#define SPI_DEV_MUTEX_OPT \ + (SEM_Q_PRIORITY | SEM_DELETE_SAFE | SEM_INVERSION_SAFE) + +typedef struct _spi_1553b_drv_ctrl { + VXB_DEVICE_ID pDev; + + int cs; + int mode; + unsigned int freq; + + INT32 (*read)(VXB_DEVICE_ID pDev, UINT8 cmd); + STATUS (*write)(VXB_DEVICE_ID pDev, UINT8 cmd, UINT16 var); + + SEM_ID muteSem; /* operation semaphore */ + VXB_SPI_MAST_SPEC *specialInfo; +} SM2130_SPI_DEV; + +#endif