s5p6818 gpio controller driver


s5p6818 gpio controller driver implementation analysis

linux version 3.4.39

lable 1:

GPIO platform_device_register();

/* arch/arm/mach-s5p6818/devices.c */

/*------------------------------------------------------------------------------
 * register cpu platform devices
 */
void __init nxp_cpu_devs_register(void)
{
#if defined(CONFIG_GPIO_NXP)
	printk("mach: add device generic gpio (array:%d)\n", ARRAY_SIZE(gpio_devices));
	platform_add_devices(gpio_devices, ARRAY_SIZE(gpio_devices));
#endif
}

/*------------------------------------------------------------------------------
 * GPIO device
 */
#if defined(CONFIG_GPIO_NXP)
#if defined(CONFIG_GPIO_NXP_GROUP_A)
static struct resource gpio_resource_A = {
	.start	=  0,
	.end	= 32,
	.flags	= IORESOURCE_IO,
};
static struct platform_device gpio_device_A = {
	.name	= DEV_NAME_GPIO,
	.id		= 0,
	.resource	= &gpio_resource_A,
	.num_resources	= 1,
};
#endif
#if defined(CONFIG_GPIO_NXP_GROUP_B)
static struct resource gpio_resource_B = {
	.start	=  0,
	.end	= 32,
	.flags	= IORESOURCE_IO,
};
static struct platform_device gpio_device_B = {
	.name	= DEV_NAME_GPIO,
	.id		= 1,
	.resource	= &gpio_resource_B,
	.num_resources	= 1,
};
#endif
#if defined(CONFIG_GPIO_NXP_GROUP_C)
static struct resource gpio_resource_C = {
	.start	=  0,
	.end	= 32,
	.flags	= IORESOURCE_IO,
};
static struct platform_device gpio_device_C  = {
	.name	= DEV_NAME_GPIO,
	.id		= 2,
	.resource	= &gpio_resource_C,
	.num_resources	= 1,
};
#endif
#if defined(CONFIG_GPIO_NXP_GROUP_D)
static struct resource gpio_resource_D = {
	.start	=  0,
	.end	= 32,
	.flags	= IORESOURCE_IO,
};
static struct platform_device gpio_device_D  = {
	.name	= DEV_NAME_GPIO,
	.id		= 3,
	.resource	= &gpio_resource_D,
	.num_resources	= 1,
};
#endif
#if defined(CONFIG_GPIO_NXP_GROUP_E)
static struct resource gpio_resource_E = {
	.start	=  0,
	.end	= 32,
	.flags	= IORESOURCE_IO,
};
static struct platform_device gpio_device_E  = {
	.name	= DEV_NAME_GPIO,
	.id		= 4,
	.resource	= &gpio_resource_E,
	.num_resources	 = 1,
};
#endif
#if defined(CONFIG_GPIO_NXP_GROUP_ALV)
static struct resource gpio_resource_ALV = {
	.start	=  0,
	.end	=  6,
	.flags	= IORESOURCE_IO,
};
static struct platform_device gpio_device_ALV  = {
	.name	= DEV_NAME_GPIO,
	.id		= 5,
	.resource	= &gpio_resource_ALV,
	.num_resources	= 1,
};
#endif

static struct platform_device *gpio_devices[] = {
#if defined(CONFIG_GPIO_NXP_GROUP_A)
	&gpio_device_A,
#endif
#if defined(CONFIG_GPIO_NXP_GROUP_B)
	&gpio_device_B,
#endif
#if defined(CONFIG_GPIO_NXP_GROUP_C)
	&gpio_device_C,
#endif
#if defined(CONFIG_GPIO_NXP_GROUP_D)
	&gpio_device_D,
#endif
#if defined(CONFIG_GPIO_NXP_GROUP_E)
	&gpio_device_E,
#endif
#if defined(CONFIG_GPIO_NXP_GROUP_ALV)
	&gpio_device_ALV,
#endif
};
#endif /* CONFIG_GPIO_NXP */

GPIO platform_driver_register();
probe, gpiochip_add(&gpio->chip);

/* drivers/gpio/gpio-nxp.c */

/*
 * Copyright (C) 2008, 2009 Provigent Ltd.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * Driver for the ARM PrimeCell(tm) General Purpose Input/Output (PL061)
 *
 * Data sheet: ARM DDI 0190B, September 2000
 */
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/pm.h>

#include <mach/platform.h>
#include <mach/devices.h>
#include <mach/soc.h>

/*
#define pr_debug(msg...)		{ printk(KERN_INFO "gpio: " msg); }
*/

#if (0)
#define CHECK_ALTFUNC_RET(_gpio, _offs, _ret)	do {		\
		int io = (_gpio->index * GPIO_NUM_PER_BANK) + _offs;		\
		int cn = nxp_soc_gpio_get_io_func(io);						\
		int fn = GET_GPIO_ALTFUNC(_gpio->index, _offs);				\
		if (cn != fn) {												\
			printk("Fail : io used alt function %d [%s:%u=%d]\n",	\
			cn, io_name[_gpio->index], _offs, io);					\
			return _ret; 	\
		}					\
	} while(0)
#else
#define	CHECK_ALTFUNC_RET(_gpio, _offs, _ret)	do { } while (0)
#endif

struct nxp_gpio {
	int 		index; 		/* Bank Index : A(0), B(1), C(2), D(3), E(4), ALIVE(5) */
	spinlock_t	lock;		/* GPIO registers */
	struct 	gpio_chip chip;
};

static const char *io_name[] = { "GPIOA", "GPIOB", "GPIOC", "GPIOD", "GPIOE", "GPIOALV" };
#define	GET_GPIO(c)	container_of(chip, struct nxp_gpio, chip)

static int nxp_gpio_request(struct gpio_chip *chip, unsigned offset)
{
	struct nxp_gpio *gpio = GET_GPIO(chip);
	int io, fn;

	io = (gpio->index * GPIO_NUM_PER_BANK) + offset;
	fn = GET_GPIO_ALTFUNC(gpio->index, offset);

	CHECK_ALTFUNC_RET(gpio, offset, EINVAL);

	nxp_soc_gpio_set_io_func(io, fn);
	pr_debug("%s: io [%s:%d=%d]\n", __func__, io_name[gpio->index], offset, io);

	return 0;
}

static int nxp_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
{
	struct nxp_gpio *gpio = GET_GPIO(chip);
	int io, fn;

	io = (gpio->index * GPIO_NUM_PER_BANK) + offset;
	fn = GET_GPIO_ALTFUNC(gpio->index, offset);

	CHECK_ALTFUNC_RET(gpio, offset, EINVAL);

	nxp_soc_gpio_set_io_func(io, fn);
	nxp_soc_gpio_set_io_dir(io, 0);

	pr_debug("%s: io [%s:%d=%d]\n", __func__, io_name[gpio->index], offset, io);
	return 0;
}

static int nxp_gpio_direction_output(struct gpio_chip *chip,
				unsigned offset, int value)
{
	struct nxp_gpio *gpio = GET_GPIO(chip);
	int io, fn;

	io = (gpio->index * GPIO_NUM_PER_BANK) + offset;
	fn = GET_GPIO_ALTFUNC(gpio->index, offset);

	CHECK_ALTFUNC_RET(gpio, offset, EINVAL);

	nxp_soc_gpio_set_io_func(io, fn);
	nxp_soc_gpio_set_out_value(io, value);
	nxp_soc_gpio_set_io_dir(io, 1);

	pr_debug("%s: io [%s:%d=%d], val=%d\n",
		__func__, io_name[gpio->index], offset, io, value);
	return 0;
}

static int nxp_gpio_get_value(struct gpio_chip *chip, unsigned offset)
{
	struct nxp_gpio *gpio = GET_GPIO(chip);
	int io = gpio->index * GPIO_NUM_PER_BANK + offset;

	pr_debug("%s: io [%s:%d=%d]\n", __func__, io_name[gpio->index], offset, io);

	return nxp_soc_gpio_get_in_value(io);
}

static void nxp_gpio_set_value(struct gpio_chip *chip, unsigned offset, int value)
{
	struct nxp_gpio *gpio = GET_GPIO(chip);
	int io, fn, cn;

	io = gpio->index * GPIO_NUM_PER_BANK + offset;
	fn = GET_GPIO_ALTFUNC(gpio->index, offset);
	cn = nxp_soc_gpio_get_io_func(io);
#if (0)
	if (cn != fn) {
		printk("Fail : io used alt function %d [%s:%u=%d]\n",
			cn, io_name[gpio->index], offset, io);
		return;
	}
#endif
	nxp_soc_gpio_set_io_dir(io, 1);
	nxp_soc_gpio_set_out_value(io, value);

	pr_debug("%s: io [%s:%d=%d], val=%d\n",
		__func__, io_name[gpio->index], offset, io, value);
}

static int nxp_gpio_to_irq( struct gpio_chip *chip , unsigned offset )
{
	struct nxp_gpio *gpio = GET_GPIO(chip);
	unsigned int io = gpio->index * GPIO_NUM_PER_BANK + offset;

	/*printk("~~~ %s() offset:%d, io:%d, irq:%d\n", __func__, \
			offset, io, io + IRQ_GPIO_START);*/

	return (io + IRQ_GPIO_START);
}

#ifdef CONFIG_PM
static int nxp_gpio_suspend(struct platform_device *pdev, pm_message_t state)
{
	PM_DBGOUT("%s\n", __func__);
	return 0;
}

static int nxp_gpio_resume(struct platform_device *pdev)
{
	PM_DBGOUT("%s\n", __func__);
	return 0;
}
#else
#define	nxp_gpio_suspend	NULL
#define	nxp_gpio_resume		NULL
#endif

static int nxp_gpio_probe(struct platform_device *pdev)
{
	struct resource *res = pdev->resource;
	struct nxp_gpio *gpio = NULL;
	int ret;

	pr_debug("%s: %s, %d ~ %2d\n",
		__func__, io_name[pdev->id], res->start, res->end);
	if (!res) {
		printk("Error: not allocated gpio resource [%d]\n", pdev->id);
		return -EINVAL;
	}

	gpio = kzalloc(sizeof(*gpio), GFP_KERNEL);
	if (gpio == NULL)
		return -ENOMEM;

	spin_lock_init(&gpio->lock);

	gpio->index = pdev->id;
	gpio->chip.request = nxp_gpio_request;
	gpio->chip.to_irq = nxp_gpio_to_irq;
	gpio->chip.direction_input = nxp_gpio_direction_input;
	gpio->chip.direction_output = nxp_gpio_direction_output;
	gpio->chip.get = nxp_gpio_get_value;
	gpio->chip.set = nxp_gpio_set_value;
	gpio->chip.ngpio = res->end - res->start;
	gpio->chip.label = io_name[pdev->id];
	gpio->chip.dev = &pdev->dev;
	gpio->chip.owner = THIS_MODULE;
	gpio->chip.base = pdev->id * GPIO_NUM_PER_BANK;

	/* register GPIOLib */
	ret = gpiochip_add(&gpio->chip);
	if (ret)
		goto free_mem;

	return ret;

free_mem:
	kfree(gpio);
	return ret;
}

static int nxp_gpio_remove(struct platform_device *pdev)
{
	return 0;
}

static struct platform_driver nxp_gpio_driver = {
	.probe		= nxp_gpio_probe,
	.remove		= __devexit_p(nxp_gpio_remove),
	.suspend	= nxp_gpio_suspend,
	.resume		= nxp_gpio_resume,
	.driver		= {
		.name	= DEV_NAME_GPIO,
		.owner	= THIS_MODULE,
	},
};

static int __init nxp_gpio_init(void)
{
	return platform_driver_register(&nxp_gpio_driver);
}
subsys_initcall(nxp_gpio_init);

MODULE_DESCRIPTION("GPIO driver for the Nexell");
MODULE_LICENSE("GPL");
/* arch\arm\mach-s5p6818\include\mach\gpio.h */

/*
 */
#include "s5p6818_irq.h"

#define GPIO_NUM_PER_BANK	32
#define ARCH_NR_GPIOS 		(GPIO_NUM_PER_BANK * 6)	/* For GPIO A, B, C, D, E, ALVIE */

extern const unsigned char gpio_alt_no[][GPIO_NUM_PER_BANK];
#define GET_GPIO_ALTFUNC(io,idx)    (gpio_alt_no[io][idx])

#include <asm-generic/gpio.h>

struct platform_device gpio_device, id,用來確定io組,io number;

lable 1.1:
gpio_chip ops,實現分析;

static int nxp_gpio_request(struct gpio_chip *chip, unsigned offset)
{
	struct nxp_gpio *gpio = GET_GPIO(chip);
	int io, fn;

	io = (gpio->index * GPIO_NUM_PER_BANK) + offset;
	fn = GET_GPIO_ALTFUNC(gpio->index, offset);

	CHECK_ALTFUNC_RET(gpio, offset, EINVAL);

	nxp_soc_gpio_set_io_func(io, fn);
	pr_debug("%s: io [%s:%d=%d]\n", __func__, io_name[gpio->index], offset, io);

	return 0;
}

nxp_gpio_request(); 實現分析:
gpio->index = pdev->id;
io number: (gpio->index * GPIO_NUM_PER_BANK) + offset;

配置io為GPIO 功能
fn = CHECK_ALTFUNC_RET(gpio, offset, EINVAL);
nxp_soc_gpio_set_io_func(io, fn);

/*------------------------------------------------------------------------------
 * 	Description	: set gpio pad function
 *	In[io]		: gpio pad number, 32*n + bit
 * 				: (n= GPIO_A:0, GPIO_B:1, GPIO_C:2, GPIO_D:3, GPIO_E:4, bit= 0 ~ 32)
 *	In[mode]	: gpio pad function
 *				: 0 = GPIO mode
 *				: 1 = Alternate function 1
 *				: 2 = Alternate function 2
 *				: 3 = Alternate function 3
 *	Return 		: none.
 */
void nxp_soc_gpio_set_io_func(unsigned int io, unsigned int func)
{
	unsigned int grp = PAD_GET_GROUP(io);
	unsigned int bit = PAD_GET_BITNO(io);
	DBGOUT("%s (%d.%02d)\n", __func__, grp, bit);

	switch (io & ~(32-1)) {
	case PAD_GPIO_A:
	case PAD_GPIO_B:
	case PAD_GPIO_C:
	case PAD_GPIO_D:
	case PAD_GPIO_E:
		IO_LOCK(grp);
		NX_GPIO_SetPadFunction(grp, bit, func);
		IO_UNLOCK(grp);
		break;
	case PAD_GPIO_ALV:
		break;
	default:
		printk("fail, soc gpio io:%d, group:%d (%s)\n", io, grp, __func__);
		break;
	};

	return;
}
EXPORT_SYMBOL(nxp_soc_gpio_set_io_func);

nxp_soc_gpio_set_io_func();實現分析:
根據io number計算出 io group, offset,
都是為了確認具體是是操作哪個寄存器,
哪個bit,配置為什么值
unsigned int grp = PAD_GET_GROUP(io);
unsigned int bit = PAD_GET_BITNO(io);
call NX_GPIO_SetPadFunction(grp, bit, func);

//--------------------------------------------------------------------------
// Pin Configuration
//--------------------------------------------------------------------------
/**
 *	@brief		Set PAD Fuction
 *	@param[in]	ModuleIndex		A index of module. (0:GPIOA, 1:GPIOB, 2:GPIOC, 3:GPIOD, 4:GPIOE )
 *	@param[in]	BitNumber	Bit number ( 0 ~ 31 )
 *	@param[in]	padfunc		Pad Function
 *	@return		None
 *	@remarks	Each gpio pins can use to GPIO Pin or Alternate Function 0 or Alternate Function 1 or \n
 *				Alternate Function 2. So This function Sets gpio pin's function.
 */
void	NX_GPIO_SetPadFunction( U32 ModuleIndex, U32 BitNumber, NX_GPIO_PADFUNC padfunc )
{
	register struct NX_GPIO_RegisterSet	*pRegister;

	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );
	NX_ASSERT( 0 != (__g_NX_GPIO_VALID_BIT[ModuleIndex] & (1 << BitNumber)) );
	NX_ASSERT( NX_GPIO_PADFUNC_3 >= padfunc );

	pRegister = __g_ModuleVariables[ModuleIndex].pRegister;

	NX_ASSERT( CNULL != pRegister );

	NX_GPIO_SetBit2( &pRegister->GPIOxALTFN[BitNumber/16], BitNumber%16, (U32)padfunc );
}

NX_GPIO_SetPadFunction();實現分析:
獲取寄存器地址,配置;
pRegister = __g_ModuleVariables[ModuleIndex].pRegister;
寄存器的基地址,__g_ModuleVariables[ModuleIndex].pRegister,是什么時候初始化 和 mmap的?

static	struct
{
	struct NX_GPIO_RegisterSet *pRegister;

} __g_ModuleVariables[NUMBER_OF_GPIO_MODULE] = { {CNULL,}, };

lable 1.2:
gpio io phy addr mmap;

從start_kernel();開始講起;

start_kernel()
	|
	...
	setup_arch();
		|
		paging_init(mdesc);
			|
			mdesc->map_io();
static void __init cpu_map_io(void)
{
	int cores = LIVE_NR_CPUS;

	printk("~~~ %s()\n", __func__);
	
	/*
	 * check memory map
	 */
	unsigned long io_end = cpu_iomap_desc[ARRAY_SIZE(cpu_iomap_desc)-1].virtual +
						   cpu_iomap_desc[ARRAY_SIZE(cpu_iomap_desc)-1].length;
#if defined(CFG_MEM_PHY_DMAZONE_SIZE)
	unsigned long dma_start = CONSISTENT_END - CFG_MEM_PHY_DMAZONE_SIZE;
#else
	unsigned long dma_start = CONSISTENT_END - SZ_2M;	// refer to dma-mapping.c
#endif
	if (io_end > dma_start)
		printk(KERN_ERR "\n****** BUG: Overlapped io mmap 0x%lx with dma start 0x%lx ******\n",
			io_end, dma_start);

	/* debug */
	_IOMAP();

	/* make iotable */
	iotable_init(cpu_iomap_desc, ARRAY_SIZE(cpu_iomap_desc));

#if defined(CFG_MEM_PHY_DMAZONE_SIZE)
	printk(KERN_INFO "CPU : DMA Zone Size =%2dM, CORE %d\n", CFG_MEM_PHY_DMAZONE_SIZE>>20, cores);
	init_consistent_dma_size(CFG_MEM_PHY_DMAZONE_SIZE);
#else
	printk(KERN_INFO "CPU : DMA Zone Size =%2dM, CORE %d\n", SZ_2M>>20, cores);
#endif

	nxp_cpu_arch_init();
	nxp_board_base_init();

	nxp_cpu_clock_init();
	nxp_cpu_clock_print();
}

cpu_iomap_desc,:

