|
|
|
/* vxbFtGpioCtrl.c - Driver for GPIO controller */
|
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
* This program is OPEN SOURCE software: you can redistribute it and/or modify it;
|
|
|
|
* This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY;
|
|
|
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* includes */
|
|
|
|
|
|
|
|
#include <vxWorks.h>
|
|
|
|
#include <vsbConfig.h>
|
|
|
|
#include <intLib.h>
|
|
|
|
#include <errnoLib.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <sioLib.h>
|
|
|
|
#include <ioLib.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <logLib.h>
|
|
|
|
#include <hwif/util/hwMemLib.h>
|
|
|
|
#include <hwif/util/vxbParamSys.h>
|
|
|
|
#include <hwif/vxbus/vxbIntrCtlr.h>
|
|
|
|
#include <hwif/vxbus/vxBus.h>
|
|
|
|
#include <vxbFtGpio.h>
|
|
|
|
|
|
|
|
#define GPIO_DBG_ON
|
|
|
|
#ifdef GPIO_DBG_ON
|
|
|
|
#define GPIO_DBG_IRQ 0x00000001
|
|
|
|
#define GPIO_DBG_RW 0x00000002
|
|
|
|
#define GPIO_DBG_ERR 0x00000004
|
|
|
|
#define GPIO_DBG_ALL 0xffffffff
|
|
|
|
#define GPIO_DBG_OFF 0x00000000
|
|
|
|
LOCAL UINT32 gpioDbgMask = GPIO_DBG_ALL;
|
|
|
|
IMPORT FUNCPTR _func_logMsg;
|
|
|
|
|
|
|
|
#define GPIO_DBG(mask, string, a, b, c, d, e, f) \
|
|
|
|
if ((gpioDbgMask & mask) || (mask == GPIO_DBG_ALL)) \
|
|
|
|
if (_func_logMsg != NULL) \
|
|
|
|
(* _func_logMsg)(string, a, b, c, d, e, f)
|
|
|
|
#else
|
|
|
|
#define GPIO_DBG(mask, string, a, b, c, d, e, f)
|
|
|
|
#endif /* GPIO_DBG_ON */
|
|
|
|
|
|
|
|
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);
|
|
|
|
LOCAL STATUS vxbFtGpioPinOuput (VXB_DEVICE_ID pDev, UINT32 port, UINT32 pin,
|
|
|
|
UINT32 value);
|
|
|
|
LOCAL STATUS vxbFtGpioISRSet (VXB_DEVICE_ID pDev, UINT32 pin,
|
|
|
|
VOIDFUNCPTR pIsr, void * pArg);
|
|
|
|
LOCAL void vxbFtGpioISR (FT_GPIO_DRVCTRL * pDrvCtrl);
|
|
|
|
|
|
|
|
LOCAL struct drvBusFuncs vxbFtGpioDrvFuncs =
|
|
|
|
{
|
|
|
|
vxbFtGpioInstInit, /* devInstanceInit */
|
|
|
|
vxbFtGpioInstInit2, /* devInstanceInit2 */
|
|
|
|
vxbFtGpioInstConnect /* devConnect */
|
|
|
|
};
|
|
|
|
|
|
|
|
LOCAL device_method_t vxbFtGpioDrv_methods[] =
|
|
|
|
{
|
|
|
|
DEVMETHOD (busDevShow, vxbFtGpioShow),
|
|
|
|
DEVMETHOD_END
|
|
|
|
};
|
|
|
|
|
|
|
|
/* FT2000/4 GPIO VxBus registration info */
|
|
|
|
|
|
|
|
LOCAL struct vxbDevRegInfo vxbFtGpioDrvRegistration =
|
|
|
|
{
|
|
|
|
NULL, /* pNext */
|
|
|
|
VXB_DEVID_DEVICE, /* devID */
|
|
|
|
VXB_BUSID_PLB, /* busID = PLB */
|
|
|
|
VXB_VER_4_0_0, /* busVer */
|
|
|
|
"ftGpio", /* drvName */
|
|
|
|
&vxbFtGpioDrvFuncs, /* pDrvBusFuncs */
|
|
|
|
&vxbFtGpioDrv_methods[0], /* pMethods */
|
|
|
|
NULL /* devProbe */
|
|
|
|
};
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
*
|
|
|
|
* vxbFtGpioDrvRegister - register FT2000/4 GPIO driver
|
|
|
|
*
|
|
|
|
* This routine registers the FT2000/4 GPIO driver with the vxBus subsystem.
|
|
|
|
*
|
|
|
|
* RETURNS: N/A
|
|
|
|
*
|
|
|
|
* ERRNO: N/A
|
|
|
|
*/
|
|
|
|
|
|
|
|
void vxbFtGpioDrvRegister (void)
|
|
|
|
{
|
|
|
|
/* call the vxBus routine to register the GPIO driver */
|
|
|
|
|
|
|
|
vxbDevRegister (&vxbFtGpioDrvRegistration);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
*
|
|
|
|
* vxbFtGpioInstInit - first level initialization routine of GPIO modules
|
|
|
|
*
|
|
|
|
* This is the function called to perform the first level initialization of
|
|
|
|
* the six FT2000/4 GPIO modules.
|
|
|
|
*
|
|
|
|
* NOTE:
|
|
|
|
*
|
|
|
|
* This routine is called early during system initialization, and
|
|
|
|
* *MUST NOT* make calls to OS facilities such as memory allocation
|
|
|
|
* and I/O.
|
|
|
|
*
|
|
|
|
* RETURNS: N/A
|
|
|
|
*
|
|
|
|
* ERRNO: N/A
|
|
|
|
*
|
|
|
|
* \NOMANUAL
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
LOCAL void vxbFtGpioInstInit
|
|
|
|
(
|
|
|
|
VXB_DEVICE_ID pInst
|
|
|
|
)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
*
|
|
|
|
* vxbFtGpioInstInit2 - second level initialization routine of GPIO modules
|
|
|
|
*
|
|
|
|
* This routine performs the second level initialization of the GPIO modules.
|
|
|
|
*
|
|
|
|
* This routine is called later during system initialization. OS features
|
|
|
|
* such as memory allocation are available at this time.
|
|
|
|
*
|
|
|
|
* RETURNS: N/A
|
|
|
|
*
|
|
|
|
* ERRNO: N/A
|
|
|
|
*
|
|
|
|
* \NOMANUAL
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
LOCAL void vxbFtGpioInstInit2
|
|
|
|
(
|
|
|
|
VXB_DEVICE_ID pInst
|
|
|
|
)
|
|
|
|
{
|
|
|
|
STATUS st[GPIO_PORT_MUM];
|
|
|
|
FT_GPIO_DRVCTRL * pDrvCtrl;
|
|
|
|
UINT32 port = 0, pin = 0;
|
|
|
|
HCF_DEVICE * pHcf;
|
|
|
|
UINT8 ** ppPortModeTable[GPIO_PORT_MUM];
|
|
|
|
UINT8 *pPortModeTable[GPIO_PORT_MUM];
|
|
|
|
|
|
|
|
pDrvCtrl = (FT_GPIO_DRVCTRL *)hwMemAlloc(sizeof (FT_GPIO_DRVCTRL));
|
|
|
|
|
|
|
|
if (pDrvCtrl == NULL)
|
|
|
|
{
|
|
|
|
GPIO_DBG(GPIO_DBG_ERR, "vxbFtGpioInstInit: pDrvCtrl alloc failed\r\n.",1,2,3,4,5,6);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
pInst->pDrvCtrl = pDrvCtrl;
|
|
|
|
pDrvCtrl->pInst = pInst;
|
|
|
|
|
|
|
|
/* map register base */
|
|
|
|
|
|
|
|
if (vxbRegMap(pInst, 0, &pDrvCtrl->gpioHandle) == ERROR)
|
|
|
|
{
|
|
|
|
GPIO_DBG (GPIO_DBG_ERR, "vxbFtGpioInstInit: vxbRegMap GPIO ERROR\n", 1, 2, 3, 4, 5, 6);
|
|
|
|
#ifndef _VXBUS_BASIC_HWMEMLIB
|
|
|
|
hwMemFree ((char *)pDrvCtrl);
|
|
|
|
#endif /* _VXBUS_BASIC_HWMEMLIB */
|
|
|
|
|
|
|
|
pInst->pDrvCtrl = NULL;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
pDrvCtrl->gpioModeSet = vxbFtGpioPinModeSet;
|
|
|
|
pDrvCtrl->gpioInput = vxbFtGpioPinInput;
|
|
|
|
pDrvCtrl->gpioOutput = vxbFtGpioPinOuput;
|
|
|
|
pDrvCtrl->gpioISRSet = vxbFtGpioISRSet;
|
|
|
|
pDrvCtrl->intEnabled = FALSE;
|
|
|
|
|
|
|
|
/* clear all interrupt */
|
|
|
|
GPIO_WRITE_4 (pDrvCtrl, GPIO_INTEN_A, 0);
|
|
|
|
|
|
|
|
ppPortModeTable[0] = &pPortModeTable[0];
|
|
|
|
ppPortModeTable[1] = &pPortModeTable[1];
|
|
|
|
|
|
|
|
pHcf = (struct hcfDevice *) hcfDeviceGet (pInst);
|
|
|
|
|
|
|
|
if (pHcf == NULL)
|
|
|
|
{
|
|
|
|
#ifndef _VXBUS_BASIC_HWMEMLIB
|
|
|
|
hwMemFree ((char *)pDrvCtrl);
|
|
|
|
#endif /* _VXBUS_BASIC_HWMEMLIB */
|
|
|
|
|
|
|
|
pInst->pDrvCtrl = NULL;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (devResourceGet (pHcf, "trigger", HCF_RES_INT,(void *) &pDrvCtrl->triggerMode) != OK)
|
|
|
|
{
|
|
|
|
pDrvCtrl->triggerMode = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
st[0] = devResourceGet (pHcf, "portAModeTable", HCF_RES_ADDR, (void **)ppPortModeTable[0]);
|
|
|
|
st[1] = devResourceGet (pHcf, "portBModeTable", HCF_RES_ADDR, (void **)ppPortModeTable[1]);
|
|
|
|
|
|
|
|
for(port = 0; port < GPIO_PORT_MUM; port++)
|
|
|
|
{
|
|
|
|
for(pin = 0; pin < FT_GPIO_PORT_WIDTH; pin ++)
|
|
|
|
{
|
|
|
|
if(st[port] == OK)
|
|
|
|
vxbFtGpioPinModeSet(pInst, port, pin, *(pPortModeTable[port] + pin));
|
|
|
|
else
|
|
|
|
vxbFtGpioPinModeSet(pInst, port, pin, GPIO_MODE_NOT_USED);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
*
|
|
|
|
* vxbFtInstConnect - third level initialization routine of GPIO modules
|
|
|
|
*
|
|
|
|
* This is the function called to perform the third level initialization of
|
|
|
|
* the GPIO modules.
|
|
|
|
*
|
|
|
|
* RETURNS: N/A
|
|
|
|
*
|
|
|
|
* ERRNO: N/A
|
|
|
|
*
|
|
|
|
* \NOMANUAL
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
LOCAL void vxbFtGpioInstConnect
|
|
|
|
(
|
|
|
|
VXB_DEVICE_ID pInst
|
|
|
|
)
|
|
|
|
{
|
|
|
|
/* nothing is done here */
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
LOCAL STATUS vxbFtGpioBitSet(FT_GPIO_DRVCTRL * pDrvCtrl, UINT32 reg, UINT32 pin, UINT32 bit)
|
|
|
|
{
|
|
|
|
UINT32 value=0;
|
|
|
|
|
|
|
|
if(pin >= FT_GPIO_PORT_WIDTH)
|
|
|
|
{
|
|
|
|
GPIO_DBG(GPIO_DBG_ERR, "[reg 0x%x]Bad pin %d! Only support pin: 0~%d \r\n", reg, pin, FT_GPIO_PORT_WIDTH - 1,4,5,6);
|
|
|
|
return ERROR;
|
|
|
|
}
|
|
|
|
if((bit!=0)&&(bit!=1))
|
|
|
|
{
|
|
|
|
GPIO_DBG(GPIO_DBG_ERR, "[reg 0x%x]Bad bit value %d! \r\n", reg, bit,3,4,5,6);
|
|
|
|
return ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
value = GPIO_READ_4(pDrvCtrl, reg);
|
|
|
|
|
|
|
|
switch(bit)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
value &= ~(1<<pin);
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
value |= (1<<pin);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
GPIO_WRITE_4(pDrvCtrl, reg, value);
|
|
|
|
|
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
*
|
|
|
|
* vxbFtGpioPinIntEnable - enable interrupt of a pin
|
|
|
|
*
|
|
|
|
* the function enable interrupt of a pin.
|
|
|
|
*
|
|
|
|
* RETURNS: OK or ERROR
|
|
|
|
*
|
|
|
|
* ERRNO: N/A
|
|
|
|
*
|
|
|
|
* \NOMANUAL
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
LOCAL STATUS vxbFtGpioPinIntEnable
|
|
|
|
(
|
|
|
|
VXB_DEVICE_ID pDev,
|
|
|
|
UINT32 pin
|
|
|
|
)
|
|
|
|
{
|
|
|
|
FT_GPIO_DRVCTRL * pDrvCtrl = pDev->pDrvCtrl;
|
|
|
|
STATUS st = OK;
|
|
|
|
|
|
|
|
/*all pin of portA use a common interrupt number*/
|
|
|
|
if(pDrvCtrl->intEnabled == FALSE)
|
|
|
|
{
|
|
|
|
st |= vxbIntConnect(pDev, 0, vxbFtGpioISR, pDrvCtrl);
|
|
|
|
st |= vxbIntEnable(pDev, 0, vxbFtGpioISR, pDrvCtrl);
|
|
|
|
if (OK == st)
|
|
|
|
pDrvCtrl->intEnabled = TRUE;
|
|
|
|
else
|
|
|
|
GPIO_DBG(GPIO_DBG_ERR, "Failed to enable port 0 pin %d interrupt\r\n", pin, 2,3,4,5,6);
|
|
|
|
}
|
|
|
|
return st;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
*
|
|
|
|
* vxbFtGpioPinIntDisable - disable interrupt of a pin
|
|
|
|
*
|
|
|
|
* the function disable interrupt of a pin.
|
|
|
|
*
|
|
|
|
* RETURNS: OK or ERROR
|
|
|
|
*
|
|
|
|
* ERRNO: N/A
|
|
|
|
*
|
|
|
|
* \NOMANUAL
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
LOCAL STATUS vxbFtGpioPinIntDisable
|
|
|
|
(
|
|
|
|
VXB_DEVICE_ID pDev,
|
|
|
|
UINT32 pin
|
|
|
|
)
|
|
|
|
{
|
|
|
|
FT_GPIO_DRVCTRL * pDrvCtrl = pDev->pDrvCtrl;
|
|
|
|
STATUS st = OK;
|
|
|
|
STATUS disableFlag = TRUE;
|
|
|
|
UINT32 i;
|
|
|
|
|
|
|
|
/*all pin of a portA use a common interrupt number,
|
|
|
|
so only if all of pins of portA are not used as interrupt pin,
|
|
|
|
we need to disable the interrupt*/
|
|
|
|
if(pDrvCtrl->intEnabled == TRUE)
|
|
|
|
{
|
|
|
|
for(i = 0; i < FT_GPIO_PORT_WIDTH; i++)
|
|
|
|
{
|
|
|
|
if((pDrvCtrl->pinMode[0][i] == GPIO_MODE_INT) && (i != pin))
|
|
|
|
{
|
|
|
|
/*have another pin that used as interrupt pin, so don't need to disable interrupt */
|
|
|
|
disableFlag = FALSE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(disableFlag == TRUE)
|
|
|
|
{
|
|
|
|
st |= vxbIntDisable(pDev, 0, vxbFtGpioISR, pDrvCtrl);
|
|
|
|
st |= vxbIntDisconnect(pDev, 0, vxbFtGpioISR, pDrvCtrl);
|
|
|
|
if (OK == st)
|
|
|
|
pDrvCtrl->intEnabled = FALSE;
|
|
|
|
else
|
|
|
|
GPIO_DBG(GPIO_DBG_ERR, "Failed to disable port 0 pin %d interrupt\r\n", pin, 2,3,4,5,6);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return st;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
*
|
|
|
|
* vxbFtGpioPinModeSet - set mode of a pin
|
|
|
|
*
|
|
|
|
* the function set mode of a pin.
|
|
|
|
*
|
|
|
|
* RETURNS: OK or ERROR
|
|
|
|
*
|
|
|
|
* ERRNO: N/A
|
|
|
|
*
|
|
|
|
* \NOMANUAL
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
LOCAL STATUS vxbFtGpioPinModeSet
|
|
|
|
(
|
|
|
|
VXB_DEVICE_ID pDev,
|
|
|
|
UINT32 port,
|
|
|
|
UINT32 pin,
|
|
|
|
UINT32 mode
|
|
|
|
)
|
|
|
|
{
|
|
|
|
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);
|
|
|
|
return ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* only port A support interrupt */
|
|
|
|
if((mode == GPIO_MODE_INT) && (port != GPIO_PORT_A))
|
|
|
|
{
|
|
|
|
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 |= 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);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
st |= vxbFtGpioBitSet(pDrvCtrl, GPIO_SW_DDR_B, pin, GPIO_DIR_IN);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case GPIO_MODE_OUT:
|
|
|
|
if (port == GPIO_PORT_A)
|
|
|
|
{
|
|
|
|
/* 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);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
st |= vxbFtGpioBitSet(pDrvCtrl, GPIO_SW_DDR_B, pin, GPIO_DIR_OUT);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case GPIO_MODE_INT:
|
|
|
|
if(port == GPIO_PORT_A)
|
|
|
|
{
|
|
|
|
switch(pDrvCtrl->triggerMode)
|
|
|
|
{
|
|
|
|
case VXB_INTR_TRIG_FALLING_EDGE:
|
|
|
|
level = GPIO_INT_TYPE_EDGE;
|
|
|
|
polar = GPIO_INT_POL_LOW_DOWN;
|
|
|
|
break;
|
|
|
|
case VXB_INTR_TRIG_RISING_EDGE:
|
|
|
|
level = GPIO_INT_TYPE_EDGE;
|
|
|
|
polar = GPIO_INT_POL_HIGH_UP;
|
|
|
|
break;
|
|
|
|
case VXB_INTR_TRIG_ACTIVE_LOW:
|
|
|
|
level = GPIO_INT_TYPE_LEVEL;
|
|
|
|
polar = GPIO_INT_POL_LOW_DOWN;
|
|
|
|
break;
|
|
|
|
case VXB_INTR_TRIG_ACTIVE_HIGH:
|
|
|
|
level = GPIO_INT_TYPE_LEVEL;
|
|
|
|
polar = GPIO_INT_POL_HIGH_UP;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
pDrvCtrl->pinMode[port][pin] = GPIO_MODE_NOT_USED;
|
|
|
|
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 |= 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);
|
|
|
|
st |= vxbFtGpioBitSet(pDrvCtrl, GPIO_INT_POLARITY_A, pin, polar);
|
|
|
|
st |= vxbFtGpioBitSet(pDrvCtrl, GPIO_INTEN_A, pin, GPIO_INT_ENA);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return ERROR;
|
|
|
|
}
|
|
|
|
if (OK != st)
|
|
|
|
{
|
|
|
|
pDrvCtrl->pinMode[port][pin] = GPIO_MODE_NOT_USED;
|
|
|
|
GPIO_DBG(GPIO_DBG_ERR, "Mode set error of port %d pin %d\r\n", port, pin,3,4,5,6);
|
|
|
|
return ERROR;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pDrvCtrl->pinMode[port][pin] = mode;
|
|
|
|
}
|
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
*
|
|
|
|
* vxbFtGpioPinInput - gpio pin input value
|
|
|
|
*
|
|
|
|
* The function return value of specified intput pin.
|
|
|
|
*
|
|
|
|
* RETURNS: input value
|
|
|
|
*
|
|
|
|
* ERRNO: N/A
|
|
|
|
*
|
|
|
|
* \NOMANUAL
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
LOCAL UINT32 vxbFtGpioPinInput
|
|
|
|
(
|
|
|
|
VXB_DEVICE_ID pDev,
|
|
|
|
UINT32 port,
|
|
|
|
UINT32 pin
|
|
|
|
)
|
|
|
|
{
|
|
|
|
FT_GPIO_DRVCTRL * pDrvCtrl = pDev->pDrvCtrl;
|
|
|
|
|
|
|
|
if ((port > GPIO_PORT_B) || (pin >= FT_GPIO_PORT_WIDTH))
|
|
|
|
{
|
|
|
|
GPIO_DBG(GPIO_DBG_ERR, "Parameter is out of range :GPIO port %d, pin %d \r\n", port, pin,3,4,5,6);
|
|
|
|
return (UINT32)ERROR;
|
|
|
|
}
|
|
|
|
if (pDrvCtrl->pinMode[port][pin] != GPIO_MODE_IN)
|
|
|
|
{
|
|
|
|
GPIO_DBG(GPIO_DBG_ERR, "port %d pin %d is not in input mode\r\n",port, pin,3,4,5,6);
|
|
|
|
return (UINT32)ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( port == GPIO_PORT_A)
|
|
|
|
return ((GPIO_READ_4(pDrvCtrl, GPIO_EXT_A) >> pin) & 1);
|
|
|
|
else
|
|
|
|
return ((GPIO_READ_4(pDrvCtrl, GPIO_EXT_B) >> pin) & 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
*
|
|
|
|
* vxbFtGpioPinOuput - output value to gpio pin
|
|
|
|
*
|
|
|
|
* Write value to the specified pin.
|
|
|
|
*
|
|
|
|
* RETURNS: OK or ERROR if the pin is invalid.
|
|
|
|
*
|
|
|
|
* ERRNO: N/A
|
|
|
|
*
|
|
|
|
* \NOMANUAL
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
LOCAL STATUS vxbFtGpioPinOuput
|
|
|
|
(
|
|
|
|
VXB_DEVICE_ID pDev,
|
|
|
|
UINT32 port,
|
|
|
|
UINT32 pin,
|
|
|
|
UINT32 value
|
|
|
|
)
|
|
|
|
{
|
|
|
|
FT_GPIO_DRVCTRL * pDrvCtrl = pDev->pDrvCtrl;
|
|
|
|
|
|
|
|
if ((port > GPIO_PORT_B) || (pin >= FT_GPIO_PORT_WIDTH))
|
|
|
|
{
|
|
|
|
GPIO_DBG(GPIO_DBG_ERR, "Parameter is out of range :GPIO port %d, pin %d \r\n", port, pin,3,4,5,6);
|
|
|
|
return ERROR;
|
|
|
|
}
|
|
|
|
if (pDrvCtrl->pinMode[port][pin] != GPIO_MODE_OUT)
|
|
|
|
{
|
|
|
|
GPIO_DBG(GPIO_DBG_ERR, "port %d pin %d is not in output mode\r\n",port, pin,3,4,5,6);
|
|
|
|
return ERROR;
|
|
|
|
}
|
|
|
|
if((value!=0)&&(value!=1))
|
|
|
|
{
|
|
|
|
GPIO_DBG(GPIO_DBG_ERR, "Bad pin value %d! Only support value: 0,1 \r\n", value,2,3,4,5,6);
|
|
|
|
return ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (port == GPIO_PORT_A)
|
|
|
|
vxbFtGpioBitSet(pDrvCtrl, GPIO_SW_DR_A, pin, value);
|
|
|
|
else
|
|
|
|
vxbFtGpioBitSet(pDrvCtrl, GPIO_SW_DR_B, pin, value);
|
|
|
|
|
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
*
|
|
|
|
* vxbFtGpioISRSet - set a function to be called on the gpio interrupt
|
|
|
|
*
|
|
|
|
* This function is called to set a function which can be called when
|
|
|
|
* the gpio interrupt occurs.
|
|
|
|
*
|
|
|
|
* RETURNS: OK or ERROR if the pin is invalid.
|
|
|
|
*
|
|
|
|
* ERRNO: N/A
|
|
|
|
*
|
|
|
|
* \NOMANUAL
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
LOCAL STATUS vxbFtGpioISRSet
|
|
|
|
(
|
|
|
|
VXB_DEVICE_ID pDev,
|
|
|
|
UINT32 pin,
|
|
|
|
VOIDFUNCPTR pIsr, /* ISR */
|
|
|
|
void * pArg /* parameter */
|
|
|
|
)
|
|
|
|
{
|
|
|
|
FT_GPIO_DRVCTRL * pDrvCtrl = pDev->pDrvCtrl;
|
|
|
|
|
|
|
|
if (pin >= FT_GPIO_PORT_WIDTH)
|
|
|
|
{
|
|
|
|
GPIO_DBG(GPIO_DBG_ERR, "Parameter is out of range :GPIO pin %d \r\n", pin, 2,3,4,5,6);
|
|
|
|
return ERROR;
|
|
|
|
}
|
|
|
|
if (pDrvCtrl->pinMode[0][pin] != GPIO_MODE_INT)
|
|
|
|
{
|
|
|
|
GPIO_DBG(GPIO_DBG_ERR, "port 0 pin %d is not in interrupt mode\r\n",pin,2,3,4,5,6);
|
|
|
|
return ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
pDrvCtrl->isrTable[pin].pIsr = pIsr;
|
|
|
|
pDrvCtrl->isrTable[pin].pArg = pArg;
|
|
|
|
|
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
*
|
|
|
|
* vxbFtGpioISR - interrupt level processing for gpio module
|
|
|
|
*
|
|
|
|
* This routine handles gpio interrupts. It acknowledges the interrupt and
|
|
|
|
* calls the routine installed by vxbFtGpioISRSet().
|
|
|
|
*
|
|
|
|
* RETURNS: N/A
|
|
|
|
*
|
|
|
|
* ERRNO: N/A
|
|
|
|
*
|
|
|
|
* \NOMANUAL
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
LOCAL void vxbFtGpioISR
|
|
|
|
(
|
|
|
|
FT_GPIO_DRVCTRL * pDrvCtrl
|
|
|
|
)
|
|
|
|
{
|
|
|
|
UINT32 val;
|
|
|
|
UINT32 ix;
|
|
|
|
|
|
|
|
/* read interrupt flags */
|
|
|
|
|
|
|
|
val = GPIO_READ_4 (pDrvCtrl, GPIO_INTSTATUS_A);
|
|
|
|
|
|
|
|
if (val == 0)
|
|
|
|
{
|
|
|
|
GPIO_DBG(GPIO_DBG_ERR, "vxFtGpioISR: it's not a gpio interrupt. \r\n.",
|
|
|
|
1,2,3,4,5,6);
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (ix = 0; ix < FT_GPIO_PORT_WIDTH; ix++)
|
|
|
|
{
|
|
|
|
UINT32 bit = 1 << ix;
|
|
|
|
if (val & bit)
|
|
|
|
{
|
|
|
|
if (pDrvCtrl->isrTable[ix].pIsr != NULL)
|
|
|
|
{
|
|
|
|
pDrvCtrl->isrTable[ix].pIsr(pDrvCtrl->isrTable[ix].pArg);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* suspicious int */
|
|
|
|
|
|
|
|
GPIO_DBG(GPIO_DBG_ERR, "vxFtGpioISR: neet to set ISR for pin %d \r\n.",
|
|
|
|
ix,2,3,4,5,6);
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
exit:
|
|
|
|
/* clear interrupt flags */
|
|
|
|
|
|
|
|
GPIO_WRITE_4 (pDrvCtrl, GPIO_PORTA_EOI_A, val);
|
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
int i,j;
|
|
|
|
VXB_DEVICE_ID pDev;
|
|
|
|
FT_GPIO_DRVCTRL * pCtrl;
|
|
|
|
|
|
|
|
pDev = vxbInstByNameFind("ftGpio", gpio);
|
|
|
|
if (pDev == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
pCtrl = pDev->pDrvCtrl;
|
|
|
|
for(i = 0; i < GPIO_PORT_MUM; i++)
|
|
|
|
{
|
|
|
|
for(j = 0; j < FT_GPIO_PORT_WIDTH; j++)
|
|
|
|
printf("port %d pin %d mode %d\n", i, j, pCtrl->pinMode[i][j]);
|
|
|
|
}
|
|
|
|
|
|
|
|
printf("intEnabled %d\n", pCtrl->intEnabled);
|
|
|
|
printf("triggerMode %x\n", pCtrl->triggerMode);
|
|
|
|
}
|
|
|
|
|
|
|
|
void gpioModeSetTest (UINT32 gpio, UINT32 port, UINT32 pin, UINT32 mode)
|
|
|
|
{
|
|
|
|
VXB_DEVICE_ID pDev;
|
|
|
|
FT_GPIO_DRVCTRL * pCtrl;
|
|
|
|
|
|
|
|
pDev = vxbInstByNameFind("ftGpio", gpio);
|
|
|
|
if (pDev == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
pCtrl = pDev->pDrvCtrl;
|
|
|
|
|
|
|
|
pCtrl->gpioModeSet(pDev, port, pin, mode);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void gpioOutTest (UINT32 gpio, UINT32 port, UINT32 pin, UINT32 val)
|
|
|
|
{
|
|
|
|
VXB_DEVICE_ID pDev;
|
|
|
|
FT_GPIO_DRVCTRL * pCtrl;
|
|
|
|
|
|
|
|
pDev = vxbInstByNameFind("ftGpio", gpio);
|
|
|
|
if (pDev == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
pCtrl = pDev->pDrvCtrl;
|
|
|
|
|
|
|
|
pCtrl->gpioOutput(pDev, port, pin, val);
|
|
|
|
}
|
|
|
|
|
|
|
|
void gpioInTest (UINT32 gpio, UINT32 port, UINT32 pin)
|
|
|
|
{
|
|
|
|
VXB_DEVICE_ID pDev;
|
|
|
|
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));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
LOCAL void gpioIsrFunction(void * arg)
|
|
|
|
{
|
|
|
|
UINT32 * pin = (UINT32 *)arg;
|
|
|
|
logMsg("GPIO pin %d ISR \n",* pin,0,0,0,0,0);
|
|
|
|
}
|
|
|
|
|
|
|
|
LOCAL UINT32 isrArgTest = 0;
|
|
|
|
|
|
|
|
void gpioIsrSetTest (UINT32 gpio, UINT32 pin)
|
|
|
|
{
|
|
|
|
VXB_DEVICE_ID pDev;
|
|
|
|
FT_GPIO_DRVCTRL * pCtrl;
|
|
|
|
|
|
|
|
pDev = vxbInstByNameFind("ftGpio", gpio);
|
|
|
|
if (pDev == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
pCtrl = pDev->pDrvCtrl;
|
|
|
|
|
|
|
|
isrArgTest = pin;
|
|
|
|
|
|
|
|
pCtrl->gpioISRSet(pDev, pin, gpioIsrFunction, &isrArgTest);
|
|
|
|
|
|
|
|
}
|
|
|
|
#endif
|