
/*****************************************************************************
* Copyright (c) 2003 Digi International Inc., All Rights Reserved
* 
* This software contains proprietary and confidential information of Digi
* International Inc.  By accepting transfer of this copy, Recipient agrees
* to retain this software in confidence, to prevent disclosure to others,
* and to make no use of this software other than that for which it was
* delivered.  This is an unpublished copyrighted work of Digi International
* Inc.  Except as permitted by federal law, 17 USC 117, copying is strictly
* prohibited.
* 
* Restricted Rights Legend
*
* Use, duplication, or disclosure by the Government is subject to
* restrictions set forth in sub-paragraph (c)(1)(ii) of The Rights in
* Technical Data and Computer Software clause at DFARS 252.227-7031 or
* subparagraphs (c)(1) and (2) of the Commercial Computer Software -
* Restricted Rights at 48 CFR 52.227-19, as applicable.
*
* Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
*
*****************************************************************************/
/*
 * $Log: processorgpio.c,v $
 * Revision 1.2.2.3  2008/09/17 16:27:48  lzhen
 * Use HW RTS toggle to support CRTSTOGGLE when predelay and postdelay are both zero,
 * in this case, the RTS pin has to use the default GPIO function for RTS. Vantive:        27819
 *
 *
 * Revision 1.2  2007/07/18 18:42:42  vshankar
 * Used polarity and level/edge trigger to set external interrupt control register
 *
 * Revision 1.1  2007/07/13 15:29:50  vshankar
 * New file for NS9215 and NS9210 processors
 *
 *
 */
#include <assert.h>
#include "processorgpio.h"
#include <Npttypes.h>
#include <gpiomux_def.h>
#include <io_ctrl_mod.h>
#include <scm_reg.h>

#ifndef BOOT_LOADER
#include "NA_ISR.h"
#endif

int ProcessorGpioSetInput(unsigned long addr, unsigned long bit)
{
    unsigned long gpio = addr*32 + bit;

    return (NAconfigureGPIOpin(gpio, NA_GPIO_INPUT_STATE, 0) == SUCCESS);
}

int ProcessorGpioSetOutput(unsigned long addr, unsigned long bit, unsigned long default_value)
{
    unsigned long gpio = addr*32 + bit;

    return (NAconfigureGPIOpin(gpio, NA_GPIO_OUTPUT_STATE, default_value) == SUCCESS);
}

/* Returns 0 or non-zero. */
unsigned long ProcessorGpioGetValue(unsigned long addr, unsigned long bit)
{
    unsigned long gpio = addr*32 + bit;
    unsigned int value;

    NAgetGPIOpin(gpio, &value); 

    return value;
}

/* value is zero or non-zero.  GPIO pin will be set based on it. */
int ProcessorGpioSetOutputValue(unsigned long addr, unsigned long bit, unsigned long value)
{
    unsigned long gpio = addr*32 + bit;

    return (NAconfigureGPIOpin(gpio, NA_GPIO_OUTPUT_STATE, value) == SUCCESS);
}

int ProcessorGpioSetFunction(unsigned long addr, unsigned long bit, int gpio_function)
{
    unsigned long gpio = addr*32 + bit;
    
    return (NAconfigureGPIOpin(gpio, gpio_function, 0) == SUCCESS);
}

#ifndef BOOT_LOADER
/* This is the table for NS9750. */
typedef struct interrupt_table_t {
    int gpio;		    /* GPIO number 0-49. */
    unsigned char function; /* Which gpio function is interrupt. */
    int irq;		    /* IRQ SOURCE */
    int idx;            /* IRQ index */
} interrupt_table_t;