/* arch/arm/mach-s5p6818/include/mach/s5p6818_iomap.h

/*
 *	Length must be aligned 1MB
 *
 *	Refer to mach/iomap.h
 *
 *	Physical : __PB_IO_MAP_ ## _n_ ## _PHYS
 *	Virtual  : __PB_IO_MAP_ ## _n_ ## _VIRT
 *
 *	name	.virtual, 	.pfn, 		.length,	.type
 */
PB_IO_MAP( 	REGS, 	0xF0000000,	0xC0000000,	0x00300000,	MT_DEVICE )		/* NOMAL IO, Reserved */
PB_IO_MAP( 	CCI4, 	0xF0300000,	0xE0000000,	0x00100000,	MT_DEVICE )		/* CCI-400 */
PB_IO_MAP( 	SRAM, 	0xF0400000,	0xFFF00000,	0x00100000,	MT_DEVICE )		/* SRAM */
PB_IO_MAP( 	NAND, 	0xF0500000,	0x2C000000,	0x00100000,	MT_DEVICE )		/* NAND  */
PB_IO_MAP( 	IROM, 	0xF0600000,	0x00000000,	0x00100000,	MT_DEVICE )		/* IROM  */
/* arch/arm/mach-s5p6818/include/mach/map_desc.h */

/*
 * (C) Copyright 2009
 * jung hyun kim, Nexell Co, <jhkim@nexell.co.kr>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#ifndef __ASM_ARCH_MAP_DESC_H
#define __ASM_ARCH_MAP_DESC_H

#include <asm/mach/map.h>

#ifdef	PB_IO_MAP
#undef	PB_IO_MAP
#endif

#define PB_IO_MAP(_n_, _v_, _p_, _s_, _t_)	\
	{ 										\
		.virtual	= _v_,					\
		.pfn 		= __phys_to_pfn(_p_),	\
		.length 	= _s_, 					\
		.type 		= _t_ 					\
	},

static struct map_desc cpu_iomap_desc[] =
{
	#include <mach/s5p6818_iomap.h>
};

#endif	/* __ASM_ARCH_MAP_DESC_H */
__init cpu_map_io(void)  
    |
    iotable_init(cpu_iomap_desc, ARRAY_SIZE(cpu_iomap_desc));
		|
		create_mapping(md, false); /*線性 mmap io phy addreass  to virtual address: */

上面io phy address線性mmap 到virt address;映射后即可通過虛擬地址訪問io register;

io phy address 到 virtual address的轉換:

define IO_ADDRESS(x) (x - __PB_IO_MAP_REGS_PHYS + __PB_IO_MAP_REGS_VIRT)

__PB_IO_MAP_REGS_PHYS,哪里定義?

/* arch/arm/mach-s5p6818/include/mach/iomap.h */

#define PB_IO_MAP(_n_, _v_, _p_, _s_, _t_)		\
	enum { 										\
		__PB_IO_MAP_ ## _n_ ## _VIRT	= _v_,	\
		__PB_IO_MAP_ ## _n_ ## _PHYS	= _p_,	\
		};

展開:

PB_IO_MAP( 	REGS, 	0xF0000000,	0xC0000000,	0x00300000,	MT_DEVICE )  
enum { 										\
		__PB_IO_MAP_ ## REGS ## _VIRT	= _v_,	\
		__PB_IO_MAP_ ## REGS ## _PHYS	= _p_,	\
};
->:
enum { 										\
		__PB_IO_MAP_REGS_VIRT	= 0xF0000000,	\
		__PB_IO_MAP_REGS_PHYS	= 0xC0000000,	\
};

NX_GPIO_SetBaseAddress();中
初始化GPIO controller的base虛擬地址給到全局變量__g_ModuleVariables[ModuleIndex].pRegister;

void nxp_cpu_arch_init(void)
	|
	cpu_base_init(void) {
		...
		NX_GPIO_Initialize();
		for (i = 0; NX_GPIO_GetNumberOfModule() > i; i++) {
			printk("~~~ %s() gpio group %d, io_phy_addr:0x%lx, io_virt_addr:0x%lx\n",
				__func__, i,
				(unsigned long)NX_GPIO_GetPhysicalAddress(i),
				(unsigned long)IO_ADDRESS(NX_GPIO_GetPhysicalAddress(i)) );

			NX_GPIO_SetBaseAddress(i, (void*)IO_ADDRESS(NX_GPIO_GetPhysicalAddress(i)));
			NX_GPIO_OpenModule(i);
		}
		...
	}

	/* arch/arm/plat-s5p6818/nanopi3/board.c */
	void nxp_board_base_init(void)
	{
		if (g_initGpio)
		{
			bd_gpio_init(); /* board all gpio init */
			bd_alive_init();
			DBGOUT("%s: Board initialized\n", CFG_SYS_BOARD_NAME);

			g_initGpio = 0;
		}
}
//------------------------------------------------------------------------------
/**
 *	@brief		Set a base address of register set.
 *	@param[in]	ModuleIndex		A index of module.
 *	@param[in]	BaseAddress Module's base address
 *	@return		None.
 */
void	NX_GPIO_SetBaseAddress( U32 ModuleIndex, void* BaseAddress )
{
	NX_ASSERT( CNULL != BaseAddress );
	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );

	__g_ModuleVariables[ModuleIndex].pRegister = (struct NX_GPIO_RegisterSet *)BaseAddress;
}

NX_GPIO_GetPhysicalAddress(i);獲取GPIO controller的物理base地址

//------------------------------------------------------------------------------
// Basic Interface
//------------------------------------------------------------------------------
/**
 *	@brief		Get module's physical address.
 *	@param[in]	ModuleIndex		A index of module.
 *	@return		Module's physical address
 */
U32		NX_GPIO_GetPhysicalAddress( U32 ModuleIndex )
{
	static const U32 PhysicalAddr[] = { PHY_BASEADDR_LIST_ALPHA( GPIO ) }; // PHY_BASEADDR_GPIO?_MODULE

	NX_CASSERT( NUMBER_OF_GPIO_MODULE == (sizeof(PhysicalAddr)/sizeof(PhysicalAddr[0])) );
	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );

	return (U32)PhysicalAddr[ModuleIndex];
}
static const U32 PhysicalAddr[] = { PHY_BASEADDR_LIST_ALPHA( GPIO ) }; // PHY_BASEADDR_GPIO?_MODULE
PhysicalAddr是個數組;

#define PHY_BASEADDR_LIST_ALPHA(NAME)                           _GET_MACRO_LIST_ALPHA( NAME, PHY_BASEADDR_  , _MODULE, NUMBER_OF_ ## NAME ## _MODULE )
#define _GET_MACRO_LIST_ALPHA(NAME,PRE,POST,COUNT)  CAT( _GET_MACRO_LIST_ALPHA_, COUNT )(NAME,PRE,POST)
#define CAT(a, ...) a ## __VA_ARGS__
#define NUMBER_OF_GPIO_MODULE                               5
又:
#define _GET_MACRO_LIST_ALPHA_1(NAME,PRE,POST)      PRE ## NAME ## A ## POST
#define _GET_MACRO_LIST_ALPHA_2(NAME,PRE,POST)      PRE ## NAME ## A ## POST , PRE ## NAME ## B ## POST
#define _GET_MACRO_LIST_ALPHA_3(NAME,PRE,POST)      _GET_MACRO_LIST_ALPHA_2(NAME,PRE,POST) , PRE ## NAME ## C ## POST
#define _GET_MACRO_LIST_ALPHA_4(NAME,PRE,POST)      _GET_MACRO_LIST_ALPHA_3(NAME,PRE,POST) , PRE ## NAME ## D ## POST
#define _GET_MACRO_LIST_ALPHA_5(NAME,PRE,POST)      _GET_MACRO_LIST_ALPHA_4(NAME,PRE,POST) , PRE ## NAME ## E ## POST
#define _GET_MACRO_LIST_ALPHA_6(NAME,PRE,POST)      _GET_MACRO_LIST_ALPHA_5(NAME,PRE,POST) , PRE ## NAME ## F ## POST

宏展開,有:

#define PHY_BASEADDR_LIST_ALPHA(NAME)                           _GET_MACRO_LIST_ALPHA( NAME, PHY_BASEADDR_  , _MODULE, NUMBER_OF_ ## NAME ## _MODULE )
#define PHY_BASEADDR_LIST_ALPHA(GPIO)                           _GET_MACRO_LIST_ALPHA(GPIO, PHY_BASEADDR_  , _MODULE, NUMBER_OF_GPIO_MODULE )


#define _GET_MACRO_LIST_ALPHA(NAME,PRE,POST,COUNT)                                        CAT( _GET_MACRO_LIST_ALPHA_, COUNT )(NAME,PRE,POST)
_GET_MACRO_LIST_ALPHA(GPIO, PHY_BASEADDR_  , _MODULE, NUMBER_OF_GPIO_MODULE )     CAT( _GET_MACRO_LIST_ALPHA_, NUMBER_OF_GPIO_MODULE )(GPIO, PHY_BASEADDR_,_MODULE)

#define CAT(a, ...) a ## __VA_ARGS__
CAT( _GET_MACRO_LIST_ALPHA_, NUMBER_OF_GPIO_MODULE )(GPIO, PHY_BASEADDR_,_MODULE)  _GET_MACRO_LIST_ALPHA_5(GPIO, PHY_BASEADDR_, _MODULE)

又:

#define _GET_MACRO_LIST_ALPHA_1(NAME,PRE,POST)      PRE ## NAME ## A ## POST
#define _GET_MACRO_LIST_ALPHA_2(NAME,PRE,POST)      PRE ## NAME ## A ## POST , PRE ## NAME ## B ## POST
#define _GET_MACRO_LIST_ALPHA_3(NAME,PRE,POST)      _GET_MACRO_LIST_ALPHA_2(NAME,PRE,POST) , PRE ## NAME ## C ## POST
#define _GET_MACRO_LIST_ALPHA_4(NAME,PRE,POST)      _GET_MACRO_LIST_ALPHA_3(NAME,PRE,POST) , PRE ## NAME ## D ## POST
#define _GET_MACRO_LIST_ALPHA_5(NAME,PRE,POST)      _GET_MACRO_LIST_ALPHA_4(NAME,PRE,POST) , PRE ## NAME ## E ## POST

所以:
_GET_MACRO_LIST_ALPHA_2(NAME,PRE,POST) PRE ## NAME ## A ## POST
_GET_MACRO_LIST_ALPHA_5(GPIO, PHY_BASEADDR_, _MODULE): PHY_BASEADDR_GPIOA_MODULE,PHY_BASEADDR_GPIOB_MODULE,PHY_BASEADDR_GPIOC_MODULE,PHY_BASEADDR_GPIOD_MODULE,PHY_BASEADDR_GPIOE_MODULE


終於找到,arch/arm/mach-s5p6818/prototype/base/nx_chip.h
#define PHY_BASEADDR_GPIOA_MODULE                           0xC001A000
#define PHY_BASEADDR_GPIOB_MODULE                           0xC001B000
#define PHY_BASEADDR_GPIOC_MODULE                           0xC001C000
#define PHY_BASEADDR_GPIOD_MODULE                           0xC001D000
#define PHY_BASEADDR_GPIOE_MODULE                           0xC001E000

kernel log 有:

[    0.000000] ~~~ cpu_map_io()  
[    0.000000] CPU : iomap[ 0]: p 0xc0000000 -> v 0xf0000000 len=0x300000
[    0.000000] CPU : iomap[ 1]: p 0xe0000000 -> v 0xf0300000 len=0x100000
[    0.000000] CPU : iomap[ 2]: p 0xfff00000 -> v 0xf0400000 len=0x100000
[    0.000000] CPU : iomap[ 3]: p 0x2c000000 -> v 0xf0500000 len=0x100000
[    0.000000] CPU : iomap[ 4]: p 0x00000000 -> v 0xf0600000 len=0x100000
[    0.000000] memblock_reserve: [0x00000065e3ef60-0x00000065e3f000] memblock_alloc_base_nid+0x4c/0x60
[    0.000000] ~~~ create_mapping() phys:0xc0000000, pfn:0xc0000, virt:0xf0000000, length:0x300000
[    0.000000] ~~~ create_mapping() phys:0xe0000000, pfn:0xe0000, virt:0xf0300000, length:0x100000
[    0.000000] ~~~ create_mapping() phys:0xfff00000, pfn:0xfff00, virt:0xf0400000, length:0x100000
[    0.000000] ~~~ create_mapping() phys:0x2c000000, pfn:0x2c000, virt:0xf0500000, length:0x100000
[    0.000000] ~~~ create_mapping() phys:0x0, pfn:0x0, virt:0xf0600000, length:0x100000
[    0.000000] CPU : DMA Zone Size =16M, CORE 8
[    0.000000] ~~~ cpu_base_init() gpio group 0, io_phy_addr:0xc001a000, io_virt_addr:0xf001a000
[    0.000000] ~~~ cpu_base_init() gpio group 1, io_phy_addr:0xc001b000, io_virt_addr:0xf001b000
[    0.000000] ~~~ cpu_base_init() gpio group 2, io_phy_addr:0xc001c000, io_virt_addr:0xf001c000
[    0.000000] ~~~ cpu_base_init() gpio group 3, io_phy_addr:0xc001d000, io_virt_addr:0xf001d000
[    0.000000] ~~~ cpu_base_init() gpio group 4, io_phy_addr:0xc001e000, io_virt_addr:0xf001e000
/* arch\arm\plat-s5p6818\common\cfg_type.h */

/*------------------------------------------------------------------------------
*  GPIO function config type
*/
#define PAD_MODE_SHIFT          0
#define PAD_FUNC_SHIFT          8
#define PAD_LEVEL_SHIFT         12
#define PAD_PULLUP_SHIFT        16
#define PAD_STRENGTH_SHIFT      20

#define PAD_GET_GROUP(pad)      ((pad >> 0x5) & 0x07)       /* Divide 32 */
#define PAD_GET_BITNO(pad)      ((pad & 0x1F) >> 0x0)
#define PAD_GET_FUNC(pad)       (0xF & (pad >> PAD_FUNC_SHIFT))
#define PAD_GET_MODE(pad)       (0xF & (pad >> PAD_MODE_SHIFT))
#define PAD_GET_LEVEL(pad)      (0xF & (pad >> PAD_LEVEL_SHIFT))
#define PAD_GET_PULLUP(pad)     (0xF & (pad >> PAD_PULLUP_SHIFT))
#define PAD_GET_STRENGTH(pad)   (0xF & (pad >> PAD_STRENGTH_SHIFT))
#define PAD_GET_BUSPAD(pad)     (pad & 0xFF)

/*  gpio group pad start num. */
enum {
    PAD_GPIO_A      = (0 * 32),
    PAD_GPIO_B      = (1 * 32),
    PAD_GPIO_C      = (2 * 32),
    PAD_GPIO_D      = (3 * 32),
    PAD_GPIO_E      = (4 * 32),
    PAD_GPIO_ALV    = (5 * 32),
};

/* gpio mode, altfunction, gpio in/out or interrput */
enum {
    PAD_MODE_ALT    = (0 << PAD_MODE_SHIFT),
    PAD_MODE_IN     = (1 << PAD_MODE_SHIFT),
    PAD_MODE_OUT    = (2 << PAD_MODE_SHIFT),
    PAD_MODE_INT    = (3 << PAD_MODE_SHIFT),
};

/* gpio altfunction, refer to NX_GPIO_PADFUNC in nx_gpio.h */
enum {
    PAD_FUNC_ALT0   = (0 << PAD_FUNC_SHIFT),
    PAD_FUNC_ALT1   = (1 << PAD_FUNC_SHIFT),
    PAD_FUNC_ALT2   = (2 << PAD_FUNC_SHIFT),
    PAD_FUNC_ALT3   = (3 << PAD_FUNC_SHIFT),
};

/* ouput level or interrupt detect mode, refer to NX_GPIO_INTMODE in nx_gpio.h */
enum {
    PAD_LEVEL_LOW         = (0 << PAD_LEVEL_SHIFT),     /* if alive, async lowlevel */
    PAD_LEVEL_HIGH        = (1 << PAD_LEVEL_SHIFT),     /* if alive, async highlevel */
    PAD_LEVEL_FALLINGEDGE = (2 << PAD_LEVEL_SHIFT),     /* if alive, async fallingedge */
    PAD_LEVEL_RISINGEDGE  = (3 << PAD_LEVEL_SHIFT),     /* if alive, async eisingedge */
    PAD_LEVEL_LOW_SYNC    = (4 << PAD_LEVEL_SHIFT),     /* if gpio , not support */
    PAD_LEVEL_HIGH_SYNC   = (5 << PAD_LEVEL_SHIFT),     /* if gpio , not support */
    PAD_LEVEL_BOTHEDGE    = (4 << PAD_LEVEL_SHIFT),     /* if alive, not support */
    PAD_LEVEL_ALT         = (6 << PAD_LEVEL_SHIFT),     /* if pad function is alt, not set */
};

enum {
    PAD_PULL_DN     = (0 << PAD_PULLUP_SHIFT),          /* Do not support Alive-GPIO */
    PAD_PULL_UP     = (1 << PAD_PULLUP_SHIFT),
    PAD_PULL_OFF    = (2 << PAD_PULLUP_SHIFT),
};

enum {
    PAD_STRENGTH_0 = (0 << PAD_STRENGTH_SHIFT),
    PAD_STRENGTH_1 = (1 << PAD_STRENGTH_SHIFT),
    PAD_STRENGTH_2 = (2 << PAD_STRENGTH_SHIFT),
    PAD_STRENGTH_3 = (3 << PAD_STRENGTH_SHIFT),
};

/* alive wakeup detect mode */
enum {
    PAD_WAKEUP_ASYNC_LOWLEVEL   = (0),
    PAD_WAKEUP_ASYNC_HIGHLEVEL  = (1),
    PAD_WAKEUP_FALLINGEDGE      = (2),
    PAD_WAKEUP_RISINGEDGE       = (3),
    PAD_WAKEUP_SYNC_LOWLEVEL    = (4),
    PAD_WAKEUP_SYNC_HIGHLEVEL   = (5),
};

lable 2:
上面完成了,GPIO控制器物理地址到虛擬地址mmap的分析,如下,
SOC GPIO控制器 GPIO功能配置 操作接口實現:

/* arch\arm\mach-s5p6818\include\mach\gpio_desc.h */

