/* * (C) Copyright 2007-2013 * Allwinner Technology Co., Ltd. * Jerry Wang * * See file CREDITS for list of people who contributed to this * project. * * 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 #include #include #include #include DECLARE_GLOBAL_DATA_PTR; //#define GPIO_REG_READ(reg) smc_readl((reg)) //#define GPIO_REG_WRITE(reg, value) smc_writel((value), (reg)) #define GPIO_REG_READ(reg) (readl((reg))) #define GPIO_REG_WRITE(reg, value) writel((value), (reg)) /* #define GPIO_REG_WRITE(reg, value) {tick_printf("line:%d %s reg:0x%x value:0x%x\n", __LINE__, __func__, reg, value); writel((value), (reg));} */ /**############################################################################################################# * * GPIO(PIN) Operations * -##############################################################################################################*/ #ifdef CONFIG_SUNXI_GPIO_V2 #define PIOC_REG_o_CFG0 (0x00) #define PIOC_REG_o_CFG1 (0x04) #define PIOC_REG_o_CFG2 (0x08) #define PIOC_REG_o_CFG3 (0x0C) #define PIOC_REG_o_DATA (0x10) #define PIOC_REG_o_DRV0 (0x14) #define PIOC_REG_o_DRV1 (0x18) #define PIOC_REG_o_DRV2 (0x1C) #define PIOC_REG_o_DRV3 (0x20) #define PIOC_REG_o_PUL0 (0x24) #define PIOC_REG_o_PUL1 (0x28) #define PIOC_o_OFFSET (0x30) #define PIOC_o_DLEVEL (8) #define PIO_CFG_MASK (0x0f) #else #define PIOC_REG_o_CFG0 (0x00) #define PIOC_REG_o_CFG1 (0x04) #define PIOC_REG_o_CFG2 (0x08) #define PIOC_REG_o_CFG3 (0x0C) #define PIOC_REG_o_DATA (0x10) #define PIOC_REG_o_DRV0 (0x14) #define PIOC_REG_o_DRV1 (0x18) #define PIOC_REG_o_PUL0 (0x1C) #define PIOC_REG_o_PUL1 (0x20) #define PIO_CFG_MASK (0x07) #define PIOC_o_OFFSET (0x24) #define PIOC_o_DLEVEL (16) #endif #define _PIO_REG_CFG(n, i) \ ((volatile unsigned int *)((unsigned long)SUNXI_PIO_BASE + \ ((n)-1) * PIOC_o_OFFSET + ((i)<<2) + PIOC_REG_o_CFG0)) #define _PIO_REG_DLEVEL(n, i) \ ((volatile unsigned int *)((unsigned long)SUNXI_PIO_BASE + \ ((n)-1) * PIOC_o_OFFSET + ((i)<<2) + PIOC_REG_o_DRV0)) #define _PIO_REG_PULL(n, i) \ ((volatile unsigned int *)((unsigned long)SUNXI_PIO_BASE + \ ((n)-1) * PIOC_o_OFFSET + ((i)<<2) + PIOC_REG_o_PUL0)) #define _PIO_REG_DATA(n) \ ((volatile unsigned int *)((unsigned long)SUNXI_PIO_BASE + \ ((n)-1) * PIOC_o_OFFSET + PIOC_REG_o_DATA)) #define _PIO_REG_CFG_VALUE(n, i) \ readl(IOMEM_ADDR(SUNXI_PIO_BASE + ((n)-1) * PIOC_o_OFFSET + ((i)<<2) + PIOC_REG_o_CFG0)) #define _PIO_REG_DLEVEL_VALUE(n, i) \ readl(IOMEM_ADDR(SUNXI_PIO_BASE + ((n)-1) * PIOC_o_OFFSET + ((i)<<2) + PIOC_REG_o_DRV0)) #define _PIO_REG_PULL_VALUE(n, i) \ readl(IOMEM_ADDR(SUNXI_PIO_BASE + ((n)-1) * PIOC_o_OFFSET + ((i)<<2) + PIOC_REG_o_PUL0)) #define _PIO_REG_DATA_VALUE(n) \ readl(IOMEM_ADDR(SUNXI_PIO_BASE + ((n)-1) * PIOC_o_OFFSET + PIOC_REG_o_DATA)) #define _PIO_REG_BASE(n) \ ((volatile unsigned int *)((unsigned long)SUNXI_PIO_BASE +((n)-1) * PIOC_o_OFFSET)) #ifdef SUNXI_R_PIO_BASE #define _R_PIO_REG_CFG(n, i) \ ((volatile unsigned int *)((unsigned long)SUNXI_R_PIO_BASE + ((n)-12) * PIOC_o_OFFSET + \ ((i) << 2) + PIOC_REG_o_CFG0)) #define _R_PIO_REG_DLEVEL(n, i) \ ((volatile unsigned int *)((unsigned long)SUNXI_R_PIO_BASE + ((n)-12) * PIOC_o_OFFSET + \ ((i) << 2) + PIOC_REG_o_DRV0)) #define _R_PIO_REG_PULL(n, i) \ ((volatile unsigned int *)((unsigned long)SUNXI_R_PIO_BASE + ((n)-12) * PIOC_o_OFFSET + \ ((i) << 2) + PIOC_REG_o_PUL0)) #define _R_PIO_REG_DATA(n) \ ((volatile unsigned int *)((unsigned long)SUNXI_R_PIO_BASE + ((n)-12) * PIOC_o_OFFSET + PIOC_REG_o_DATA)) #define _R_PIO_REG_CFG_VALUE(n, i) \ readl(IOMEM_ADDR(SUNXI_R_PIO_BASE + ((n)-12) * PIOC_o_OFFSET + ((i) << 2) + PIOC_REG_o_CFG0)) #define _R_PIO_REG_DLEVEL_VALUE(n, i) \ readl(IOMEM_ADDR(SUNXI_R_PIO_BASE + ((n)-12) * PIOC_o_OFFSET + ((i) << 2) + PIOC_REG_o_DRV0)) #define _R_PIO_REG_PULL_VALUE(n, i) \ readl(IOMEM_ADDR(SUNXI_R_PIO_BASE + ((n)-12) * PIOC_o_OFFSET + ((i) << 2) + PIOC_REG_o_PUL0)) #define _R_PIO_REG_DATA_VALUE(n) \ readl(IOMEM_ADDR(SUNXI_R_PIO_BASE + ((n)-12) * PIOC_o_OFFSET + PIOC_REG_o_DATA)) #define _R_PIO_REG_BASE(n) \ ((volatile unsigned int *)((unsigned long)SUNXI_R_PIO_BASE + ((n)-12) * PIOC_o_OFFSET)) volatile void* PIO_REG_CFG(int port, int port_num) { if(port < 12) { return _PIO_REG_CFG(port, port_num); } else { return _R_PIO_REG_CFG(port, port_num); } } volatile void* PIO_REG_PULL(int port, int port_num) { if(port < 12) { return _PIO_REG_PULL(port, port_num); } else { return _R_PIO_REG_PULL(port, port_num); } } volatile void* PIO_REG_DLEVEL(int port,int port_num) { if(port < 12) { return _PIO_REG_DLEVEL(port, port_num); } else { return _R_PIO_REG_DLEVEL(port, port_num); } } volatile void* PIO_REG_DATA(int port) { if(port < 12) { return _PIO_REG_DATA(port); } else { return _R_PIO_REG_DATA(port); } } u32 PIO_REG_CFG_VALUE(uint port, uint i) { u32 value = 0; if( port < 12) { value = _PIO_REG_CFG_VALUE(port,i); } else { value = _R_PIO_REG_CFG_VALUE(port,i); } return value; } u32 PIO_REG_DLEVEL_VALUE(uint port, uint i) { u32 value = 0; if( port < 12) { value = _R_PIO_REG_DLEVEL_VALUE(port,i); } else { value = _R_PIO_REG_DLEVEL_VALUE(port,i); } return value; } u32 PIO_REG_PULL_VALUE(uint port, uint i) { u32 value = 0; if( port < 12) { value = _PIO_REG_PULL_VALUE(port,i); } else { value = _R_PIO_REG_PULL_VALUE(port,i); } return value; } u32 PIO_REG_DATA_VALUE(uint port) { u32 value = 0; if( port < 12) { value = _PIO_REG_DATA_VALUE(port); } else { value = _R_PIO_REG_DATA_VALUE(port); } return value; } #else volatile void* PIO_REG_CFG(int port, int port_num) { return _PIO_REG_CFG(port, port_num); } volatile void* PIO_REG_PULL(int port, int port_num) { return _PIO_REG_PULL(port, port_num); } volatile void* PIO_REG_DLEVEL(int port,int port_num) { return _PIO_REG_DLEVEL(port, port_num); } volatile void* PIO_REG_DATA(int port) { return _PIO_REG_DATA(port); } u32 PIO_REG_CFG_VALUE(uint port, uint i) { return _PIO_REG_CFG_VALUE(port,i); } u32 PIO_REG_DLEVEL_VALUE(uint port, uint i) { return _PIO_REG_DLEVEL_VALUE(port,i); } u32 PIO_REG_PULL_VALUE(uint port, uint i) { return _PIO_REG_PULL_VALUE(port,i); } u32 PIO_REG_DATA_VALUE(uint port) { return _PIO_REG_DATA_VALUE(port); } #endif #define PIO_REG_BASE(n) ((volatile unsigned int *)(SUNXI_PIO_BASE +((n)-1)*24)) __s32 gpio_get_all_pin_status(ulong p_handler, user_gpio_set_t *gpio_status, __u32 gpio_count_max, __u32 if_get_from_hardware) { char *tmp_buf; __u32 group_count_max, first_port; system_gpio_set_t *user_gpio_set, *tmp_sys_gpio_data; user_gpio_set_t *script_gpio; __u32 port_num_func, port_num_pull; volatile __u32 *tmp_group_func_addr = NULL, *tmp_group_pull_addr; volatile __u32 *tmp_group_data_addr, *tmp_group_dlevel_addr; __u32 port, port_num; __u32 pre_port = 0x7fffffff, pre_port_num_func = 0x7fffffff, pre_port_num_pull = 0x7fffffff; __u32 i; if((!p_handler) || (!gpio_status)) { return EGPIO_FAIL; } if(gpio_count_max <= 0) { return EGPIO_FAIL; } tmp_buf = (char *)p_handler; group_count_max = *(int *)tmp_buf; if(group_count_max <= 0) { return EGPIO_FAIL; } user_gpio_set = (system_gpio_set_t *)(tmp_buf + 16); if(group_count_max > gpio_count_max) { group_count_max = gpio_count_max; } if(!if_get_from_hardware) { for(i = 0; i < group_count_max; i++) { tmp_sys_gpio_data = user_gpio_set + i; script_gpio = gpio_status + i; script_gpio->port = tmp_sys_gpio_data->port; script_gpio->port_num = tmp_sys_gpio_data->port_num; script_gpio->pull = tmp_sys_gpio_data->user_gpio_status.pull; script_gpio->mul_sel = tmp_sys_gpio_data->user_gpio_status.mul_sel; script_gpio->drv_level = tmp_sys_gpio_data->user_gpio_status.drv_level; script_gpio->data = tmp_sys_gpio_data->user_gpio_status.data; strcpy(script_gpio->gpio_name, tmp_sys_gpio_data->gpio_name); } } else { for(first_port = 0; first_port < group_count_max; first_port++) { tmp_sys_gpio_data = user_gpio_set + first_port; port = tmp_sys_gpio_data->port; port_num = tmp_sys_gpio_data->port_num; if(!port) { continue; } port_num_func = (port_num >> 3); port_num_pull = (port_num >> 4); tmp_group_func_addr = PIO_REG_CFG(port, port_num_func); tmp_group_pull_addr = PIO_REG_PULL(port, port_num_pull); tmp_group_dlevel_addr = PIO_REG_DLEVEL(port, port_num_pull); tmp_group_data_addr = PIO_REG_DATA(port); break; } if(first_port >= group_count_max) { return 0; } for(i = first_port; i < group_count_max; i++) { tmp_sys_gpio_data = user_gpio_set + i; script_gpio = gpio_status + i; port = tmp_sys_gpio_data->port; port_num = tmp_sys_gpio_data->port_num; script_gpio->port = port; script_gpio->port_num = port_num; strcpy(script_gpio->gpio_name, tmp_sys_gpio_data->gpio_name); port_num_func = (port_num >> 3); port_num_pull = (port_num >> 4); if((port_num_pull != pre_port_num_pull) || (port != pre_port)) { tmp_group_func_addr = PIO_REG_CFG(port, port_num_func); tmp_group_pull_addr = PIO_REG_PULL(port, port_num_pull); tmp_group_dlevel_addr = PIO_REG_DLEVEL(port, port_num_pull); tmp_group_data_addr = PIO_REG_DATA(port); } else if(pre_port_num_func != port_num_func) { tmp_group_func_addr = PIO_REG_CFG(port, port_num_func); } pre_port_num_pull = port_num_pull; pre_port_num_func = port_num_func; pre_port = port; script_gpio->pull = (GPIO_REG_READ(tmp_group_pull_addr) >> ((port_num - (port_num_pull<<4))<<1)) & 0x03; script_gpio->drv_level = (GPIO_REG_READ(tmp_group_dlevel_addr) >> ((port_num - (port_num_pull<<4))<<1)) & 0x03; script_gpio->mul_sel = (GPIO_REG_READ(tmp_group_func_addr) >> ((port_num - (port_num_func<<3))<<2)) & PIO_CFG_MASK; if(script_gpio->mul_sel <= 1) { script_gpio->data = (GPIO_REG_READ(tmp_group_data_addr) >> port_num) & 0x01; } else { script_gpio->data = -1; } } } return EGPIO_SUCCESS; } __s32 gpio_get_one_pin_status(ulong p_handler, user_gpio_set_t *gpio_status, const char *gpio_name, __u32 if_get_from_hardware) { char *tmp_buf; __u32 group_count_max; system_gpio_set_t *user_gpio_set, *tmp_sys_gpio_data; __u32 port_num_func, port_num_pull; __u32 port, port_num; __u32 i, tmp_val1, tmp_val2; if((!p_handler) || (!gpio_status)) { return EGPIO_FAIL; } tmp_buf = (char *)p_handler; group_count_max = *(int *)tmp_buf; if(group_count_max <= 0) { return EGPIO_FAIL; } else if((group_count_max > 1) && (!gpio_name)) { return EGPIO_FAIL; } user_gpio_set = (system_gpio_set_t *)(tmp_buf + 16); for(i = 0; i < group_count_max; i++) { tmp_sys_gpio_data = user_gpio_set + i; if(strcmp(gpio_name, tmp_sys_gpio_data->gpio_name)) { continue; } strcpy(gpio_status->gpio_name, tmp_sys_gpio_data->gpio_name); port = tmp_sys_gpio_data->port; port_num = tmp_sys_gpio_data->port_num; gpio_status->port = port; gpio_status->port_num = port_num; if(!if_get_from_hardware) { gpio_status->mul_sel = tmp_sys_gpio_data->user_gpio_status.mul_sel; gpio_status->pull = tmp_sys_gpio_data->user_gpio_status.pull; gpio_status->drv_level = tmp_sys_gpio_data->user_gpio_status.drv_level; gpio_status->data = tmp_sys_gpio_data->user_gpio_status.data; } else { port_num_func = (port_num >> 3); port_num_pull = (port_num >> 4); tmp_val1 = ((port_num - (port_num_func << 3)) << 2); tmp_val2 = ((port_num - (port_num_pull << 4)) << 1); gpio_status->mul_sel = (PIO_REG_CFG_VALUE(port, port_num_func)>>tmp_val1) & PIO_CFG_MASK; gpio_status->pull = (PIO_REG_PULL_VALUE(port, port_num_pull)>>tmp_val2) & 0x03; gpio_status->drv_level = (PIO_REG_DLEVEL_VALUE(port, port_num_pull)>>tmp_val2) & 0x03; if(gpio_status->mul_sel <= 1) { gpio_status->data = (PIO_REG_DATA_VALUE(port) >> port_num) & 0x01; } else { gpio_status->data = -1; } } break; } return EGPIO_SUCCESS; } __s32 gpio_set_one_pin_status(ulong p_handler, user_gpio_set_t *gpio_status, const char *gpio_name, __u32 if_set_to_current_input_status) { char *tmp_buf; __u32 group_count_max; system_gpio_set_t *user_gpio_set, *tmp_sys_gpio_data; user_gpio_set_t script_gpio; volatile __u32 *tmp_addr; __u32 port_num_func, port_num_pull; __u32 port, port_num; __u32 i, reg_val, tmp_val; if((!p_handler) || (!gpio_name)) { return EGPIO_FAIL; } if((if_set_to_current_input_status) && (!gpio_status)) { return EGPIO_FAIL; } tmp_buf = (char *)p_handler; group_count_max = *(int *)tmp_buf; if(group_count_max <= 0) { return EGPIO_FAIL; } user_gpio_set = (system_gpio_set_t *)(tmp_buf + 16); for(i = 0; i < group_count_max; i++) { tmp_sys_gpio_data = user_gpio_set + i; if(strcmp(gpio_name, tmp_sys_gpio_data->gpio_name)) { continue; } port = tmp_sys_gpio_data->port; port_num = tmp_sys_gpio_data->port_num; port_num_func = (port_num >> 3); port_num_pull = (port_num >> 4); if(if_set_to_current_input_status) { script_gpio.mul_sel = gpio_status->mul_sel; script_gpio.pull = gpio_status->pull; script_gpio.drv_level = gpio_status->drv_level; script_gpio.data = gpio_status->data; } else { script_gpio.mul_sel = tmp_sys_gpio_data->user_gpio_status.mul_sel; script_gpio.pull = tmp_sys_gpio_data->user_gpio_status.pull; script_gpio.drv_level = tmp_sys_gpio_data->user_gpio_status.drv_level; script_gpio.data = tmp_sys_gpio_data->user_gpio_status.data; } if(script_gpio.mul_sel >= 0) { tmp_addr = PIO_REG_CFG(port, port_num_func); reg_val = GPIO_REG_READ(tmp_addr); tmp_val = (port_num - (port_num_func<<3))<<2; reg_val &= ~(PIO_CFG_MASK << tmp_val); reg_val |= (script_gpio.mul_sel) << tmp_val; GPIO_REG_WRITE(tmp_addr, reg_val); } if(script_gpio.pull >= 0) { tmp_addr = PIO_REG_PULL(port, port_num_pull); reg_val = GPIO_REG_READ(tmp_addr); tmp_val = (port_num - (port_num_pull<<4))<<1; reg_val &= ~(0x03 << tmp_val); reg_val |= (script_gpio.pull) << tmp_val; GPIO_REG_WRITE(tmp_addr, reg_val); } if(script_gpio.drv_level >= 0) { tmp_addr = PIO_REG_DLEVEL(port, port_num_pull); reg_val = GPIO_REG_READ(tmp_addr); tmp_val = (port_num - (port_num_pull<<4))<<1; reg_val &= ~(0x03 << tmp_val); reg_val |= (script_gpio.drv_level) << tmp_val; GPIO_REG_WRITE(tmp_addr, reg_val); } if(script_gpio.mul_sel == 1) { if(script_gpio.data >= 0) { tmp_addr = PIO_REG_DATA(port); reg_val = GPIO_REG_READ(tmp_addr); reg_val &= ~(0x01 << port_num); reg_val |= (script_gpio.data & 0x01) << port_num; GPIO_REG_WRITE(tmp_addr, reg_val); } } break; } return EGPIO_SUCCESS; } __s32 gpio_set_one_pin_io_status(ulong p_handler, __u32 if_set_to_output_status, const char *gpio_name) { char *tmp_buf; __u32 group_count_max; system_gpio_set_t *user_gpio_set = NULL, *tmp_sys_gpio_data; volatile __u32 *tmp_group_func_addr = NULL; __u32 port, port_num, port_num_func; __u32 i, reg_val; if(!p_handler) { return EGPIO_FAIL; } if(if_set_to_output_status > 1) { return EGPIO_FAIL; } tmp_buf = (char *)p_handler; group_count_max = *(int *)tmp_buf; tmp_sys_gpio_data = (system_gpio_set_t *)(tmp_buf + 16); if(group_count_max == 0) { return EGPIO_FAIL; } else if(group_count_max == 1) { user_gpio_set = tmp_sys_gpio_data; } else if(gpio_name) { for(i=0; igpio_name)) { tmp_sys_gpio_data ++; continue; } user_gpio_set = tmp_sys_gpio_data; break; } } if(!user_gpio_set) { return EGPIO_FAIL; } port = user_gpio_set->port; port_num = user_gpio_set->port_num; port_num_func = port_num >> 3; tmp_group_func_addr = PIO_REG_CFG(port, port_num_func); reg_val = GPIO_REG_READ(tmp_group_func_addr); reg_val &= ~(PIO_CFG_MASK << (((port_num - (port_num_func<<3))<<2))); reg_val |= if_set_to_output_status << (((port_num - (port_num_func<<3))<<2)); GPIO_REG_WRITE(tmp_group_func_addr, reg_val); return EGPIO_SUCCESS; } __s32 gpio_set_one_pin_pull(ulong p_handler, __u32 set_pull_status, const char *gpio_name) { char *tmp_buf; __u32 group_count_max; system_gpio_set_t *user_gpio_set = NULL, *tmp_sys_gpio_data; volatile __u32 *tmp_group_pull_addr = NULL; __u32 port, port_num, port_num_pull; __u32 i, reg_val; if(!p_handler) { return EGPIO_FAIL; } if(set_pull_status >= 4) { return EGPIO_FAIL; } tmp_buf = (char *)p_handler; group_count_max = *(int *)tmp_buf; tmp_sys_gpio_data = (system_gpio_set_t *)(tmp_buf + 16); if(group_count_max == 0) { return EGPIO_FAIL; } else if(group_count_max == 1) { user_gpio_set = tmp_sys_gpio_data; } else if(gpio_name) { for(i=0; igpio_name)) { tmp_sys_gpio_data ++; continue; } user_gpio_set = tmp_sys_gpio_data; break; } } if(!user_gpio_set) { return EGPIO_FAIL; } port = user_gpio_set->port; port_num = user_gpio_set->port_num; port_num_pull = port_num >> 4; tmp_group_pull_addr = PIO_REG_PULL(port, port_num_pull); reg_val = GPIO_REG_READ(tmp_group_pull_addr); reg_val &= ~(0x03 << (((port_num - (port_num_pull<<4))<<1))); reg_val |= (set_pull_status << (((port_num - (port_num_pull<<4))<<1))); GPIO_REG_WRITE(tmp_group_pull_addr, reg_val); return EGPIO_SUCCESS; } __s32 gpio_set_one_pin_driver_level(ulong p_handler, __u32 set_driver_level, const char *gpio_name) { char *tmp_buf; __u32 group_count_max; system_gpio_set_t *user_gpio_set = NULL, *tmp_sys_gpio_data; volatile __u32 *tmp_group_dlevel_addr = NULL; __u32 port, port_num, port_num_dlevel; __u32 i, reg_val; if(!p_handler) { return EGPIO_FAIL; } if(set_driver_level >= 4) { return EGPIO_FAIL; } tmp_buf = (char *)p_handler; group_count_max = *(int *)tmp_buf; tmp_sys_gpio_data = (system_gpio_set_t *)(tmp_buf + 16); if(group_count_max == 0) { return EGPIO_FAIL; } else if(group_count_max == 1) { user_gpio_set = tmp_sys_gpio_data; } else if(gpio_name) { for(i=0; igpio_name)) { tmp_sys_gpio_data ++; continue; } user_gpio_set = tmp_sys_gpio_data; break; } } if(!user_gpio_set) { return EGPIO_FAIL; } port = user_gpio_set->port; port_num = user_gpio_set->port_num; port_num_dlevel = port_num >> 4; tmp_group_dlevel_addr = PIO_REG_DLEVEL(port, port_num_dlevel); reg_val = GPIO_REG_READ(tmp_group_dlevel_addr); reg_val &= ~(0x03 << (((port_num - (port_num_dlevel<<4))<<1))); reg_val |= (set_driver_level << (((port_num - (port_num_dlevel<<4))<<1))); GPIO_REG_WRITE(tmp_group_dlevel_addr, reg_val); return EGPIO_SUCCESS; } __s32 gpio_read_one_pin_value(ulong p_handler, const char *gpio_name) { char *tmp_buf; __u32 group_count_max; system_gpio_set_t *user_gpio_set = NULL, *tmp_sys_gpio_data; __u32 port, port_num, port_num_func, func_val; __u32 i, reg_val; if(!p_handler) { return EGPIO_FAIL; } tmp_buf = (char *)p_handler; group_count_max = *(int *)tmp_buf; tmp_sys_gpio_data = (system_gpio_set_t *)(tmp_buf + 16); if(group_count_max == 0) { return EGPIO_FAIL; } else if(group_count_max == 1) { user_gpio_set = tmp_sys_gpio_data; } else if(gpio_name) { for(i=0; igpio_name)) { tmp_sys_gpio_data ++; continue; } user_gpio_set = tmp_sys_gpio_data; break; } } if(!user_gpio_set) { return EGPIO_FAIL; } port = user_gpio_set->port; port_num = user_gpio_set->port_num; port_num_func = port_num >> 3; reg_val = PIO_REG_CFG_VALUE(port, port_num_func); func_val = (reg_val >> ((port_num - (port_num_func<<3))<<2)) & PIO_CFG_MASK; if(func_val == 0) { reg_val = (PIO_REG_DATA_VALUE(port) >> port_num) & 0x01; return reg_val; } return EGPIO_FAIL; } __s32 gpio_write_one_pin_value(ulong p_handler, __u32 value_to_gpio, const char *gpio_name) { char *tmp_buf; __u32 group_count_max; system_gpio_set_t *user_gpio_set = NULL, *tmp_sys_gpio_data; volatile __u32 *tmp_group_data_addr = NULL; __u32 port, port_num, port_num_func, func_val; __u32 i, reg_val; if(!p_handler) { return EGPIO_FAIL; } if(value_to_gpio >= 2) { return EGPIO_FAIL; } tmp_buf = (char *)p_handler; group_count_max = *(int *)tmp_buf; tmp_sys_gpio_data = (system_gpio_set_t *)(tmp_buf + 16); if(group_count_max == 0) { return EGPIO_FAIL; } else if(group_count_max == 1) { user_gpio_set = tmp_sys_gpio_data; } else if(gpio_name) { for(i=0; igpio_name)) { tmp_sys_gpio_data ++; continue; } user_gpio_set = tmp_sys_gpio_data; break; } } if(!user_gpio_set) { return EGPIO_FAIL; } port = user_gpio_set->port; port_num = user_gpio_set->port_num; port_num_func = port_num >> 3; reg_val = PIO_REG_CFG_VALUE(port, port_num_func); func_val = (reg_val >> ((port_num - (port_num_func<<3))<<2)) & PIO_CFG_MASK; if(func_val == 1) { tmp_group_data_addr = PIO_REG_DATA(port); reg_val = GPIO_REG_READ(tmp_group_data_addr); reg_val &= ~(1 << port_num); reg_val |= (value_to_gpio << port_num); GPIO_REG_WRITE(tmp_group_data_addr, reg_val); return EGPIO_SUCCESS; } return EGPIO_FAIL; } int gpio_request_early(void *user_gpio_list, __u32 group_count_max, __s32 set_gpio) { user_gpio_set_t *tmp_user_gpio_data, *gpio_list; __u32 first_port; __u32 tmp_group_func_data; __u32 tmp_group_pull_data; __u32 tmp_group_dlevel_data; __u32 tmp_group_data_data; __u32 data_change = 0; // __u32 *tmp_group_port_addr; volatile __u32 *tmp_group_func_addr, *tmp_group_pull_addr; volatile __u32 *tmp_group_dlevel_addr, *tmp_group_data_addr; __u32 port, port_num, port_num_func, port_num_pull, port_num_dlevel; __u32 pre_port, pre_port_num_func; __u32 pre_port_num_pull; __s32 i, tmp_val; debug("gpio: conut=%d, set gpio = %d\n", group_count_max, set_gpio); gpio_list = (user_gpio_set_t *)user_gpio_list; for(first_port = 0; first_port < group_count_max; first_port++) { tmp_user_gpio_data = gpio_list + first_port; port = tmp_user_gpio_data->port; port_num = tmp_user_gpio_data->port_num; if(!port) { continue; } port_num_func = (port_num >> 3); port_num_pull = (port_num >> 4); port_num_dlevel = (port_num / PIOC_o_DLEVEL); tmp_group_func_addr = PIO_REG_CFG(port, port_num_func); tmp_group_pull_addr = PIO_REG_PULL(port, port_num_pull); tmp_group_dlevel_addr = PIO_REG_DLEVEL(port, port_num_dlevel); tmp_group_data_addr = PIO_REG_DATA(port); tmp_group_func_data = GPIO_REG_READ(tmp_group_func_addr); tmp_group_pull_data = GPIO_REG_READ(tmp_group_pull_addr); tmp_group_dlevel_data = GPIO_REG_READ(tmp_group_dlevel_addr); tmp_group_data_data = GPIO_REG_READ(tmp_group_data_addr); pre_port = port; pre_port_num_func = port_num_func; pre_port_num_pull = port_num_pull; tmp_val = (port_num - (port_num_func << 3)) << 2; tmp_group_func_data &= ~(PIO_CFG_MASK << tmp_val); if(set_gpio) { tmp_group_func_data |= (tmp_user_gpio_data->mul_sel & PIO_CFG_MASK) << tmp_val; } tmp_val = (port_num - (port_num_pull << 4)) << 1; if(tmp_user_gpio_data->pull >= 0) { tmp_group_pull_data &= ~( 0x03 << tmp_val); tmp_group_pull_data |= (tmp_user_gpio_data->pull & 0x03) << tmp_val; } #if (PIOC_o_DLEVEL == 8) tmp_val = (port_num % 8) * 4; #endif if(tmp_user_gpio_data->drv_level >= 0) { tmp_group_dlevel_data &= ~( 0x03 << tmp_val); tmp_group_dlevel_data |= (tmp_user_gpio_data->drv_level & 0x03) << tmp_val; } if(tmp_user_gpio_data->mul_sel == 1) { if(tmp_user_gpio_data->data >= 0) { tmp_val = tmp_user_gpio_data->data & 1; tmp_group_data_data &= ~(1 << port_num); tmp_group_data_data |= tmp_val << port_num; data_change = 1; } } debug("---name = %s, port = %d,portnum=%d,mul_sel=%d,pull=%d drive= %d, data=%d\n", tmp_user_gpio_data->gpio_name, tmp_user_gpio_data->port, tmp_user_gpio_data->port_num, tmp_user_gpio_data->mul_sel, tmp_user_gpio_data->pull, tmp_user_gpio_data->drv_level, tmp_user_gpio_data->data); break; } if(first_port >= group_count_max) { return -1; } for(i = first_port + 1; i < group_count_max; i++) { tmp_user_gpio_data = gpio_list + i; port = tmp_user_gpio_data->port; port_num = tmp_user_gpio_data->port_num; debug("+++name = %s, port = %d,portnum=%d,mul_sel=%d,pull=%d drive= %d, data=%d\n", tmp_user_gpio_data->gpio_name, tmp_user_gpio_data->port, tmp_user_gpio_data->port_num, tmp_user_gpio_data->mul_sel, tmp_user_gpio_data->pull, tmp_user_gpio_data->drv_level, tmp_user_gpio_data->data); if(!port) { break; } port_num_func = (port_num >> 3); port_num_pull = (port_num >> 4); port_num_dlevel = (port_num / PIOC_o_DLEVEL); if ((port_num_pull != pre_port_num_pull) || (port != pre_port) || (pre_port_num_func != port_num_func)) { GPIO_REG_WRITE(tmp_group_func_addr, tmp_group_func_data); GPIO_REG_WRITE(tmp_group_pull_addr, tmp_group_pull_data); GPIO_REG_WRITE(tmp_group_dlevel_addr, tmp_group_dlevel_data); if(data_change) { data_change = 0; GPIO_REG_WRITE(tmp_group_data_addr, tmp_group_data_data); } tmp_group_func_addr = PIO_REG_CFG(port, port_num_func); tmp_group_pull_addr = PIO_REG_PULL(port, port_num_pull); tmp_group_dlevel_addr = PIO_REG_DLEVEL(port, port_num_dlevel); tmp_group_data_addr = PIO_REG_DATA(port); tmp_group_func_data = GPIO_REG_READ(tmp_group_func_addr); tmp_group_pull_data = GPIO_REG_READ(tmp_group_pull_addr); tmp_group_dlevel_data = GPIO_REG_READ(tmp_group_dlevel_addr); tmp_group_data_data = GPIO_REG_READ(tmp_group_data_addr); } pre_port_num_pull = port_num_pull; pre_port_num_func = port_num_func; pre_port = port; tmp_val = (port_num - (port_num_func << 3)) << 2; if(tmp_user_gpio_data->mul_sel >= 0) { tmp_group_func_data &= ~(PIO_CFG_MASK << tmp_val); if(set_gpio) { tmp_group_func_data |= (tmp_user_gpio_data->mul_sel & PIO_CFG_MASK) << tmp_val; } } tmp_val = (port_num - (port_num_pull << 4)) << 1; if(tmp_user_gpio_data->pull >= 0) { tmp_group_pull_data &= ~( 0x03 << tmp_val); tmp_group_pull_data |= (tmp_user_gpio_data->pull & 0x03) << tmp_val; } #if (PIOC_o_DLEVEL == 8) tmp_val = (port_num % 8) * 4; #endif if(tmp_user_gpio_data->drv_level >= 0) { tmp_group_dlevel_data &= ~( 0x03 << tmp_val); tmp_group_dlevel_data |= (tmp_user_gpio_data->drv_level & 0x03) << tmp_val; } if(tmp_user_gpio_data->mul_sel == 1) { if(tmp_user_gpio_data->data >= 0) { tmp_val = tmp_user_gpio_data->data & 1; tmp_group_data_data &= ~(1 << port_num); tmp_group_data_data |= tmp_val << port_num; data_change = 1; } } } if(tmp_group_func_addr) { GPIO_REG_WRITE(tmp_group_func_addr, tmp_group_func_data); GPIO_REG_WRITE(tmp_group_pull_addr, tmp_group_pull_data); GPIO_REG_WRITE(tmp_group_dlevel_addr, tmp_group_dlevel_data); if(data_change) { GPIO_REG_WRITE(tmp_group_data_addr, tmp_group_data_data); } } return 0; } ulong sunxi_gpio_request(user_gpio_set_t *gpio_list, __u32 group_count_max) { char *user_gpio_buf; system_gpio_set_t *user_gpio_set, *tmp_sys_gpio_data; user_gpio_set_t *tmp_user_gpio_data; __u32 real_gpio_count = 0, first_port; __u32 tmp_group_func_data = 0; __u32 tmp_group_pull_data = 0; __u32 tmp_group_dlevel_data = 0; __u32 tmp_group_data_data = 0; __u32 func_change = 0, pull_change = 0; __u32 dlevel_change = 0, data_change = 0; volatile __u32 *tmp_group_func_addr = NULL, *tmp_group_pull_addr = NULL; volatile __u32 *tmp_group_dlevel_addr = NULL, *tmp_group_data_addr = NULL; __u32 port, port_num, port_num_func, port_num_pull, port_num_dlevel; __u32 pre_port = 0x7fffffff, pre_port_num_func = 0x7fffffff; __u32 pre_port_num_pull = 0x7fffffff; __s32 i, tmp_val; if((!gpio_list) || (!group_count_max)) { return (u32)0; } for(i = 0; i < group_count_max; i++) { tmp_user_gpio_data = gpio_list + i; if(!tmp_user_gpio_data->port) { continue; } real_gpio_count ++; } user_gpio_buf = (char *)malloc(16 + sizeof(system_gpio_set_t) * real_gpio_count); if(!user_gpio_buf) { return (u32)0; } memset(user_gpio_buf, 0, 16 + sizeof(system_gpio_set_t) * real_gpio_count); *(int *)user_gpio_buf = real_gpio_count; user_gpio_set = (system_gpio_set_t *)(user_gpio_buf + 16); for(first_port = 0; first_port < group_count_max; first_port++) { tmp_user_gpio_data = gpio_list + first_port; port = tmp_user_gpio_data->port; port_num = tmp_user_gpio_data->port_num; if(!port) { continue; } port_num_func = (port_num >> 3); port_num_pull = (port_num >> 4); port_num_dlevel = (port_num / PIOC_o_DLEVEL); tmp_group_func_addr = PIO_REG_CFG(port, port_num_func); tmp_group_pull_addr = PIO_REG_PULL(port, port_num_pull); tmp_group_dlevel_addr = PIO_REG_DLEVEL(port, port_num_dlevel); tmp_group_data_addr = PIO_REG_DATA(port); tmp_group_func_data = *tmp_group_func_addr; tmp_group_pull_data = *tmp_group_pull_addr; tmp_group_dlevel_data = *tmp_group_dlevel_addr; tmp_group_data_data = *tmp_group_data_addr; break; } if(first_port >= group_count_max) { return 0; } for(i = first_port; i < group_count_max; i++) { tmp_sys_gpio_data = user_gpio_set + i; tmp_user_gpio_data = gpio_list + i; port = tmp_user_gpio_data->port; port_num = tmp_user_gpio_data->port_num; if(!port) { continue; } strcpy(tmp_sys_gpio_data->gpio_name, tmp_user_gpio_data->gpio_name); tmp_sys_gpio_data->port = port; tmp_sys_gpio_data->port_num = port_num; tmp_sys_gpio_data->user_gpio_status.mul_sel = tmp_user_gpio_data->mul_sel; tmp_sys_gpio_data->user_gpio_status.pull = tmp_user_gpio_data->pull; tmp_sys_gpio_data->user_gpio_status.drv_level = tmp_user_gpio_data->drv_level; tmp_sys_gpio_data->user_gpio_status.data = tmp_user_gpio_data->data; port_num_func = (port_num >> 3); port_num_pull = (port_num >> 4); port_num_dlevel = (port_num / 8); if ((port_num_pull != pre_port_num_pull) || (port != pre_port) || (pre_port_num_func != port_num_func)) { if(func_change) { *tmp_group_func_addr = tmp_group_func_data; func_change = 0; } if(pull_change) { pull_change = 0; *tmp_group_pull_addr = tmp_group_pull_data; } if(dlevel_change) { dlevel_change = 0; *tmp_group_dlevel_addr = tmp_group_dlevel_data; } if(data_change) { data_change = 0; *tmp_group_data_addr = tmp_group_data_data; } tmp_group_func_addr = PIO_REG_CFG(port, port_num_func); tmp_group_pull_addr = PIO_REG_PULL(port, port_num_pull); tmp_group_dlevel_addr = PIO_REG_DLEVEL(port, port_num_pull); tmp_group_data_addr = PIO_REG_DATA(port); tmp_group_func_data = *tmp_group_func_addr; tmp_group_pull_data = *tmp_group_pull_addr; tmp_group_dlevel_data = *tmp_group_dlevel_addr; tmp_group_data_data = *tmp_group_data_addr; } pre_port_num_pull = port_num_pull; pre_port_num_func = port_num_func; pre_port = port; if(tmp_user_gpio_data->mul_sel >= 0) { tmp_val = (port_num - (port_num_func<<3)) << 2; tmp_sys_gpio_data->hardware_gpio_status.mul_sel = (tmp_group_func_data >> tmp_val) & PIO_CFG_MASK; tmp_group_func_data &= ~( PIO_CFG_MASK << tmp_val); tmp_group_func_data |= (tmp_user_gpio_data->mul_sel & PIO_CFG_MASK) << tmp_val; func_change = 1; } tmp_val = (port_num - (port_num_pull<<4)) << 1; if(tmp_user_gpio_data->pull >= 0) { tmp_sys_gpio_data->hardware_gpio_status.pull = (tmp_group_pull_data >> tmp_val) & 0x03; if(tmp_user_gpio_data->pull >= 0) { tmp_group_pull_data &= ~( 0x03 << tmp_val); tmp_group_pull_data |= (tmp_user_gpio_data->pull & 0x03) << tmp_val; pull_change = 1; } } #if (PIOC_o_DLEVEL == 8) tmp_val = (port_num % 8) * 4; #endif if(tmp_user_gpio_data->drv_level >= 0) { tmp_sys_gpio_data->hardware_gpio_status.drv_level = (tmp_group_dlevel_data >> tmp_val) & 0x03; if(tmp_user_gpio_data->drv_level >= 0) { tmp_group_dlevel_data &= ~( 0x03 << tmp_val); tmp_group_dlevel_data |= (tmp_user_gpio_data->drv_level & 0x03) << tmp_val; dlevel_change = 1; } } if(tmp_user_gpio_data->mul_sel == 1) { if(tmp_user_gpio_data->data >= 0) { tmp_val = tmp_user_gpio_data->data; tmp_val &= 1; tmp_group_data_data &= ~(1 << port_num); tmp_group_data_data |= tmp_val << port_num; data_change = 1; } } } if(tmp_group_func_addr) { *tmp_group_func_addr = tmp_group_func_data; if(pull_change) { *tmp_group_pull_addr = tmp_group_pull_data; } if(dlevel_change) { *tmp_group_dlevel_addr = tmp_group_dlevel_data; } if(data_change) { *tmp_group_data_addr = tmp_group_data_data; } } return (ulong)user_gpio_buf; } //note : just free malloc memory __s32 gpio_release(ulong p_handler, __s32 unused_para) { char *tmp_buf; __u32 group_count_max; if(!p_handler) { return EGPIO_FAIL; } tmp_buf = (char *)p_handler; group_count_max = *(int *)tmp_buf; if(!group_count_max) { return EGPIO_FAIL; } free((char *)p_handler); return EGPIO_SUCCESS; } #define FDT_INFO(fmt,args...) printf("FDT INFO:"fmt,##args); #define FDT_ERR(fmt,args...) printf("FDT ERROR:"fmt,##args); static int fdt_get_new_pull(int nodeoffset) { if (fdt_getprop_string(working_fdt, nodeoffset, "bias-pull-up", NULL) >= 0) return 1; if (fdt_getprop_string(working_fdt, nodeoffset, "bias-pull-down", NULL) >= 0) return 0; if (fdt_getprop_string(working_fdt, nodeoffset, "bias-disable", NULL) >= 0) return 0; return -1; } /** * fdt_get_pin - Read all pin from node * * @node_path: fdt path or alians * @prop_name: pin property name--ex "pinctrl-0" * @gpio_list: recevice the gpio data */ int fdt_get_all_pin(int nodeoffset,const char* pinctrl_name,user_gpio_set_t* gpio_list) { //int nodeoffset; /* node offset from libfdt */ char *pins = NULL; char *function = NULL; int ret; char path_tmp[128] = {0}; char port_name[32][12]; //format PA0,PB6 .... char pin_name[32][64] = {{0}}; // u32 handle[10] = {0}; int handle_num = 0; int i,j; int name_num = 0,port_num = 0; int gpio_list_index = 0; u32 pull; u32 drive; u32 muxsel; //get property vaule by handle /*nodeoffset = fdt_path_offset (working_fdt,node_path ); if(nodeoffset < 0) { printf ("error:fdt err returned %s\n",fdt_strerror(nodeoffset)); return -1; }*/ handle_num = fdt_getprop_u32(working_fdt,nodeoffset,pinctrl_name,handle); if(handle_num < 0) { FDT_ERR("%s:get property handle %s error:%s\n",__func__, pinctrl_name,fdt_strerror(handle_num) ); return -1; } for(i = 0; i < handle_num; i++) { debug("%s:get property handle %s ok, index %d,value is 0x%x\n",__func__, pinctrl_name,i,handle[i] ); nodeoffset = fdt_node_offset_by_phandle(working_fdt,handle[i]); if(nodeoffset < 0 ) { FDT_ERR("%s:get property by handle error\n",__func__); return -1; } ret = fdt_get_path(working_fdt,nodeoffset,path_tmp,sizeof(path_tmp)); if(ret < 0 ) { FDT_ERR("%s:get path by nodeoffset error\n",__func__); return -1; } debug("path for handle is %s\n", path_tmp); name_num = 0; port_num = 0; ret = fdt_getprop_string(working_fdt,nodeoffset,"allwinner,pins",&pins); if (ret < 0) ret = fdt_getprop_string(working_fdt, nodeoffset, "pins", &pins); if(ret >=0 ) { int len = ret; char *data = pins; j = 0; while (j < len) { strcpy(port_name[port_num++],data); j += strlen(data) + 1; data += strlen(data) + 1; } } ret = fdt_getprop_string(working_fdt,nodeoffset,"allwinner,pname",&pins); if (ret < 0) ret = fdt_getprop_string(working_fdt, nodeoffset, "pname", &pins); if(ret >=0 ) { int len = ret; char *data = pins; j = 0; while (j < len) { strcpy(pin_name[name_num++],data); j += strlen(data) + 1; data += strlen(data) + 1; } } #if 0 if(name_num != port_num) { printf ("error:pin name num(%d) != port num(%d)\n",name_num, port_num); return -1; } #endif ret = fdt_getprop_string(working_fdt,nodeoffset,"allwinner,function",&function); if (ret < 0) { ret = fdt_getprop_string(working_fdt, nodeoffset, "function", &function); if (ret < 0) { FDT_ERR("get function err returned %s\n", fdt_strerror(ret)); return -1; } } ret = fdt_getprop_u32(working_fdt,nodeoffset,"allwinner,muxsel",&muxsel); if (ret < 0) { ret = fdt_getprop_u32(working_fdt, nodeoffset, "muxsel", &muxsel); if (ret < 0) { FDT_ERR("get muxsel err returned %s\n", fdt_strerror(ret)); return -1; } } ret = fdt_getprop_u32(working_fdt,nodeoffset,"allwinner,drive",&drive); if (ret < 0) { ret = fdt_getprop_u32(working_fdt, nodeoffset, "drive-strength", &drive); if (ret < 0) { FDT_ERR("get drive err returned %s\n", fdt_strerror(ret)); return -1; } switch (drive) { case 10: drive = 0; break; case 20: drive = 1; break; case 30: drive = 2; break; case 40: drive = 3; break; default: FDT_ERR("get drive value err %d\n", drive); return -1; } } ret = fdt_getprop_u32(working_fdt,nodeoffset,"allwinner,pull",&pull); if(ret < 0) { pull = fdt_get_new_pull(nodeoffset); if (pull < 0) { FDT_ERR("get pull err returned %s\n", fdt_strerror(ret)); return -1; } } for(j = 0; j < port_num; j++) { char *src; char ch; int tmp_value = 0; int tmp_mul; src = &port_name[j][2]; ch = *src++; while(ch != '\0') { if((ch >= '0') && (ch <= '9')) { tmp_value = tmp_value * 10 + (ch - '0'); ch = *src++; } else { FDT_ERR("format gpio %s\n",pin_name[j] ); break; } } tmp_mul = muxsel;//get_mul_by_func_name(function); if(tmp_mul<0) { FDT_ERR(" muxsel not configed\n"); return -1; } strncpy(gpio_list[gpio_list_index].gpio_name, pin_name[j], sizeof(gpio_list[gpio_list_index].gpio_name) - 1); gpio_list[gpio_list_index].port = port_name[j][1] - 'A'+1; gpio_list[gpio_list_index].port_num = tmp_value; gpio_list[gpio_list_index].mul_sel = tmp_mul & 0xf; gpio_list[gpio_list_index].pull = pull; gpio_list[gpio_list_index].drv_level = drive; gpio_list[gpio_list_index].data = 0; gpio_list_index++; } } for(i = 0; i < gpio_list_index; i++) { debug("name = %s, port = %d,portnum=%d,mul_sel=%d,pull=%d drive= %d, data=%d\n", gpio_list[i].gpio_name, gpio_list[i].port, gpio_list[i].port_num, gpio_list[i].mul_sel, gpio_list[i].pull, gpio_list[i].drv_level, gpio_list[i].data); } return gpio_list_index; } /** * fdt_get_pin_num - get pin num from device node * * @node_path: device path or alians * @prop_name: ex "pinctrl-0" */ int fdt_get_pin_num(int nodeoffset,const char* pinctrl_name) { //int nodeoffset; /* node offset from libfdt */ char *pins = NULL; int ret; u32 handle[10] = {0}; int handle_num = 0; int i,j; int port_num = 0; //get property vaule by handle /*nodeoffset = fdt_path_offset (working_fdt,node_path ); if(nodeoffset < 0) { printf ("error:fdt err returned %s\n",fdt_strerror(nodeoffset)); return -1; }*/ handle_num = fdt_getprop_u32(working_fdt,nodeoffset,pinctrl_name,handle); if(handle_num < 0) { FDT_ERR("%s:get property handle %s error:%s\n",__func__, pinctrl_name,fdt_strerror(handle_num) ); return -1; } port_num = 0; for(i = 0; i < handle_num; i++) { //printf("get property handle %s ok, index %d,value is 0x%x\n", "pinctrl-0",i,handle[i] ); nodeoffset = fdt_node_offset_by_phandle(working_fdt,handle[i]); if(nodeoffset < 0 ) { FDT_ERR("%s:get property by handle error\n",__func__); return -1; } ret = fdt_getprop_string(working_fdt,nodeoffset,"allwinner,pins",&pins); if (ret < 0) ret = fdt_getprop_string(working_fdt, nodeoffset, "pins", &pins); if(ret >=0 ) { int len = ret; char *data = pins; j = 0; while (j < len) { port_num++; j += strlen(data) + 1; data += strlen(data) + 1; } } } return port_num; } /** * fdt_config_all_pin - config all pin for device * * @node_path: device tree path */ int fdt_set_all_pin(const char* node_path,const char* pinctrl_name) { user_gpio_set_t pin_set[32]; int pin_count = 0; int ret = 0; int nodeoffset; //get property vaule by handle nodeoffset = fdt_path_offset (working_fdt,node_path ); if(nodeoffset < 0) { FDT_ERR("%s:[%s]-->%s\n",__func__,node_path,fdt_strerror(nodeoffset)); return -1; } #if 0 pin_count = fdt_get_pin_num(nodeoffset,pinctrl_name); if(pin_count < 0) { return -1; } pin_set = malloc(pin_count*sizeof(user_gpio_set_t)); if(pin_set == NULL) { FDT_ERR("%s:malloc fail\n", __func__); return -1; } #endif pin_count = fdt_get_all_pin( nodeoffset, pinctrl_name,pin_set); if(pin_count < 0) { return -1; } ret = gpio_request_early(pin_set,pin_count,1); //free(pin_set); return ret; } int fdt_set_all_pin_by_offset(int nodeoffset,const char* pinctrl_name) { user_gpio_set_t pin_set[32] ; int pin_count = 0; int ret = 0; if(nodeoffset < 0) { FDT_ERR("%s:fdt bad nodeoffset %d\n",__func__,nodeoffset); return -1; } memset(pin_set, 0 , sizeof(pin_set)); #if 0 pin_count = fdt_get_pin_num(nodeoffset,pinctrl_name); if(pin_count < 0) { return -1; } pin_set = malloc(pin_count*sizeof(user_gpio_set_t)); if(pin_set == NULL) { FDT_ERR("%s:malloc fail\n", __func__); return -1; } #endif pin_count = fdt_get_all_pin( nodeoffset, pinctrl_name,pin_set); if(pin_count < 0) { return -1; } ret = gpio_request_early(pin_set,pin_count,1); //free(pin_set); return ret; } /** * fdt_config_all_pin - config all pin for device * * @node_path: device tree path */ int fdt_set_pin_byname(user_gpio_set_t *pin_list,int pin_count, const char* pin_name) { user_gpio_set_t *pin; int ret = 0; int i = 0; for(i = 0; i < pin_count; i++) { pin = pin_list+i; if(strcmp(pin->gpio_name, pin_name) == 0) { break; } } //not find if(i >= pin_count) { return -1; } ret = gpio_request_early(pin,1,1); return ret; } /** * fdt_get_gpio - Read one gpio from node * * @nodeoffset: fdt nodeoffset * @prop_name: gpio property naem * @gpio_list: recevice the gpio data */ int fdt_get_one_gpio_by_offset(int nodeoffset, const char* prop_name,user_gpio_set_t* gpio_list) { int ret ; u32 data[10]; memset(data, 0, sizeof(data)); //get property vaule by handle if(nodeoffset < 0) { debug ("fdt err returned %s\n",fdt_strerror(nodeoffset)); return -1; } ret = fdt_getprop_u32(working_fdt,nodeoffset,prop_name,data); if(ret < 0 ) { debug("%s : err returned %s\n",__func__,fdt_strerror(ret)); return -1; } strcpy(gpio_list->gpio_name,prop_name); gpio_list->port = data[1] + 1; //0: PA gpio_list->port_num = data[2]; gpio_list->mul_sel = data[3]; gpio_list->pull = data[4]; gpio_list->drv_level = data[5]; gpio_list->data = data[6]; debug("name = %s, port = %x,portnum=%x,mul_sel=%x,pull=%x drive= %x, data=%x\n", gpio_list->gpio_name, gpio_list->port, gpio_list->port_num, gpio_list->mul_sel, gpio_list->pull, gpio_list->drv_level, gpio_list->data); return ret; } int fdt_get_one_gpio(const char* node_path, const char* prop_name,user_gpio_set_t* gpio_list) { int nodeoffset; /* node offset from libfdt */ int ret ; u32 data[10]; memset(data, 0, sizeof(data)); //get property vaule by handle nodeoffset = fdt_path_offset (working_fdt,node_path ); if(nodeoffset < 0) { debug ("fdt err returned %s\n",fdt_strerror(nodeoffset)); return -1; } ret = fdt_getprop_u32(working_fdt,nodeoffset,prop_name,data); if(ret < 0 ) { debug("%s :%s|%s err returned %s\n",__func__,node_path,prop_name,fdt_strerror(ret)); return -1; } strcpy(gpio_list->gpio_name,prop_name); gpio_list->port = data[1] + 1; //0: PA gpio_list->port_num = data[2]; gpio_list->mul_sel = data[3]; gpio_list->pull = data[4]; gpio_list->drv_level = data[5]; gpio_list->data = data[6]; debug("name = %s, port = %x,portnum=%x,mul_sel=%x,pull=%x drive= %x, data=%x\n", gpio_list->gpio_name, gpio_list->port, gpio_list->port_num, gpio_list->mul_sel, gpio_list->pull, gpio_list->drv_level, gpio_list->data); return 0; } /** * fdt_set_one_gpio - config one gpio for device * * @node_path: device tree path * @prop_name: gpio name ex "vdevice_gpio_1" ---- vdevice_gpio_1 = <&r_pio PL 0 1 1 1 1>; */ int fdt_set_one_gpio(const char* node_path, const char* prop_name) { user_gpio_set_t gpio_set[1]; if(fdt_get_one_gpio(node_path, prop_name,gpio_set)) { return -1; } return gpio_request_early(&gpio_set,1,1); } int fdt_set_normal_gpio(user_gpio_set_t *gpio_set, int gpio_count) { return gpio_request_early(&gpio_set,gpio_count,1); } int script_parser_fetch(char *node_path, char *prop_name, int value[], int def_val) { int nodeoffset; int ret; //get property vaule by handle nodeoffset = fdt_path_offset (working_fdt, node_path ); if(nodeoffset < 0) { debug ("fdt err returned %s\n",fdt_strerror(nodeoffset)); value[0] = def_val; return -1; } ret = fdt_getprop_u32(working_fdt,nodeoffset, prop_name, (u32*)value); if(ret < 0 ) { debug("%s :%s|%s err returned %s\n",__func__,node_path,prop_name,fdt_strerror(ret)); value[0] = def_val; return -1; } return 0; } /** * fdt_get_regulator_name - get regulator name from device node * * @node_path: device path or alians * @prop_name: ex "pinctrl-0" */ const char *fdt_get_regulator_name(int nodeoffset, const char *name) { char supply_name[32]; u32 handle = 0; int handle_num = 0; sprintf(supply_name, "%s-supply", name); handle_num = fdt_getprop_u32(working_fdt, nodeoffset, supply_name, &handle); if (handle_num < 0) { FDT_ERR("%s:get property handle %s error:%s\n", __func__, supply_name, fdt_strerror(handle_num)); return NULL; } nodeoffset = fdt_node_offset_by_phandle(working_fdt, handle); if (nodeoffset < 0) { FDT_ERR("%s:get property by handle error\n", __func__); return NULL; } return fdt_get_name(working_fdt, nodeoffset, NULL); }