interrupt_table_t ns9215_interrupt_table[] = {
/* gpio, function, irq */
    {1,   NA_GPIO_FUNC1_STATE, EXTERNAL0_INTERRUPT, 0},
    {9,   NA_GPIO_FUNC2_STATE, EXTERNAL0_INTERRUPT, 0},
    {16,  NA_GPIO_FUNC2_STATE, EXTERNAL0_INTERRUPT, 0},
    {104, NA_GPIO_FUNC2_STATE, EXTERNAL0_INTERRUPT, 0},
    {2,   NA_GPIO_FUNC1_STATE, EXTERNAL1_INTERRUPT, 1},
    {10,  NA_GPIO_FUNC2_STATE, EXTERNAL1_INTERRUPT, 1},
    {17,  NA_GPIO_FUNC2_STATE, EXTERNAL1_INTERRUPT, 1},
    {105, NA_GPIO_FUNC2_STATE, EXTERNAL1_INTERRUPT, 1},
    {4,   NA_GPIO_FUNC1_STATE, EXTERNAL2_INTERRUPT, 2},
    {11,  NA_GPIO_FUNC2_STATE, EXTERNAL2_INTERRUPT, 2},
    {18,  NA_GPIO_FUNC2_STATE, EXTERNAL2_INTERRUPT, 2},
    {106, NA_GPIO_FUNC2_STATE, EXTERNAL2_INTERRUPT, 2},
    {5,   NA_GPIO_FUNC1_STATE, EXTERNAL3_INTERRUPT, 3},
#if (PROCESSOR == ns9215)
    {67,  NA_GPIO_FUNC2_STATE, EXTERNAL3_INTERRUPT, 3},
    {101, NA_GPIO_FUNC2_STATE, EXTERNAL3_INTERRUPT, 3},
#endif
    {19,  NA_GPIO_FUNC2_STATE, EXTERNAL3_INTERRUPT, 3}
};


int ProcessorGpioSetInterrupt(unsigned long addr, unsigned long bit, int level, int edge_trigger)
{
    int i;
    unsigned long gpio = addr*32 + bit;

    for (i = 0; i < (int)(sizeof(ns9215_interrupt_table)
	    /sizeof(ns9215_interrupt_table[0])); i++)
    {
        if (gpio == (unsigned long) ns9215_interrupt_table[i].gpio)
        {            
            if (NAconfigureGPIOpin(gpio, ns9215_interrupt_table[i].function, 0) != SUCCESS)
                return -1;
            else
            {
                /* set it as edge trigger */
                narm_write_reg (NA_SCM_EICR_REG, NA_SCM_EICR_GET_ADDRESS(ns9215_interrupt_table[i].idx), lvedg, edge_trigger);
                narm_write_reg (NA_SCM_EICR_REG, NA_SCM_EICR_GET_ADDRESS(ns9215_interrupt_table[i].idx), plty, level);
                
                return ns9215_interrupt_table[i].irq;
            }
        }
    }
    
    return -1;
}
#endif /* !BOOT_LOADER */

#if defined(NS9215)
    #define VALID_GPIO_PIN(channel)     (channel < 108)
#elif defined(NS9210)
/*
 * NS9210 is the same as the NS9215, except it is in a smaller package with
 * fewer pins.  GPIO pins 50-103 don't exist in the NS9210 package.  GPIO
 * pins 104-107 are actually address lines 24 through 27.
 */
    #define VALID_GPIO_PIN(channel)     (   (channel < 50) \
                                         || ((channel > 103) && (channel < 108)) \
                                         ) 
#endif


int ProcessorGpioPin(int pin, unsigned long *addr, unsigned long *gpio_pin)
{
    if (!VALID_GPIO_PIN(pin))
        return FALSE;
    *addr = pin / 32;
    *gpio_pin = pin % 32;
    return TRUE;
}


int ProcessorGpioGetAddress(unsigned long *addr, unsigned long *pin)
{
    int gpio = (*addr * 32) + *pin;

    if (VALID_GPIO_PIN(gpio))
    { 
        *addr = (unsigned long)NA_GPIO_CONFIG_getAddress(gpio);
        return TRUE;
    }
    
    return FALSE;
}