/*
 * (C) Copyright 2009
 * jung hyun kim, Nexell Co, <jhkim@nexell.co.kr>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
#ifndef __MACH_GPIO_DESC_H__
#define __MACH_GPIO_DESC_H__

enum {
	ALT_NO_0 = 0,
	ALT_NO_1 = 1,
	ALT_NO_2 = 2,
	ALT_NO_3 = 3,
};

#define	ALT_NO_GPIO_A	\
	  ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 ,	\
	  ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 ,	\
	  ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 ,	\
	  ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 	\

#define	ALT_NO_GPIO_B	\
	  ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 ,	\
	  ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_2 , ALT_NO_2 , ALT_NO_1 , ALT_NO_2 , ALT_NO_1 ,	\
	  ALT_NO_2 , ALT_NO_1 , ALT_NO_2 , ALT_NO_1 , ALT_NO_1 , ALT_NO_1 , ALT_NO_1 , ALT_NO_1 ,	\
	  ALT_NO_1 , ALT_NO_1 , ALT_NO_1 , ALT_NO_1 , ALT_NO_1 , ALT_NO_1 , ALT_NO_1 , ALT_NO_1		\

#define	ALT_NO_GPIO_C	\
	  ALT_NO_1 , ALT_NO_1 , ALT_NO_1 , ALT_NO_1 , ALT_NO_1 , ALT_NO_1 , ALT_NO_1 , ALT_NO_1 ,	\
	  ALT_NO_1 , ALT_NO_1 , ALT_NO_1 , ALT_NO_1 , ALT_NO_1 , ALT_NO_1 , ALT_NO_1 , ALT_NO_1 ,	\
	  ALT_NO_1 , ALT_NO_1 , ALT_NO_1 , ALT_NO_1 , ALT_NO_1 , ALT_NO_1 , ALT_NO_1 , ALT_NO_1 ,	\
	  ALT_NO_1 , ALT_NO_1 , ALT_NO_1 , ALT_NO_1,  ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0		\

#define	ALT_NO_GPIO_D	\
	  ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 ,	\
	  ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 ,	\
	  ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 ,	\
	  ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0		\

#define	ALT_NO_GPIO_E	\
	  ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 ,	\
	  ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 ,	\
	  ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 ,	\
	  ALT_NO_0 , ALT_NO_1 , ALT_NO_1 , ALT_NO_1 , ALT_NO_1 , ALT_NO_1 , ALT_NO_1 , ALT_NO_1		\

#define	ALT_NO_ALIVE		\
	  ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 ,	\
	  ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 ,	\
	  ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 ,	\
	  ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0 , ALT_NO_0		\

#endif
/* arch\arm\mach-s5p6818\soc\gpio.c */

/*
 * (C) Copyright 2009
 * jung hyun kim, Nexell Co, <jhkim@nexell.co.kr>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/delay.h>
#include <mach/platform.h>
#include <mach/gpio_desc.h>
#include <mach/gpio.h>

#if (0)
#define DBGOUT(msg...)		{ printk("pio: " msg); }
#else
#define DBGOUT(msg...)		do {} while (0)
#endif

const unsigned char gpio_alt_no[][GPIO_NUM_PER_BANK] = {
	{ ALT_NO_GPIO_A }, { ALT_NO_GPIO_B }, { ALT_NO_GPIO_C },
	{ ALT_NO_GPIO_D }, { ALT_NO_GPIO_E }, { ALT_NO_ALIVE  },
};

/*-----------------------------------------------------------------------------*/
#define	ALIVE_INDEX			NUMBER_OF_GPIO_MODULE
static spinlock_t 			lock[ALIVE_INDEX + 1];	/* A, B, C, D, E, alive */
static unsigned long 		lock_flags[ALIVE_INDEX + 1];

#define	IO_LOCK_INIT(x)		spin_lock_init(&lock[x])
#define	IO_LOCK(x)			spin_lock_irqsave(&lock[x], lock_flags[x])
#define	IO_UNLOCK(x)		spin_unlock_irqrestore(&lock[x], lock_flags[x])

/*------------------------------------------------------------------------------
 * 	Description	: set gpio pad function
 *	In[io]		: gpio pad number, 32*n + bit
 * 				: (n= GPIO_A:0, GPIO_B:1, GPIO_C:2, GPIO_D:3, GPIO_E:4, bit= 0 ~ 32)
 *	In[mode]	: gpio pad function
 *				: 0 = GPIO mode
 *				: 1 = Alternate function 1
 *				: 2 = Alternate function 2
 *				: 3 = Alternate function 3
 *	Return 		: none.
 */
void nxp_soc_gpio_set_io_func(unsigned int io, unsigned int func)
{
	unsigned int grp = PAD_GET_GROUP(io);
	unsigned int bit = PAD_GET_BITNO(io);
	DBGOUT("%s (%d.%02d)\n", __func__, grp, bit);

	switch (io & ~(32-1)) {
	case PAD_GPIO_A:
	case PAD_GPIO_B:
	case PAD_GPIO_C:
	case PAD_GPIO_D:
	case PAD_GPIO_E:
		IO_LOCK(grp);
		NX_GPIO_SetPadFunction(grp, bit, func);
		IO_UNLOCK(grp);
		break;
	case PAD_GPIO_ALV:
		break;
	default:
		printk("fail, soc gpio io:%d, group:%d (%s)\n", io, grp, __func__);
		break;
	};

	return;
}
EXPORT_SYMBOL(nxp_soc_gpio_set_io_func);

/*------------------------------------------------------------------------------
 * 	Description	: set gpio alt function number
 *	In[io]		: gpio pad number, 32*n + bit
 * 				: (n= GPIO_A:0, GPIO_B:1, GPIO_C:2, GPIO_D:3, GPIO_E:4, bit= 0 ~ 32)
  *	Return 		: gpio alt function vlaue.
 */
int nxp_soc_gpio_get_altnum(unsigned int io)
{
	unsigned int grp = PAD_GET_GROUP(io);
	unsigned int bit = PAD_GET_BITNO(io);

	return gpio_alt_no[grp][bit];
}
EXPORT_SYMBOL_GPL(nxp_soc_gpio_get_altnum);

/*------------------------------------------------------------------------------
 * 	Description	: get gpio pad function
 *	In[io]		: gpio pad number, 32*n + bit
 * 				: (n= GPIO_A:0, GPIO_B:1, GPIO_C:2, GPIO_D:3, GPIO_E:4, bit= 0 ~ 32)
 *	Return		: -1 = invalid gpio
 *				:  0 = GPIO mode
 *				:  1 = Alternate function 1
 *				:  2 = Alternate function 2
 *				:  3 = Alternate function 3
 */
unsigned int nxp_soc_gpio_get_io_func(unsigned int io)
{
	unsigned int grp = PAD_GET_GROUP(io);
	unsigned int bit = PAD_GET_BITNO(io);
	unsigned int fn = -1;
	DBGOUT("%s (%d.%02d)\n", __func__, grp, bit);

	switch (io & ~(32-1)) {
	case PAD_GPIO_A:
	case PAD_GPIO_B:
	case PAD_GPIO_C:
	case PAD_GPIO_D:
	case PAD_GPIO_E:
		IO_LOCK(grp);
		fn = NX_GPIO_GetPadFunction(grp, bit);
		IO_UNLOCK(grp);
		break;

	case PAD_GPIO_ALV:
		fn = 0;
		break;

	default:
		printk("fail, soc gpio io:%d, group:%d (%s)\n", io, grp, __func__);
		break;
	};

	return fn;
}
EXPORT_SYMBOL(nxp_soc_gpio_get_io_func);

/*------------------------------------------------------------------------------
 * 	Description	: set gpio io direction
 *	In[io]		: gpio pad number, 32*n + bit
 * 				: (n= GPIO_A:0, GPIO_B:1, GPIO_C:2, GPIO_D:3, GPIO_E:4, ALIVE:5, bit= 0 ~ 32)
 *	In[out]		: '1' is output mode, '0' is input mode
 *	Return 		: none.
 */
void nxp_soc_gpio_set_io_dir(unsigned int io, int out)
{
	unsigned int grp = PAD_GET_GROUP(io);
	unsigned int bit = PAD_GET_BITNO(io);
	DBGOUT("%s (%d.%02d)\n", __func__, grp, bit);

	switch (io & ~(32-1)) {
	case PAD_GPIO_A:
	case PAD_GPIO_B:
	case PAD_GPIO_C:
	case PAD_GPIO_D:
	case PAD_GPIO_E:
		IO_LOCK(grp);
		NX_GPIO_SetOutputEnable(grp, bit, out ? CTRUE : CFALSE);
		IO_UNLOCK(grp);
		break;

	case PAD_GPIO_ALV:
		IO_LOCK(grp);
		NX_ALIVE_SetOutputEnable(bit, out ? CTRUE : CFALSE);
		IO_UNLOCK(grp);
		break;

	default:
		printk("fail, soc gpio io:%d, group:%d (%s)\n", io, grp, __func__);
		break;
	};

	return;
}
EXPORT_SYMBOL(nxp_soc_gpio_set_io_dir);

/*------------------------------------------------------------------------------
 * 	Description	: get gpio io direction
 *	In[io]		: gpio pad number, 32*n + bit
 * 				: (n= GPIO_A:0, GPIO_B:1, GPIO_C:2, GPIO_D:3, GPIO_E:4, ALIVE:5, bit= 0 ~ 32)
 *	Return 		: -1 = invalid gpio.
 *				:  0 = gpio's input mode.
 *				:  1 = gpio's output mode.
 */
int nxp_soc_gpio_get_io_dir(unsigned int io)
{
	unsigned int grp = PAD_GET_GROUP(io);
	unsigned int bit = PAD_GET_BITNO(io);
	int dir = -1;
	DBGOUT("%s (%d.%02d)\n", __func__, grp, bit);

	switch (io & ~(32-1)) {
	case PAD_GPIO_A:
	case PAD_GPIO_B:
	case PAD_GPIO_C:
	case PAD_GPIO_D:
	case PAD_GPIO_E:
		IO_LOCK(grp);
		dir = NX_GPIO_GetOutputEnable(grp, bit) ? 1 : 0;
		IO_UNLOCK(grp);
		break;

	case PAD_GPIO_ALV:
		IO_LOCK(grp);
		dir = NX_ALIVE_GetOutputEnable(bit) ? 1 : 0;
		IO_UNLOCK(grp);
		break;

	default:
		printk("fail, soc gpio io:%d, group:%d (%s)\n", io, grp, __func__);
		break;
	};

	return dir;
}
EXPORT_SYMBOL(nxp_soc_gpio_get_io_dir);

/*------------------------------------------------------------------------------
 * 	Description	: set pull enb of gpio pin
 *	In[io]		: gpio pad number, 32*n + bit
 * 				: (n= GPIO_A:0, GPIO_B:1, GPIO_C:2, GPIO_D:3, GPIO_E:4, bit= 0 ~ 32)
 *	In[on]		: '1' is pull enable, '0' is pull disable
 *	Return 		: none.
 */
void nxp_soc_gpio_set_io_pull_enb(unsigned int io, int on)
{
	unsigned int grp = PAD_GET_GROUP(io);
	unsigned int bit = PAD_GET_BITNO(io);
	DBGOUT("%s (%d.%02d)\n", __func__, grp, bit);

	switch (io & ~(32-1)) {
	case PAD_GPIO_A:
	case PAD_GPIO_B:
	case PAD_GPIO_C:
	case PAD_GPIO_D:
	case PAD_GPIO_E:
		IO_LOCK(grp);
		NX_GPIO_SetPullEnable(grp, bit, on ? CTRUE : CFALSE);
		IO_UNLOCK(grp);
		break;

	default:
		printk("fail, soc gpio io:%d, group:%d (%s)\n", io, grp, __func__);
		break;
	};

	return;
}
EXPORT_SYMBOL(nxp_soc_gpio_set_io_pull_enb);

/*------------------------------------------------------------------------------
 * 	Description	: get pull enb of gpio pin
 *	In[io]		: gpio pad number, 32*n + bit
 * 				: (n= GPIO_A:0, GPIO_B:1, GPIO_C:2, GPIO_D:3, GPIO_E:4, bit= 0 ~ 32)
 *	Return 		: -1 = invalid gpio.
 *		 		:  0 = pull disable.
 *				:  1 = pull enable.
 */
int nxp_soc_gpio_get_io_pull_enb(unsigned int io)
{
	unsigned int grp = PAD_GET_GROUP(io);
	unsigned int bit = PAD_GET_BITNO(io);
	int enb  = -1;
	DBGOUT("%s (%d.%02d)\n", __func__, grp, bit);

	switch (io & ~(32-1)) {
	case PAD_GPIO_A:
	case PAD_GPIO_B:
	case PAD_GPIO_C:
	case PAD_GPIO_D:
	case PAD_GPIO_E:
		IO_LOCK(grp);
		enb = NX_GPIO_GetPullEnable(grp, bit) ? 1 : 0;
		IO_UNLOCK(grp);
		break;

	default:
		printk("fail, soc gpio io:%d, group:%d (%s)\n", io, grp, __func__);
		break;
	};

	return enb;
}
EXPORT_SYMBOL(nxp_soc_gpio_get_io_pull_enb);

/*------------------------------------------------------------------------------
 * 	Description	: set pull select of gpio pin
 *	In[io]		: gpio pad number, 32*n + bit
 * 				: (n= GPIO_A:0, GPIO_B:1, GPIO_C:2, GPIO_D:3, GPIO_E:4, ALIVE:5, bit= 0 ~ 32)
 *	In[on]		: '1' is pull up, '0' is pull down
 *	Return 		: none.
 */
void nxp_soc_gpio_set_io_pull_sel(unsigned int io, int up)
{
	unsigned int grp = PAD_GET_GROUP(io);
	unsigned int bit = PAD_GET_BITNO(io);
	DBGOUT("%s (%d.%02d)\n", __func__, grp, bit);

	switch (io & ~(32-1)) {
	case PAD_GPIO_A:
	case PAD_GPIO_B:
	case PAD_GPIO_C:
	case PAD_GPIO_D:
	case PAD_GPIO_E:
		IO_LOCK(grp);
		NX_GPIO_SetPullEnable(grp, bit, up);
		IO_UNLOCK(grp);
		break;

	case PAD_GPIO_ALV:
		IO_LOCK(grp);
		NX_ALIVE_SetPullUpEnable(bit, up ? CTRUE : CFALSE);
		IO_UNLOCK(grp);
		break;

	default:
		printk("fail, soc gpio io:%d, group:%d (%s)\n", io, grp, __func__);
		break;
	};

	return;
}
EXPORT_SYMBOL(nxp_soc_gpio_set_io_pull_sel);

/*------------------------------------------------------------------------------
 * 	Description	: get pull select status
 *	In[io]		: gpio pad number, 32*n + bit
 * 				: (n= GPIO_A:0, GPIO_B:1, GPIO_C:2, GPIO_D:3, GPIO_E:4, ALIVE:5, bit= 0 ~ 32)
 *	Return 		: -1 = invalid gpio.
 *		 		:  0 = pull down.
 *				:  1 = pull up.
 *				:  2 = pull off.
 */
int nxp_soc_gpio_get_io_pull_sel(unsigned int io)
{
	unsigned int grp = PAD_GET_GROUP(io);
	unsigned int bit = PAD_GET_BITNO(io);
	int up  = -1;
	DBGOUT("%s (%d.%02d)\n", __func__, grp, bit);

	switch (io & ~(32-1)) {
	case PAD_GPIO_A:
	case PAD_GPIO_B:
	case PAD_GPIO_C:
	case PAD_GPIO_D:
	case PAD_GPIO_E:
		IO_LOCK(grp);
		up = NX_GPIO_GetPullEnable(grp, bit);
		IO_UNLOCK(grp);
		break;

	case PAD_GPIO_ALV:
		IO_LOCK(grp);
		up = NX_ALIVE_GetPullUpEnable(bit) ? 1 : 0;
		IO_UNLOCK(grp);
		break;

	default:
		printk("fail, soc gpio io:%d, group:%d (%s)\n", io, grp, __func__);
		break;
	};

	return up;
}
EXPORT_SYMBOL(nxp_soc_gpio_get_io_pull_sel);

/*------------------------------------------------------------------------------
 * 	Description	: set gpio drive strength
 *	In[io]		: gpio pad number, 32*n + bit
 * 				: (n= GPIO_A:0, GPIO_B:1, GPIO_C:2, GPIO_D:3, GPIO_E:4, bit= 0 ~ 32)
 *	In[high]	: '1' is high level, '0' is low level
 *	Return 		: none.
 */
void nxp_soc_gpio_set_io_drv(int gpio, int mode)
{
	int grp, bit;

	if (gpio > (PAD_GPIO_ALV - 1) )
		return;

	grp = PAD_GET_GROUP(gpio);
	bit = PAD_GET_BITNO(gpio);

	NX_GPIO_SetDriveStrength(grp, bit, (NX_GPIO_DRVSTRENGTH)mode); /* pad strength */
}
EXPORT_SYMBOL(nxp_soc_gpio_set_io_drv);

/*------------------------------------------------------------------------------
 * 	Description	: get gpio drive strength
 *	In[io]		: gpio pad number, 32*n + bit
 * 				: (n= GPIO_A:0, GPIO_B:1, GPIO_C:2, GPIO_D:3, GPIO_E:4, bit= 0 ~ 32)
 *	In[high]	: '1' is high level, '0' is low level
 *	Return 		: none.
 */
int nxp_soc_gpio_get_io_drv(int gpio)
{
	int grp, bit;

	if (gpio > (PAD_GPIO_ALV - 1) )
		return -1;

	grp = PAD_GET_GROUP(gpio);
	bit = PAD_GET_BITNO(gpio);

	return (int)NX_GPIO_GetDriveStrength(grp, bit); /* pad strength */
}
EXPORT_SYMBOL(nxp_soc_gpio_get_io_drv);

/*------------------------------------------------------------------------------
 * 	Description	: set gpio output level
 *	In[io]		: gpio pad number, 32*n + bit
 * 				: (n= GPIO_A:0, GPIO_B:1, GPIO_C:2, GPIO_D:3, GPIO_E:4, ALIVE:5, bit= 0 ~ 32)
 *	In[high]	: '1' is high level, '0' is low level
 *	Return 		: none.
 */
void nxp_soc_gpio_set_out_value(unsigned int io, int high)
{
	unsigned int grp = PAD_GET_GROUP(io);
	unsigned int bit = PAD_GET_BITNO(io);
	DBGOUT("%s (%d.%02d)\n", __func__, grp, bit);

	switch (io & ~(32-1)) {
	case PAD_GPIO_A:
	case PAD_GPIO_B:
	case PAD_GPIO_C:
	case PAD_GPIO_D:
	case PAD_GPIO_E:
		IO_LOCK(grp);
		NX_GPIO_SetOutputValue(grp, bit, high ? CTRUE : CFALSE);
		IO_UNLOCK(grp);
		break;

	case PAD_GPIO_ALV:
		IO_LOCK(grp);
		NX_ALIVE_SetOutputValue(bit, high ? CTRUE : CFALSE);
		IO_UNLOCK(grp);
		break;

	default:
		printk("fail, soc gpio io:%d, group:%d (%s)\n", io, grp, __func__);
		break;
	};

	return;
}
EXPORT_SYMBOL(nxp_soc_gpio_set_out_value);

/*------------------------------------------------------------------------------
 * 	Description	: get gpio output level
 *	In[io]		: gpio pad number, 32*n + bit
 * 				: (n= GPIO_A:0, GPIO_B:1, GPIO_C:2, GPIO_D:3, GPIO_E:4, ALIVE:5, bit= 0 ~ 32)
 *	Return 		: -1 = invalid gpio.
 *		 		:  0 = gpio's output value is low level.
 *				:  1 = gpio's output value is high level.
 */
