summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra/nvrm/io/ap15/nvrm_gpio.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-tegra/nvrm/io/ap15/nvrm_gpio.c')
-rw-r--r--arch/arm/mach-tegra/nvrm/io/ap15/nvrm_gpio.c950
1 files changed, 440 insertions, 510 deletions
diff --git a/arch/arm/mach-tegra/nvrm/io/ap15/nvrm_gpio.c b/arch/arm/mach-tegra/nvrm/io/ap15/nvrm_gpio.c
index c558baf1b5cd..905179934d33 100644
--- a/arch/arm/mach-tegra/nvrm/io/ap15/nvrm_gpio.c
+++ b/arch/arm/mach-tegra/nvrm/io/ap15/nvrm_gpio.c
@@ -30,562 +30,492 @@
*
*/
-#include "ap15/ap15rm_gpio_vi.h"
-#include "nvrm_gpio_private.h"
-#include "nvassert.h"
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/irq.h>
+#include <mach/gpio.h>
+
+#include "nvrm_gpio.h"
#include "nvos.h"
+#include "nvrm_structure.h"
+#include "nvrm_pmu.h"
#include "nvrm_pinmux_utils.h"
-#include "ap15/arapbpm.h"
+#include "ap15/ap15rm_private.h"
+#include "ap15/ap15rm_gpio_vi.h"
#include "nvodm_gpio_ext.h"
+#include "nvodm_query_discovery.h"
+#include "nvrm_hwintf.h"
+#include "nvassert.h"
-// Treats GPIO pin handle releases like the pin is completely invalidated:
-// returned to SFIO state and tristated. See the FIXME comment below
-// to see why this isn't enabled currently...
+/* Treats GPIO pin handle releases like the pin is completely invalidated:
+ * returned to SFIO state and tristated. */
#define RELEASE_IS_INVALIDATE 1
#define NV_ENABLE_GPIO_POWER_RAIL 1
+#define TOTAL_GPIO_BANK 7
+#define GPIO_PORT_PER_BANK 4
+#define GPIO_PIN_PER_PORT 8
+#define GPIO_PORT_ID(bank, port) ((((bank)&0xFF) << 2) | (((port) & 0x3)))
+#define GPIO_PIN_ID(bank, port, pin) ((((bank)&0xFF) << 5) | \
+ (((port) & 0x3) <<3) | ((pin) & 0x7))
+
+#define GET_PIN(h) ((((NvU32)(h))) & 0xFF)
+#define GET_PORT(h) ((((NvU32)(h)) >> 8) & 0xFF)
+#define GET_BANK(h) ((((NvU32)(h)) >> 16) & 0xFF)
+
+#define NVRM_GPIO_CAP_FEAT_EDGE_INTR 0x000000001
+#define GPIO_ARCH_FEATURE (NVRM_GPIO_CAP_FEAT_EDGE_INTR)
+
+extern NvError tegra_gpio_io_power_config(NvRmDeviceHandle hRm, int port,
+ int pin, unsigned int enable);
+
typedef struct NvRmGpioPinInfoRec {
- NvBool used;
- NvU32 port;
- NvU32 inst;
- NvU32 pin;
- NvRmGpioPinMode mode;
- /* Sets up a chain of pins associated by one semaphore. Usefull to parse the
- * pins when an interrupt is received. */
- NvU32 nextPin;
- NvU16 irqNumber;
+ NvBool used;
+ NvU32 port;
+ NvU32 inst;
+ NvU32 pin;
+ NvRmGpioPinMode mode;
+ /* Sets up a chain of pins associated by one semaphore.
+ * Usefull to parse the pins when an interrupt is received. */
+ NvU32 nextPin;
+ NvU16 irqNumber;
} NvRmGpioPinInfo;
-typedef struct NvRmGpioRec
-{
- NvU32 RefCount;
- NvRmDeviceHandle hRm;
- NvRmGpioPinInfo *pPinInfo;
- NvRmGpioCaps *caps;
- NvU32 *pIvlReg;
+typedef struct NvRmGpioRec {
+ NvU32 RefCount;
+ NvRmDeviceHandle hRm;
+ NvRmGpioPinInfo *pPinInfo;
} NvRmGpio;
-
static NvRmGpioHandle s_hGpio = NULL;
-
static NvOsMutexHandle s_GpioMutex = NULL;
-NvError
-NvRmGpioOpen(
- NvRmDeviceHandle hRm,
- NvRmGpioHandle* phGpio)
+NvError NvRmGpioOpen(NvRmDeviceHandle hRm, NvRmGpioHandle * phGpio)
{
- NvError err = NvSuccess;
- NvU32 total_pins;
- NvU32 i;
- NvU32 gpioShadowSize;
- NvU32 gpioShadowPhysical;
-
- NV_ASSERT(hRm);
- NV_ASSERT(phGpio);
-
- if (!s_GpioMutex)
- {
- err = NvOsMutexCreate(&s_GpioMutex);
- if (err != NvSuccess)
- {
- goto fail;
- }
- }
-
- NvOsMutexLock(s_GpioMutex);
- if (s_hGpio)
- {
- s_hGpio->RefCount++;
- goto exit;
- }
-
- s_hGpio = (NvRmGpio *)NvOsAlloc(sizeof(NvRmGpio));
- if (!s_hGpio)
- {
- err = NvError_InsufficientMemory;
- goto exit;
- }
- NvOsMemset(s_hGpio, 0, sizeof(NvRmGpio));
- s_hGpio->hRm = hRm;
-
- err = NvRmGpioGetCapabilities(hRm, (void **)&(s_hGpio->caps));
- if (err)
- {
- // Was a default supplied?
- if (s_hGpio->caps == NULL)
- {
- goto fail;
- }
- }
-
- total_pins = s_hGpio->caps->Instances * s_hGpio->caps->PortsPerInstances *
- s_hGpio->caps->PinsPerPort;
-
- s_hGpio->pPinInfo = NvOsAlloc(sizeof(NvRmGpioPinInfo) * total_pins);
- if (s_hGpio->pPinInfo == NULL)
- {
- NvOsFree(s_hGpio);
- goto exit;
- }
- NvOsMemset(s_hGpio->pPinInfo, 0, sizeof(NvRmGpioPinInfo) * total_pins);
- for (i=0; i<total_pins; i++)
- {
- s_hGpio->pPinInfo[i].irqNumber = NVRM_IRQ_INVALID;
- }
- s_hGpio->RefCount++;
-
- gpioShadowSize = sizeof(NvU32) * (NvU8)s_hGpio->caps->PortsPerInstances * (NvU8)s_hGpio->caps->Instances;
- gpioShadowPhysical = NV_REGR(hRm, NvRmModuleID_Pmif, 0, APBDEV_PMC_SCRATCH19_0);
- /* Hack. There is no need for shadow on AP20 */
- if (hRm->ChipId.Id >= 0x20 || !gpioShadowPhysical)
- {
- s_hGpio->pIvlReg = NvOsAlloc(gpioShadowSize);
- NvOsMemset(s_hGpio->pIvlReg, 0, gpioShadowSize);
- }
- else
- {
- /* Map the shadow region that the OAL is using by reading the physical
- * address stored in PMC scratch register */
- err = NvOsPhysicalMemMap(gpioShadowPhysical, gpioShadowSize,
- NvOsMemAttribute_Uncached,
- NVOS_MEM_READ_WRITE,
- (void **)&(s_hGpio->pIvlReg));
- if (err != NvSuccess)
- {
- goto fail;
- }
- }
+ NvError err = NvSuccess;
+ NvU32 total_pins;
+ NvU32 i;
+
+ NV_ASSERT(hRm);
+ NV_ASSERT(phGpio);
+
+ if (!s_GpioMutex) {
+ err = NvOsMutexCreate(&s_GpioMutex);
+ if (err != NvSuccess)
+ goto fail;
+ }
+
+ NvOsMutexLock(s_GpioMutex);
+ if (s_hGpio) {
+ s_hGpio->RefCount++;
+ goto exit;
+ }
+
+ s_hGpio = (NvRmGpio *) NvOsAlloc(sizeof(NvRmGpio));
+ if (!s_hGpio) {
+ err = NvError_InsufficientMemory;
+ goto exit;
+ }
+ NvOsMemset(s_hGpio, 0, sizeof(NvRmGpio));
+ s_hGpio->hRm = hRm;
+
+ total_pins = TOTAL_GPIO_BANK * GPIO_PORT_PER_BANK * GPIO_PIN_PER_PORT;
+ s_hGpio->pPinInfo = NvOsAlloc(sizeof(NvRmGpioPinInfo) * total_pins);
+ if (s_hGpio->pPinInfo == NULL) {
+ NvOsFree(s_hGpio);
+ err = NvError_InsufficientMemory;
+ s_hGpio = NULL;
+ goto exit;
+ }
+ NvOsMemset(s_hGpio->pPinInfo, 0, sizeof(NvRmGpioPinInfo) * total_pins);
+ for (i = 0; i < total_pins; i++)
+ s_hGpio->pPinInfo[i].irqNumber = NVRM_IRQ_INVALID;
+ s_hGpio->RefCount++;
+
exit:
- *phGpio = s_hGpio;
- NvOsMutexUnlock(s_GpioMutex);
+ *phGpio = s_hGpio;
+ NvOsMutexUnlock(s_GpioMutex);
fail:
- return err;
+ return err;
}
void NvRmGpioClose(NvRmGpioHandle hGpio)
{
- if (!hGpio)
- return;
-
- NV_ASSERT(hGpio->RefCount);
-
- NvOsMutexLock(s_GpioMutex);
- hGpio->RefCount--;
- if (hGpio->RefCount == 0)
- {
- NvU32 gpioShadowSize;
- NvU32 gpioShadowPhysical;
-
- NvOsFree(s_hGpio->pPinInfo);
- gpioShadowSize = sizeof(NvU32) * s_hGpio->caps->PortsPerInstances * s_hGpio->caps->Instances;
- gpioShadowPhysical = NV_REGR(hGpio->hRm, NvRmModuleID_Pmif, 0, APBDEV_PMC_SCRATCH19_0);
- if (hGpio->hRm->ChipId.Id >= 0x20 || !gpioShadowPhysical)
- {
- NvOsFree(s_hGpio->pIvlReg);
- }
- else
- {
- NvOsPhysicalMemUnmap(s_hGpio->pIvlReg, gpioShadowSize);
- }
- NvOsFree(s_hGpio);
- s_hGpio = NULL;
- }
- NvOsMutexUnlock(s_GpioMutex);
+ if (!hGpio)
+ return;
+
+ NV_ASSERT(hGpio->RefCount);
+
+ NvOsMutexLock(s_GpioMutex);
+ hGpio->RefCount--;
+ if (hGpio->RefCount == 0) {
+ NvOsFree(s_hGpio->pPinInfo);
+ NvOsFree(s_hGpio);
+ s_hGpio = NULL;
+ }
+ NvOsMutexUnlock(s_GpioMutex);
}
-
NvError
-NvRmGpioAcquirePinHandle(
- NvRmGpioHandle hGpio,
- NvU32 port,
- NvU32 pinNumber,
- NvRmGpioPinHandle *phPin)
+NvRmGpioAcquirePinHandle(NvRmGpioHandle hGpio,
+ NvU32 port, NvU32 pinNumber, NvRmGpioPinHandle * phPin)
{
- NvU32 MaxPorts;
-
- NV_ASSERT(hGpio != NULL);
-
- NvOsMutexLock(s_GpioMutex);
- if (port == NVRM_GPIO_CAMERA_PORT)
- {
- // The Camera has dedicated gpio pins that must be controlled
- // through a non-standard gpio port control.
- NvRmPrivGpioViAcquirePinHandle(hGpio->hRm, pinNumber);
- *phPin = GPIO_MAKE_PIN_HANDLE(NVRM_GPIO_CAMERA_INST, port, pinNumber);
- }
- else if ((port >= NVODM_GPIO_EXT_PORT_0) &&
- (port <= NVODM_GPIO_EXT_PORT_F))
- {
- // Create a pin handle for GPIOs that are
- // sourced by external (off-chip) peripherals
- *phPin = GPIO_MAKE_PIN_HANDLE((port & 0xFF), port, pinNumber);
- }
- else
- {
- NV_ASSERT(4 == hGpio->caps->PortsPerInstances);
- MaxPorts = hGpio->caps->Instances * 4;
-
- if ((port > MaxPorts) || (pinNumber > hGpio->caps->PinsPerPort))
- {
- NV_ASSERT(!" Illegal port or pin number. ");
- }
-
- *phPin = GPIO_MAKE_PIN_HANDLE(port >> 2, port & 0x3, pinNumber);
- }
- NvOsMutexUnlock(s_GpioMutex);
- return NvSuccess;
+ int gpio_nr;
+ int ret_status;
+
+ NV_ASSERT(hGpio != NULL);
+
+ if (port == NVRM_GPIO_CAMERA_PORT) {
+ NvOsMutexLock(s_GpioMutex);
+ /* The Camera has dedicated gpio pins that must be controlled
+ * through a non-standard gpio port control. */
+ NvRmPrivGpioViAcquirePinHandle(hGpio->hRm, pinNumber);
+ *phPin = GPIO_MAKE_PIN_HANDLE(NVRM_GPIO_CAMERA_INST, port,
+ pinNumber);
+ NvOsMutexUnlock(s_GpioMutex);
+ } else if ((port >= NVODM_GPIO_EXT_PORT_0) &&
+ (port <= NVODM_GPIO_EXT_PORT_F)) {
+ /* Create a pin handle for GPIOs that are
+ * sourced by external (off-chip) peripherals */
+ *phPin = GPIO_MAKE_PIN_HANDLE((port & 0xFF), port, pinNumber);
+ } else {
+ gpio_nr = GPIO_PIN_ID((port >> 2), (port & 0x3), pinNumber);
+ if ((gpio_nr >= ARCH_NR_GPIOS) ||
+ (pinNumber >= GPIO_PIN_PER_PORT)) {
+ printk(KERN_ERR "Requested port %d or pin %d number "
+ " is not supported", port, pinNumber);
+ return NvError_NotSupported;
+ }
+ ret_status = gpio_request(gpio_nr, "nvrm_gpio");
+ if (unlikely(ret_status != 0)) {
+ return NvError_AlreadyAllocated;
+ }
+ *phPin = GPIO_MAKE_PIN_HANDLE((port >> 2), (port & 0x3),
+ pinNumber);
+ }
+ return NvSuccess;
}
-void NvRmGpioReleasePinHandles(
- NvRmGpioHandle hGpio,
- NvRmGpioPinHandle *hPin,
- NvU32 pinCount)
+void NvRmGpioReleasePinHandles(NvRmGpioHandle hGpio,
+ NvRmGpioPinHandle * hPin, NvU32 pinCount)
{
- NvU32 i;
- NvU32 port;
- NvU32 pin;
- NvU32 instance;
-
- if (hPin == NULL) return;
-
- for (i=0; i<pinCount; i++)
- {
- instance = GET_INSTANCE(hPin[i]);
- port = GET_PORT(hPin[i]);
- pin = GET_PIN(hPin[i]);
-
- NvOsMutexLock(s_GpioMutex);
- if (port == NVRM_GPIO_CAMERA_PORT)
- {
- NvRmPrivGpioViReleasePinHandles(hGpio->hRm, pin);
- }
- else if ((port >= NVODM_GPIO_EXT_PORT_0) &&
- (port <= NVODM_GPIO_EXT_PORT_F))
- {
- // Do nothing for now...
- }
- else
- {
- NvU32 alphaPort;
-
- alphaPort = instance * s_hGpio->caps->PortsPerInstances + port;
- if (s_hGpio->pPinInfo[pin + alphaPort * s_hGpio->caps->PinsPerPort].used)
- {
- NV_DEBUG_PRINTF(("Warning: Releasing in-use GPIO pin handle GPIO_P%c.%02u (%c=%u)\n",
- 'A'+alphaPort,pin,'A'+alphaPort, alphaPort));
+ NvU32 i;
+ NvU32 port;
+ NvU32 pin;
+ NvU32 bank;
+ int gpio_nr;
+ NvU32 alphaPort;
+
+ if (hPin == NULL)
+ return;
+
+ for (i = 0; i < pinCount; i++) {
+ bank = GET_BANK(hPin[i]);
+ port = GET_PORT(hPin[i]);
+ pin = GET_PIN(hPin[i]);
+ NvOsMutexLock(s_GpioMutex);
+ if (port == NVRM_GPIO_CAMERA_PORT) {
+ NvRmPrivGpioViReleasePinHandles(hGpio->hRm, pin);
+ } else if ((port >= NVODM_GPIO_EXT_PORT_0) &&
+ (port <= NVODM_GPIO_EXT_PORT_F)) {
+ /* Do nothing for now... */
+ } else {
+ gpio_nr = GPIO_PIN_ID(bank, port & 0x3, pin);
+ if (gpio_nr >= ARCH_NR_GPIOS) {
+ printk(KERN_ERR "Illegal pin handle at place "
+ " %u of the list\n",i);
+ NvOsMutexUnlock(s_GpioMutex);
+ continue;
+ }
+ gpio_free(gpio_nr);
+ alphaPort = (NvU32) GPIO_PORT_ID(bank, port);
+ if (s_hGpio->pPinInfo[gpio_nr].used) {
+ NV_DEBUG_PRINTF(("Warning: Releasing in-use "
+ "GPIO pin handle GPIO_P%c.%02u "
+ "(%c=%u)\n", 'A' + alphaPort, pin,
+ 'A' + alphaPort, alphaPort));
#if RELEASE_IS_INVALIDATE
- GPIO_MASKED_WRITE(hGpio->hRm, instance, port, CNF, pin, 0);
- NvRmSetGpioTristate(hGpio->hRm, alphaPort, pin, NV_TRUE);
- s_hGpio->pPinInfo[pin + alphaPort*s_hGpio->caps->PinsPerPort].used = NV_FALSE;
+ tegra_gpio_disable(gpio_nr);
+ NvRmSetGpioTristate(hGpio->hRm,
+ alphaPort, pin, NV_TRUE);
+ s_hGpio->pPinInfo[gpio_nr].used = NV_FALSE;
#endif
- }
- }
- NvOsMutexUnlock(s_GpioMutex);
- }
-
- return;
+ }
+ }
+ NvOsMutexUnlock(s_GpioMutex);
+ }
+ return;
}
-
-void NvRmGpioReadPins(
- NvRmGpioHandle hGpio,
- NvRmGpioPinHandle *hPin,
- NvRmGpioPinState *pPinState,
- NvU32 pinCount )
+void NvRmGpioReadPins(NvRmGpioHandle hGpio,
+ NvRmGpioPinHandle * hPin,
+ NvRmGpioPinState * pPinState, NvU32 pinCount)
{
- NvU32 inst;
- NvU32 port;
- NvU32 pin;
- NvU32 RegValue;
- NvU32 i;
-
- NV_ASSERT(hPin != NULL);
- NV_ASSERT(hGpio != NULL);
- NV_ASSERT(hGpio->caps != NULL);
-
- for (i=0; i<pinCount; i++)
- {
- port = GET_PORT(hPin[i]);
- pin = GET_PIN(hPin[i]);
- inst = GET_INSTANCE(hPin[i]);
-
- if (port == NVRM_GPIO_CAMERA_PORT)
- {
- pPinState[i] = NvRmPrivGpioViReadPins(hGpio->hRm, pin);
- }
- else if ((port >= (NvU32)NVODM_GPIO_EXT_PORT_0) &&
- (port <= (NvU32)NVODM_GPIO_EXT_PORT_F))
- {
- pPinState[i] = NvOdmExternalGpioReadPins(port, pin);
- }
- else
- {
- GPIO_REGR(hGpio->hRm, inst, port, OE, RegValue);
- if (RegValue & (1<<pin))
- {
- GPIO_REGR(hGpio->hRm, inst, port, OUT, RegValue);
- } else
- {
- GPIO_REGR(hGpio->hRm, inst, port, IN, RegValue);
- }
- pPinState[i] = (RegValue >> pin) & 0x1;
- }
- }
+ NvU32 bank;
+ NvU32 port;
+ NvU32 pin;
+ NvU32 i;
+ int gpio_nr;
+
+ NV_ASSERT(hPin != NULL);
+ NV_ASSERT(hGpio != NULL);
+
+ for (i = 0; i < pinCount; i++) {
+ port = GET_PORT(hPin[i]);
+ pin = GET_PIN(hPin[i]);
+ bank = GET_BANK(hPin[i]);
+
+ if (port == NVRM_GPIO_CAMERA_PORT) {
+ pPinState[i] = NvRmPrivGpioViReadPins(hGpio->hRm, pin);
+ } else if ((port >= (NvU32) NVODM_GPIO_EXT_PORT_0) &&
+ (port <= (NvU32) NVODM_GPIO_EXT_PORT_F)) {
+ pPinState[i] = NvOdmExternalGpioReadPins(port, pin);
+ } else {
+ gpio_nr = GPIO_PIN_ID(bank, port, pin);
+ if (gpio_nr >= ARCH_NR_GPIOS) {
+ printk(KERN_ERR "Illegal pin handle at place "
+ " %u of the list\n",i);
+ continue;
+ }
+ pPinState[i] = gpio_get_value(gpio_nr) & 0x1;
+ }
+ }
}
-void NvRmGpioWritePins(
- NvRmGpioHandle hGpio,
- NvRmGpioPinHandle *hPin,
- NvRmGpioPinState *pPinState,
- NvU32 pinCount )
+void NvRmGpioWritePins(NvRmGpioHandle hGpio,
+ NvRmGpioPinHandle * hPin,
+ NvRmGpioPinState * pPinState, NvU32 pinCount)
{
- NvU32 inst;
- NvU32 port;
- NvU32 pin;
- NvU32 i;
-
- NV_ASSERT(hPin != NULL);
- NV_ASSERT(hGpio != NULL);
- NV_ASSERT(hGpio->caps != NULL);
-
- for (i=0; i<pinCount; i++)
- {
- inst = GET_INSTANCE(hPin[i]);
- port = GET_PORT(hPin[i]);
- pin = GET_PIN(hPin[i]);
-
- if (port == NVRM_GPIO_CAMERA_PORT)
- {
- NvRmPrivGpioViWritePins(hGpio->hRm, pin, pPinState[i]);
- }
- else if ((port >= (NvU32)NVODM_GPIO_EXT_PORT_0) &&
- (port <= (NvU32)NVODM_GPIO_EXT_PORT_F))
- {
- NvOdmExternalGpioWritePins(port, pin, pPinState[i]);
- }
- else
- {
- // When updating a contiguous set of pins that are
- // all located in the same port, merge the register
- // write into a single atomic update.
- NvU32 updateVec = 0;
- updateVec = (1<<(pin + GPIO_PINS_PER_PORT));
- updateVec |= ((pPinState[i] & 0x1)<<pin);
- while ((i+1<pinCount) &&
- GET_INSTANCE(hPin[i+1])==inst &&
- GET_PORT(hPin[i+1]==port))
- {
- pin = GET_PIN(hPin[i+1]);
- updateVec |= (1<<(pin + GPIO_PINS_PER_PORT));
- updateVec |= ((pPinState[i+1]&0x1)<<pin);
- i++;
- }
- NV_REGW(hGpio->hRm, NvRmPrivModuleID_Gpio, inst,
- (port*NV_GPIO_PORT_REG_SIZE)+GPIO_MSK_CNF_0+GPIO_OUT_0,
- updateVec);
- }
- }
-
- return;
+ NvU32 port;
+ NvU32 pin;
+ NvU32 bank;
+ NvU32 i;
+ int gpio_nr;
+
+ NV_ASSERT(hPin != NULL);
+ NV_ASSERT(hGpio != NULL);
+
+ for (i = 0; i < pinCount; i++) {
+ port = GET_PORT(hPin[i]);
+ pin = GET_PIN(hPin[i]);
+ bank = GET_BANK(hPin[i]);
+
+ if (port == NVRM_GPIO_CAMERA_PORT) {
+ NvRmPrivGpioViWritePins(hGpio->hRm, pin, pPinState[i]);
+ } else if ((port >= (NvU32) NVODM_GPIO_EXT_PORT_0) &&
+ (port <= (NvU32) NVODM_GPIO_EXT_PORT_F)) {
+ NvOdmExternalGpioWritePins(port, pin, pPinState[i]);
+ } else {
+ gpio_nr = GPIO_PIN_ID(bank, port, pin);
+ if (gpio_nr >= ARCH_NR_GPIOS) {
+ printk(KERN_ERR "Illegal pin handle at place "
+ " %u of the list\n",i);
+ continue;
+ }
+ gpio_set_value(gpio_nr, pPinState[i] & 0x1);
+ }
+ }
+
+ return;
}
-
-NvError NvRmGpioConfigPins(
- NvRmGpioHandle hGpio,
- NvRmGpioPinHandle *hPin,
- NvU32 pinCount,
- NvRmGpioPinMode Mode)
+NvError NvRmGpioConfigPins(NvRmGpioHandle hGpio,
+ NvRmGpioPinHandle * hPin,
+ NvU32 pinCount, NvRmGpioPinMode Mode)
{
- NvError err = NvSuccess;
- NvU32 i;
- NvU32 inst;
- NvU32 port;
- NvU32 pin;
- NvU32 pinNumber;
- NvU32 Reg;
- NvU32 alphaPort;
-
- NvOsMutexLock(s_GpioMutex);
-
- for (i=0; i< pinCount; i++)
- {
- inst = GET_INSTANCE(hPin[i]);
- port = GET_PORT(hPin[i]);
- pin = GET_PIN(hPin[i]);
-
- if (port == NVRM_GPIO_CAMERA_PORT)
- {
- // If they are trying to do the wrong thing, assert.
- // If they are trying to do the only allowed thing,
- // quietly skip it, as nothing needs to be done.
- if (Mode != NvOdmGpioPinMode_Output)
- {
- NV_ASSERT(!"Only output is supported for camera gpio.\n");
- }
- continue;
- }
-
- /* Absolute pin number to index into pPinInfo array and the alphabetic port names. */
- alphaPort = inst * s_hGpio->caps->PortsPerInstances + port;
- pinNumber = pin + alphaPort * s_hGpio->caps->PinsPerPort;
-
- s_hGpio->pPinInfo[pinNumber].mode = Mode;
- s_hGpio->pPinInfo[pinNumber].inst = inst;
- s_hGpio->pPinInfo[pinNumber].port = port;
- s_hGpio->pPinInfo[pinNumber].pin = pin;
-
- /* Don't try to colapse this swtich as the ordering of the register
- * writes matter. */
- switch (Mode)
- {
- case NvRmGpioPinMode_Output:
- GPIO_MASKED_WRITE(hGpio->hRm, inst, port, OE, pin, 1);
- GPIO_MASKED_WRITE(hGpio->hRm, inst, port, CNF, pin, 1);
-
- break;
-
- case NvRmGpioPinMode_InputData:
- GPIO_MASKED_WRITE(hGpio->hRm, inst, port, OE, pin, 0);
- GPIO_MASKED_WRITE(hGpio->hRm, inst, port, CNF, pin, 1);
-
- break;
-
- case NvRmGpioPinMode_InputInterruptLow:
- GPIO_MASKED_WRITE(hGpio->hRm, inst, port, OE, pin, 0);
- GPIO_MASKED_WRITE(hGpio->hRm, inst, port, CNF, pin, 1);
-
- GPIO_MASKED_WRITE(hGpio->hRm, inst, port, INT_LVL, pin, 0);
- break;
-
- case NvRmGpioPinMode_InputInterruptHigh:
- GPIO_MASKED_WRITE(hGpio->hRm, inst, port, OE, pin, 0);
- GPIO_MASKED_WRITE(hGpio->hRm, inst, port, CNF, pin, 1);
-
- GPIO_MASKED_WRITE(hGpio->hRm, inst, port, INT_LVL, pin, 1);
- break;
-
- case NvRmGpioPinMode_InputInterruptAny:
- if(hGpio->caps->Features & NVRM_GPIO_CAP_FEAT_EDGE_INTR)
- {
- GPIO_MASKED_WRITE(hGpio->hRm, inst, port, OE, pin, 0);
- GPIO_MASKED_WRITE(hGpio->hRm, inst, port, CNF, pin, 1);
-
- GPIO_REGR(hGpio->hRm, inst, port, INT_LVL, Reg);
- // see the # Bug ID: 359459
- Reg = (Reg & GPIO_INT_LVL_UNSHADOWED_MASK) |
- (s_hGpio->pIvlReg[alphaPort] & GPIO_INT_LVL_SHADOWED_MASK);
- Reg |= (GPIO_INT_LVL_0_EDGE_0_FIELD << pin);
- Reg |= (GPIO_INT_LVL_0_DELTA_0_FIELD << pin);
- s_hGpio->pIvlReg[alphaPort] = Reg;
- GPIO_REGW(hGpio->hRm, inst, port, INT_LVL, Reg);
- }
- else
- {
- NV_ASSERT(!"Not supported");
- }
-
- break;
-
- case NvRmGpioPinMode_Function:
- GPIO_MASKED_WRITE(hGpio->hRm, inst, port, CNF, pin, 0);
- break;
- case NvRmGpioPinMode_Inactive:
- GPIO_MASKED_WRITE(hGpio->hRm, inst, port, INT_ENB, pin, 0);
- GPIO_MASKED_WRITE(hGpio->hRm, inst, port, CNF, pin, 0);
- break;
- case NvRmGpioPinMode_InputInterruptRisingEdge:
- if(hGpio->caps->Features & NVRM_GPIO_CAP_FEAT_EDGE_INTR)
- {
- GPIO_MASKED_WRITE(hGpio->hRm, inst, port, OE, pin, 0);
- GPIO_MASKED_WRITE(hGpio->hRm, inst, port, CNF, pin, 1);
- GPIO_REGW(hGpio->hRm, inst, port, INT_CLR, (1 << pin));
- GPIO_REGR(hGpio->hRm, inst, port, INT_LVL, Reg);
- // see the # Bug ID: 359459
- Reg = (Reg & GPIO_INT_LVL_UNSHADOWED_MASK) | (s_hGpio->pIvlReg[alphaPort] & GPIO_INT_LVL_SHADOWED_MASK);
- Reg |= (GPIO_INT_LVL_0_BIT_0_FIELD << pin);
- Reg |= (GPIO_INT_LVL_0_EDGE_0_FIELD << pin);
- Reg &= ~(GPIO_INT_LVL_0_DELTA_0_FIELD << pin);
- s_hGpio->pIvlReg[alphaPort] = Reg;
- GPIO_REGW(hGpio->hRm, inst, port, INT_LVL, Reg);
- }
- else
- {
- NV_ASSERT(!"Not supported");
- }
- break;
- case NvRmGpioPinMode_InputInterruptFallingEdge:
- if(hGpio->caps->Features & NVRM_GPIO_CAP_FEAT_EDGE_INTR)
- {
- GPIO_MASKED_WRITE(hGpio->hRm, inst, port, OE, pin, 0);
- GPIO_MASKED_WRITE(hGpio->hRm, inst, port, CNF, pin, 1);
- GPIO_REGW(hGpio->hRm, inst, port, INT_CLR, (1 << pin));
- GPIO_REGR(hGpio->hRm, inst, port, INT_LVL, Reg);
- // see the # Bug ID: 359459
- Reg = (Reg & GPIO_INT_LVL_UNSHADOWED_MASK) |(s_hGpio->pIvlReg[alphaPort] & GPIO_INT_LVL_SHADOWED_MASK);
- Reg &= ~(GPIO_INT_LVL_0_BIT_0_FIELD << pin);
- Reg |= (GPIO_INT_LVL_0_EDGE_0_FIELD << pin);
- Reg &= ~(GPIO_INT_LVL_0_DELTA_0_FIELD << pin);
- s_hGpio->pIvlReg[alphaPort] = Reg;
- GPIO_REGW(hGpio->hRm, inst, port, INT_LVL, Reg);
- }
- else
- {
- NV_ASSERT(!"Not supported");
- }
- break;
- default:
- NV_ASSERT(!"Invalid gpio mode");
- break;
- }
-
- /* Pad group global tristates are only modified when the pin transitions
- * from an inactive state to an active one. Active-to-active and
- * inactive-to-inactive transitions are ignored */
- if ((!s_hGpio->pPinInfo[pinNumber].used) && (Mode!=NvRmGpioPinMode_Inactive))
- {
+ NvError err = NvSuccess;
+ NvU32 i;
+ NvU32 bank;
+ NvU32 port;
+ NvU32 pin;
+ NvU32 alphaPort;
+ int ret_status;
+ int gpio_nr;
+ struct irq_chip *chip;
+ int gpio_irq;
+
+ NvOsMutexLock(s_GpioMutex);
+
+ for (i = 0; i < pinCount; i++) {
+ bank = GET_BANK(hPin[i]);
+ port = GET_PORT(hPin[i]);
+ pin = GET_PIN(hPin[i]);
+
+ if (port == NVRM_GPIO_CAMERA_PORT) {
+ /* If they are trying to do the wrong thing, assert.
+ * If they are trying to do the only allowed thing,
+ * quietly skip it, as nothing needs to be done. */
+ if (Mode != NvOdmGpioPinMode_Output) {
+ NV_ASSERT(!"Only output is supported for "
+ "camera gpio.\n");
+ }
+ continue;
+ }
+
+ /* Absolute pin number to index into pPinInfo array and
+ * the alphabetic port names. */
+ gpio_nr = GPIO_PIN_ID(bank, port, pin);
+ gpio_irq = gpio_to_irq(gpio_nr);
+ if (gpio_nr >= ARCH_NR_GPIOS) {
+ printk(KERN_ERR "Illegal pin handle at place "
+ " %u of the list\n",i);
+ continue;
+ }
+
+ alphaPort = GPIO_PORT_ID(bank, port);
+
+ s_hGpio->pPinInfo[gpio_nr].mode = Mode;
+ s_hGpio->pPinInfo[gpio_nr].inst = bank;
+ s_hGpio->pPinInfo[gpio_nr].port = port;
+ s_hGpio->pPinInfo[gpio_nr].pin = pin;
+
+ /* Don't try to colapse this swtich as the ordering of
+ * the register writes matter. */
+ switch (Mode) {
+ case NvRmGpioPinMode_Output:
+ tegra_gpio_enable(gpio_nr);
+ ret_status = gpio_direction_output(gpio_nr, 0);
+ if (unlikely(ret_status != 0)) {
+ NV_ASSERT(!"Not initialized");
+ return NvError_NotInitialized;
+ }
+ break;
+
+ case NvRmGpioPinMode_InputData:
+ tegra_gpio_enable(gpio_nr);
+ ret_status = gpio_direction_input(gpio_nr);
+ if (unlikely(ret_status != 0)) {
+ NV_ASSERT(!"Not initialized");
+ return NvError_NotInitialized;
+ }
+ break;
+
+ case NvRmGpioPinMode_InputInterruptLow:
+ gpio_direction_input(gpio_nr);
+ tegra_gpio_enable(gpio_nr);
+ chip = get_irq_chip(gpio_irq);
+ if ((chip) && (chip->set_type))
+ chip->set_type(gpio_irq, IRQ_TYPE_LEVEL_LOW);
+ break;
+
+ case NvRmGpioPinMode_InputInterruptHigh:
+ gpio_direction_input(gpio_nr);
+ tegra_gpio_enable(gpio_nr);
+ chip = get_irq_chip(gpio_irq);
+ if ((chip) && (chip->set_type))
+ chip->set_type(gpio_irq, IRQ_TYPE_LEVEL_HIGH);
+ break;
+
+ case NvRmGpioPinMode_InputInterruptAny:
+ if (GPIO_ARCH_FEATURE & NVRM_GPIO_CAP_FEAT_EDGE_INTR) {
+ gpio_direction_input(gpio_nr);
+ tegra_gpio_enable(gpio_nr);
+ chip = get_irq_chip(gpio_irq);
+ if ((chip) && (chip->set_type))
+ chip->set_type(gpio_irq,
+ IRQ_TYPE_EDGE_BOTH);
+ } else {
+ NV_ASSERT(!"Not supported");
+ }
+ break;
+
+ case NvRmGpioPinMode_Function:
+ tegra_gpio_disable(gpio_nr);
+ break;
+
+ case NvRmGpioPinMode_Inactive:
+ chip = get_irq_chip(gpio_irq);
+ if ((chip) && (chip->set_type))
+ chip->mask(gpio_irq);
+ tegra_gpio_disable(gpio_nr);
+ break;
+
+ case NvRmGpioPinMode_InputInterruptRisingEdge:
+ if (GPIO_ARCH_FEATURE & NVRM_GPIO_CAP_FEAT_EDGE_INTR) {
+ gpio_direction_input(gpio_nr);
+ tegra_gpio_enable(gpio_nr);
+
+ chip = get_irq_chip(gpio_irq);
+ if ((chip) && (chip->set_type))
+ chip->set_type(gpio_irq,
+ IRQ_TYPE_EDGE_RISING);
+ } else {
+ NV_ASSERT(!"Not supported");
+ }
+ break;
+
+ case NvRmGpioPinMode_InputInterruptFallingEdge:
+ if (GPIO_ARCH_FEATURE & NVRM_GPIO_CAP_FEAT_EDGE_INTR) {
+ gpio_direction_input(gpio_nr);
+ tegra_gpio_enable(gpio_nr);
+ chip = get_irq_chip(gpio_irq);
+ if ((chip) && (chip->set_type))
+ chip->set_type(gpio_irq,
+ IRQ_TYPE_EDGE_FALLING);
+ } else {
+ NV_ASSERT(!"Not supported");
+ }
+ break;
+
+ default:
+ NV_ASSERT(!"Invalid gpio mode");
+ break;
+ }
+
+ /* Pad group global tristates are only modified when
+ * the pin transitions from an inactive state to an
+ * active one. Active-to-active and inactive-to-inactive
+ * transitions are ignored */
+ if ((!s_hGpio->pPinInfo[gpio_nr].used)
+ && (Mode != NvRmGpioPinMode_Inactive)) {
#if NV_ENABLE_GPIO_POWER_RAIL
- err = NvRmGpioIoPowerConfig(hGpio->hRm, alphaPort, pin, NV_TRUE);
+ err = tegra_gpio_io_power_config(hGpio->hRm,
+ alphaPort, pin, true);
#endif
- NvRmSetGpioTristate(hGpio->hRm, alphaPort, pin, NV_FALSE);
- }
- else if ((s_hGpio->pPinInfo[pinNumber].used) && (Mode==NvRmGpioPinMode_Inactive))
- {
+ NvRmSetGpioTristate(hGpio->hRm,
+ alphaPort, pin, NV_FALSE);
+ } else if ((s_hGpio->pPinInfo[gpio_nr].used)
+ && (Mode == NvRmGpioPinMode_Inactive)) {
#if NV_ENABLE_GPIO_POWER_RAIL
- err = NvRmGpioIoPowerConfig(hGpio->hRm, alphaPort, pin, NV_FALSE);
+ err = tegra_gpio_io_power_config(hGpio->hRm,
+ alphaPort, pin, false);
#endif
- NvRmSetGpioTristate(hGpio->hRm, alphaPort, pin, NV_TRUE);
- }
- if (Mode != NvRmGpioPinMode_Inactive)
- s_hGpio->pPinInfo[pinNumber].used = NV_TRUE;
- else
- s_hGpio->pPinInfo[pinNumber].used = NV_FALSE;
- }
-
- NvOsMutexUnlock(s_GpioMutex);
- return err;
+ NvRmSetGpioTristate(hGpio->hRm,
+ alphaPort, pin, NV_TRUE);
+ }
+ if (Mode != NvRmGpioPinMode_Inactive)
+ s_hGpio->pPinInfo[gpio_nr].used = NV_TRUE;
+ else
+ s_hGpio->pPinInfo[gpio_nr].used = NV_FALSE;
+ }
+
+ NvOsMutexUnlock(s_GpioMutex);
+ return err;
}
-NvError NvRmGpioGetIrqs(
- NvRmDeviceHandle hRmDevice,
- NvRmGpioPinHandle * hPin,
- NvU32 * Irq,
- NvU32 pinCount )
+NvError NvRmGpioGetIrqs(NvRmDeviceHandle hRmDevice,
+ NvRmGpioPinHandle * hPin, NvU32 * Irq, NvU32 pinCount)
{
- NvU32 i;
- for (i=0; i< pinCount; i++)
- {
- NvU32 port, pin, inst;
-
- port = GET_PORT(hPin[i]);
- pin = GET_PIN(hPin[i]);
- inst = GET_INSTANCE(hPin[i]);
-
- Irq[i] = NvRmGetIrqForLogicalInterrupt(hRmDevice,
- NVRM_MODULE_ID(NvRmPrivModuleID_Gpio, inst),
- pin + port * GPIO_PINS_PER_PORT);
- }
- return NvSuccess;
+ NvU32 i;
+ int irq_base;
+ NvU32 bank;
+ NvU32 port;
+ NvU32 pin;
+ int gpio_nr;
+
+ irq_base = gpio_to_irq(0);
+ for (i = 0; i < pinCount; i++) {
+ bank = GET_BANK(hPin[i]);
+ port = GET_PORT(hPin[i]);
+ pin = GET_PIN(hPin[i]);
+ gpio_nr = GPIO_PIN_ID(bank, port, pin);
+ if (gpio_nr >= ARCH_NR_GPIOS) {
+ printk(KERN_ERR "Illegal pin handle at place "
+ " %u of the list\n",i);
+ continue;
+ }
+ Irq[i] = irq_base + gpio_nr;
+ }
+ return NvSuccess;
}
-