summaryrefslogtreecommitdiffstats
path: root/exynos4412_gpios.c
diff options
context:
space:
mode:
Diffstat (limited to 'exynos4412_gpios.c')
-rw-r--r--exynos4412_gpios.c151
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); "