int nxp_soc_gpio_get_out_value(unsigned int io)
{
	unsigned int grp = PAD_GET_GROUP(io);
	unsigned int bit = PAD_GET_BITNO(io);
	int val = -1;
	DBGOUT("%s (%d.%02d)\n", __func__, grp, bit);

	switch (io & ~(32-1)) {
	case PAD_GPIO_A:
	case PAD_GPIO_B:
	case PAD_GPIO_C:
	case PAD_GPIO_D:
	case PAD_GPIO_E:
		IO_LOCK(grp);
		val = NX_GPIO_GetOutputValue(grp, bit) ? 1 : 0;
		IO_UNLOCK(grp);
		break;

	case PAD_GPIO_ALV:
		IO_LOCK(grp);
		val = NX_ALIVE_GetOutputValue(bit) ? 1 : 0;
		IO_UNLOCK(grp);
		break;

	default:
		printk("fail, soc gpio io:%d, group:%d (%s)\n", io, grp, __func__);
		break;
	};

	return val;
}
EXPORT_SYMBOL(nxp_soc_gpio_get_out_value);

/*------------------------------------------------------------------------------
 * 	Description	: get gpio input value
 *	In[io]		: gpio pad number, 32*n + bit
 * 				: (n= GPIO_A:0, GPIO_B:1, GPIO_C:2, GPIO_D:3, GPIO_E:4, ALIVE:5, bit= 0 ~ 32)
 *	Return 		: -1 = invalid gpio.
 *		 		:  0 = gpio's input value is low level , alive input is low.
 *				:  1 = gpio's input value is high level, alive input is high.
 */
int nxp_soc_gpio_get_in_value(unsigned int io)
{
	unsigned int grp = PAD_GET_GROUP(io);
	unsigned int bit = PAD_GET_BITNO(io);
	int val = -1;
	DBGOUT("%s (%d.%02d)\n", __func__, grp, bit);

	switch (io & ~(32-1)) {
	case PAD_GPIO_A:
	case PAD_GPIO_B:
	case PAD_GPIO_C:
	case PAD_GPIO_D:
	case PAD_GPIO_E:
		IO_LOCK(grp);
		val = NX_GPIO_GetInputValue(grp, bit) ? 1 : 0;
		IO_UNLOCK(grp);
		break;

	case PAD_GPIO_ALV:
		IO_LOCK(grp);
		val = NX_ALIVE_GetInputValue(bit) ? 1 : 0;
		IO_UNLOCK(grp);
		break;

	default:
		printk("fail, soc gpio io:%d, group:%d (%s)\n", io, grp, __func__);
		break;
	};

	return val;
}
EXPORT_SYMBOL(nxp_soc_gpio_get_in_value);

/*------------------------------------------------------------------------------
 * 	Description	: enable gpio interrupt
 *	In[io]		: gpio pad number, 32*n + bit
 * 				: (n= GPIO_A:0, GPIO_B:1, GPIO_C:2, GPIO_D:3, GPIO_E:4, ALIVE:5, bit= 0 ~ 32)
 *	In[on]		: gpio interrupt enable or disable
 *	Return 		: none.
 */
void nxp_soc_gpio_set_int_enable(unsigned int io, int on)
{
	unsigned int grp = PAD_GET_GROUP(io);
	unsigned int bit = PAD_GET_BITNO(io);
	DBGOUT("%s (%d.%02d)\n", __func__, grp, bit);

	switch (io & ~(32-1)) {
	case PAD_GPIO_A:
	case PAD_GPIO_B:
	case PAD_GPIO_C:
	case PAD_GPIO_D:
	case PAD_GPIO_E:
		IO_LOCK(grp);
		NX_GPIO_SetInterruptEnable(grp, bit, on ? CTRUE : CFALSE);
		IO_UNLOCK(grp);
		break;

	case PAD_GPIO_ALV:
		IO_LOCK(grp);
		NX_ALIVE_SetDetectEnable(bit, on ? CTRUE : CFALSE);
		NX_ALIVE_SetInterruptEnable(bit, on ? CTRUE : CFALSE);
		IO_UNLOCK(grp);
		break;

	default:
		printk("fail, soc gpio io:%d, group:%d (%s)\n", io, grp, __func__);
		break;
	};

	return;
}
EXPORT_SYMBOL(nxp_soc_gpio_set_int_enable);

/*------------------------------------------------------------------------------
 * 	Description	: get gpio interrupt mode
 *	In[io]		: gpio pad number, 32*n + bit
 * 				: (n= GPIO_A:0, GPIO_B:1, GPIO_C:2, GPIO_D:3, GPIO_E:4, ALIVE:5, bit= 0 ~ 32)
 *	Return 		: -1 = invalid gpio.
 *		 		:  0 = gpio's interrupt disable.
 *				:  1 = gpio's interrupt enable.
 */
int nxp_soc_gpio_get_int_enable(unsigned int io)
{
	unsigned int grp = PAD_GET_GROUP(io);
	unsigned int bit = PAD_GET_BITNO(io);
	int enb = -1;
	DBGOUT("%s (%d.%02d)\n", __func__, grp, bit);

	switch (io & ~(32-1)) {
	case PAD_GPIO_A:
	case PAD_GPIO_B:
	case PAD_GPIO_C:
	case PAD_GPIO_D:
	case PAD_GPIO_E:
		IO_LOCK(grp);
		enb = NX_GPIO_GetInterruptEnable(grp, bit) ? 1 : 0;
		IO_UNLOCK(grp);
		break;

	case PAD_GPIO_ALV:
		IO_LOCK(grp);
		enb = NX_ALIVE_GetInterruptEnable(bit) ? 1 : 0;
		IO_UNLOCK(grp);
		break;

	default:
		printk("fail, soc gpio io:%d, group:%d (%s)\n", io, grp, __func__);
		break;
	};

	return enb;
}
EXPORT_SYMBOL(nxp_soc_gpio_get_int_enable);

/*------------------------------------------------------------------------------
 * 	Description	: set gpio interrupt mode
 *	In[io]		: gpio pad number, 32*n + bit
 * 				: (n= GPIO_A:0, GPIO_B:1, GPIO_C:2, GPIO_D:3, GPIO_E:4, ALIVE:5, bit= 0 ~ 32)
 *	In[mode]	: gpio interrupt detect mode
 *				: 0 = Low level detect
 *				: 1 = High level detect
 *				: 2 = Falling edge detect
 *				: 3 = Rising edge detect
 *				: alive interrupt detect mode
 *				: 0 = async low level detect mode
 *				: 1 = async high level detect mode
 *				: 2 = sync falling edge detect mode
 *				: 3 = sync rising edge detect mode
 *				: 4 = sync low level detect mode
 *				: 5 = sync high level detect mode
 *	Return 		: none.
 */
void nxp_soc_gpio_set_int_mode(unsigned int io, unsigned int mode)
{
	unsigned int grp = PAD_GET_GROUP(io);
	unsigned int bit = PAD_GET_BITNO(io);
	int det = 0;
	DBGOUT("%s (%d.%02d, %d)\n", __func__, grp, bit, mode);

	switch (io & ~(32-1)) {
	case PAD_GPIO_A:
	case PAD_GPIO_B:
	case PAD_GPIO_C:
	case PAD_GPIO_D:
	case PAD_GPIO_E:
		IO_LOCK(grp);
		NX_GPIO_SetInterruptMode(grp, bit, mode);
		IO_UNLOCK(grp);
		break;

	case PAD_GPIO_ALV:
		IO_LOCK(grp);
		/* all disable */
		for (det = 0; 6 > det; det++)
			NX_ALIVE_SetDetectMode(det, bit, CFALSE);
		/* enable */
		NX_ALIVE_SetDetectMode(mode, bit, CTRUE);
		NX_ALIVE_SetOutputEnable(bit, CFALSE);
		IO_UNLOCK(grp);
		break;

	default:
		printk("fail, soc gpio io:%d, group:%d (%s)\n", io, grp, __func__);
		break;
	};

	return;
}
EXPORT_SYMBOL(nxp_soc_gpio_set_int_mode);

/*------------------------------------------------------------------------------
 * 	Description	: get gpio interrupt mode
 *	In[io]		: gpio pad number, 32*n + bit
 * 				: (n= GPIO_A:0, GPIO_B:1, GPIO_C:2, GPIO_D:3, GPIO_E:4, bit= 0 ~ 32)
 *	Return		: -1 = invalid gpio or Not set interrupt mode.
 *				:  0 = Low level detect
 *				:  1 = High level detect
 *				:  2 = Falling edge detect
 *				:  3 = Rising edge detect
 *				: alive interrupt detect mode
 *				: 0 = async low level detect mode
 *				: 1 = async high level detect mode
 *				: 2 = sync falling edge detect mode
 *				: 3 = sync rising edge detect mode
 *				: 4 = sync low level detect mode
 *				: 5 = sync high level detect mode
 */
int nxp_soc_gpio_get_int_mode(unsigned int io)
{
	unsigned int grp = PAD_GET_GROUP(io);
	unsigned int bit = PAD_GET_BITNO(io);
	int	mod = -1;
	int det = 0;
	DBGOUT("%s (%d.%02d)\n", __func__, grp, bit);

	switch (io & ~(32-1)) {
	case PAD_GPIO_A:
	case PAD_GPIO_B:
	case PAD_GPIO_C:
	case PAD_GPIO_D:
	case PAD_GPIO_E:
		IO_LOCK(grp);
		mod = NX_GPIO_GetInterruptMode(grp, bit);
		IO_UNLOCK(grp);
		break;
	case PAD_GPIO_ALV:
		IO_LOCK(grp);
		for (det = 0; 6 > det; det++) {
			if(NX_ALIVE_GetDetectMode(det, bit)) {
				mod = det;
				break;
			}
		}
		IO_UNLOCK(grp);
		break;
	default:
		printk("fail, soc gpio io:%d, group:%d (%s)\n", io, grp, __func__);
		break;
	};

	return mod;
}
EXPORT_SYMBOL(nxp_soc_gpio_get_int_mode);

/*------------------------------------------------------------------------------
 * 	Description	: indicates whether a specified interrupt is pended or not
 *	In[io]		: gpio pad number, 32*n + bit
 * 				: (n= GPIO_A:0, GPIO_B:1, GPIO_C:2, GPIO_D:3, GPIO_E:4, ALIVE:5, bit= 0 ~ 32)
 *	Return 		: -1 = invalid gpio.
 *		 		:  0 = interrupt not pend.
 *				:  1 = interrupt pended.
 */
int nxp_soc_gpio_get_int_pend(unsigned int io)
{
	unsigned int grp = PAD_GET_GROUP(io);
	unsigned int bit = PAD_GET_BITNO(io);
	int pend = -1;
	DBGOUT("%s (%d.%02d)\n", __func__, grp, bit);

	switch (io & ~(32-1)) {
	case PAD_GPIO_A:
	case PAD_GPIO_B:
	case PAD_GPIO_C:
	case PAD_GPIO_D:
	case PAD_GPIO_E:
		IO_LOCK(grp);
		pend = NX_GPIO_GetInterruptPending(grp, bit) ? 1 : 0;
		IO_UNLOCK(grp);
		break;

	case PAD_GPIO_ALV:
		IO_LOCK(grp);
		pend = NX_ALIVE_GetInterruptPending(bit) ? 1 : 0;
		IO_UNLOCK(grp);
		break;

	default:
		printk("fail, soc gpio io:%d, group:%d (%s)\n", io, grp, __func__);
		break;
	};

	return pend;
}
EXPORT_SYMBOL(nxp_soc_gpio_get_int_pend);

/*------------------------------------------------------------------------------
 * 	Description	: clear pending state of gpio interrupts
 *	In[io]		: gpio pad number, 32*n + bit
 * 				: (n= GPIO_A:0, GPIO_B:1, GPIO_C:2, GPIO_D:3, GPIO_E:4, ALIVE:5, bit= 0 ~ 32)
 *	Return 		: none.
 */
void nxp_soc_gpio_clr_int_pend(unsigned int io)
{
	unsigned int grp = PAD_GET_GROUP(io);
	unsigned int bit = PAD_GET_BITNO(io);
	DBGOUT("%s (%d.%02d)\n", __func__, grp, bit);

	switch (io & ~(32-1)) {
	case PAD_GPIO_A:
	case PAD_GPIO_B:
	case PAD_GPIO_C:
	case PAD_GPIO_D:
	case PAD_GPIO_E:
		IO_LOCK(grp);
		NX_GPIO_ClearInterruptPending(grp, bit);
		NX_GPIO_GetInterruptPending(grp, bit);
		IO_UNLOCK(grp);
		break;

	case PAD_GPIO_ALV:
		IO_LOCK(grp);
		NX_ALIVE_ClearInterruptPending(bit);
		NX_ALIVE_GetInterruptPending(bit);
		IO_UNLOCK(grp);
		break;

	default:
		printk("fail, soc gpio io:%d, group:%d (%s)\n", io, grp, __func__);
		break;
	};

	return;
}
EXPORT_SYMBOL(nxp_soc_gpio_clr_int_pend);

/*------------------------------------------------------------------------------
 * 	Description	: enable alive detect mode
 *	In[io]		: alive pad number, 0~7
 *	In[on]		:  alive detect mode interrupt enable or disable
 *	Return 		: none.
 */
void nxp_soc_alive_set_det_enable(unsigned int io, int on)
{
	unsigned int bit = PAD_GET_BITNO(io);
	DBGOUT("%s (%d)\n", __func__, bit);

	IO_LOCK(ALIVE_INDEX);

	NX_ALIVE_SetOutputEnable(bit, CFALSE);
	NX_ALIVE_SetDetectEnable(bit, on ? CTRUE : CFALSE);

	IO_UNLOCK(ALIVE_INDEX);

	return;
}
EXPORT_SYMBOL_GPL(nxp_soc_alive_set_det_enable);

/*------------------------------------------------------------------------------
 * 	Description	: get alive detect mode type
 *	In[io]		: alive pad number, 0~7
 *	Return 		: 0 = no detect mode.
 *				: 1 = detect mode.
 */
int nxp_soc_alive_get_det_enable(unsigned int io)
{
	unsigned int bit = PAD_GET_BITNO(io);
	int mod = 0;
	DBGOUT("%s (%d)\n", __func__, bit);

	IO_LOCK(ALIVE_INDEX);

	mod = NX_ALIVE_GetDetectEnable(bit) ? 1 : 0;

	IO_UNLOCK(ALIVE_INDEX);

	return mod;
}
EXPORT_SYMBOL_GPL(nxp_soc_alive_get_det_enable);

/*------------------------------------------------------------------------------
 * 	Description	: set alive pad detection mode
 *	In[io]		: alive pad number, 0~7
 *	In[mode]	: alive detection mode
 *				: 0 = async low level detect mode
 *				: 1 = async high level detect mode
 *				: 2 = sync falling edge detect mode
 *				: 3 = sync rising edge detect mode
 *				: 4 = sync low level detect mode
 *				: 5 = sync high level detect mode
 *	In[on]		: alive detection mode enable or disable
 *	Return 		: none.
 */
void nxp_soc_alive_set_det_mode(unsigned int io, unsigned int mode, int on)
{
	unsigned int bit = PAD_GET_BITNO(io);
	DBGOUT("%s (%d)\n", __func__, bit);

	IO_LOCK(ALIVE_INDEX);

	NX_ALIVE_SetDetectMode(mode, bit, on ? CTRUE : CFALSE);

	IO_UNLOCK(ALIVE_INDEX);

	return;
}
EXPORT_SYMBOL_GPL(nxp_soc_alive_set_det_mode);

/*------------------------------------------------------------------------------
 * 	Description	: get alive pad detection mode
 *	In[io]		: alive pad number, 0~7
 *	Return 		: 0 = detect mode is disabled.
 *				: 1 = detect mode is enabled.
 */
int nxp_soc_alive_get_det_mode(unsigned int io, unsigned int mode)
{
	unsigned int bit = PAD_GET_BITNO(io);
	int mod = 0;
	DBGOUT("%s (%d)\n", __func__, bit);

	IO_LOCK(ALIVE_INDEX);

	mod = NX_ALIVE_GetDetectMode(mode, bit) ? 1 : 0;

	IO_UNLOCK(ALIVE_INDEX);

	return mod;
}
EXPORT_SYMBOL_GPL(nxp_soc_alive_get_det_mode);

/*------------------------------------------------------------------------------
 * 	Description	: get alive pad interrupt pend bit staus
 *	In[io]		: alive pad number, 0~7
 *	Return 		: 0 = interrupt not pend.
 *				: 1 = interrupt pended.
 */
int nxp_soc_alive_get_int_pend(unsigned int io)
{
	unsigned int bit = PAD_GET_BITNO(io);
	int pend = -1;
	DBGOUT("%s (%d)\n", __func__, bit);

	IO_LOCK(ALIVE_INDEX);

	pend = NX_ALIVE_GetInterruptPending(bit);

	IO_UNLOCK(ALIVE_INDEX);

	return pend;
}
EXPORT_SYMBOL_GPL(nxp_soc_alive_get_int_pend);

/*------------------------------------------------------------------------------
 * 	Description	: clear alive pad interrupt pend bit
 *	In[io]		: alive pad number, 0~7
 *	Return 		: none.
 */
void nxp_soc_alive_clr_int_pend(unsigned int io)
{
	unsigned int bit = PAD_GET_BITNO(io);
	DBGOUT("%s (%d)\n", __func__, bit);

	IO_LOCK(ALIVE_INDEX);

	NX_ALIVE_ClearInterruptPending(bit);

	IO_UNLOCK(ALIVE_INDEX);

	return;
}
EXPORT_SYMBOL_GPL(nxp_soc_alive_clr_int_pend);

/*-----------------------------------------------------------------------------*/
static int __init nxp_soc_gpio_device_init(void)
{
	int n = ALIVE_INDEX + 1;
	int i = 0;

	for (; n > i; i++)
		IO_LOCK_INIT(i);

	return 0;
}
core_initcall(nxp_soc_gpio_device_init);

lable 3:
SOC GPIO 控制器 register 操作接口實現:

/* arch\arm\mach-s5p6818\prototype\module\nx_gpio.h */

//------------------------------------------------------------------------------
//
//	Copyright (C) 2009 Nexell Co., All Rights Reserved
//	Nexell Co. Proprietary & Confidential
//
//	NEXELL INFORMS THAT THIS CODE AND INFORMATION IS PROVIDED "AS IS" BASE
//	AND WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING
//	BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS
//	FOR A PARTICULAR PURPOSE.
//
//	Module		: GPIO
//	File		: nx_gpio.h
//	Description:
//	Author		: Firmware Team
//	History	:
//
//------------------------------------------------------------------------------
#ifndef __NX_GPIO_H__
#define __NX_GPIO_H__

#include "../base/nx_prototype.h"

