531 lines
17 KiB
C
531 lines
17 KiB
C
/*
|
|
* (C) Copyright 2007-2011
|
|
* Allwinner Technology Co., Ltd. <www.allwinnertech.com>
|
|
* Tom Cubie <tangliang@allwinnertech.com>
|
|
*
|
|
*/
|
|
|
|
#include <common.h>
|
|
#include <asm/io.h>
|
|
#include <arch/gpio.h>
|
|
#include <arch/gpio_new.h>
|
|
#include <spare_head.h>
|
|
#include <libfdt.h>
|
|
|
|
void sunxi_gpio_set_cfgbank(struct sunxi_gpio *pio, int bank_offset, u32 val)
|
|
{
|
|
u32 index = GPIO_CFG_INDEX(bank_offset);
|
|
u32 offset = GPIO_CFG_OFFSET(bank_offset);
|
|
|
|
clrsetbits_le32(&pio->cfg[0] + index, 0xf << offset, val << offset);
|
|
}
|
|
|
|
void sunxi_gpio_set_cfgpin(u32 pin, u32 val)
|
|
{
|
|
u32 bank = GPIO_BANK(pin);
|
|
struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
|
|
|
|
sunxi_gpio_set_cfgbank(pio, pin, val);
|
|
}
|
|
|
|
int sunxi_gpio_get_cfgbank(struct sunxi_gpio *pio, int bank_offset)
|
|
{
|
|
u32 index = GPIO_CFG_INDEX(bank_offset);
|
|
u32 offset = GPIO_CFG_OFFSET(bank_offset);
|
|
u32 cfg;
|
|
|
|
cfg = readl(&pio->cfg[0] + index);
|
|
cfg >>= offset;
|
|
|
|
return cfg & 0xf;
|
|
}
|
|
|
|
int sunxi_gpio_get_cfgpin(u32 pin)
|
|
{
|
|
u32 bank = GPIO_BANK(pin);
|
|
struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
|
|
|
|
return sunxi_gpio_get_cfgbank(pio, pin);
|
|
}
|
|
|
|
int sunxi_gpio_set_drv(u32 pin, u32 val)
|
|
{
|
|
u32 bank = GPIO_BANK(pin);
|
|
u32 index = GPIO_DRV_INDEX(pin);
|
|
u32 offset = GPIO_DRV_OFFSET(pin);
|
|
struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
|
|
|
|
clrsetbits_le32(&pio->drv[0] + index, 0x3 << offset, val << offset);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sunxi_gpio_set_pull(u32 pin, u32 val)
|
|
{
|
|
u32 bank = GPIO_BANK(pin);
|
|
u32 index = GPIO_PULL_INDEX(pin);
|
|
u32 offset = GPIO_PULL_OFFSET(pin);
|
|
struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
|
|
clrsetbits_le32(&pio->pull[0] + index, 0x3 << offset, val << offset);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int boot_set_gpio(void *user_gpio_list, u32 group_count_max, int set_gpio)
|
|
{
|
|
normal_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 port, port_num, port_num_func, port_num_pull, port_num_dlevel;
|
|
u32 pre_port, pre_port_num_func, pre_port_num_dlevel;
|
|
u32 pre_port_num_pull;
|
|
volatile u32 *tmp_group_func_addr, *tmp_group_pull_addr;
|
|
volatile u32 *tmp_group_dlevel_addr, *tmp_group_data_addr;
|
|
int i, tmp_val;
|
|
|
|
gpio_list = (normal_gpio_set_t *)user_gpio_list;
|
|
/* printf("gpio: conut=%d, set gpio = %d\n", group_count_max, set_gpio); */
|
|
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;
|
|
}
|
|
|
|
/*32-bit register */
|
|
port_num_func = (port_num /(32/CFG_BIT_WIDTH));
|
|
port_num_pull = (port_num /(32/PULL_BIT_WIDTH));
|
|
port_num_dlevel = (port_num /(32/DRV_BIT_WIDTH));
|
|
|
|
if (port < 12) {
|
|
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);
|
|
} else {
|
|
tmp_group_func_addr = R_PIO_REG_CFG(port, port_num_func);
|
|
tmp_group_pull_addr = R_PIO_REG_PULL(port, port_num_pull);
|
|
tmp_group_dlevel_addr = R_PIO_REG_DLEVEL(port, port_num_dlevel);
|
|
tmp_group_data_addr = R_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;
|
|
pre_port_num_dlevel = port_num_dlevel;
|
|
|
|
/* update funtion */
|
|
tmp_val = (port_num % (32/CFG_BIT_WIDTH)) * CFG_BIT_WIDTH;
|
|
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;
|
|
}
|
|
/* update pull */
|
|
tmp_val = (port_num % (32/PULL_BIT_WIDTH)) * PULL_BIT_WIDTH;
|
|
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;
|
|
}
|
|
/* update driver level */
|
|
tmp_val = (port_num % (32/DRV_BIT_WIDTH)) * DRV_BIT_WIDTH;
|
|
if (tmp_user_gpio_data->drv_level >= 0) {
|
|
tmp_group_dlevel_data &= ~(PIO_DRV_MASK << tmp_val);
|
|
tmp_group_dlevel_data |=
|
|
(tmp_user_gpio_data->drv_level & PIO_DRV_MASK) << tmp_val;
|
|
}
|
|
/* update data */
|
|
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;
|
|
}
|
|
}
|
|
|
|
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;
|
|
if (!port) {
|
|
break;
|
|
}
|
|
port_num_func = (port_num /(32/CFG_BIT_WIDTH));
|
|
port_num_pull = (port_num /(32/PULL_BIT_WIDTH));
|
|
port_num_dlevel = (port_num /(32/DRV_BIT_WIDTH));
|
|
|
|
/* The same register is not written before and after */
|
|
if ((port_num_pull != pre_port_num_pull) ||
|
|
(port != pre_port)) {
|
|
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);
|
|
}
|
|
|
|
if (port < 12) {
|
|
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);
|
|
} else {
|
|
tmp_group_func_addr = R_PIO_REG_CFG(port, port_num_func);
|
|
tmp_group_pull_addr = R_PIO_REG_PULL(port, port_num_pull);
|
|
tmp_group_dlevel_addr = R_PIO_REG_DLEVEL(port, port_num_dlevel);
|
|
tmp_group_data_addr = R_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);
|
|
} else if (pre_port_num_func != port_num_func ||
|
|
pre_port_num_dlevel != port_num_dlevel) {
|
|
|
|
if (pre_port_num_func != port_num_func) {
|
|
GPIO_REG_WRITE(tmp_group_func_addr, tmp_group_func_data);
|
|
if (port < 12) {
|
|
tmp_group_func_addr = PIO_REG_CFG(port, port_num_func);
|
|
} else {
|
|
tmp_group_func_addr = R_PIO_REG_CFG(port, port_num_func);
|
|
}
|
|
tmp_group_func_data = GPIO_REG_READ(tmp_group_func_addr);
|
|
}
|
|
if (pre_port_num_dlevel != port_num_dlevel) {
|
|
GPIO_REG_WRITE(tmp_group_dlevel_addr, tmp_group_dlevel_data);
|
|
if (port < 12) {
|
|
tmp_group_dlevel_addr = PIO_REG_DLEVEL(port, port_num_dlevel);
|
|
} else {
|
|
tmp_group_dlevel_addr = PIO_REG_DLEVEL(port, port_num_dlevel);
|
|
}
|
|
tmp_group_dlevel_data = GPIO_REG_READ(tmp_group_dlevel_addr);
|
|
}
|
|
}
|
|
|
|
pre_port_num_func = port_num_func;
|
|
pre_port_num_pull = port_num_pull;
|
|
pre_port_num_dlevel = port_num_dlevel;
|
|
pre_port = port;
|
|
|
|
/* write to the same register */
|
|
tmp_val = (port_num % (32/CFG_BIT_WIDTH)) * CFG_BIT_WIDTH;
|
|
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 % (32/PULL_BIT_WIDTH)) * PULL_BIT_WIDTH;
|
|
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;
|
|
}
|
|
|
|
tmp_val = (port_num % (32/DRV_BIT_WIDTH)) * DRV_BIT_WIDTH;
|
|
if (tmp_user_gpio_data->drv_level >= 0) {
|
|
tmp_group_dlevel_data &= ~(PIO_DRV_MASK << tmp_val);
|
|
tmp_group_dlevel_data |=
|
|
(tmp_user_gpio_data->drv_level & PIO_DRV_MASK) << 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;
|
|
}
|
|
}
|
|
} /* for */
|
|
|
|
/* The last set of data written */
|
|
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;
|
|
}
|
|
|
|
|
|
#ifdef CFG_SET_GPIO_NEW
|
|
/* Due to the incompatibility of port in the code, this function is redefined*/
|
|
int boot_set_gpio_new(void *user_gpio_list, u32 group_count_max, int set_gpio)
|
|
{
|
|
normal_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 port, port_num, port_num_func, port_num_pull, port_num_dlevel;
|
|
u32 pre_port, pre_port_num_func, pre_port_num_dlevel;
|
|
u32 pre_port_num_pull;
|
|
volatile u32 *tmp_group_func_addr, *tmp_group_pull_addr;
|
|
volatile u32 *tmp_group_dlevel_addr, *tmp_group_data_addr;
|
|
int i, tmp_val;
|
|
|
|
gpio_list = (normal_gpio_set_t *)user_gpio_list;
|
|
/* printf("gpio: conut=%d, set gpio = %d\n", group_count_max, set_gpio); */
|
|
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 == PORT_NO_USE || port_num == PORT_NUM_NO_USE) {
|
|
continue;
|
|
}
|
|
|
|
/*32-bit register */
|
|
port_num_func = (port_num /(32/CFG_BIT_WIDTH));
|
|
port_num_pull = (port_num /(32/PULL_BIT_WIDTH));
|
|
port_num_dlevel = (port_num /(32/DRV_BIT_WIDTH));
|
|
|
|
if (port < 12) {
|
|
tmp_group_func_addr = NEW_PIO_REG_CFG(port, port_num_func);
|
|
tmp_group_pull_addr = NEW_PIO_REG_PULL(port, port_num_pull);
|
|
tmp_group_dlevel_addr = NEW_PIO_REG_DLEVEL(port, port_num_dlevel);
|
|
tmp_group_data_addr = NEW_PIO_REG_DATA(port);
|
|
} else {
|
|
tmp_group_func_addr = R_NEW_PIO_REG_CFG(port, port_num_func);
|
|
tmp_group_pull_addr = R_NEW_PIO_REG_PULL(port, port_num_pull);
|
|
tmp_group_dlevel_addr = R_NEW_PIO_REG_DLEVEL(port, port_num_dlevel);
|
|
tmp_group_data_addr = R_NEW_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;
|
|
pre_port_num_dlevel = port_num_dlevel;
|
|
|
|
/* update funtion */
|
|
tmp_val = (port_num % (32/CFG_BIT_WIDTH)) * CFG_BIT_WIDTH;
|
|
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;
|
|
}
|
|
/* update pull */
|
|
tmp_val = (port_num % (32/PULL_BIT_WIDTH)) * PULL_BIT_WIDTH;
|
|
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;
|
|
}
|
|
/* update driver level */
|
|
tmp_val = (port_num % (32/DRV_BIT_WIDTH)) * DRV_BIT_WIDTH;
|
|
if (tmp_user_gpio_data->drv_level >= 0) {
|
|
tmp_group_dlevel_data &= ~(PIO_DRV_MASK << tmp_val);
|
|
tmp_group_dlevel_data |=
|
|
(tmp_user_gpio_data->drv_level & PIO_DRV_MASK) << tmp_val;
|
|
}
|
|
/* update data */
|
|
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;
|
|
}
|
|
}
|
|
|
|
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;
|
|
if (port == PORT_NO_USE || port_num == PORT_NUM_NO_USE) {
|
|
continue;
|
|
}
|
|
port_num_func = (port_num /(32/CFG_BIT_WIDTH));
|
|
port_num_pull = (port_num /(32/PULL_BIT_WIDTH));
|
|
port_num_dlevel = (port_num /(32/DRV_BIT_WIDTH));
|
|
|
|
/* The same register is not written before and after */
|
|
if ((port_num_pull != pre_port_num_pull) ||
|
|
(port != pre_port)) {
|
|
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);
|
|
}
|
|
|
|
if (port < 12) {
|
|
tmp_group_func_addr = NEW_PIO_REG_CFG(port, port_num_func);
|
|
tmp_group_pull_addr = NEW_PIO_REG_PULL(port, port_num_pull);
|
|
tmp_group_dlevel_addr = NEW_PIO_REG_DLEVEL(port, port_num_dlevel);
|
|
tmp_group_data_addr = NEW_PIO_REG_DATA(port);
|
|
} else {
|
|
tmp_group_func_addr = R_NEW_PIO_REG_CFG(port, port_num_func);
|
|
tmp_group_pull_addr = R_NEW_PIO_REG_PULL(port, port_num_pull);
|
|
tmp_group_dlevel_addr = R_NEW_PIO_REG_DLEVEL(port, port_num_dlevel);
|
|
tmp_group_data_addr = R_NEW_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);
|
|
} else if (pre_port_num_func != port_num_func ||
|
|
pre_port_num_dlevel != port_num_dlevel) {
|
|
|
|
if (pre_port_num_func != port_num_func) {
|
|
GPIO_REG_WRITE(tmp_group_func_addr, tmp_group_func_data);
|
|
if (port < 12) {
|
|
tmp_group_func_addr = NEW_PIO_REG_CFG(port, port_num_func);
|
|
} else {
|
|
tmp_group_func_addr = R_NEW_PIO_REG_CFG(port, port_num_func);
|
|
}
|
|
tmp_group_func_data = GPIO_REG_READ(tmp_group_func_addr);
|
|
}
|
|
if (pre_port_num_dlevel != port_num_dlevel) {
|
|
GPIO_REG_WRITE(tmp_group_dlevel_addr, tmp_group_dlevel_data);
|
|
if (port < 12) {
|
|
tmp_group_dlevel_addr = NEW_PIO_REG_DLEVEL(port, port_num_dlevel);
|
|
} else {
|
|
tmp_group_dlevel_addr = NEW_PIO_REG_DLEVEL(port, port_num_dlevel);
|
|
}
|
|
tmp_group_dlevel_data = GPIO_REG_READ(tmp_group_dlevel_addr);
|
|
}
|
|
}
|
|
|
|
pre_port_num_func = port_num_func;
|
|
pre_port_num_pull = port_num_pull;
|
|
pre_port_num_dlevel = port_num_dlevel;
|
|
pre_port = port;
|
|
|
|
/* write to the same register */
|
|
tmp_val = (port_num % (32/CFG_BIT_WIDTH)) * CFG_BIT_WIDTH;
|
|
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 % (32/PULL_BIT_WIDTH)) * PULL_BIT_WIDTH;
|
|
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;
|
|
}
|
|
|
|
tmp_val = (port_num % (32/DRV_BIT_WIDTH)) * DRV_BIT_WIDTH;
|
|
if (tmp_user_gpio_data->drv_level >= 0) {
|
|
tmp_group_dlevel_data &= ~(PIO_DRV_MASK << tmp_val);
|
|
tmp_group_dlevel_data |=
|
|
(tmp_user_gpio_data->drv_level & PIO_DRV_MASK) << 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;
|
|
}
|
|
}
|
|
} /* for */
|
|
|
|
/* The last set of data written */
|
|
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;
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifdef CFG_SUNXI_FDT
|
|
int fdt_get_one_gpio(const char *node_path, const char *prop_name,
|
|
normal_gpio_cfg *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) {
|
|
printf("fdt err returned %s\n", fdt_strerror(nodeoffset));
|
|
return -1;
|
|
}
|
|
|
|
ret = fdt_getprop_u32(working_fdt, nodeoffset, prop_name, data);
|
|
if (ret < 0) {
|
|
printf("%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]; //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];
|
|
|
|
boot_info(
|
|
"port = %x,portnum=%x,mul_sel=%x,pull=%x drive= %x, data=%x\n",
|
|
gpio_list->port, gpio_list->port_num, gpio_list->mul_sel,
|
|
gpio_list->pull, gpio_list->drv_level, gpio_list->data);
|
|
return 0;
|
|
}
|
|
#endif
|