diff options
Diffstat (limited to 'exynos4412_gpios.c')
| -rw-r--r-- | exynos4412_gpios.c | 151 |
1 files changed, 123 insertions, 28 deletions
diff --git a/exynos4412_gpios.c b/exynos4412_gpios.c index 582e167..07e1cc8 100644 --- a/exynos4412_gpios.c +++ b/exynos4412_gpios.c @@ -22,33 +22,83 @@ #include <sys/mman.h> - /* uint32_t bank_con_addr; */ - /* uint32_t bank_dat_addr; */ - /* uint32_t bank_pud_addr; */ - /* uint32_t bank_drv_addr; */ - /* uint32_t bank_con_pdn_addr; */ - /* uint32_t bank_pud_pdn_addr; */ - - - /* if (!strcmp(bank, "gpj1")){ */ - /* bank_con_addr = 0x11400260; /\* GPJ1CON *\/ */ - /* bank_dat_addr = 0x11400264; /\* GPJ1DAT *\/ */ - /* bank_pud_addr = 0x11400268; /\* GPJ1PUD *\/ */ - /* bank_drv_addr = 0x1140026c; /\* GPJ1DRV *\/ */ - /* bank_con_pdn_addr = 0x11440270; /\* GPJ1CONPDN *\/ */ - /* bank_pud_pdn_addr = 0x11440274; /\* GPJ1PUDPDN *\/ */ - /* } else { */ - /* errno = -EINVAL; */ - /* return NULL; */ - /* } */ - - enum gpio_direction { GPIO_INPUT = 0, GPIO_OUTPUT = 1, /* The rest of the values up to 0xf seem to be dependent on the pin */ }; +struct gpio_bank_data { + char *name; + uint32_t nr_gpios; + uint32_t con_offset; + uint32_t dat_offset; + uint32_t pud_offset; + uint32_t drv_offset; + uint32_t con_pdn_offset; + uint32_t pud_pdn_offset; +}; + +struct gpio_bank_data gpio_banks_data[] = { + { + .name = "gpj1", + .nr_gpios = 4, + .con_offset = 0x0260, /* GPJ1CON */ + .dat_offset = 0x0264, /* GPJ1DAT */ + .pud_offset = 0x0268, /* GPJ1PUD */ + .drv_offset = 0x026c, /* GPJ1DRV */ + .con_pdn_offset = 0x0270, /* GPJ1CONPDN */ + .pud_pdn_offset = 0x0274, /* GPJ1PUDPDN */ + }, + { + /* Sentinel */ + }, +}; + +static struct gpio_bank_data *get_gpio_bank_data(char *bank) +{ + + int i = 0; + + while (1) { + if (gpio_banks_data[i].name == NULL) + break; + + if (!strcmp(gpio_banks_data[i].name, bank)) + return &(gpio_banks_data[i]); + + i++; + } + + return NULL; +} + + +static void print_gpio_banks_data(void) +{ + + int i = 0; + + while (1) { + if (gpio_banks_data[i].name == NULL) + break; + + printf("%s[%d] {\n", gpio_banks_data[i].name, + gpio_banks_data[i].nr_gpios); + printf("\tcon_offset: %p\n", gpio_banks_data[i].con_offset); + printf("\tdat_offset: %p\n", gpio_banks_data[i].dat_offset); + printf("\tpud_offset: %p\n", gpio_banks_data[i].pud_offset); + printf("\tdrv_offset: %p\n", gpio_banks_data[i].drv_offset); + printf("\tcon_pdn_offset: %p\n", + gpio_banks_data[i].con_pdn_offset); + printf("\tpud_pdn_offset: %p\n", + gpio_banks_data[i].pud_pdn_offset); + printf("}\n"); + + i++; + } +} + static char *gpio_direction_str(int value) { /* The GP<x>CON field size is 4 bits. So the maximum value it can take @@ -68,28 +118,71 @@ static char *gpio_direction_str(int value) } } -static int decode_bank_con(char *bank, uint32_t gpio_offset, uint32_t *virt_addr) + +static int decode_bank_dat(char *bank, uint32_t gpio_offset, + uint32_t *virt_addr) { + struct gpio_bank_data *gpio_bank_data; + + int result = 0; + + uint32_t *addr; + uint32_t offset; + uint32_t value; + + /* TODO: check if the port is configured as "functional pin" (not input + * or output) and return an UNDEFINED value. + */ + + gpio_bank_data = get_gpio_bank_data(bank); + if (gpio_bank_data == NULL) { + errno = EINVAL; + return -1; + } + + offset = gpio_bank_data->dat_offset; + + addr = virt_addr + offset; + value = *virt_addr; + printf("%s: %s: offset %p value: 0x%x\n", __func__, bank, + addr - virt_addr, value); + + result = ((value >> (gpio_offset)) & 1); + + printf("%s: %s[%d]: value: %d\n", __func__, bank, gpio_offset, result); + + return 0; +} + +static int decode_bank_con(char *bank, uint32_t gpio_offset, + uint32_t *virt_addr) +{ + struct gpio_bank_data *gpio_bank_data; + int shift = 0; int result = 0; char* direction; + uint32_t offset; uint32_t *addr; uint32_t value; printf("%s: Mapped at %p\n", __func__, virt_addr); - if (!strcmp(bank, "gpj1")) { - addr = virt_addr + 0x260; - value = *virt_addr; - printf("%s: %s: offset %p value: 0x%x\n", __func__, bank, - addr - virt_addr, value); - } else { + gpio_bank_data = get_gpio_bank_data(bank); + if (gpio_bank_data == NULL) { errno = EINVAL; return -1; } + offset = gpio_bank_data->con_offset; + + addr = virt_addr + offset; + value = *virt_addr; + printf("%s: %s: offset %p value: 0x%x\n", __func__, bank, + addr - virt_addr, value); + result = ((value >> (gpio_offset * 4)) & 0xf); direction = gpio_direction_str(result); @@ -135,7 +228,9 @@ int dump_gpio_infos(char *devmem, int fd, size_t page_size, char *bank, addr = mmap_gpio_bank(devmem, fd, page_size, "gpj1"); printf("%s: Mapped at %p\n", __func__, addr); + print_gpio_banks_data(); rc = decode_bank_con("gpj1", 1, addr); + rc = decode_bank_dat("gpj1", 1, addr); if (rc == -1) { rc = errno; printf("decode_gpio(\"%s\", %d, 0x%x); " |