#ifdef	__cplusplus
extern "C"
{
#endif

//------------------------------------------------------------------------------
/// @defgroup	GPIO GPIO
//------------------------------------------------------------------------------
//@{

	/// @brief	GPIO Module's Register List
	struct	NX_GPIO_RegisterSet
	{
		volatile U32 GPIOxOUT;			///< 0x00	: Output Register
		volatile U32 GPIOxOUTENB;		///< 0x04	: Output Enable Register
		volatile U32 GPIOxDETMODE[2];	///< 0x08	: Event Detect Mode Register
		volatile U32 GPIOxINTENB;		///< 0x10	: Interrupt Enable Register
		volatile U32 GPIOxDET;			///< 0x14	: Event Detect Register
		volatile U32 GPIOxPAD;			///< 0x18	: PAD Status Register
		volatile U32 GPIOxPUENB;		///< 0x1C	: Pull Up Enable Register
		volatile U32 GPIOxALTFN[2];		///< 0x20	: Alternate Function Select Register
		volatile U32 GPIOxDETMODEEX;    ///< 0x28   : Event Detect Mode extended Register

		volatile U32 __Reserved[4];		///< 0x2B	:
		volatile U32 GPIOxDETENB;		///< 0x3C	: IntPend Detect Enable Register

		volatile U32 GPIOx_SLEW;					///< 0x40	: Slew Register
		volatile U32 GPIOx_SLEW_DISABLE_DEFAULT;    ///< 0x44	: Slew set On/Off Register
		volatile U32 GPIOx_DRV1;                    ///< 0x48	: drive strength LSB Register
		volatile U32 GPIOx_DRV1_DISABLE_DEFAULT;    ///< 0x4C	: drive strength LSB set On/Off Register
		volatile U32 GPIOx_DRV0;                    ///< 0x50	: drive strength MSB Register
		volatile U32 GPIOx_DRV0_DISABLE_DEFAULT;    ///< 0x54	: drive strength MSB set On/Off Register
		volatile U32 GPIOx_PULLSEL;                 ///< 0x58	: Pull UP/DOWN Selection Register
		volatile U32 GPIOx_PULLSEL_DISABLE_DEFAULT; ///< 0x5C	: Pull UP/DOWN Selection On/Off Register
		volatile U32 GPIOx_PULLENB;                 ///< 0x60	: Pull Enable/Disable Register
		volatile U32 GPIOx_PULLENB_DISABLE_DEFAULT; ///< 0x64	: Pull Enable/Disable selection On/Off Register
		volatile U32 GPIOx_InputMuxSelect0;			///< 0x68
		volatile U32 GPIOx_InputMuxSelect1;			///< 0x6C
		U8 __Reserved1[0x1000-0x70];
	};

	///@brief	GPIO Interrupts for interrupt interface
	enum
	{
		NX_GPIO_INT_GPIO0	= 0,	///<	GPIO 0 Interrupt
		NX_GPIO_INT_GPIO1	= 1,	///<	GPIO 1 Interrupt
		NX_GPIO_INT_GPIO2	= 2,	///<	GPIO 2 Interrupt
		NX_GPIO_INT_GPIO3	= 3,	///<	GPIO 3 Interrupt
		NX_GPIO_INT_GPIO4	= 4,	///<	GPIO 4 Interrupt
		NX_GPIO_INT_GPIO5	= 5,	///<	GPIO 5 Interrupt
		NX_GPIO_INT_GPIO6	= 6,	///<	GPIO 6 Interrupt
		NX_GPIO_INT_GPIO7	= 7,	///<	GPIO 7 Interrupt
		NX_GPIO_INT_GPIO8	= 8,	///<	GPIO 8 Interrupt
		NX_GPIO_INT_GPIO9	= 9,	///<	GPIO 9 Interrupt
		NX_GPIO_INT_GPIO10	= 10,	///<	GPIO 10 Interrupt
		NX_GPIO_INT_GPIO11	= 11,	///<	GPIO 11 Interrupt
		NX_GPIO_INT_GPIO12	= 12,	///<	GPIO 12 Interrupt
		NX_GPIO_INT_GPIO13	= 13,	///<	GPIO 13 Interrupt
		NX_GPIO_INT_GPIO14	= 14,	///<	GPIO 14 Interrupt
		NX_GPIO_INT_GPIO15	= 15,	///<	GPIO 15 Interrupt
		NX_GPIO_INT_GPIO16	= 16,	///<	GPIO 16 Interrupt
		NX_GPIO_INT_GPIO17	= 17,	///<	GPIO 17 Interrupt
		NX_GPIO_INT_GPIO18	= 18,	///<	GPIO 18 Interrupt
		NX_GPIO_INT_GPIO19	= 19,	///<	GPIO 19 Interrupt
		NX_GPIO_INT_GPIO20	= 20,	///<	GPIO 20 Interrupt
		NX_GPIO_INT_GPIO21	= 21,	///<	GPIO 21 Interrupt
		NX_GPIO_INT_GPIO22	= 22,	///<	GPIO 22 Interrupt
		NX_GPIO_INT_GPIO23	= 23,	///<	GPIO 23 Interrupt
		NX_GPIO_INT_GPIO24	= 24,	///<	GPIO 24 Interrupt
		NX_GPIO_INT_GPIO25	= 25,	///<	GPIO 25 Interrupt
		NX_GPIO_INT_GPIO26	= 26,	///<	GPIO 26 Interrupt
		NX_GPIO_INT_GPIO27	= 27,	///<	GPIO 27 Interrupt
		NX_GPIO_INT_GPIO28	= 28,	///<	GPIO 28 Interrupt
		NX_GPIO_INT_GPIO29	= 29,	///<	GPIO 29 Interrupt
		NX_GPIO_INT_GPIO30	= 30,	///<	GPIO 30 Interrupt
		NX_GPIO_INT_GPIO31	= 31	///<	GPIO 31 Interrupt
	};

	/// @brief	GPIO interrupt mode
	typedef enum
	{
		NX_GPIO_INTMODE_LOWLEVEL	= 0UL,		///< Low level detect
		NX_GPIO_INTMODE_HIGHLEVEL	= 1UL,		///< High level detect
		NX_GPIO_INTMODE_FALLINGEDGE = 2UL,		///< Falling edge detect
		NX_GPIO_INTMODE_RISINGEDGE	= 3UL,		///< Rising edge detect
		NX_GPIO_INTMODE_BOTHEDGE    = 4UL  		///< both (rise and falling) edge detect

	}NX_GPIO_INTMODE;

	/// @brief	I/O mode
	typedef enum
	{
		NX_GPIO_PADFUNC_0			= 0UL,			///< Alternate function 0
		NX_GPIO_PADFUNC_1			= 1UL,			///< Alternate function 1
		NX_GPIO_PADFUNC_2			= 2UL,			///< Alternate function 2
		NX_GPIO_PADFUNC_3			= 3UL			///< Alternate function 3

	} NX_GPIO_PADFUNC ;

	typedef enum
	{
		NX_GPIO_DRVSTRENGTH_0		= 0UL,
		NX_GPIO_DRVSTRENGTH_1		= 1UL,
		NX_GPIO_DRVSTRENGTH_2		= 2UL,
		NX_GPIO_DRVSTRENGTH_3		= 3UL

	}NX_GPIO_DRVSTRENGTH;

	typedef enum
	{
		NX_GPIO_PULL_DOWN			= 0UL,
		NX_GPIO_PULL_UP			    = 1UL,
		NX_GPIO_PULL_OFF			= 2UL
	} NX_GPIO_PULL;

//------------------------------------------------------------------------------
/// @name	Module Interface
//@{
CBOOL	NX_GPIO_Initialize( void );
U32		NX_GPIO_GetNumberOfModule( void );
//@}

//------------------------------------------------------------------------------
///	@name	Basic Interface
//@{
U32		NX_GPIO_GetPhysicalAddress( U32 ModuleIndex );
U32		NX_GPIO_GetSizeOfRegisterSet( void );
void	NX_GPIO_SetBaseAddress( U32 ModuleIndex, void* BaseAddress );
void*	NX_GPIO_GetBaseAddress( U32 ModuleIndex );
CBOOL	NX_GPIO_OpenModule( U32 ModuleIndex );
CBOOL	NX_GPIO_CloseModule( U32 ModuleIndex );
CBOOL	NX_GPIO_CheckBusy( U32 ModuleIndex );
//@}

//------------------------------------------------------------------------------
///	@name	Interrupt Interface
//@{
U32		NX_GPIO_GetInterruptNumber( U32 ModuleIndex );

void	NX_GPIO_SetInterruptEnable( U32 ModuleIndex, S32 IntNum, CBOOL Enable );
CBOOL	NX_GPIO_GetInterruptEnable( U32 ModuleIndex, S32 IntNum );
CBOOL	NX_GPIO_GetInterruptPending( U32 ModuleIndex, S32 IntNum );
void	NX_GPIO_ClearInterruptPending( U32 ModuleIndex, S32 IntNum );

void	NX_GPIO_SetInterruptEnableAll( U32 ModuleIndex, CBOOL Enable );
CBOOL	NX_GPIO_GetInterruptEnableAll( U32 ModuleIndex );
CBOOL	NX_GPIO_GetInterruptPendingAll( U32 ModuleIndex );
void	NX_GPIO_ClearInterruptPendingAll( U32 ModuleIndex );

void	NX_GPIO_SetInterruptEnable32( U32 ModuleIndex, U32 EnableFlag );
U32		NX_GPIO_GetInterruptEnable32( U32 ModuleIndex );
U32		NX_GPIO_GetInterruptPending32( U32 ModuleIndex );
void	NX_GPIO_ClearInterruptPending32( U32 ModuleIndex, U32 PendingFlag );

S32		NX_GPIO_GetInterruptPendingNumber( U32 ModuleIndex );	// -1 if None
//@}

//------------------------------------------------------------------------------
///	@name	GPIO Operation.
//@{
void			NX_GPIO_SetInterruptMode( U32 ModuleIndex, U32 BitNumber, NX_GPIO_INTMODE IntMode );
NX_GPIO_INTMODE	NX_GPIO_GetInterruptMode( U32 ModuleIndex, U32 BitNumber );
void			NX_GPIO_SetDetectEnable ( U32 ModuleIndex, U32 BitNumber, CBOOL DetectEnb );
CBOOL			NX_GPIO_GetDetectEnable ( U32 ModuleIndex, U32 BitNumber );
void			NX_GPIO_SetDetectEnable32 ( U32 ModuleIndex, U32 EnableFlag );
U32				NX_GPIO_GetDetectEnable32 ( U32 ModuleIndex );
void			NX_GPIO_SetOutputEnable ( U32 ModuleIndex, U32 BitNumber, CBOOL OutputEnb );
CBOOL			NX_GPIO_GetOutputEnable ( U32 ModuleIndex, U32 BitNumber );
void			NX_GPIO_SetOutputEnable32 ( U32 ModuleIndex, CBOOL OutputEnb );
U32				NX_GPIO_GetOutputEnable32 ( U32 ModuleIndex );
void			NX_GPIO_SetOutputValue	( U32 ModuleIndex, U32 BitNumber, CBOOL Value );
CBOOL			NX_GPIO_GetOutputValue	( U32 ModuleIndex, U32 BitNumber );
void			NX_GPIO_SetOutputValue32	( U32 ModuleIndex, U32 Value );
U32				NX_GPIO_GetOutputValue32	( U32 ModuleIndex );
CBOOL			NX_GPIO_GetInputValue		( U32 ModuleIndex, U32 BitNumber );

void			NX_GPIO_SetPadFunction( U32 ModuleIndex, U32 BitNumber, NX_GPIO_PADFUNC padfunc );
void	NX_GPIO_SetPadFunction32( U32 ModuleIndex, U32 MSBValue, U32 LSBValue );
NX_GPIO_PADFUNC	NX_GPIO_GetPadFunction( U32 ModuleIndex, U32 BitNumber );

//------------------------------------------------------------------------------
///	@name	GPIO Operation.
//@{
void	NX_GPIO_SetSlew	( U32 ModuleIndex, U32 BitNumber, CBOOL Enable );
CBOOL	NX_GPIO_GetSlew	( U32 ModuleIndex, U32 BitNumber );
void	NX_GPIO_SetSlewDisableDefault	( U32 ModuleIndex, U32 BitNumber, CBOOL Enable );

void	NX_GPIO_SetSlew32	( U32 ModuleIndex, U32 Value );
U32		NX_GPIO_GetSlew32	( U32 ModuleIndex );
void	NX_GPIO_SetDriveStrength(U32 ModuleIndex, U32 BitNumber, NX_GPIO_DRVSTRENGTH drvstrength);
NX_GPIO_DRVSTRENGTH		NX_GPIO_GetDriveStrength(U32 ModuleIndex, U32 BitNumber);
void	NX_GPIO_SetDriveStrengthDisableDefault	( U32 ModuleIndex, U32 BitNumber, CBOOL Enable );

void	NX_GPIO_SetPullSelect   ( U32 ModuleIndex, U32 BitNumber, CBOOL enable);
CBOOL	NX_GPIO_GetPullSelect   ( U32 ModuleIndex, U32 BitNumber );

void	NX_GPIO_SetPullEnable	( U32 ModuleIndex, U32 BitNumber, NX_GPIO_PULL PullSel );
NX_GPIO_PULL	NX_GPIO_GetPullEnable	( U32 ModuleIndex, U32 BitNumber );
void	NX_GPIO_SetPullEnable32	( U32 ModuleIndex, U32 PullEnb, U32 PullSel );
void	NX_GPIO_GetPullEnable32	( U32 ModuleIndex, U32* PullEnb, U32* PullSel );


U32				NX_GPIO_GetValidBit( U32 ModuleIndex );

void NX_GPIO_SetPadFunctionEnable (  U32 padInfo  );


//@}

//@}

#ifdef	__cplusplus
}
#endif

#endif //__NX_GPIO_H__
//------------------------------------------------------------------------------
//
//	Copyright (C) Nexell Co. 2012
//
//  This confidential and proprietary software may be used only as authorized by a
//  licensing agreement from Nexell Co.
//  The entire notice above must be reproduced on all authorized copies and copies
//  may only be made to the extent permitted by a licensing agreement from Nexell Co.
//
//	Module		: GPIO
//	File		: nx_gpio.h
//	Description	:
//	Author		: Firmware Team
//	History		:
//------------------------------------------------------------------------------

#include "nx_gpio.h"

U32 __g_NX_GPIO_VALID_BIT[NUMBER_OF_GPIO_MODULE] =
{
	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF	// A, B, C, D, E
};


static const U32 __g_GPIO_PAD_INFO[32][NUMBER_OF_GPIO_MODULE] =
{
    { PADINDEX_WITH_CHANNEL_LIST_ALPHA(GPIO, GPIO_0_) },
    { PADINDEX_WITH_CHANNEL_LIST_ALPHA(GPIO, GPIO_1_) },
    { PADINDEX_WITH_CHANNEL_LIST_ALPHA(GPIO, GPIO_2_) },
    { PADINDEX_WITH_CHANNEL_LIST_ALPHA(GPIO, GPIO_3_) },
    { PADINDEX_WITH_CHANNEL_LIST_ALPHA(GPIO, GPIO_4_) },
    { PADINDEX_WITH_CHANNEL_LIST_ALPHA(GPIO, GPIO_5_) },
    { PADINDEX_WITH_CHANNEL_LIST_ALPHA(GPIO, GPIO_6_) },
    { PADINDEX_WITH_CHANNEL_LIST_ALPHA(GPIO, GPIO_7_) },
    { PADINDEX_WITH_CHANNEL_LIST_ALPHA(GPIO, GPIO_8_) },
    { PADINDEX_WITH_CHANNEL_LIST_ALPHA(GPIO, GPIO_9_) },
    { PADINDEX_WITH_CHANNEL_LIST_ALPHA(GPIO, GPIO_10_) },
    { PADINDEX_WITH_CHANNEL_LIST_ALPHA(GPIO, GPIO_11_) },
    { PADINDEX_WITH_CHANNEL_LIST_ALPHA(GPIO, GPIO_12_) },
    { PADINDEX_WITH_CHANNEL_LIST_ALPHA(GPIO, GPIO_13_) },
    { PADINDEX_WITH_CHANNEL_LIST_ALPHA(GPIO, GPIO_14_) },
    { PADINDEX_WITH_CHANNEL_LIST_ALPHA(GPIO, GPIO_15_) },
    { PADINDEX_WITH_CHANNEL_LIST_ALPHA(GPIO, GPIO_16_) },
    { PADINDEX_WITH_CHANNEL_LIST_ALPHA(GPIO, GPIO_17_) },
    { PADINDEX_WITH_CHANNEL_LIST_ALPHA(GPIO, GPIO_18_) },
    { PADINDEX_WITH_CHANNEL_LIST_ALPHA(GPIO, GPIO_19_) },
    { PADINDEX_WITH_CHANNEL_LIST_ALPHA(GPIO, GPIO_20_) },
    { PADINDEX_WITH_CHANNEL_LIST_ALPHA(GPIO, GPIO_21_) },
    { PADINDEX_WITH_CHANNEL_LIST_ALPHA(GPIO, GPIO_22_) },
    { PADINDEX_WITH_CHANNEL_LIST_ALPHA(GPIO, GPIO_23_) },
    { PADINDEX_WITH_CHANNEL_LIST_ALPHA(GPIO, GPIO_24_) },
    { PADINDEX_WITH_CHANNEL_LIST_ALPHA(GPIO, GPIO_25_) },
    { PADINDEX_WITH_CHANNEL_LIST_ALPHA(GPIO, GPIO_26_) },
    { PADINDEX_WITH_CHANNEL_LIST_ALPHA(GPIO, GPIO_27_) },
    { PADINDEX_WITH_CHANNEL_LIST_ALPHA(GPIO, GPIO_28_) },
    { PADINDEX_WITH_CHANNEL_LIST_ALPHA(GPIO, GPIO_29_) },
    { PADINDEX_WITH_CHANNEL_LIST_ALPHA(GPIO, GPIO_30_) },
    { PADINDEX_WITH_CHANNEL_LIST_ALPHA(GPIO, GPIO_31_) }
};

static	struct
{
	struct NX_GPIO_RegisterSet *pRegister;

} __g_ModuleVariables[NUMBER_OF_GPIO_MODULE] = { {CNULL,}, };

enum { NX_GPIO_MAX_BIT = 32 };

//------------------------------------------------------------------------------
// inline Function
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
/**
 *	@brief		Set 1bit value
 *	@param[in]	Value	This Value is changed when SetBit() executed.
 *	@param[in]	Bit		Bit number
 *	@param[in]	Enable	CTRUE( Set ).\n
 *						CFALSE( Clear )
 *	@return		None.
 *	@see		NX_GPIO_GetBit
 */


__inline void NX_GPIO_SetBit
(
	volatile U32* Value,
	U32 Bit,
	CBOOL Enable
)
{
	register U32 newvalue;

	NX_ASSERT( CNULL != Value );
	NX_ASSERT( NX_GPIO_MAX_BIT > Bit );

	newvalue = *Value;

	newvalue &=		~(1UL		<< Bit );
	newvalue |=		(U32)Enable << Bit ;

	WriteIO32(Value, newvalue);
}

