diff options
author | Gary King <gking@nvidia.com> | 2010-05-14 10:36:33 -0700 |
---|---|---|
committer | Gary King <gking@nvidia.com> | 2010-05-14 20:04:06 -0700 |
commit | 106de33bf7f410bade659e110a5a7b187b46b8b2 (patch) | |
tree | 4d8231dc38fb3c05b6ccb911ff1e3b840d1d444b /arch/arm/mach-tegra/gpio.c | |
parent | e0426ba3077eae7e326c56487f34719f9638ddb5 (diff) |
[ARM/tegra] add NvRm, ODM services, ODM kit for harmony & whistler
add power rail support to GPIO driver
Change-Id: I45d4c1110a635047d68fb14f3e72a28f99acbe1b
Diffstat (limited to 'arch/arm/mach-tegra/gpio.c')
-rw-r--r-- | arch/arm/mach-tegra/gpio.c | 119 |
1 files changed, 94 insertions, 25 deletions
diff --git a/arch/arm/mach-tegra/gpio.c b/arch/arm/mach-tegra/gpio.c index afc926624deb..2f06f5849177 100644 --- a/arch/arm/mach-tegra/gpio.c +++ b/arch/arm/mach-tegra/gpio.c @@ -20,6 +20,7 @@ #include <linux/init.h> #include <linux/irq.h> #include <linux/interrupt.h> +#include <linux/delay.h> #include <linux/io.h> #include <linux/gpio.h> @@ -27,6 +28,11 @@ #include <mach/iomap.h> #include <mach/pinmux.h> +#include <mach/nvrm_linux.h> +#include "nvcommon.h" +#include "nvrm_pmu.h" +#include "nvodm_query_discovery.h" + #define GPIO_BANK(x) ((x) >> 5) #define GPIO_PORT(x) (((x) >> 3) & 0x3) #define GPIO_BIT(x) ((x) & 0x7) @@ -59,6 +65,7 @@ #define GPIO_INT_LVL_LEVEL_LOW 0x000000 extern int gpio_get_pinmux_group(int gpio_nr); +int tegra_gpio_io_power_config(int gpio_nr, unsigned int enable); struct tegra_gpio_bank { int bank; @@ -99,16 +106,6 @@ static void tegra_gpio_mask_write(u32 reg, int gpio, int value) __raw_writel(val, reg); } -void tegra_gpio_enable(int gpio) -{ - tegra_gpio_mask_write(GPIO_MSK_CNF(gpio), gpio, 1); -} - -void tegra_gpio_disable(int gpio) -{ - tegra_gpio_mask_write(GPIO_MSK_CNF(gpio), gpio, 0); -} - static void tegra_set_gpio_tristate(int gpio_nr, tegra_tristate_t ts) { tegra_pingroup_t pg; @@ -123,29 +120,29 @@ static void tegra_set_gpio_tristate(int gpio_nr, tegra_tristate_t ts) } } -static int tegra_gpio_request(struct gpio_chip *chip, unsigned offset) +void tegra_gpio_enable(int gpio) { - int port; - int pin; + WARN_ON(tegra_gpio_io_power_config(gpio, 1) != 0); + tegra_gpio_mask_write(GPIO_MSK_CNF(gpio), gpio, 1); + tegra_set_gpio_tristate(gpio, TEGRA_TRI_NORMAL); +} - port = GPIO_BANK(offset) * 4 + GPIO_PORT(offset); - pin = GPIO_BIT(offset); +void tegra_gpio_disable(int gpio) +{ + tegra_gpio_mask_write(GPIO_MSK_CNF(gpio), gpio, 0); + tegra_set_gpio_tristate(gpio, TEGRA_TRI_TRISTATE); + WARN_ON(tegra_gpio_io_power_config(gpio, 0) != 0); +} - tegra_gpio_mask_write(GPIO_MSK_CNF(offset), offset, 1); - tegra_set_gpio_tristate(offset, TEGRA_TRI_NORMAL); +static int tegra_gpio_request(struct gpio_chip *chip, unsigned offset) +{ + tegra_gpio_enable(offset); 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_mask_write(GPIO_MSK_CNF(offset), offset, 0); - tegra_set_gpio_tristate(offset, TEGRA_TRI_TRISTATE); + tegra_gpio_disable(offset); } static void tegra_gpio_set(struct gpio_chip *chip, unsigned offset, int value) @@ -385,6 +382,47 @@ static struct irq_chip tegra_gpio_irq_chip = { */ static struct lock_class_key gpio_lock_class; +struct gpio_power_rail_info { + NvU64 guid; + NvU32 address; + NvU32 mv; +}; + +static struct gpio_power_rail_info gpio_power_rail_table[] = { + [TEGRA_VDDIO_BB] = {.guid = NV_VDD_BB_ODM_ID,}, + [TEGRA_VDDIO_LCD] = {.guid = NV_VDD_LCD_ODM_ID,}, + [TEGRA_VDDIO_VI] = {.guid = NV_VDD_VI_ODM_ID,}, + [TEGRA_VDDIO_UART] = {.guid = NV_VDD_UART_ODM_ID,}, + [TEGRA_VDDIO_DDR] = {.guid = NV_VDD_DDR_ODM_ID,}, + [TEGRA_VDDIO_NAND] = {.guid = NV_VDD_NAND_ODM_ID,}, + [TEGRA_VDDIO_SYS] = {.guid = NV_VDD_SYS_ODM_ID,}, + [TEGRA_VDDIO_AUDIO] = {.guid = NV_VDD_AUD_ODM_ID,}, + [TEGRA_VDDIO_SD] = {.guid = NV_VDD_SDIO_ODM_ID,}, +}; + +static void gpio_rail_init(void) +{ + unsigned int i; + + if (!s_hRmGlobal) + return; + + for (i = 0; i < NV_ARRAY_SIZE(gpio_power_rail_table); i++) { + struct gpio_power_rail_info *rail = &gpio_power_rail_table[i]; + const NvOdmPeripheralConnectivity *conn; + NvRmPmuVddRailCapabilities caps; + + conn = NvOdmPeripheralGetGuid(rail->guid); + if (!conn || !conn->NumAddress) + continue; + + rail->address = conn->AddressList[0].Address; + + NvRmPmuGetCapabilities(NULL, rail->address, &caps); + rail->mv = (caps.RmProtected) ? 0 : caps.requestMilliVolts; + } +} + static int __init tegra_gpio_init(void) { struct tegra_gpio_bank *bank; @@ -420,6 +458,7 @@ static int __init tegra_gpio_init(void) spin_lock_init(&bank->lvl_lock[j]); } + gpio_rail_init(); return 0; } @@ -472,3 +511,33 @@ static int __init tegra_gpio_debuginit(void) } late_initcall(tegra_gpio_debuginit); #endif + +int tegra_gpio_io_power_config(int gpio_nr, unsigned int enable) +{ + struct gpio_power_rail_info *rail; + tegra_pingroup_t pg; + NvU32 settle; + int vddio_id; + + pg = gpio_get_pinmux_group(gpio_nr); + if (pg < 0) + return pg; + vddio_id = tegra_pinmux_get_vddio(pg); + if(vddio_id < 0) + return vddio_id; + + if (unlikely(!s_hRmGlobal)) + return 0; + + rail = &gpio_power_rail_table[vddio_id]; + if (!rail->address || !rail->mv) + return 0; + + NvRmPmuSetVoltage(s_hRmGlobal, rail->address, + (enable) ? rail->mv : ODM_VOLTAGE_OFF, &settle); + + if (settle) + udelay(settle); + + return 0; +} |