diff options
-rw-r--r-- | arch/arm/mach-tegra/gpio.c | 360 | ||||
-rw-r--r-- | arch/arm/mach-tegra/nvrm/io/ap15/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/mach-tegra/nvrm/io/ap15/ap15rm_gpio_vi.c | 10 | ||||
-rw-r--r-- | arch/arm/mach-tegra/nvrm/io/ap15/nvrm_gpio.c | 950 | ||||
-rw-r--r-- | arch/arm/mach-tegra/nvrm/io/ap15/nvrm_gpio_private.c | 186 | ||||
-rw-r--r-- | arch/arm/mach-tegra/nvrm/io/ap15/nvrm_gpio_private.h | 129 | ||||
-rw-r--r-- | arch/arm/mach-tegra/odm_kit/adaptations/misc/harmony/nvodm_usbulpi.c | 63 |
7 files changed, 850 insertions, 849 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; +} diff --git a/arch/arm/mach-tegra/nvrm/io/ap15/Makefile b/arch/arm/mach-tegra/nvrm/io/ap15/Makefile index 3148c14ba4d7..656d900e32ad 100644 --- a/arch/arm/mach-tegra/nvrm/io/ap15/Makefile +++ b/arch/arm/mach-tegra/nvrm/io/ap15/Makefile @@ -22,7 +22,6 @@ obj-y += ap15rm_pwm.o obj-y += ap15rm_gpio_vi.o obj-y += nvrm_dma.o obj-y += nvrm_gpio.o -obj-y += nvrm_gpio_private.o obj-y += nvrm_gpio_stub_helper.o obj-y += ap15rm_dma_intr.o obj-y += rm_spi_hw_private.o diff --git a/arch/arm/mach-tegra/nvrm/io/ap15/ap15rm_gpio_vi.c b/arch/arm/mach-tegra/nvrm/io/ap15/ap15rm_gpio_vi.c index dfad64c856c0..ac6fc966d44f 100644 --- a/arch/arm/mach-tegra/nvrm/io/ap15/ap15rm_gpio_vi.c +++ b/arch/arm/mach-tegra/nvrm/io/ap15/ap15rm_gpio_vi.c @@ -29,14 +29,16 @@ * POSSIBILITY OF SUCH DAMAGE. * */ - #include "ap15/ap15rm_gpio_vi.h" -#include "nvrm_gpio_private.h" -#include "nvassert.h" +#include "nvrm_pmu.h" +#include "nvrm_gpio.h" #include "nvos.h" +#include "ap15/ap15rm_private.h" #include "ap15/arvi.h" +#include "nvrm_structure.h" +#include "nvrm_hwintf.h" #include "nvodm_query_discovery.h" -#include "nvrm_pmu.h" +#include "nvassert.h" #define NV_ENABLE_VI_POWER_RAIL 1 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; } - diff --git a/arch/arm/mach-tegra/nvrm/io/ap15/nvrm_gpio_private.c b/arch/arm/mach-tegra/nvrm/io/ap15/nvrm_gpio_private.c deleted file mode 100644 index 361413dec1a1..000000000000 --- a/arch/arm/mach-tegra/nvrm/io/ap15/nvrm_gpio_private.c +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright (c) 2007-2009 NVIDIA Corporation. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NVIDIA Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "nvrm_gpio_private.h" -#include "nvassert.h" -#include "nvos.h" - -static NvRmGpioCaps s_ap15_caps = {6, 4, GPIO_PINS_PER_PORT, NVRM_GPIO_CAP_FEAT_EDGE_INTR /* (SEE BUG# 366493) */}; - -static NvRmModuleCapability s_capsArray[] = { - /* Major, minor, eco and caps structure */ - { 2, 0, 0, &s_ap15_caps }, -}; - -static NvBool s_GpioIoPowerInitialized = NV_FALSE; - -static NvRmGpioIoPowerInfo s_GpioIoPowerTable[] = -{ - {NV_VDD_SYS_ODM_ID, 0}, - {NV_VDD_BB_ODM_ID, 0}, - {NV_VDD_VI_ODM_ID, 0}, - {NV_VDD_SDIO_ODM_ID, 0}, - {NV_VDD_LCD_ODM_ID, 0}, - {NV_VDD_UART_ODM_ID, 0} -}; - -NvError -NvRmGpioGetCapabilities( - NvRmDeviceHandle hRm, - void **Capability ) -{ - NvError err = NvSuccess; - - NV_ASSERT(hRm); - - err = NvRmModuleGetCapabilities(hRm, NvRmPrivModuleID_Gpio, s_capsArray, - NV_ARRAY_SIZE(s_capsArray), Capability); - if (err) - { - /* Default to AP15 caps. - FIXME: findout why the RM API is returning failure. */ - NV_ASSERT(0); - *Capability = (void*)&s_ap15_caps; - } - - ((NvRmGpioCaps *)*Capability)->Instances = - NvRmModuleGetNumInstances(hRm, NvRmPrivModuleID_Gpio); - - return err; -} - -static NvError NvRmGpioIoPowerDiscover( - NvRmDeviceHandle hRm) -{ - NvU32 i; - const NvOdmPeripheralConnectivity* pCon = NULL; - - for (i = 0; i < NV_ARRAY_SIZE(s_GpioIoPowerTable); i++) - { - pCon = NvOdmPeripheralGetGuid(s_GpioIoPowerTable[i].PowerRailId); - if (!pCon || !pCon->NumAddress) - return NvError_NotSupported; - s_GpioIoPowerTable[i].PmuRailAddress = pCon->AddressList[0].Address; - } - return NvSuccess; -} - -NvError NvRmGpioIoPowerConfig( - NvRmDeviceHandle hRm, - NvU32 port, - NvU32 pinNumber, - NvBool Enable) -{ - NvRmPmuVddRailCapabilities RailCaps; - NvU32 SettlingTime; - NvRmGpioIoPowerInfo *pGpioIoPower; - - if (!s_GpioIoPowerInitialized) - { - NvError err = NvRmGpioIoPowerDiscover(hRm); - if (err) - return err; - s_GpioIoPowerInitialized = NV_TRUE; - } - - if ((port == GPIO_PORT('s')) || - (port == GPIO_PORT('q')) || - (port == GPIO_PORT('r'))) - { - /* NV_VDD_SYS_ODM_ID */ - pGpioIoPower = &s_GpioIoPowerTable[0]; - } - else if ((port == GPIO_PORT('o')) || - ((port == GPIO_PORT('v')) && (pinNumber < 4))) - { - /* NV_VDD_BB_ODM_ID */ - pGpioIoPower = &s_GpioIoPowerTable[1]; - } - else if ((port == GPIO_PORT('l')) || - ((port == GPIO_PORT('d')) && (pinNumber > 4)) || - ((port == GPIO_PORT('t')) && (pinNumber < 5))) - { - /* NV_VDD_VI_ODM_ID */ - pGpioIoPower = &s_GpioIoPowerTable[2]; - } - else if (((port == GPIO_PORT('d')) && (pinNumber < 5)) || - ((port == GPIO_PORT('b')) && (pinNumber > 3)) || - ((port == GPIO_PORT('v')) && ((pinNumber > 3) && - (pinNumber < 7))) || - ((port == GPIO_PORT('a')) && ((pinNumber > 5) || - (pinNumber == 0)))) - { - /* NV_VDD_SDIO_ODM_ID */ - pGpioIoPower = &s_GpioIoPowerTable[3]; - } - else if ((port == GPIO_PORT('e')) || - (port == GPIO_PORT('f')) || - (port == GPIO_PORT('m')) || - ((port == GPIO_PORT('c')) && ((pinNumber == 1) || - (pinNumber == 6))) || - ((port == GPIO_PORT('w')) && (pinNumber < 2)) || - ((port == GPIO_PORT('j')) && ((pinNumber == 1) || - (pinNumber == 3) || (pinNumber == 4))) || - ((port == GPIO_PORT('v')) && (pinNumber == 7)) || - ((port == GPIO_PORT('n')) && (pinNumber > 3)) || - ((port == GPIO_PORT('b')) && ((pinNumber == 2) || - (pinNumber == 3)))) - { - /* NV_VDD_LCD_ODM_ID */ - pGpioIoPower = &s_GpioIoPowerTable[4]; - } - else - { - /* NV_VDD_UART_ODM_ID */ - pGpioIoPower = &s_GpioIoPowerTable[5]; - } - - if (Enable) - { - NvRmPmuGetCapabilities(hRm, - pGpioIoPower->PmuRailAddress, &RailCaps); - NvRmPmuSetVoltage(hRm, - pGpioIoPower->PmuRailAddress, - RailCaps.requestMilliVolts, &SettlingTime); - } - else - { - NvRmPmuSetVoltage(hRm, - pGpioIoPower->PmuRailAddress, - ODM_VOLTAGE_OFF, &SettlingTime); - } - if (SettlingTime) - NvOsWaitUS(SettlingTime); - - return NvSuccess; -} - diff --git a/arch/arm/mach-tegra/nvrm/io/ap15/nvrm_gpio_private.h b/arch/arm/mach-tegra/nvrm/io/ap15/nvrm_gpio_private.h deleted file mode 100644 index deb48f2d97f5..000000000000 --- a/arch/arm/mach-tegra/nvrm/io/ap15/nvrm_gpio_private.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (c) 2007-2009 NVIDIA Corporation. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NVIDIA Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef INCLUDED_NVRM_GPIO_PRIVATE_H -#define INCLUDED_NVRM_GPIO_PRIVATE_H - -#include "nvrm_gpio.h" -#include "ap15/argpio.h" -#include "nvrm_structure.h" -#include "ap15/ap15rm_private.h" -#include "nvrm_hwintf.h" -#include "nvodm_query_discovery.h" -#include "nvrm_pmu.h" - -#define GPIO_INTR_MAX 32 -#define GPIO_PORT(x) ((x) - 'a') -#define GET_PIN(h) ((((NvU32)(h))) & 0xFF) -#define GET_PORT(h) ((((NvU32)(h)) >> 8) & 0xFF) -#define GET_INSTANCE(h) ((((NvU32)(h)) >> 16) & 0xFF) - -// Size of a port register. -#define NV_GPIO_PORT_REG_SIZE (GPIO_CNF_1 - GPIO_CNF_0) -#define GPIO_INT_LVL_UNSHADOWED_MASK \ - (GPIO_INT_LVL_0_BIT_7_FIELD | GPIO_INT_LVL_0_BIT_6_FIELD | \ - GPIO_INT_LVL_0_BIT_5_FIELD | GPIO_INT_LVL_0_BIT_4_FIELD | \ - GPIO_INT_LVL_0_BIT_3_FIELD | GPIO_INT_LVL_0_BIT_2_FIELD | \ - GPIO_INT_LVL_0_BIT_1_FIELD | GPIO_INT_LVL_0_BIT_0_FIELD) - -#define GPIO_INT_LVL_SHADOWED_MASK (~GPIO_INT_LVL_UNSHADOWED_MASK) - -// Gpio register read/write macros - -#define GPIO_PINS_PER_PORT 8 - -#define GPIO_MASKED_WRITE(rm, Instance, Port, Reg, Pin, value) \ - do \ - { \ - NV_REGW((rm), NvRmPrivModuleID_Gpio, (Instance), ((Port) * NV_GPIO_PORT_REG_SIZE) + GPIO_MSK_CNF_0 + \ - (GPIO_##Reg##_0), (((1<<((Pin)+ GPIO_PINS_PER_PORT)) | ((value) << (Pin))))); \ - } while (0) - - -// Gpio register read/write macros -#define GPIO_REGR( rm, Instance, Port, Reg, ReadData) \ - do \ - { \ - ReadData = NV_REGR((rm), NvRmPrivModuleID_Gpio, (Instance), ((Port) * NV_GPIO_PORT_REG_SIZE) + \ - (GPIO_##Reg##_0)); \ - } while (0) - -#define GPIO_REGW( rm, Instance, Port, Reg, Data2Write ) \ - do \ - { \ - NV_REGW((rm), NvRmPrivModuleID_Gpio, (Instance), ((Port) * NV_GPIO_PORT_REG_SIZE) + \ - (GPIO_##Reg##_0), (Data2Write)); \ - } while (0) - -/* Bit mask of hardware features present in GPIO controller. */ -typedef enum { - NVRM_GPIO_CAP_FEAT_NONE = 0, - NVRM_GPIO_CAP_FEAT_EDGE_INTR = 0x000000001 -} NvRmGpioCapFeatures; - - -typedef struct NvRmGpioCapsRec { - NvU32 Instances; - NvU32 PortsPerInstances; - NvU32 PinsPerPort; - NvU32 Features; -} NvRmGpioCaps; - -typedef struct NvRmGpioIoPowerInfoRec -{ - // SoC Power rail GUID - NvU64 PowerRailId; - - // PMU Rail Address - NvU32 PmuRailAddress; - -} NvRmGpioIoPowerInfo; - -/** - * GPIO wrapper for NvRmModuleGetCapabilities(). - * - * @param hRm The RM device handle - * @param Capability Out parameter: the cap that maches the current hardware - */ -NvError -NvRmGpioGetCapabilities( - NvRmDeviceHandle hRm, - void **Capability ); - -NvError NvRmGpioIoPowerConfig( - NvRmDeviceHandle hRm, - NvU32 port, - NvU32 pinNumber, - NvBool Enable); - -#endif // INCLUDED_NVRM_GPIO_PRIVATE_H - diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/misc/harmony/nvodm_usbulpi.c b/arch/arm/mach-tegra/odm_kit/adaptations/misc/harmony/nvodm_usbulpi.c index 113879b3afdd..63bdf09a14ae 100644 --- a/arch/arm/mach-tegra/odm_kit/adaptations/misc/harmony/nvodm_usbulpi.c +++ b/arch/arm/mach-tegra/odm_kit/adaptations/misc/harmony/nvodm_usbulpi.c @@ -47,6 +47,8 @@ #define MAX_CLOCKS 3 #define NVODM_PORT(x) ((x) - 'a') +#define ULPI_RESET_PORT NVODM_PORT('v') +#define ULPI_RESET_PIN 1 #ifdef NV_DRIVER_DEBUG @@ -60,45 +62,64 @@ typedef struct NvOdmUsbUlpiRec NvU64 CurrentGUID; } NvOdmUsbUlpi; +static NvOdmServicesGpioHandle s_hGpio = NULL; +static NvOdmGpioPinHandle s_hResetPin = NULL; + NvOdmUsbUlpiHandle NvOdmUsbUlpiOpen(NvU32 Instance) { NvOdmUsbUlpi*pDevice = NULL; NvU32 ClockInstances[MAX_CLOCKS]; NvU32 ClockFrequencies[MAX_CLOCKS]; NvU32 NumClocks; - NvOdmServicesGpioHandle hGpio; - NvOdmGpioPinHandle hResetPin; - NvU32 Port = NVODM_PORT('v'); - NvU32 Pin = 1; pDevice = NvOdmOsAlloc(sizeof(NvOdmUsbUlpi)); if(pDevice == NULL) - goto ExitUlpiOdm; + return NULL; - if(!NvOdmExternalClockConfig(SMSC3317GUID, NV_FALSE, ClockInstances, ClockFrequencies, &NumClocks)) + if(!NvOdmExternalClockConfig(SMSC3317GUID, NV_FALSE, ClockInstances, + ClockFrequencies, &NumClocks)) { - NV_DRIVER_TRACE (("ERROR NvOdmUsbUlpiOpen: NvOdmExternalClockConfig fail\n")); + NV_DRIVER_TRACE (("ERROR NvOdmUsbUlpiOpen: " + "NvOdmExternalClockConfig fail\n")); goto ExitUlpiOdm; } NvOdmOsSleepMS(10); + + if (!s_hGpio) + s_hGpio = NvOdmGpioOpen(); + if (!s_hGpio) + { + NV_DRIVER_TRACE (("ERROR NvOdmUsbUlpiOpen: " + "Not able to open gpio handle\n")); + goto ExitUlpiOdm; + } + + if (!s_hResetPin) + s_hResetPin = NvOdmGpioAcquirePinHandle(s_hGpio, ULPI_RESET_PORT, + ULPI_RESET_PIN); + if (!s_hResetPin) + { + NvOdmGpioClose(s_hGpio); + s_hGpio = NULL; + NV_DRIVER_TRACE (("ERROR NvOdmGpioAcquirePinHandle: " + "Not able to Acq pinhandle\n")); + goto ExitUlpiOdm; + } + // Pull high on RESETB ( 22nd pin of smsc3315) - hGpio = NvOdmGpioOpen(); - hResetPin = NvOdmGpioAcquirePinHandle(hGpio, Port, Pin); // config as out put pin - NvOdmGpioConfig(hGpio,hResetPin, NvOdmGpioPinMode_Output); + NvOdmGpioConfig(s_hGpio,s_hResetPin, NvOdmGpioPinMode_Output); // Set low to write high on ULPI_RESETB pin - NvOdmGpioSetState(hGpio, hResetPin, 0x01); - NvOdmGpioSetState(hGpio, hResetPin, 0x0); + NvOdmGpioSetState(s_hGpio, s_hResetPin, 0x01); + NvOdmGpioSetState(s_hGpio, s_hResetPin, 0x0); NvOdmOsSleepMS(5); - NvOdmGpioSetState(hGpio, hResetPin, 0x01); + NvOdmGpioSetState(s_hGpio, s_hResetPin, 0x01); pDevice->CurrentGUID = SMSC3317GUID; return pDevice; ExitUlpiOdm: NvOdmOsFree(pDevice); - pDevice = NULL; - return NULL; } @@ -107,7 +128,17 @@ void NvOdmUsbUlpiClose(NvOdmUsbUlpiHandle hOdmUlpi) if (hOdmUlpi) { NvOdmOsFree(hOdmUlpi); - hOdmUlpi = NULL; } + if (s_hResetPin) + { + NvOdmGpioReleasePinHandle(s_hGpio, s_hResetPin); + s_hResetPin = NULL; + } + if (s_hGpio) + { + NvOdmGpioClose(s_hGpio); + s_hGpio = NULL; + } + } |