//------------------------------------------------------------------------------
/**
 *	@brief		Get bit value
 *	@param[in]	Value	Check this value of 1bit state
 *	@param[in]	Bit		Bit number
 *	@return		CTRUE	indicate that bit is Seted.\n
 *				CFALSE	indicate that bit is cleared.
 *	@see		NX_GPIO_SetBit
 */
__inline CBOOL NX_GPIO_GetBit
(
	U32 Value,
	U32 Bit
)
{
	NX_ASSERT( NX_GPIO_MAX_BIT > Bit );

	return (CBOOL)(( Value >> Bit ) & ( 1UL ) );
}

//------------------------------------------------------------------------------
/**
 *	@brief		Set 2bit value
 *	@param[in]	Value		This Value is changed when SetBit2() executed.
 *	@param[in]	Bit			Bit number
 *	@param[in]	BitValue	Set value of bit
 *	@return		None.
 *	@see		NX_GPIO_GetBit2
 */
__inline void NX_GPIO_SetBit2
(
	volatile U32* Value,
	U32 Bit,
	U32 BitValue
)
{
	register U32 newvalue = *Value;

	NX_ASSERT( CNULL != Value );
	NX_ASSERT( NX_GPIO_MAX_BIT > Bit );

	newvalue = (U32)(newvalue & ~(3UL<<(Bit*2)));
	newvalue = (U32)(newvalue | (BitValue<<(Bit*2)));
	
	WriteIO32(Value, newvalue);
}

//------------------------------------------------------------------------------
/**
 *	@brief		Get 2bit value
 *	@param[in]	Value	Check this value of 2bit state
 *	@param[in]	Bit		Bit number
 *	@return		2bit value
 *	@see		NX_GPIO_SetBit2
 */

__inline U32 NX_GPIO_GetBit2
(
	U32 Value,
	U32 Bit
)
{
	NX_ASSERT( NX_GPIO_MAX_BIT > Bit );

	return (U32)((U32)(Value>>(Bit*2)) & 3UL);
}

//------------------------------------------------------------------------------
// Module Interface
//------------------------------------------------------------------------------
/**
 *	@brief	Initialize of prototype enviroment & local variables.
 *	@return CTRUE	indicate that Initialize is successed.\n
 *			CFALSE	indicate that Initialize is failed.\n
 */
CBOOL	NX_GPIO_Initialize( void )
{
	static CBOOL bInit = CFALSE;
	U32 i;

	if( CFALSE == bInit )
	{
		for( i=0; i < NUMBER_OF_GPIO_MODULE; i++ )
		{
			__g_ModuleVariables[i].pRegister = CNULL;
		}

		bInit = CTRUE;
	}

	for( i = 0 ; i < NUMBER_OF_GPIO_MODULE; i++) {
		 __g_NX_GPIO_VALID_BIT[i] = 0xFFFFFFFF;
//		__g_NX_GPIO_VALID_NUM_OF_INT[i] = 32;
//		__g_NX_GPIO_VALID_INT_MASK[i] = 0xFFFFFFFF;
	};

	return CTRUE;
}

//------------------------------------------------------------------------------
/**
 *	@brief		Get number of modules in the chip.
 *	@return		Module's number.
 */
U32		NX_GPIO_GetNumberOfModule( void )
{
	return NUMBER_OF_GPIO_MODULE;
}

//------------------------------------------------------------------------------
// Basic Interface
//------------------------------------------------------------------------------
/**
 *	@brief		Get module's physical address.
 *	@param[in]	ModuleIndex		A index of module.
 *	@return		Module's physical address
 */
U32		NX_GPIO_GetPhysicalAddress( U32 ModuleIndex )
{
	static const U32 PhysicalAddr[] = { PHY_BASEADDR_LIST_ALPHA( GPIO ) }; // PHY_BASEADDR_GPIO?_MODULE

	NX_CASSERT( NUMBER_OF_GPIO_MODULE == (sizeof(PhysicalAddr)/sizeof(PhysicalAddr[0])) );
	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );

	return (U32)PhysicalAddr[ModuleIndex];
}

//------------------------------------------------------------------------------
/**
 *	@brief		Get a size, in byte, of register set.
 *	@return		Size of module's register set.
 */
U32		NX_GPIO_GetSizeOfRegisterSet( void )
{
	return sizeof( struct NX_GPIO_RegisterSet );
}

//------------------------------------------------------------------------------
/**
 *	@brief		Set a base address of register set.
 *	@param[in]	ModuleIndex		A index of module.
 *	@param[in]	BaseAddress Module's base address
 *	@return		None.
 */
void	NX_GPIO_SetBaseAddress( U32 ModuleIndex, void* BaseAddress )
{
	NX_ASSERT( CNULL != BaseAddress );
	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );

	__g_ModuleVariables[ModuleIndex].pRegister = (struct NX_GPIO_RegisterSet *)BaseAddress;
}

//------------------------------------------------------------------------------
/**
 *	@brief		Get a base address of register set
 *	@param[in]	ModuleIndex		A index of module.
 *	@return		Module's base address.
 */
void*	NX_GPIO_GetBaseAddress( U32 ModuleIndex )
{
	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );

	return (void*)__g_ModuleVariables[ModuleIndex].pRegister;
}

//------------------------------------------------------------------------------
/**
 *	@brief		Initialize selected modules with default value.
 *	@param[in]	ModuleIndex		A index of module.
 *	@return		CTRUE	indicate that Initialize is successed. \n
 *				CFALSE	indicate that Initialize is failed.
 */
CBOOL	NX_GPIO_OpenModule( U32 ModuleIndex )
{
	register	struct NX_GPIO_RegisterSet *pRegister;

	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );

	pRegister = __g_ModuleVariables[ModuleIndex].pRegister;

	NX_ASSERT( CNULL != pRegister );

	WriteIO32(&pRegister->GPIOx_SLEW_DISABLE_DEFAULT, 0xFFFFFFFF );
	WriteIO32(&pRegister->GPIOx_DRV1_DISABLE_DEFAULT, 0xFFFFFFFF );
	WriteIO32(&pRegister->GPIOx_DRV0_DISABLE_DEFAULT, 0xFFFFFFFF );
	WriteIO32(&pRegister->GPIOx_PULLSEL_DISABLE_DEFAULT, 0xFFFFFFFF );
	WriteIO32(&pRegister->GPIOx_PULLENB_DISABLE_DEFAULT, 0xFFFFFFFF );

	return CTRUE;
}

//------------------------------------------------------------------------------
/**
 *	@brief		Deinitialize selected module to the proper stage.
 *	@param[in]	ModuleIndex		A index of module.
 *	@return		CTRUE	indicate that Deinitialize is successed. \n
 *				CFALSE	indicate that Deinitialize is failed.
 */
CBOOL	NX_GPIO_CloseModule( U32 ModuleIndex )
{
	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );

	return CTRUE;
}

//------------------------------------------------------------------------------
/**
 *	@brief		Indicates whether the selected modules is busy or not.
 *	@param[in]	ModuleIndex		A index of module.
 *	@return		CTRUE	indicate that Module is Busy. \n
 *				CFALSE	indicate that Module is NOT Busy.
 */
CBOOL	NX_GPIO_CheckBusy( U32 ModuleIndex )
{
	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );

	return CFALSE;
}


//------------------------------------------------------------------------------
// Interrupt Interface
//------------------------------------------------------------------------------
/**
 *	@brief		Get a interrupt number for interrupt controller.
 *	@return		Interrupt number
 */
 U32		NX_GPIO_GetInterruptNumber( U32 ModuleIndex )
{
	const U32 INTNumber[NUMBER_OF_GPIO_MODULE] =
	{
		INTNUM_LIST_ALPHA(GPIO)
	};

	NX_CASSERT( NUMBER_OF_GPIO_MODULE == (sizeof(INTNumber)/sizeof(INTNumber[0])) );
	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );

	return INTNumber[ModuleIndex];
}

//------------------------------------------------------------------------------
/**
 *	@brief		Set a specified interrupt to be enable or disable.
 *	@param[in]	ModuleIndex		A index of module. (0:GPIOA, 1:GPIOB, 2:GPIOC, 3:GPIOD, 4:GPIOE )
 *	@param[in]	IntNum	Interrupt Number. ( 0 ~ 31 ), if ModuleIndex is GPIOC then IntNum is only 0 ~ 20.
 *	@param[in]	Enable	CTRUE	indicate that Interrupt Enable. \n
 *						CFALSE	indicate that Interrupt Disable.
 *	@return		None.
 */
void	NX_GPIO_SetInterruptEnable( U32 ModuleIndex, S32 IntNum, CBOOL Enable )
{
	register	struct NX_GPIO_RegisterSet *pRegister;
	register	U32 ReadValue ;

	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );
	NX_ASSERT( (CFALSE==Enable) || (CTRUE==Enable) );

	pRegister = __g_ModuleVariables[ModuleIndex].pRegister;

	NX_ASSERT( CNULL != pRegister );

	ReadValue = ReadIO32(&pRegister->GPIOxINTENB);

	ReadValue &= ~( (U32)1		<< IntNum);
	ReadValue |= ( (U32)Enable	<< IntNum );

	WriteIO32(&pRegister->GPIOxINTENB, ReadValue);

	NX_GPIO_SetDetectEnable(ModuleIndex, IntNum, Enable);
}

//------------------------------------------------------------------------------
/**
 *	@brief		Indicates whether a specified interrupt is enabled or disabled.
 *	@param[in]	ModuleIndex		A index of module. (0:GPIOA, 1:GPIOB, 2:GPIOC, 3:GPIOD, 4:GPIOE )
 *	@param[in]	IntNum	Interrupt Number.
 *	@return		CTRUE	indicate that Interrupt is enabled. \n
 *				CFALSE	indicate that Interrupt is disabled.
 */
CBOOL	NX_GPIO_GetInterruptEnable( U32 ModuleIndex, S32 IntNum )
{
	register	struct NX_GPIO_RegisterSet *pRegister;

	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );
	NX_ASSERT( NX_GPIO_MAX_BIT > (U32)IntNum );

	pRegister = __g_ModuleVariables[ModuleIndex].pRegister;

	NX_ASSERT( CNULL != pRegister );

	if( ReadIO32(&pRegister->GPIOxINTENB) & (1UL << IntNum ) )
	{
		return CTRUE;
	}

	return CFALSE;
}

//------------------------------------------------------------------------------
/**
 *	@brief		Set a specified interrupt to be enable or disable.
 *	@param[in]	ModuleIndex		A index of module. (0:GPIOA, 1:GPIOB, 2:GPIOC, 3:GPIOD, 4:GPIOE )
 *	@param[in]	EnableFlag	Specify interrupt bit for enable of disable. Each bit's meaning is like below	\n
 *							- EnableFlag[0] : Set GPIO0 interrupt enable or disable. \n
 *							...
 *							- EnableFlag[31] : Set GPIO31 interrupt enable or disable. \n
 *	@return		None.
 */
void	NX_GPIO_SetInterruptEnable32( U32 ModuleIndex, U32 EnableFlag )
{
	register	struct NX_GPIO_RegisterSet *pRegister;

	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );

	pRegister = __g_ModuleVariables[ModuleIndex].pRegister;

	NX_ASSERT( CNULL != pRegister );

	WriteIO32(&pRegister->GPIOxINTENB, EnableFlag );

	NX_GPIO_SetDetectEnable32(ModuleIndex, EnableFlag);
}

//------------------------------------------------------------------------------
/**
 *	@brief		Indicates current setting value of interrupt enable bit.
 *	@param[in]	ModuleIndex		A index of module. (0:GPIOA, 1:GPIOB, 2:GPIOC, 3:GPIOD, 4:GPIOE )
 *	@return		Current setting value of interrupt. \n
 *				"1" means interrupt is enabled. \n
 *				"0" means interrupt is disabled. \n
 *				- Return Value[0] : GPIO0 interrupt's setting value. \n
 *				...
 *				- Return Value[31] : GPIO31 interrupt's setting value. \n
 */
U32		NX_GPIO_GetInterruptEnable32( U32 ModuleIndex )
{
	register	struct NX_GPIO_RegisterSet *pRegister;

	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );

	pRegister = __g_ModuleVariables[ModuleIndex].pRegister;

	NX_ASSERT( CNULL != pRegister );

	return (U32)ReadIO32(&pRegister->GPIOxINTENB );
}

//------------------------------------------------------------------------------
/**
 *	@brief		Indicates whether a specified interrupt is pended or not
 *	@param[in]	ModuleIndex		A index of module. (0:GPIOA, 1:GPIOB, 2:GPIOC, 3:GPIOD, 4:GPIOE )
 *	@param[in]	IntNum	Interrupt Number.
 *	@return		CTRUE	indicate that Pending is seted. \n
 *				CFALSE	indicate that Pending is Not Seted.
 */
CBOOL	NX_GPIO_GetInterruptPending( U32 ModuleIndex, S32 IntNum )
{
	register	struct NX_GPIO_RegisterSet *pRegister;

	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );
	NX_ASSERT( NX_GPIO_MAX_BIT > (U32)IntNum );

	pRegister = __g_ModuleVariables[ModuleIndex].pRegister;

	NX_ASSERT( CNULL != pRegister );

	if( ReadIO32(&pRegister->GPIOxDET) & (1UL << IntNum ) )
	{
		return CTRUE;
	}

	return CFALSE;
}

//------------------------------------------------------------------------------
/**
 *	@brief		Indicates current setting value of interrupt pending bit.
 *	@param[in]	ModuleIndex		A index of module. (0:GPIOA, 1:GPIOB, 2:GPIOC, 3:GPIOD, 4:GPIOE )
 *	@return		Current setting value of pending bit. \n
 *				"1" means pend bit is occured. \n
 *				"0" means pend bit is NOT occured. \n
 *				- Return Value[0] : GPIO0 pending state. \n
 *				...
 *				- Return Value[31] : GPIO31 pending state. \n
 */
U32		NX_GPIO_GetInterruptPending32( U32 ModuleIndex )
{
	register	struct NX_GPIO_RegisterSet *pRegister;

	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );

	pRegister = __g_ModuleVariables[ModuleIndex].pRegister;

	NX_ASSERT( CNULL != pRegister );

	return(U32)ReadIO32(&pRegister->GPIOxDET);
}

//------------------------------------------------------------------------------
/**
 *	@brief		Clear a pending state of specified interrupt.
 *	@param[in]	ModuleIndex		A index of module. (0:GPIOA, 1:GPIOB, 2:GPIOC, 3:GPIOD, 4:GPIOE )
 *	@param[in]	IntNum	Interrupt number.
 *	@return		None.
 */
void	NX_GPIO_ClearInterruptPending( U32 ModuleIndex, S32 IntNum )
{
	register	struct NX_GPIO_RegisterSet *pRegister;

	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );
	NX_ASSERT( NX_GPIO_MAX_BIT > (U32)IntNum );

	pRegister = __g_ModuleVariables[ModuleIndex].pRegister;

	NX_ASSERT( CNULL != pRegister );

	WriteIO32(&pRegister->GPIOxDET, 1UL << IntNum);
}

//------------------------------------------------------------------------------
/**
 *	@brief		Clear a pending state of specified interrupt.
 *	@param[in]	ModuleIndex		A index of module. (0:GPIOA, 1:GPIOB, 2:GPIOC, 3:GPIOD, 4:GPIOE )
 *	@param[in]	PendingFlag		Specify pend bit to clear. Each bit's meaning is like below	\n \n
 *								- PendingFlag[0] : GPIO0 pending bit. \n
 *									...
 *								- PendingFlag[31] : GPIO31 pending bit. \n
 *	@return		None.
 */
void	NX_GPIO_ClearInterruptPending32( U32 ModuleIndex, U32 PendingFlag )
{
	register	struct NX_GPIO_RegisterSet *pRegister;

	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );

	pRegister = __g_ModuleVariables[ModuleIndex].pRegister;

	NX_ASSERT( CNULL != pRegister );

	WriteIO32(&pRegister->GPIOxDET, PendingFlag);
}

//------------------------------------------------------------------------------
/**
 *	@brief		Set all interrupts to be enables or disables.
 *	@param[in]	ModuleIndex		A index of module. (0:GPIOA, 1:GPIOB, 2:GPIOC, 3:GPIOD, 4:GPIOE )
 *	@param[in]	Enable	CTRUE	indicate that Set to all interrupt enable. \n
 *						CFALSE	indicate that Set to all interrupt disable.
 *	@return		None.
 */
void	NX_GPIO_SetInterruptEnableAll( U32 ModuleIndex, CBOOL Enable )
{
	register	struct NX_GPIO_RegisterSet *pRegister;
	register		U32	setvalue;

	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );
	NX_ASSERT( (CFALSE==Enable) || (CTRUE==Enable) );

	pRegister = __g_ModuleVariables[ModuleIndex].pRegister;

	NX_ASSERT( CNULL != pRegister );

	if( Enable )
	{	setvalue = 0xFFFFFFFF;	}
	else
	{	setvalue = 0x0;	}

	WriteIO32(&pRegister->GPIOxINTENB, setvalue);

	NX_GPIO_SetInterruptEnable32(ModuleIndex, setvalue);
}

//------------------------------------------------------------------------------
/**
 *	@brief		Indicates whether some of interrupts are enable or not.
 *	@param[in]	ModuleIndex		A index of module. (0:GPIOA, 1:GPIOB, 2:GPIOC, 3:GPIOD, 4:GPIOE )
 *	@return		CTRUE	indicate that At least one( or more ) interrupt is enabled. \n
 *				CFALSE	indicate that All interrupt is disabled.
 */
CBOOL	NX_GPIO_GetInterruptEnableAll( U32 ModuleIndex )
{
	register	struct NX_GPIO_RegisterSet *pRegister;

	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );

	pRegister = __g_ModuleVariables[ModuleIndex].pRegister;

	NX_ASSERT( CNULL != pRegister );

	if( ReadIO32(&pRegister->GPIOxINTENB) )
	{
		return CTRUE;
	}
	return CFALSE;
}

//------------------------------------------------------------------------------
/**
 *	@brief		Indicates whether some of interrupts are pended or not.
 *	@param[in]	ModuleIndex		A index of module. (0:GPIOA, 1:GPIOB, 2:GPIOC, 3:GPIOD, 4:GPIOE )
 *	@return		CTRUE	indicate that At least one( or more ) pending is seted. \n
 *				CFALSE	indicate that All pending is NOT seted.
 */
CBOOL	NX_GPIO_GetInterruptPendingAll( U32 ModuleIndex )
{
	register	struct NX_GPIO_RegisterSet *pRegister;

	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );

	pRegister = __g_ModuleVariables[ModuleIndex].pRegister;

	NX_ASSERT( CNULL != pRegister );

	if( ReadIO32(&pRegister->GPIOxDET) )
	{
		return CTRUE;
	}
	return CFALSE;
}

//------------------------------------------------------------------------------
/**
 *	@brief		Clear pending state of all interrupts.
 *	@param[in]	ModuleIndex		A index of module. (0:GPIOA, 1:GPIOB, 2:GPIOC, 3:GPIOD, 4:GPIOE )
 *	@return		None.
 */
