summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra/nvrm/io/ap15/nvrm_gpio.c
diff options
context:
space:
mode:
authorLaxman Dewangan <ldewangan@nvidia.com>2010-03-17 14:07:40 +0530
committerGary King <gking@nvidia.com>2010-03-19 18:58:47 -0800
commit3fd0b4e9712b848d23f2f341ab4e5b472f50932f (patch)
tree05919b564ce4e4d99557c5c3d40b3d54d289c4de /arch/arm/mach-tegra/nvrm/io/ap15/nvrm_gpio.c
parent57fd96a49d0e279725c215fcc806a9357fd6390c (diff)
Tegra gpio: Wrapping up nvrm gpio to native gpio.
NvRm Gpio driver will be wrapper on the native gpio driver such that it will provide the same existing api and implementation will be use the native gpio driver. In this approach, it does not need to change the existing gpio client driver. Tested on whistler with sdcard insert/remove, touch panel and scroll wheel. Tested on harmony with the suspend/resume. Change-Id: I2fa98f8f62a111a1463c1e5b1034e145eaae42a3 Reviewed-on: http://git-master/r/851 Tested-by: Ramachandrudu Kandhala <rkandhala@nvidia.com> Reviewed-by: Gary King <gking@nvidia.com>
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;
}
-