summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra/gpio.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-tegra/gpio.c')
-rw-r--r--arch/arm/mach-tegra/gpio.c360
1 files changed, 357 insertions, 3 deletions
diff --git a/arch/arm/mach-tegra/gpio.c b/arch/arm/mach-tegra/gpio.c
index 9448cad678b7..d40f3345e0af 100644
--- a/arch/arm/mach-tegra/gpio.c
+++ b/arch/arm/mach-tegra/gpio.c
@@ -21,14 +21,16 @@
*
*/
+#include "nvrm_pmu.h"
+#include "nvos.h"
+#include "nvodm_query_discovery.h"
+
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/io.h>
-
#include <asm/io.h>
#include <asm/gpio.h>
-
#define GPIO_BANK(x) ((x) >> 5)
#define GPIO_PORT(x) (((x) >> 3) & 0x3)
#define GPIO_BIT(x) ((x) & 0x7)
@@ -278,7 +280,7 @@ static int __init tegra_gpio_init(void)
unsigned long phys;
phys = tegra_get_module_inst_base("gpio",0);
- add_gpio_base = IO_ADDRESS(phys);
+ add_gpio_base = (unsigned long)IO_ADDRESS(phys);
for (i = 0; i < ARRAY_SIZE(tegra_gpio_banks); i++) {
for (j = 0; j < 4; j++) {
@@ -359,3 +361,355 @@ static int __init tegra_gpio_debuginit(void)
}
late_initcall(tegra_gpio_debuginit);
#endif
+
+struct gpio_power_rail_info {
+ /* SoC power rail GUID */
+ NvU64 power_rail_guid;
+
+ /* Pmu rail address */
+ NvU32 power_rail_address;
+};
+
+static unsigned int is_gpio_rail_initailized = 0;
+static struct gpio_power_rail_info gpio_power_rail_table[] = {
+ {.power_rail_guid = NV_VDD_SYS_ODM_ID, .power_rail_address = 0},
+ {.power_rail_guid = NV_VDD_BB_ODM_ID, .power_rail_address = 0},
+ {.power_rail_guid = NV_VDD_VI_ODM_ID, .power_rail_address = 0},
+ {.power_rail_guid = NV_VDD_SDIO_ODM_ID, .power_rail_address = 0},
+ {.power_rail_guid = NV_VDD_LCD_ODM_ID, .power_rail_address = 0},
+ {.power_rail_guid = NV_VDD_UART_ODM_ID, .power_rail_address = 0},
+};
+
+/* Initialize power rails for different gpios pins */
+static struct gpio_power_rail_info *gpio_power_rail_map[ARCH_NR_GPIOS] = {
+ /* Port a */
+ &gpio_power_rail_table[3],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[3],
+ &gpio_power_rail_table[3],
+
+ /* Port b */
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[4],
+ &gpio_power_rail_table[4],
+ &gpio_power_rail_table[3],
+ &gpio_power_rail_table[3],
+ &gpio_power_rail_table[3],
+ &gpio_power_rail_table[3],
+
+ /* Port c */
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[4],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[4],
+ &gpio_power_rail_table[5],
+
+ /* Port d */
+ &gpio_power_rail_table[3],
+ &gpio_power_rail_table[3],
+ &gpio_power_rail_table[3],
+ &gpio_power_rail_table[3],
+ &gpio_power_rail_table[3],
+ &gpio_power_rail_table[2],
+ &gpio_power_rail_table[2],
+ &gpio_power_rail_table[2],
+
+ /* Port e */
+ &gpio_power_rail_table[4],
+ &gpio_power_rail_table[4],
+ &gpio_power_rail_table[4],
+ &gpio_power_rail_table[4],
+ &gpio_power_rail_table[4],
+ &gpio_power_rail_table[4],
+ &gpio_power_rail_table[4],
+ &gpio_power_rail_table[4],
+
+ /* Port f */
+ &gpio_power_rail_table[4],
+ &gpio_power_rail_table[4],
+ &gpio_power_rail_table[4],
+ &gpio_power_rail_table[4],
+ &gpio_power_rail_table[4],
+ &gpio_power_rail_table[4],
+ &gpio_power_rail_table[4],
+ &gpio_power_rail_table[4],
+
+ /* Port g */
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+
+ /* Port h */
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+
+ /* Port i */
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+
+ /* Port j */
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[4],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[4],
+ &gpio_power_rail_table[4],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+
+ /* Port k */
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+
+ /* Port l */
+ &gpio_power_rail_table[2],
+ &gpio_power_rail_table[2],
+ &gpio_power_rail_table[2],
+ &gpio_power_rail_table[2],
+ &gpio_power_rail_table[2],
+ &gpio_power_rail_table[2],
+ &gpio_power_rail_table[2],
+ &gpio_power_rail_table[2],
+
+ /* Port m */
+ &gpio_power_rail_table[4],
+ &gpio_power_rail_table[4],
+ &gpio_power_rail_table[4],
+ &gpio_power_rail_table[4],
+ &gpio_power_rail_table[4],
+ &gpio_power_rail_table[4],
+ &gpio_power_rail_table[4],
+ &gpio_power_rail_table[4],
+
+ /* Port n */
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[4],
+ &gpio_power_rail_table[4],
+ &gpio_power_rail_table[4],
+ &gpio_power_rail_table[4],
+
+ /* Port o */
+ &gpio_power_rail_table[1],
+ &gpio_power_rail_table[1],
+ &gpio_power_rail_table[1],
+ &gpio_power_rail_table[1],
+ &gpio_power_rail_table[1],
+ &gpio_power_rail_table[1],
+ &gpio_power_rail_table[1],
+ &gpio_power_rail_table[1],
+
+ /* Port p */
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+
+ /* Port q */
+ &gpio_power_rail_table[0],
+ &gpio_power_rail_table[0],
+ &gpio_power_rail_table[0],
+ &gpio_power_rail_table[0],
+ &gpio_power_rail_table[0],
+ &gpio_power_rail_table[0],
+ &gpio_power_rail_table[0],
+ &gpio_power_rail_table[0],
+
+ /* Port r */
+ &gpio_power_rail_table[0],
+ &gpio_power_rail_table[0],
+ &gpio_power_rail_table[0],
+ &gpio_power_rail_table[0],
+ &gpio_power_rail_table[0],
+ &gpio_power_rail_table[0],
+ &gpio_power_rail_table[0],
+ &gpio_power_rail_table[0],
+
+ /* Port s */
+ &gpio_power_rail_table[0],
+ &gpio_power_rail_table[0],
+ &gpio_power_rail_table[0],
+ &gpio_power_rail_table[0],
+ &gpio_power_rail_table[0],
+ &gpio_power_rail_table[0],
+ &gpio_power_rail_table[0],
+ &gpio_power_rail_table[0],
+
+ /* Port t */
+ &gpio_power_rail_table[2],
+ &gpio_power_rail_table[2],
+ &gpio_power_rail_table[2],
+ &gpio_power_rail_table[2],
+ &gpio_power_rail_table[2],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+
+ /* Port u */
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+
+ /* Port v */
+ &gpio_power_rail_table[1],
+ &gpio_power_rail_table[1],
+ &gpio_power_rail_table[1],
+ &gpio_power_rail_table[1],
+ &gpio_power_rail_table[3],
+ &gpio_power_rail_table[3],
+ &gpio_power_rail_table[3],
+ &gpio_power_rail_table[4],
+
+ /* Port w */
+ &gpio_power_rail_table[4],
+ &gpio_power_rail_table[4],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+
+ /* Port x */
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+
+ /* Port y */
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+
+ /* Port z */
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+
+ /* Port AA */
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+
+ /* Port BB */
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5],
+ &gpio_power_rail_table[5]
+};
+
+static void discover_gpio_io_power_rail(NvRmDeviceHandle hRm)
+{
+ unsigned int i;
+ const NvOdmPeripheralConnectivity* connectivity = NULL;
+
+ for (i = 0; i < NV_ARRAY_SIZE(gpio_power_rail_table); i++) {
+ connectivity = NvOdmPeripheralGetGuid(
+ gpio_power_rail_table[i].power_rail_guid);
+ if (!connectivity || !connectivity->NumAddress)
+ continue;
+ gpio_power_rail_table[i].power_rail_address =
+ connectivity->AddressList[0].Address;
+ }
+}
+NvError tegra_gpio_io_power_config(NvRmDeviceHandle hRm, int port,
+ int pin, 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);
+ 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;
+
+ if (enable) {
+ NvRmPmuGetCapabilities(hRm, gpio_io_power->power_rail_address,
+ &rail_caps);
+ NvRmPmuSetVoltage(hRm, gpio_io_power->power_rail_address,
+ rail_caps.requestMilliVolts,
+ &settling_time);
+ } else {
+ NvRmPmuSetVoltage(hRm, gpio_io_power->power_rail_address,
+ ODM_VOLTAGE_OFF, &settling_time);
+ }
+ if (settling_time)
+ NvOsWaitUS(settling_time);
+
+ return NvSuccess;
+}