void	NX_GPIO_ClearInterruptPendingAll( U32 ModuleIndex )
{
	register	struct NX_GPIO_RegisterSet *pRegister;

	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );

	pRegister = __g_ModuleVariables[ModuleIndex].pRegister;

	NX_ASSERT( CNULL != pRegister );

	WriteIO32(&pRegister->GPIOxDET, (U32)(0xFFFFFFFF));
}

//------------------------------------------------------------------------------
/**
 *	@brief		Get a interrupt number which has the most prority of pended interrupts
 *	@param[in]	ModuleIndex		A index of module. (0:GPIOA, 1:GPIOB, 2:GPIOC, 3:GPIOD, 4:GPIOE )
 *	@return		Pending Number( If all pending is not set then return -1 ).
 */
S32		NX_GPIO_GetInterruptPendingNumber( U32 ModuleIndex )	// -1 if None
{
	register struct NX_GPIO_RegisterSet	*pRegister;
	register	U32 intnum;
	register	U32 intpend;

	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );

	pRegister = __g_ModuleVariables[ModuleIndex].pRegister;

	NX_ASSERT( CNULL != pRegister );


	intpend = ReadIO32(&pRegister->GPIOxDET);

	for( intnum=0 ; intnum<32 ; intnum++ )
	{
		if( 0 != (intpend & (1UL<<intnum)) )
		{
			return intnum;
		}
	}

	return -1;
}

//------------------------------------------------------------------------------
// GPIO Operation.
//------------------------------------------------------------------------------

/**
 *	@brief		Set interrupt mode
 *	@param[in]	ModuleIndex	A index of module. (0:GPIOA, 1:GPIOB, 2:GPIOC, 3:GPIOD, 4:GPIOE )
 *	@param[in]	BitNumber	Bit number ( 0 ~ 31 )
 *	@param[in]	IntMode		GPIO interrupt detect mode
 *	@return		None.
 */
void				NX_GPIO_SetInterruptMode( U32 ModuleIndex, U32 BitNumber, NX_GPIO_INTMODE IntMode )
{
	register struct NX_GPIO_RegisterSet	*pRegister;

	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );
	NX_ASSERT( 0 != (__g_NX_GPIO_VALID_BIT[ModuleIndex] & (1 << BitNumber)) );
	NX_ASSERT( NX_GPIO_INTMODE_BOTHEDGE >= IntMode );

	pRegister = __g_ModuleVariables[ModuleIndex].pRegister;

	NX_ASSERT( CNULL != pRegister );

	NX_GPIO_SetBit2( &pRegister->GPIOxDETMODE[BitNumber/16], BitNumber%16, (U32)IntMode & 0x03 );
	NX_GPIO_SetBit( &pRegister->GPIOxDETMODEEX, BitNumber, (U32)(IntMode>>2) );
}

//------------------------------------------------------------------------------
/**
 *	@brief		Get interrupt mode
 *	@param[in]	ModuleIndex		A index of module. (0:GPIOA, 1:GPIOB, 2:GPIOC, 3:GPIOD, 4:GPIOE )
 *	@param[in]	BitNumber	Bit number ( 0 ~ 31 )
 *	@return		GPIO interrupt detect mode
 */
NX_GPIO_INTMODE	NX_GPIO_GetInterruptMode( U32 ModuleIndex, U32 BitNumber )
{
	register struct NX_GPIO_RegisterSet	*pRegister;
	U32 regvalue;

	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );
	NX_ASSERT( 0 != (__g_NX_GPIO_VALID_BIT[ModuleIndex] & (1 << BitNumber)) );

	pRegister = __g_ModuleVariables[ModuleIndex].pRegister;

	NX_ASSERT( CNULL != pRegister );

	regvalue = NX_GPIO_GetBit2( ReadIO32(&pRegister->GPIOxDETMODE[BitNumber/16]), BitNumber%16 );
	regvalue |= (NX_GPIO_GetBit( ReadIO32(&pRegister->GPIOxDETMODEEX), BitNumber)<<2);

	return (NX_GPIO_INTMODE)regvalue;
}

//------------------------------------------------------------------------------
/**
 *	@brief		Get gpio output enable
 *	@param[in]	ModuleIndex		A index of module. (0:GPIOA, 1:GPIOB, 2:GPIOC, 3:GPIOD, 4:GPIOE )
 *	@param[in]	BitNumber	Bit number ( 0 ~ 31 )
 *	@param[in]	OutputEnb	CTRUE	indicate that Output Mode. \n
 *							CFALSE	indicate that Input Mode.
 *	@return		None.
 */
void	NX_GPIO_SetOutputEnable ( U32 ModuleIndex, U32 BitNumber, CBOOL OutputEnb )
{
	register struct NX_GPIO_RegisterSet	*pRegister;

	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );
	NX_ASSERT( 0 != (__g_NX_GPIO_VALID_BIT[ModuleIndex] & (1 << BitNumber)) );
	NX_ASSERT( (CFALSE==OutputEnb) || (CTRUE==OutputEnb) );

	pRegister = __g_ModuleVariables[ModuleIndex].pRegister;

	NX_ASSERT( CNULL != pRegister );

	NX_GPIO_SetBit( &pRegister->GPIOxOUTENB, BitNumber, OutputEnb );
}

//------------------------------------------------------------------------------
/**
 *	@brief		Get gpio Event Detect
 *	@param[in]	ModuleIndex		A index of module. (0:GPIOA, 1:GPIOB, 2:GPIOC, 3:GPIOD, 4:GPIOE )
 *	@param[in]	BitNumber	Bit number ( 0 ~ 31 )
 *	@param[in]	OutputEnb	CTRUE	indicate that Event Detect Enabled. \n
 *							CFALSE	indicate that Event Detect Disabled.
 *	@return		None.
 */
CBOOL			NX_GPIO_GetDetectEnable ( U32 ModuleIndex, U32 BitNumber )
{
	register struct NX_GPIO_RegisterSet	*pRegister;

	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );
	NX_ASSERT( 0 != (__g_NX_GPIO_VALID_BIT[ModuleIndex] & (1 << BitNumber)) );

	pRegister = __g_ModuleVariables[ModuleIndex].pRegister;

	NX_ASSERT( CNULL != pRegister );

	return NX_GPIO_GetBit( ReadIO32(&pRegister->GPIOxDETENB), BitNumber );
}

U32			NX_GPIO_GetDetectEnable32 ( U32 ModuleIndex )
{
	register struct NX_GPIO_RegisterSet	*pRegister;

	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );

	pRegister = __g_ModuleVariables[ModuleIndex].pRegister;

	NX_ASSERT( CNULL != pRegister );

	return ReadIO32(&pRegister->GPIOxDETENB);
}

//------------------------------------------------------------------------------
/**
 *	@brief		Set Event Detect Enable
 *	@param[in]	ModuleIndex		A index of module. (0:GPIOA, 1:GPIOB, 2:GPIOC, 3:GPIOD, 4:GPIOE )
 *	@param[in]	BitNumber	Bit number ( 0 ~ 31 )
 *	@return		GPIO interrupt detect mode
 */
void			NX_GPIO_SetDetectEnable ( U32 ModuleIndex, U32 BitNumber, CBOOL DetectEnb )
{
	register struct NX_GPIO_RegisterSet	*pRegister;

	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );
	NX_ASSERT( 0 != (__g_NX_GPIO_VALID_BIT[ModuleIndex] & (1 << BitNumber)) );
	NX_ASSERT( (CFALSE==DetectEnb) || (CTRUE==DetectEnb) );

	pRegister = __g_ModuleVariables[ModuleIndex].pRegister;

	NX_ASSERT( CNULL != pRegister );

	NX_GPIO_SetBit( &pRegister->GPIOxDETENB, BitNumber, DetectEnb );
}

void			NX_GPIO_SetDetectEnable32 ( U32 ModuleIndex, U32 EnableFlag )
{
	register struct NX_GPIO_RegisterSet	*pRegister;

	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );

	pRegister = __g_ModuleVariables[ModuleIndex].pRegister;

	NX_ASSERT( CNULL != pRegister );

	WriteIO32(&pRegister->GPIOxDETENB, EnableFlag );
}

//------------------------------------------------------------------------------
/**
 *	@brief		Get gpio output enable
 *	@param[in]	ModuleIndex		A index of module. (0:GPIOA, 1:GPIOB, 2:GPIOC, 3:GPIOD, 4:GPIOE )
 *	@param[in]	BitNumber	Bit number ( 0 ~ 31 )
 *	@return		CTRUE	indicate that GPIO's current Setting is Output Mode.\n
 *				CFALSE	indicate that GPIO's current Setting is Input Mode.
 */
CBOOL	NX_GPIO_GetOutputEnable ( U32 ModuleIndex, U32 BitNumber )
{
	register struct NX_GPIO_RegisterSet	*pRegister;

	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );
	NX_ASSERT( 0 != (__g_NX_GPIO_VALID_BIT[ModuleIndex] & (1 << BitNumber)) );

	pRegister = __g_ModuleVariables[ModuleIndex].pRegister;

	NX_ASSERT( CNULL != pRegister );

	return NX_GPIO_GetBit( ReadIO32(&pRegister->GPIOxOUTENB), BitNumber );
}

//------------------------------------------------------------------------------
/**
 *	@brief		Get gpio output enable
 *	@param[in]	ModuleIndex		A index of module. (0:GPIOA, 1:GPIOB, 2:GPIOC, 3:GPIOD, 4:GPIOE )
 *	@param[in]	BitNumber	Bit number ( 0 ~ 31 )
 *	@param[in]	OutputEnb	CTRUE	indicate that Output Mode. \n
 *							CFALSE	indicate that Input Mode.
 *	@return		None.
 */
void	NX_GPIO_SetOutputEnable32 ( U32 ModuleIndex, CBOOL OutputEnb )
{
	register struct NX_GPIO_RegisterSet	*pRegister;

	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );
	NX_ASSERT( (CFALSE==OutputEnb) || (CTRUE==OutputEnb) );

	pRegister = __g_ModuleVariables[ModuleIndex].pRegister;

	NX_ASSERT( CNULL != pRegister );


	if(OutputEnb)
		WriteIO32(&pRegister->GPIOxOUTENB, 0xFFFFFFFF );
	else
		WriteIO32(&pRegister->GPIOxOUTENB, 0x0 );
}

//------------------------------------------------------------------------------
/**
 *	@brief		Get gpio output enable
 *	@param[in]	ModuleIndex		A index of module. (0:GPIOA, 1:GPIOB, 2:GPIOC, 3:GPIOD, 4:GPIOE )
 *	@param[in]	BitNumber	Bit number ( 0 ~ 31 )
 *	@return		CTRUE	indicate that GPIO's current Setting is Output Mode.\n
 *				CFALSE	indicate that GPIO's current Setting is Input Mode.
 */
U32		NX_GPIO_GetOutputEnable32 ( U32 ModuleIndex )
{
	register struct NX_GPIO_RegisterSet	*pRegister;

	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );

	pRegister = __g_ModuleVariables[ModuleIndex].pRegister;

	NX_ASSERT( CNULL != pRegister );

	return ReadIO32(&pRegister->GPIOxOUTENB);
}

//------------------------------------------------------------------------------
/**
 *	@brief		Set gpio output value
 *	@param[in]	ModuleIndex		A index of module. (0:GPIOA, 1:GPIOB, 2:GPIOC, 3:GPIOD, 4:GPIOE )
 *	@param[in]	BitNumber	Bit number ( 0 ~ 31 )
 *	@param[in]	Value		CTRUE	indicate that High Level. \n
 *							CFALSE	indicate that Low Level.
 *	@return		None.
 */
void	NX_GPIO_SetOutputValue	( U32 ModuleIndex, U32 BitNumber, CBOOL Value )
{
	register struct NX_GPIO_RegisterSet	*pRegister;

	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );
	NX_ASSERT( 0 != (__g_NX_GPIO_VALID_BIT[ModuleIndex] & (1 << BitNumber)) );
	NX_ASSERT( (CFALSE==Value) || (CTRUE==Value) );

	pRegister = __g_ModuleVariables[ModuleIndex].pRegister;

	NX_ASSERT( CNULL != pRegister );

	NX_GPIO_SetBit( &pRegister->GPIOxOUT, BitNumber, Value );
}

//------------------------------------------------------------------------------
/**
 *	@brief		Get gpio output value
 *	@param[in]	ModuleIndex		A index of module. (0:GPIOA, 1:GPIOB, 2:GPIOC, 3:GPIOD, 4:GPIOE )
 *	@param[in]	BitNumber	Bit number ( 0 ~ 31 )
 *	@return		CTRUE	indicate that GPIO's output value is High Level.\n
 *				CFALSE	indicate that GPIO's output value is Low Level.
 */
CBOOL	NX_GPIO_GetOutputValue	( U32 ModuleIndex, U32 BitNumber )
{
	register struct NX_GPIO_RegisterSet	*pRegister;

	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );
	NX_ASSERT( 0 != (__g_NX_GPIO_VALID_BIT[ModuleIndex] & (1 << BitNumber)) );

	pRegister = __g_ModuleVariables[ModuleIndex].pRegister;

	NX_ASSERT( CNULL != pRegister );

	return NX_GPIO_GetBit( ReadIO32(&pRegister->GPIOxOUT), BitNumber );
}

//------------------------------------------------------------------------------
/**
 *	@brief		Set gpio output value
 *	@param[in]	ModuleIndex		A index of module. (0:GPIOA, 1:GPIOB, 2:GPIOC, 3:GPIOD, 4:GPIOE )
 *	@param[in]	BitNumber	Bit number ( 0 ~ 31 )
 *	@param[in]	Value		CTRUE	indicate that High Level. \n
 *							CFALSE	indicate that Low Level.
 *	@return		None.
 */
void	NX_GPIO_SetOutputValue32	( U32 ModuleIndex, U32 Value )
{
	register struct NX_GPIO_RegisterSet	*pRegister;

	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );

	pRegister = __g_ModuleVariables[ModuleIndex].pRegister;

	NX_ASSERT( CNULL != pRegister );

	WriteIO32(&pRegister->GPIOxOUT, Value );
}

//------------------------------------------------------------------------------
/**
 *	@brief		Get gpio output value
 *	@param[in]	ModuleIndex		A index of module. (0:GPIOA, 1:GPIOB, 2:GPIOC, 3:GPIOD, 4:GPIOE )
 *	@param[in]	BitNumber	Bit number ( 0 ~ 31 )
 *	@return		CTRUE	indicate that GPIO's output value is High Level.
 *				CFALSE	indicate that GPIO's output value is Low Level.
 */
U32		NX_GPIO_GetOutputValue32	( U32 ModuleIndex )
{
	register struct NX_GPIO_RegisterSet	*pRegister;

	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );

	pRegister = __g_ModuleVariables[ModuleIndex].pRegister;

	NX_ASSERT( CNULL != pRegister );

	return ReadIO32(&pRegister->GPIOxOUT);
}

//------------------------------------------------------------------------------
/**
 *	@brief		Get gpio input value
 *	@param[in]	ModuleIndex		A index of module. (0:GPIOA, 1:GPIOB, 2:GPIOC, 3:GPIOD, 4:GPIOE )
 *	@param[in]	BitNumber	Bit number ( 0 ~ 31 )
 *	@return		CTRUE	indicate that GPIO's input value is High Level.
 *				CFALSE	indicate that GPIO's input value is Low Level.
 */
CBOOL	NX_GPIO_GetInputValue		( U32 ModuleIndex, U32 BitNumber )
{
	register struct NX_GPIO_RegisterSet	*pRegister;

	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );
	NX_ASSERT( 0 != (__g_NX_GPIO_VALID_BIT[ModuleIndex] & (1 << BitNumber)) );

	pRegister = __g_ModuleVariables[ModuleIndex].pRegister;

	NX_ASSERT( CNULL != pRegister );

	return NX_GPIO_GetBit( ReadIO32(&pRegister->GPIOxPAD), BitNumber );
}

//------------------------------------------------------------------------------
/**
 *	@brief		Set Pull sel of GPIO Pin
 *	@param[in]	ModuleIndex		A index of module. (0:GPIOA, 1:GPIOB, 2:GPIOC )
 *	@param[in]	BitNumber	Bit number ( 0 ~ 31 ), if ModuleIndex is GPIOC then Bit number is only 0 ~ 20.
 *	@param[in]	enable		CTRUE	indicate that Pull Up.
 *							CFALSE	indicate that NOT Pull Up.
 *	@return		None.
 */
void	NX_GPIO_SetPullSelect   ( U32 ModuleIndex, U32 BitNumber, CBOOL enable)
{
	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );
	NX_ASSERT( (0==enable) || (1==enable) );
	NX_ASSERT( CNULL != __g_ModuleVariables[ModuleIndex].pRegister );

	NX_GPIO_SetBit( &__g_ModuleVariables[ModuleIndex].pRegister->GPIOx_PULLSEL_DISABLE_DEFAULT, BitNumber, CTRUE );
//	NX_GPIO_SetBit( &__g_ModuleVariables[ModuleIndex].pRegister->GPIOx_PULLSEL_DISABLE_DEFAULT, BitNumber, enable );
	NX_GPIO_SetBit( &__g_ModuleVariables[ModuleIndex].pRegister->GPIOx_PULLSEL, BitNumber, enable );
}

void	NX_GPIO_SetPullSelect32 ( U32 ModuleIndex, U32 Value )
{
	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );
	NX_ASSERT( CNULL != __g_ModuleVariables[ModuleIndex].pRegister );

	WriteIO32(&__g_ModuleVariables[ModuleIndex].pRegister->GPIOx_PULLSEL, Value );
}
//------------------------------------------------------------------------------
/**
 *	@brief		Get pull sel value of GPIO Pin
 *	@param[in]	ModuleIndex		A index of module. (0:GPIOA, 1:GPIOB, 2:GPIOC )
 *	@param[in]	BitNumber	Bit number ( 0 ~ 31 ), if ModuleIndex is GPIOC then Bit number is only 0 ~ 20.
 *	@return		GPIO pull up value
 */
CBOOL	NX_GPIO_GetPullSelect   ( U32 ModuleIndex, U32 BitNumber )
{
	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );
	NX_ASSERT( CNULL != __g_ModuleVariables[ModuleIndex].pRegister );

	return NX_GPIO_GetBit( __g_ModuleVariables[ModuleIndex].pRegister->GPIOx_PULLSEL, BitNumber );
}

U32		NX_GPIO_GetPullSelect32 ( U32 ModuleIndex )
{
	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );
	NX_ASSERT( CNULL != __g_ModuleVariables[ModuleIndex].pRegister );

	return __g_ModuleVariables[ModuleIndex].pRegister->GPIOx_PULLSEL;
}

