summaryrefslogtreecommitdiff
path: root/arch/arm
diff options
context:
space:
mode:
authorLaxman Dewangan <ldewangan@nvidia.com>2010-04-01 21:06:38 +0530
committerGary King <gking@nvidia.com>2010-04-07 15:11:26 -0700
commit35ef3cf36fb1fcfbbadf6a22c44b9e83f8160216 (patch)
tree7bdd46e097f372474a72ff9dcedc18ab23fce184 /arch/arm
parent221ff969389192d4baab1a8e3caaffa906974514 (diff)
gpio: Configuring pinmux and power rail with gpio_request.
When gpio client uses the direct linux api which is provided by gpio lib of linux kernel driver, the pinmux and io power rail was not getting configured. Configuring the pinux and power rail so that client can use direct gpio api of linux and need not to use the rm gpio wrapper api. Tested on whistler. Change-Id: I02b6782fd751543d064588288104a26caab7c848 Reviewed-on: http://git-master/r/1021 Reviewed-by: Suresh Mangipudi <smangipudi@nvidia.com> Tested-by: Suresh Mangipudi <smangipudi@nvidia.com> Reviewed-by: Gary King <gking@nvidia.com>
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/mach-tegra/Makefile2
-rw-r--r--arch/arm/mach-tegra/gpio.c57
-rw-r--r--arch/arm/mach-tegra/nvrm/io/ap15/nvrm_gpio.c11
-rw-r--r--arch/arm/mach-tegra/nvrm/io/common/nvrm_i2c.c68
4 files changed, 99 insertions, 39 deletions
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
index 7116e76c5263..60c8ad936856 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -6,6 +6,8 @@ ccflags-y += -DNV_DEBUG=1
else
ccflags-y += -DNV_DEBUG=0
endif
+ccflags-y += -Iarch/arm/mach-tegra/nvrm/core/common
+
# Mandatory components
obj-y += clock.o
diff --git a/arch/arm/mach-tegra/gpio.c b/arch/arm/mach-tegra/gpio.c
index fcd706c717c3..2e5074796abd 100644
--- a/arch/arm/mach-tegra/gpio.c
+++ b/arch/arm/mach-tegra/gpio.c
@@ -30,6 +30,9 @@
#include <linux/io.h>
#include <linux/interrupt.h>
+#include <mach/nvrm_linux.h>
+#include "nvrm_pinmux_utils.h"
+
#include <asm/io.h>
#include <asm/gpio.h>
@@ -66,6 +69,9 @@ static unsigned long add_gpio_base = 0;
#define GPIO_INT_LVL_LEVEL_LOW 0x000000
#define MAX_GPIO_INSTANCES 10
+
+int tegra_gpio_io_power_config(int gpio_nr, unsigned int enable);
+
struct tegra_gpio_bank {
int bank;
int irq;
@@ -114,6 +120,36 @@ void tegra_gpio_disable(int gpio)
tegra_gpio_mask_write(GPIO_MSK_CNF(gpio), gpio, 0);
}
+static int tegra_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+ int port;
+ int pin;
+ int status;
+ port = GPIO_BANK(offset) * 4 + GPIO_PORT(offset);
+ pin = GPIO_BIT(offset);
+
+ status = tegra_gpio_io_power_config(offset, true);
+ if (unlikely(status != 0)) {
+ return -1;
+ }
+
+ tegra_gpio_mask_write(GPIO_MSK_CNF(offset), offset, 1);
+ NvRmSetGpioTristate(s_hRmGlobal, port, pin, NV_FALSE);
+ return 0;
+}
+
+static void tegra_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+ int port;
+ int pin;
+ port = GPIO_BANK(offset) * 4 + GPIO_PORT(offset);
+ pin = GPIO_BIT(offset);
+
+ tegra_gpio_io_power_config(offset, false);
+ tegra_gpio_mask_write(GPIO_MSK_CNF(offset), offset, 0);
+ NvRmSetGpioTristate(s_hRmGlobal, port, pin, NV_TRUE);
+}
+
static void tegra_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{
tegra_gpio_mask_write(GPIO_MSK_OUT(offset), offset, value);
@@ -139,6 +175,8 @@ static int tegra_gpio_direction_output(struct gpio_chip *chip,
static struct gpio_chip tegra_gpio_chip = {
.label = "tegra-gpio",
+ .request = tegra_gpio_request,
+ .free = tegra_gpio_free,
.direction_input = tegra_gpio_direction_input,
.get = tegra_gpio_get,
.direction_output = tegra_gpio_direction_output,
@@ -738,7 +776,7 @@ static struct gpio_power_rail_info *gpio_power_rail_map[ARCH_NR_GPIOS] = {
&gpio_power_rail_table[5]
};
-static void discover_gpio_io_power_rail(NvRmDeviceHandle hRm)
+static void discover_gpio_io_power_rail(void)
{
unsigned int i;
const NvOdmPeripheralConnectivity* connectivity = NULL;
@@ -752,39 +790,36 @@ static void discover_gpio_io_power_rail(NvRmDeviceHandle hRm)
connectivity->AddressList[0].Address;
}
}
-NvError tegra_gpio_io_power_config(NvRmDeviceHandle hRm, int port,
- int pin, unsigned int enable)
+int tegra_gpio_io_power_config(int gpio_nr, unsigned int enable)
{
NvRmPmuVddRailCapabilities rail_caps;
NvU32 settling_time;
struct gpio_power_rail_info *gpio_io_power;
- int gpio_nr;
if (!is_gpio_rail_initailized) {
- discover_gpio_io_power_rail(hRm);
+ discover_gpio_io_power_rail();
is_gpio_rail_initailized = 1;
}
- gpio_nr = port * 8 + pin;
gpio_io_power = gpio_power_rail_map[gpio_nr];
/* Nothing to be done if there is no pmu rail
* associated with this port */
if (gpio_io_power->power_rail_address == 0)
- return NvSuccess;
+ return 0;
if (enable) {
- NvRmPmuGetCapabilities(hRm, gpio_io_power->power_rail_address,
+ NvRmPmuGetCapabilities(s_hRmGlobal, gpio_io_power->power_rail_address,
&rail_caps);
- NvRmPmuSetVoltage(hRm, gpio_io_power->power_rail_address,
+ NvRmPmuSetVoltage(s_hRmGlobal, gpio_io_power->power_rail_address,
rail_caps.requestMilliVolts,
&settling_time);
} else {
- NvRmPmuSetVoltage(hRm, gpio_io_power->power_rail_address,
+ NvRmPmuSetVoltage(s_hRmGlobal, gpio_io_power->power_rail_address,
ODM_VOLTAGE_OFF, &settling_time);
}
if (settling_time)
NvOsWaitUS(settling_time);
- return NvSuccess;
+ return 0;
}
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 905179934d33..f20aa44712bd 100644
--- a/arch/arm/mach-tegra/nvrm/io/ap15/nvrm_gpio.c
+++ b/arch/arm/mach-tegra/nvrm/io/ap15/nvrm_gpio.c
@@ -66,8 +66,7 @@
#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);
+extern int tegra_gpio_io_power_config(int gpio_nr, unsigned int enable);
typedef struct NvRmGpioPinInfoRec {
NvBool used;
@@ -470,16 +469,16 @@ NvError NvRmGpioConfigPins(NvRmGpioHandle hGpio,
if ((!s_hGpio->pPinInfo[gpio_nr].used)
&& (Mode != NvRmGpioPinMode_Inactive)) {
#if NV_ENABLE_GPIO_POWER_RAIL
- err = tegra_gpio_io_power_config(hGpio->hRm,
- alphaPort, pin, true);
+ ret_status = tegra_gpio_io_power_config(gpio_nr, true);
+ err = (NvError)ret_status;
#endif
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 = tegra_gpio_io_power_config(hGpio->hRm,
- alphaPort, pin, false);
+ ret_status = tegra_gpio_io_power_config(gpio_nr, false);
+ err = (NvError)ret_status;
#endif
NvRmSetGpioTristate(hGpio->hRm,
alphaPort, pin, NV_TRUE);
diff --git a/arch/arm/mach-tegra/nvrm/io/common/nvrm_i2c.c b/arch/arm/mach-tegra/nvrm/io/common/nvrm_i2c.c
index 4afb5e57383a..21cb61e44013 100644
--- a/arch/arm/mach-tegra/nvrm/io/common/nvrm_i2c.c
+++ b/arch/arm/mach-tegra/nvrm/io/common/nvrm_i2c.c
@@ -154,7 +154,6 @@ NvRmI2cOpen(
NvOsMutexHandle hThreadSaftyMutex = NULL;
const NvU32 *pOdmConfigs;
NvU32 NumOdmConfigs;
- NvU32 scl, sda;
NV_ASSERT(hRmDevice);
@@ -263,31 +262,12 @@ NvRmI2cOpen(
goto fail_1;
}
- /* Initalize the GPIO handles */
+ /* Initalize the GPIO handles only */
if (c->GetGpioPins)
{
status = NvRmGpioOpen(c->hRmDevice, &c->hGpio);
if(status)
goto fail_1;
- if (c->PinMapConfig != NvOdmI2cPinMap_Multiplexed)
- {
- if ((c->GetGpioPins)(c, c->PinMapConfig, &scl, &sda))
- {
- status = NvRmGpioAcquirePinHandle(c->hGpio, (scl >> 16),
- (scl & 0xFFFF), &c->hSclPin);
- if(!status)
- {
- status = NvRmGpioAcquirePinHandle(c->hGpio, (sda >> 16),
- (sda & 0xFFFF), &c->hSdaPin);
- if(status)
- {
- NvRmGpioReleasePinHandles(c->hGpio, &c->hSclPin, 1);
- c->hSclPin = 0;
- goto fail_1;
- }
- }
- }
- }
}
status = NvRmPowerRegister(hRmDevice, NULL, &c->I2cPowerClientId);
if (status != NvSuccess)
@@ -487,6 +467,7 @@ NvError NvRmI2cTransaction(
NvU32 Index;
NvU32 RSCount = 0; // repeat start count
NvS32 StartTransIndex = -1;
+ NvU32 scl, sda;
Index = ((NvU32)hI2c) & 0x7FFFFFFF;
@@ -552,7 +533,50 @@ NvError NvRmI2cTransaction(
if ((Transaction[0].Flags & NVRM_I2C_SOFTWARE_CONTROLLER) ||
(useGpioI2c == NV_TRUE))
{
- status = NvRmGpioI2cTransaction(c, I2cPinMap, Data, DataLength,
+ if (c->hGpio == NULL)
+ {
+ status = NvRmGpioOpen(c->hRmDevice, &c->hGpio);
+ if(status)
+ {
+ NvOsMutexUnlock(c->I2cThreadSafetyMutex);
+ return status;
+ }
+ }
+ /* Initalize the GPIO pin handles if it is not done */
+ if (c->GetGpioPins)
+ {
+ if (c->PinMapConfig != NvOdmI2cPinMap_Multiplexed)
+ {
+ if ((c->hSclPin == 0) || (c->hSdaPin == 0))
+ {
+ if ((c->GetGpioPins)(c, c->PinMapConfig, &scl, &sda))
+ {
+ status = NvRmGpioAcquirePinHandle(c->hGpio,
+ (scl >> 16), (scl & 0xFFFF),
+ &c->hSclPin);
+ if(!status)
+ {
+ status = NvRmGpioAcquirePinHandle(c->hGpio,
+ (sda >> 16), (sda & 0xFFFF),
+ &c->hSdaPin);
+ if(status)
+ {
+ NvRmGpioReleasePinHandles(c->hGpio,
+ &c->hSclPin, 1);
+ c->hSclPin = 0;
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ status = NvError_NotSupported;
+ }
+
+ if (status == NvSuccess)
+ status = NvRmGpioI2cTransaction(c, I2cPinMap, Data, DataLength,
Transaction, NumOfTransactions);
NvOsMutexUnlock(c->I2cThreadSafetyMutex);
return status;