/*****************************************************************************
* 函 数 名  : bsp_gpio_direction_get
*
* 功能描述  : 查询GPIO 引脚的方向
*
* 输入参数  : UINT32 gpio        GPIO引脚编号
*
* 返 回 值  : 返回gpio引脚方向,即0为输入,1为输出
*
* 修改记录  : 2012年11月27日
*****************************************************************************/
s32 bsp_gpio_direction_get(u32 gpio)
{
    u32 chip_num;
    u32 pin;
    u32 u32GpioAddr = 0;
    u32 gpio_value = 0;

    /* 如果GPIO 没有初始化,返回错误 */
    if (GPIO_DEF_NOT_RUNNING == g_u32GpioRunning)
    {
        gpio_print_error(" GPIO is not inited.\n");
        return GPIO_ERROR;
    }

    if(gpio >= (u32)GPIO_TOTAL_PINS_NUM)
    {
        gpio_print_error(" GPIO parameter error.\n");
        return GPIO_ERROR;
    }
    chip_num   = gpio / (u32)GPIO_MAX_PINS;
    pin        = gpio % (u32)GPIO_MAX_PINS;

	if(chip_num < GPIO_MAX_BANK_NUM){
    	u32GpioAddr = s_u32GpioBaseAddr[chip_num];
	}
	else{
        gpio_print_error(" GPIO bank number error.\n");
        return GPIO_ERROR;
	}

    gpio_value = readl(u32GpioAddr + HI_GPIO_SWPORT_DDR_OFFSET);

    return (s32)((gpio_value & ((u32)0x1 << pin)) >> pin);
}
/* read gpio expander reg */
int gpio_expander_register_debug(unsigned int num, int reg)
{
	int ret;

    struct i2c_client *client = NULL;

    if(num >= GPIO_I2C_EXPANDER_NUM || (reg >= 8))
    {
        gpio_print_error("para is error, num = %d, reg = 0x%x.\n", num, reg);
        return -1;
    }

    client = gpio_expander_client[num];

	if (num < 2)
		ret = i2c_smbus_read_byte_data(client, reg);
	else
		ret = i2c_smbus_read_word_data(client, reg << 1);

	if (ret < 0)
    {
		gpio_print_error("failed reading register.\n");
		return ret;
	}

	gpio_print_info("reg(0x%x) is 0x%x.\n", reg, ret);
    
	return 0;
}
/*****************************************************************************
* 函 数 名  : bsp_gpio_set_value
*
* 功能描述  : 设置GPIO 引脚的电平值
*
* 输入参数  : u32 gpio        GPIO引脚编号
*              u32 value      管脚高/低电平
*
* 返 回 值  : 无
*
* 修改记录  : 2012年11月27日
*****************************************************************************/
void bsp_gpio_set_value(u32 gpio,u32 value)
{
    u32 chip_num;
    u32 pin;
    u32 u32GpioAddr = 0;
    u32 gpio_value = 0;
    unsigned long irq_flags;

    /* 如果GPIO 没有初始化,返回错误 */
    if (GPIO_DEF_NOT_RUNNING == g_u32GpioRunning)
    {
        gpio_print_error(" GPIO is not inited.\n");
        return ;
    }

    if(gpio >= GPIO_TOTAL_PINS_NUM)
    {
        gpio_print_error(" GPIO parameter error.\n");
        return;
    }

    /*检测GPIO方向是否输出,如果为输入,则返回错误*/
    if(0 == bsp_gpio_direction_get(gpio))
    {
        gpio_print_error(" GPIO direction error.\n");
        return;
    }

    chip_num   = gpio / (u32)GPIO_MAX_PINS;
    pin        = gpio % (u32)GPIO_MAX_PINS;

	if(chip_num < GPIO_MAX_BANK_NUM){

	    u32GpioAddr = s_u32GpioBaseAddr[chip_num];
	}
	else{
        gpio_print_error(" GPIO bank number error.\n");
		return ;
	}


    spin_lock_irqsave(&g_gpio_spinlock, irq_flags);
    (void)bsp_ipc_spin_lock(IPC_SEM_GPIO);

    gpio_value = readl(u32GpioAddr + HI_GPIO_SWPORT_DR_OFFSET);
    if(!!value)
    {
        writel(gpio_value | ((u32)0x1 << pin), u32GpioAddr + HI_GPIO_SWPORT_DR_OFFSET);
    }
    else
    {
        writel(gpio_value & ~((u32)0x1 << pin), u32GpioAddr + HI_GPIO_SWPORT_DR_OFFSET);
    }

    (void)bsp_ipc_spin_unlock(IPC_SEM_GPIO);
    spin_unlock_irqrestore(&g_gpio_spinlock, irq_flags);

}
/*****************************************************************************
* 函 数 名  : bsp_gpio_init
*
* 功能描述  : GPIO初始化接口
*
* 输入参数  : 无
*
* 返 回 值  : 无
*
* 修改记录  : 2012年11月27日
*****************************************************************************/
s32 bsp_gpio_init(void)
{
    u32  i = 0;
    int  ret = 0;
    char gpio_clk_name[40]       = "";
	char node_name[NAME_LENTH]   = "";
	char *base_addr              = NULL;	
    struct clk         *gpio_clk = NULL;
	struct device_node *dev_node = NULL;

    if (GPIO_DEF_RUNNING == g_u32GpioRunning)
    {
        return GPIO_OK;
    }

    spin_lock_init(&g_gpio_spinlock);

    for(i = 0; i < GPIO_MAX_BANK_NUM; i++)
    {
		(void)snprintf_s(node_name,NAME_LENTH,NAME_LENTH,"hisilicon,gpio%d",i);
		dev_node = of_find_compatible_node(NULL,NULL,node_name);
		if(!dev_node)
		{
			gpio_print_error("get gpio%d node failed!\n",i);
			return ERROR;
		}
		
		/* 内存映射,获得基址 */
		base_addr = (char *)of_iomap(dev_node, 0);
		if (NULL == base_addr)
		{
			gpio_print_error("gpio%d iomap fail\n",i);
			return ERROR;
		}
		s_u32GpioBaseAddr[i] = (u32)base_addr;
        (void)memset_s(gpio_clk_name, 40, 0 , 40);
        (void)snprintf_s(gpio_clk_name, 40, 40, "gpio%d_clk", i); /*lint !e119*/
        gpio_clk = (struct clk *)clk_get(NULL, gpio_clk_name);
    	if(IS_ERR(gpio_clk))
        {
    		gpio_print_error("gpio%d clk cannot get, 0x%x.\n", i, gpio_clk);
			return ERROR;
    	}

        ret = clk_enable(gpio_clk);

    }

    gpio_print_info("gpio init ok.\n");
    g_u32GpioRunning = GPIO_DEF_RUNNING;

    return ret;

}
void bsp_gpio_direction_output(u32 gpio, u32 value)
{
	unsigned int gpio_base_addr = 0;
	unsigned int gpio_number = 0;
	unsigned int reg_value_old = 0;
	unsigned int reg_value_new = 0;

    if(value > 1 || gpio > GPIO_TOTAL)
    {
        gpio_print_error("para is error, gpio = %d, value = %d.\n", gpio, value);
        return ;
    }

	gpio_base_addr = get_gpio_base_addr(gpio);
	gpio_number = get_gpio_number(gpio);

	reg_value_old  = readl(gpio_base_addr + GPIODIR);

	reg_value_new  = (((unsigned int)0x1 << gpio_number)) | (reg_value_old);

	writel(reg_value_new, gpio_base_addr + GPIODIR);

    bsp_gpio_set_value( gpio, value);

}
s32 bsp_gpio_init(void)
{
    /* 天线选择NV初始化 */
    if(0 != bsp_rf_switch_init())
    {
        gpio_print_error("bsp_rf_switch_init is fail.\n");
    }

    /* RF LDO NV初始化 */
    if(0 != bsp_ldo_gpio_init())
    {
        gpio_print_error("bsp_rf_switch_init is fail.\n");
        return -1;
    }

    return 0;
}
s32 bsp_gpio_direction_get(u32 gpio)
{
	unsigned int gpio_base_addr, gpio_number;

    if(gpio > GPIO_TOTAL)
    {
        gpio_print_error("para is error, gpio = %d.\n", gpio);
        return -1;
    }

	gpio_number = get_gpio_number(gpio);
	if (gpio_number >= GPIO_MAX_NUMBER)
    {
        gpio_print_error("para is error, gpio = %d.\n", gpio);
		return -1;
	}

	gpio_base_addr = get_gpio_base_addr(gpio);
	unsigned int reg_value  = readl(gpio_base_addr + GPIODIR);
	return (reg_value >> gpio_number) & 0x01;

}
/*i2c gpio expander*/
static int __devinit gpio_i2c_expander_init(void)
{
    unsigned int i = 0;

	struct i2c_adapter *adapter = NULL;

    //gpio_i2c_expander_reset();/* just for v7r2 test*/

	adapter = i2c_get_adapter(GPIO_I2C_EXPANDER_ADP);
	if (!adapter)
    {
		gpio_print_error("i2c_get_adapter failed.\n");
		return -1;
	}
    
    for(i = 0;i < GPIO_I2C_EXPANDER_NUM;i++)
    {
    	gpio_expander_client[i] = i2c_new_device(adapter, &expander_board_info[i]);
    	if (!gpio_expander_client[i]) {
    		gpio_print_error("i2c_new_device failed, i = %d, addr = 0x%x.\n", i, expander_board_info[i].addr);
    		return -1;
    	}
    }

#if 0
    ret = i2c_register_board_info(GPIO_I2C_EXPANDER_ADP, expander_board_info, sizeof(expander_board_info)/sizeof(struct i2c_board_info));
    if(ret < 0)
    {
        gpio_print_error("i2c_register_board_info is fail,ret = %d.\n", ret);
        return -1;
    }
#endif

	gpio_print_info("gpio ex init ok.\n");
    
	return 0;
}
void bsp_gpio_set_value(u32 gpio,u32 value)
{
    u32 gpio_base_addr = 0;
    u32 gpio_number = 0;
    u32 gpio_data_reg = 0;

    if(value > 1 || (gpio > GPIO_TOTAL))
    {
        gpio_print_error("para is error, gpio = %d, value = %d.\n", gpio, value);
        return ;
    }

    gpio_base_addr = get_gpio_base_addr(gpio);
	gpio_number = get_gpio_number(gpio);
	gpio_data_reg = ((unsigned int)0x1 << (gpio_number + 2));

	writel(value << gpio_number, gpio_base_addr + gpio_data_reg);

}
/* just for v7r2 test */
void gpio_i2c_expander_reset(void)
{

    int ret = 0;
    
    ret = gpio_request(GPIO_1_24, "gpio_expander");
    if(ret < 0)
    {
        gpio_print_error( "gpio_request is fail, ret = %d.\n", ret);
        return ;
    }
    
    gpio_direction_output(GPIO_1_24, 0);
    
    mdelay(10);
    
    gpio_direction_output(GPIO_1_24, 1);
    
}
int	gpio_i2c_expander_setup(struct i2c_client *client, unsigned gpio, unsigned ngpio, void *context)
{
    int ret = 0;
    unsigned int i = 0;

    for(i = 0;i < ngpio;i++)
    {
        ret = gpio_request(gpio + i, "gpio_expander");
        if(ret < 0)
        {
            gpio_print_error( "gpio%d request is fail, ret = %d.\n", gpio + i, ret);
            return -1;
        }

    }
    
    return 0;
    
}
s32 bsp_gpio_get_value(u32 gpio)
{
    s32 value = 0;

    u32 gpio_base_addr = 0;
    u32 gpio_number = 0;
    u32 gpio_data_reg = 0;

    if(gpio > GPIO_TOTAL)
    {
        gpio_print_error("para is error, gpio = %d.\n", gpio);
        return -1;
    }

	gpio_base_addr = get_gpio_base_addr(gpio);
	gpio_number = get_gpio_number(gpio);
	gpio_data_reg = ((unsigned int)0x1 << (gpio_number + 2));

	value = (s32)(readl(gpio_base_addr + gpio_data_reg) >> gpio_number);
	return value;

}