void	NX_GPIO_SetPullMode ( U32 ModuleIndex, U32 BitNumber, NX_GPIO_PULL mode)
{
	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );
	NX_ASSERT( (0==mode) || (1==mode) || (2==mode) );
	NX_ASSERT( CNULL != __g_ModuleVariables[ModuleIndex].pRegister );

	NX_GPIO_SetBit( &__g_ModuleVariables[ModuleIndex].pRegister->GPIOx_PULLSEL_DISABLE_DEFAULT, BitNumber, CTRUE );
	NX_GPIO_SetBit( &__g_ModuleVariables[ModuleIndex].pRegister->GPIOx_PULLENB_DISABLE_DEFAULT, BitNumber, CTRUE );

	if (mode == NX_GPIO_PULL_OFF)
	{
//NX_GPIO_SetBit( &__g_ModuleVariables[ModuleIndex].pRegister->GPIOx_PULLENB_DISABLE_DEFAULT, BitNumber, CFALSE );

		NX_GPIO_SetBit( &__g_ModuleVariables[ModuleIndex].pRegister->GPIOx_PULLENB, BitNumber, CFALSE );
		NX_GPIO_SetBit( &__g_ModuleVariables[ModuleIndex].pRegister->GPIOx_PULLSEL, BitNumber, CFALSE );
	}
	else
	{
//NX_GPIO_SetBit( &__g_ModuleVariables[ModuleIndex].pRegister->GPIOx_PULLENB_DISABLE_DEFAULT, BitNumber, CTRUE );

		NX_GPIO_SetBit( &__g_ModuleVariables[ModuleIndex].pRegister->GPIOx_PULLSEL, BitNumber, (mode & 1 ? CTRUE : CFALSE) );
		NX_GPIO_SetBit( &__g_ModuleVariables[ModuleIndex].pRegister->GPIOx_PULLENB, BitNumber, CTRUE );
	}
}


//--------------------------------------------------------------------------
// Pin Configuration
//--------------------------------------------------------------------------
/**
 *	@brief		Set PAD Fuction
 *	@param[in]	ModuleIndex		A index of module. (0:GPIOA, 1:GPIOB, 2:GPIOC, 3:GPIOD, 4:GPIOE )
 *	@param[in]	BitNumber	Bit number ( 0 ~ 31 )
 *	@param[in]	padfunc		Pad Function
 *	@return		None
 *	@remarks	Each gpio pins can use to GPIO Pin or Alternate Function 0 or Alternate Function 1 or \n
 *				Alternate Function 2. So This function Sets gpio pin's function.
 */
void	NX_GPIO_SetPadFunction( U32 ModuleIndex, U32 BitNumber, NX_GPIO_PADFUNC padfunc )
{
	register struct NX_GPIO_RegisterSet	*pRegister;

	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );
	NX_ASSERT( 0 != (__g_NX_GPIO_VALID_BIT[ModuleIndex] & (1 << BitNumber)) );
	NX_ASSERT( NX_GPIO_PADFUNC_3 >= padfunc );

	pRegister = __g_ModuleVariables[ModuleIndex].pRegister;

	NX_ASSERT( CNULL != pRegister );

	NX_GPIO_SetBit2( &pRegister->GPIOxALTFN[BitNumber/16], BitNumber%16, (U32)padfunc );
}

void	NX_GPIO_SetPadFunction32( U32 ModuleIndex, U32 MSBValue, U32 LSBValue )
{
	register struct NX_GPIO_RegisterSet	*pRegister;

	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );

	pRegister = __g_ModuleVariables[ModuleIndex].pRegister;

	NX_ASSERT( CNULL != pRegister );

	WriteIO32(&pRegister->GPIOxALTFN[0], LSBValue );
	WriteIO32(&pRegister->GPIOxALTFN[1], MSBValue );
}


//------------------------------------------------------------------------------
/**
 *	@brief		Get PAD Fuction
 *	@param[in]	ModuleIndex		A index of module. (0:GPIOA, 1:GPIOB, 2:GPIOC, 3:GPIOD, 4:GPIOE )
 *	@param[in]	BitNumber	Bit number ( 0 ~ 31 )
 *	@return		None
 */
NX_GPIO_PADFUNC	NX_GPIO_GetPadFunction( U32 ModuleIndex, U32 BitNumber )
{
	register struct NX_GPIO_RegisterSet	*pRegister;

	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );
	NX_ASSERT( 0 != (__g_NX_GPIO_VALID_BIT[ModuleIndex] & (1 << BitNumber)) );

	pRegister = __g_ModuleVariables[ModuleIndex].pRegister;

	NX_ASSERT( CNULL != pRegister );

	return (NX_GPIO_PADFUNC)NX_GPIO_GetBit2( ReadIO32(&pRegister->GPIOxALTFN[BitNumber/16]), BitNumber%16 );
}

//------------------------------------------------------------------------------
/**
 *	@brief		Get GPIO's valid bit
 *	@param[in]	ModuleIndex		A index of module. (0:GPIOA, 1:GPIOB, 2:GPIOC, 3:GPIOD, 4:GPIOE )
 *	@return		GPIO's valid bit
 *	@remarks	Each bit's indicate corresponding GPIO pin. If retun value is 0x0FF, then
 *				This indicate that GPIO have eight pins ( GPIO0 ~ GPIO7 ).
 */
U32		NX_GPIO_GetValidBit( U32 ModuleIndex )
{
	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );

	return __g_NX_GPIO_VALID_BIT[ModuleIndex];
}
//------------------------------------------------------------------------------
/**
 *	@brief		Set GPIO Slew
 *	@param[in]	ModuleIndex		A index of module. (0:GPIOA, 1:GPIOB, 2:GPIOC, 3:GPIOD, 4:GPIOE )
 *	@param[in]	BitNumber	Bit number ( 0 ~ 31 )
 *	@param[in]	Enable		Slew On/Off
 *	@return		None
 */
void		NX_GPIO_SetSlew	( U32 ModuleIndex, U32 BitNumber, CBOOL Enable )
{
	register struct NX_GPIO_RegisterSet	*pRegister;

	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );

	pRegister = __g_ModuleVariables[ModuleIndex].pRegister;

	NX_ASSERT( CNULL != pRegister );

	NX_GPIO_SetBit(&pRegister->GPIOx_SLEW, BitNumber, Enable);
}

void		NX_GPIO_SetSlewDisableDefault	( U32 ModuleIndex, U32 BitNumber, CBOOL Enable )
{
	register struct NX_GPIO_RegisterSet	*pRegister;

	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );

	pRegister = __g_ModuleVariables[ModuleIndex].pRegister;

	NX_ASSERT( CNULL != pRegister );

	NX_GPIO_SetBit(&pRegister->GPIOx_SLEW_DISABLE_DEFAULT, BitNumber, Enable);
}


//------------------------------------------------------------------------------
/**
 *	@brief		Get GPIO Slew
 *	@param[in]	ModuleIndex		A index of module. (0:GPIOA, 1:GPIOB, 2:GPIOC, 3:GPIOD, 4:GPIOE )
 *	@return		CTRUE	indicate that GPIO's slew is turned on.
 *				CFALSE	indicate that GPIO's slew is turned off.
 */
CBOOL		NX_GPIO_GetSlew	( U32 ModuleIndex, U32 BitNumber )
{
	register struct NX_GPIO_RegisterSet	*pRegister;
	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );

	pRegister = __g_ModuleVariables[ModuleIndex].pRegister;

	NX_ASSERT( CNULL != pRegister );

	return (CBOOL)NX_GPIO_GetBit(ReadIO32(&pRegister->GPIOx_SLEW), BitNumber);
}

//------------------------------------------------------------------------------
/**
 *	@brief		Set GPIO Slew
 *	@param[in]	ModuleIndex		A index of module. (0:GPIOA, 1:GPIOB, 2:GPIOC, 3:GPIOD, 4:GPIOE )
 *	@param[in]	Value			32bit input data
 *	@return		None
 */
void		NX_GPIO_SetSlew32	( U32 ModuleIndex, U32 Value )
{
	register struct NX_GPIO_RegisterSet	*pRegister;

	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );

	pRegister = __g_ModuleVariables[ModuleIndex].pRegister;

	NX_ASSERT( CNULL != pRegister );

	WriteIO32(&pRegister->GPIOx_SLEW, Value );
}

//------------------------------------------------------------------------------
/**
 *	@brief		Get GPIO Slew
 *	@param[in]	ModuleIndex		A index of module. (0:GPIOA, 1:GPIOB, 2:GPIOC, 3:GPIOD, 4:GPIOE )
 *	@return		GPIO slew value
 */
U32		NX_GPIO_GetSlew32	( U32 ModuleIndex )
{
	register struct NX_GPIO_RegisterSet	*pRegister;
	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );

	pRegister = __g_ModuleVariables[ModuleIndex].pRegister;

	NX_ASSERT( CNULL != pRegister );

	return ReadIO32(&pRegister->GPIOx_SLEW);
}


//------------------------------------------------------------------------------
/**
 *	@brief		Set GPIO Drive Strength
 *	@param[in]	ModuleIndex		A index of module. (0:GPIOA, 1:GPIOB, 2:GPIOC, 3:GPIOD, 4:GPIOE )
 *	@param[in]	BitNumber	Bit number ( 0 ~ 31 )
 *	@param[in]	DriveStrength
 *	@return		None
 */
void		NX_GPIO_SetDriveStrength	( U32 ModuleIndex, U32 BitNumber, NX_GPIO_DRVSTRENGTH drvstrength)
{
	register struct NX_GPIO_RegisterSet	*pRegister;

	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );

	pRegister = __g_ModuleVariables[ModuleIndex].pRegister;

	NX_ASSERT( CNULL != pRegister );

	NX_GPIO_SetBit(&pRegister->GPIOx_DRV1, BitNumber, (CBOOL)(((U32)drvstrength>>0) & 0x1));
	NX_GPIO_SetBit(&pRegister->GPIOx_DRV0, BitNumber, (CBOOL)(((U32)drvstrength>>1) & 0x1));
}

void		NX_GPIO_SetDriveStrengthDisableDefault	( U32 ModuleIndex, U32 BitNumber, CBOOL Enable )
{
	register struct NX_GPIO_RegisterSet	*pRegister;

	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );

	pRegister = __g_ModuleVariables[ModuleIndex].pRegister;

	NX_ASSERT( CNULL != pRegister );

	NX_GPIO_SetBit(&pRegister->GPIOx_DRV1_DISABLE_DEFAULT, BitNumber, (CBOOL)(Enable) );
	NX_GPIO_SetBit(&pRegister->GPIOx_DRV0_DISABLE_DEFAULT, BitNumber, (CBOOL)(Enable) );
}


//------------------------------------------------------------------------------
/**
 *	@brief		Get GPIO Drive Strength
 *	@param[in]	ModuleIndex		A index of module. (0:GPIOA, 1:GPIOB, 2:GPIOC, 3:GPIOD, 4:GPIOE )
 *	@param[in]	BitNumber	Bit number ( 0 ~ 31 )
 *	@return		GPIO GPIO Drive Strength
 */
NX_GPIO_DRVSTRENGTH		NX_GPIO_GetDriveStrength	( U32 ModuleIndex, U32 BitNumber )
{
	register struct NX_GPIO_RegisterSet	*pRegister;
	register U32 retvalue;

	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );

	pRegister = __g_ModuleVariables[ModuleIndex].pRegister;

	NX_ASSERT( CNULL != pRegister );

	retvalue  = NX_GPIO_GetBit(ReadIO32(&pRegister->GPIOx_DRV0), BitNumber)<<1;
	retvalue |= NX_GPIO_GetBit(ReadIO32(&pRegister->GPIOx_DRV1), BitNumber)<<0;

	return (NX_GPIO_DRVSTRENGTH)retvalue;
}

//------------------------------------------------------------------------------
/**
 *	@brief		Set GPIO PullEnb
 *	@param[in]	ModuleIndex		A index of module. (0:GPIOA, 1:GPIOB, 2:GPIOC, 3:GPIOD, 4:GPIOE )
 *	@param[in]	BitNumber		Bit number ( 0 ~ 31 )
 *	@param[in]	PullEnb			CTRUE: pull enable, CFALSE: pull disable
 *   @parma[in]  updown			0 : Pull Down	1: Pull Up	2: PullEnb - Disable 
 *	@return		None
 */
void	NX_GPIO_SetPullEnable	( U32 ModuleIndex, U32 BitNumber, NX_GPIO_PULL PullSel )
{
	register struct NX_GPIO_RegisterSet	*pRegister;

	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );

	pRegister = __g_ModuleVariables[ModuleIndex].pRegister;

	NX_ASSERT( CNULL != pRegister );

	if( PullSel == NX_GPIO_PULL_DOWN || PullSel == NX_GPIO_PULL_UP  )
	{
		NX_GPIO_SetBit(&pRegister->GPIOx_PULLSEL, BitNumber, (CBOOL)PullSel);
		NX_GPIO_SetBit(&pRegister->GPIOx_PULLENB, BitNumber, CTRUE );
	}
	else
		NX_GPIO_SetBit(&pRegister->GPIOx_PULLENB, BitNumber, CFALSE);
}

//------------------------------------------------------------------------------
/**
 *	@brief		Get GPIO PullEnb
 *	@param[in]	ModuleIndex		A index of module. (0:GPIOA, 1:GPIOB, 2:GPIOC, 3:GPIOD, 4:GPIOE )
 *	@param[in]	BitNumber		Bit number ( 0 ~ 31 )
 *	@return		GPIO PullUp Enable  -> return PullSel 
 *			      GPIO PullUp  Disble  -> return PullEnb
 */
NX_GPIO_PULL NX_GPIO_GetPullEnable	( U32 ModuleIndex, U32 BitNumber )
{
	register struct NX_GPIO_RegisterSet	*pRegister;
	register CBOOL bEnb;

	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );

	pRegister = __g_ModuleVariables[ModuleIndex].pRegister;
	bEnb 	  = NX_GPIO_GetBit(ReadIO32(&pRegister->GPIOx_PULLENB),BitNumber);
	NX_ASSERT( CNULL != pRegister );	

	if( bEnb == CTRUE )
		return (NX_GPIO_PULL)NX_GPIO_GetBit(ReadIO32(&pRegister->GPIOx_PULLSEL), BitNumber);
	else
		return (NX_GPIO_PULL)(NX_GPIO_PULL_OFF);
}

//------------------------------------------------------------------------------
/**
 *	@brief		Set GPIO PullEnb
 *	@param[in]	ModuleIndex		A index of module. (0:GPIOA, 1:GPIOB, 2:GPIOC, 3:GPIOD, 4:GPIOE )
 *	@param[in]	Value			32bit input data
 *   @param[in]  Value			Pull Up/Down ( 0 : Pull Down, 1 : Pull Down )
 *	@return		None
 */
void	NX_GPIO_SetPullEnable32	( U32 ModuleIndex, U32 PullEnb, U32 PullSel )
{
	register struct NX_GPIO_RegisterSet	*pRegister;

	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );

	pRegister = __g_ModuleVariables[ModuleIndex].pRegister;

	NX_ASSERT( CNULL != pRegister );

	WriteIO32(&pRegister->GPIOx_PULLSEL, PullSel );
	WriteIO32(&pRegister->GPIOx_PULLENB, PullEnb );
}

//------------------------------------------------------------------------------
/**
 *	@brief		Get GPIO PullEnb
 *	@param[in]	ModuleIndex		A index of module. (0:GPIOA, 1:GPIOB, 2:GPIOC, 3:GPIOD, 4:GPIOE )
 *   @param[in] PullEnb			Pull Enable 32bit Status 
 *   @param[in] PullSel			Pull Select 32bit Status 
 *	@return		None
 */
void		NX_GPIO_GetPullEnable32	( U32 ModuleIndex, U32* PullEnb, U32* PullSel )
{
	register struct NX_GPIO_RegisterSet	*pRegister;

	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );

	pRegister = __g_ModuleVariables[ModuleIndex].pRegister;
	NX_ASSERT( CNULL != pRegister );

	*PullEnb = ReadIO32(&pRegister->GPIOx_PULLENB);
	*PullSel = ReadIO32(&pRegister->GPIOx_PULLSEL);
}

//------------------------------------------------------------------------------
/**
 *	@brief		Set Input Mux Select0
 *	@param[in]	ModuleIndex		A index of module. (0:GPIOA, 1:GPIOB, 2:GPIOC, 3:GPIOD, 4:GPIOE )
 *	@param[in]	Value			32bit input data
 *	@return		None
 */
void	NX_GPIO_SetInputMuxSelect0	( U32 ModuleIndex, U32 Value )
{
	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );
	NX_ASSERT( CNULL != __g_ModuleVariables[ModuleIndex].pRegister );

	WriteIO32(&__g_ModuleVariables[ModuleIndex].pRegister->GPIOx_InputMuxSelect0, Value );
}

//------------------------------------------------------------------------------
/**
 *	@brief		Set  Input Mux Select1
 *	@param[in]	ModuleIndex		A index of module. (0:GPIOA, 1:GPIOB, 2:GPIOC, 3:GPIOD, 4:GPIOE )
 *	@param[in]	Value			32bit input data
 *	@return		None
 */
void	NX_GPIO_SetInputMuxSelect1	( U32 ModuleIndex, U32 Value )
{
	NX_ASSERT( NUMBER_OF_GPIO_MODULE > ModuleIndex );
	NX_ASSERT( CNULL != __g_ModuleVariables[ModuleIndex].pRegister );

	WriteIO32(&__g_ModuleVariables[ModuleIndex].pRegister->GPIOx_InputMuxSelect1, Value );
}

//---------------------------------------------------------
/*
	pad info
	http://nxconfluence.co.kr:8090/pages/editpage.action?pageId=2786185
*/
//---------------------------------------------------------

/*
static CBOOL  NX_GPIO_PadInfo_GetGpioUsed( U32 padinfo )
{
	return NX_BIT_GETBIT_RANGE32 ( padinfo, 16, 16 );
}
*/
static U32 NX_GPIO_PadInfo_GetModuleIndex( U32 padinfo )
{
	return NX_BIT_GETBIT_RANGE32 ( padinfo, 15, 8 );
}
static U32 NX_GPIO_PadInfo_GetBitNumber( U32 padinfo )
{
	return NX_BIT_GETBIT_RANGE32 ( padinfo, 7, 3 );
}
static NX_GPIO_PADFUNC  NX_GPIO_PadInfo_GetPadFunction( U32 padinfo )
{
	return (NX_GPIO_PADFUNC)NX_BIT_GETBIT_RANGE32 ( padinfo, 2, 0 );
}

void NX_GPIO_SetPadFunctionEnable (  U32 padinfo  )
{
	U32 moduleIndex = NX_GPIO_PadInfo_GetModuleIndex( padinfo );
	U32 bitNumber = NX_GPIO_PadInfo_GetBitNumber( padinfo );
	NX_GPIO_PADFUNC  padFunction = NX_GPIO_PadInfo_GetPadFunction( padinfo );
	NX_GPIO_SetPadFunction ( moduleIndex, bitNumber, padFunction );
}

Author: Yangkai Wang
wang_yangkai@163.com
Coding in 2021/05/06

轉載請注明出處。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM