]> Zhao Yanbai Git Server - minix.git/commitdiff
GPIO:further development 96/296/5
authorKees Jongenburger <keesj@minix3.org>
Wed, 6 Feb 2013 14:46:21 +0000 (15:46 +0100)
committerKees Jongenburger <keesj@minix3.org>
Wed, 6 Feb 2013 15:07:43 +0000 (16:07 +0100)
* Generalize GPIO handling.
* Add libs to configure gpio's clocks and pads
* Add Interrupt handling.
* Introduce mmio.h and log.h

Change-Id: I928e4c807d15031de2eede4b3ecff62df795f8ac

19 files changed:
distrib/sets/lists/minix/md.evbarm
distrib/sets/lists/minix/mi
drivers/gpio/Makefile
drivers/gpio/gpio.c
drivers/gpio/gpio.h [deleted file]
drivers/gpio/gpio_omap.c [deleted file]
etc/system.conf
include/minix/Makefile
include/minix/gpio.h [new file with mode: 0644]
include/minix/log.h [moved from drivers/gpio/log.h with 97% similarity]
include/minix/mmio.h [moved from drivers/gpio/mmio.h with 90% similarity]
include/minix/padconf.h [new file with mode: 0644]
lib/Makefile
lib/libgpio/Makefile [new file with mode: 0644]
lib/libgpio/clkconf.c [new file with mode: 0644]
lib/libgpio/clkconf.h [new file with mode: 0644]
lib/libgpio/gpio_omap.c [new file with mode: 0644]
lib/libpadconf/Makefile [new file with mode: 0644]
lib/libpadconf/padconf.c [new file with mode: 0644]

index cebc658bafee12249962f42a7cc6891fd1ebc6b6..2a60469e8588c01f5bf5a7ff5f28e7531688215b 100644 (file)
@@ -90,5 +90,9 @@
 ./usr/include/evbarm/vmparam.h         minix-sys
 ./usr/include/evbarm/wchar_limits.h    minix-sys
 ./usr/include/i386                     minix-sys       obsolete
-./usr/sbin/gpio                                minix-sys
+./usr/lib/libgpio.a                    minix-sys
+./usr/lib/libgpio_pic.a                        minix-sys
+./usr/lib/libpadconf.a                 minix-sys
+./usr/lib/libpadconf_pic.a             minix-sys
 ./usr/mdec                             minix-sys
+./usr/sbin/gpio                                minix-sys
index 69bc16829a94e79e48ee3a1f6d2451ab611cd6f9..4f2d16321f1fbd4a0b8290c7ec98ce4d816be73e 100644 (file)
 ./usr/include/minix/endpoint.h         minix-sys
 ./usr/include/minix/fslib.h            minix-sys
 ./usr/include/minix/gcov.h             minix-sys
+./usr/include/minix/gpio.h             minix-sys
 ./usr/include/minix/hash.h             minix-sys
 ./usr/include/minix/hgfs.h             minix-sys
 ./usr/include/minix/input.h            minix-sys
 ./usr/include/minix/keymap.h           minix-sys
 ./usr/include/minix/libminixfs.h       minix-sys
 ./usr/include/minix/limits.h           minix-sys
+./usr/include/minix/log.h              minix-sys
 ./usr/include/minix                    minix-sys
 ./usr/include/minix/minlib.h           minix-sys
+./usr/include/minix/mmio.h             minix-sys
 ./usr/include/minix/mount.h            minix-sys
 ./usr/include/minix/mthread.h          minix-sys
 ./usr/include/minix/netdriver.h                minix-sys
 ./usr/include/minix/netsock.h          minix-sys
 ./usr/include/minix/optset.h           minix-sys
+./usr/include/minix/padconf.h          minix-sys
 ./usr/include/minix/param.h            minix-sys
 ./usr/include/minix/partition.h                minix-sys
 ./usr/include/minix/paths.h            minix-sys
index a7f87f5a2b85fa5bddbe1fb51771cdf0469e976f..7cb5a9cc8d42ff477b61f20e76b51cf396416f4c 100644 (file)
@@ -1,9 +1,9 @@
 # Makefile for the gpio driver.
 PROG=  gpio
-SRCS=  gpio.c gpio_omap.c
+SRCS=  gpio.c
 
 DPADD+=        ${LIBBLOCKDRIVER} ${LIBSYS}
-LDADD+=        -lvtreefs -lsys
+LDADD+=        -lvtreefs -lsys -lgpio -lpadconf
 
 #
 # This is a system driver.
index 724b2664c991bba4278850276c10179b73ef7d23..4163e58320988c12095c9849162b62cb8b76620f 100644 (file)
@@ -6,10 +6,16 @@
 #include <minix/driver.h>
 #include <minix/drvlib.h>
 #include <minix/vtreefs.h>
+#include <minix/syslib.h>
+#include <minix/log.h>
+#include <minix/mmio.h>
+#include <minix/gpio.h>
+#include <minix/padconf.h>
 
 /* system headers */
 #include <sys/stat.h>
 #include <sys/queue.h>
+#include <sys/queue.h>
 
 /* usr headers */
 #include <assert.h>
@@ -21,9 +27,6 @@
 #include <string.h>
 
 /* local headers */
-#include "log.h"
-#include "mmio.h"
-#include "gpio.h"
 
 /* used for logging */
 static struct log log = {
@@ -33,8 +36,9 @@ static struct log log = {
 };
 
 #define GPIO_CB_READ 0
-#define GPIO_CB_ON 1
-#define GPIO_CB_OFF 2
+#define GPIO_CB_INTR_READ 1
+#define GPIO_CB_ON 2
+#define GPIO_CB_OFF 3
 
 /* The vtreefs library provides callback data when calling
  * the read function of inode. gpio_cbdata is used here to
@@ -51,10 +55,10 @@ struct gpio_cbdata
 };
 
 /* list of inodes used in this driver */
+/* *INDENT-OFF* */
 TAILQ_HEAD(gpio_cbdata_head, gpio_cbdata)
     gpio_cbdata_list = TAILQ_HEAD_INITIALIZER(gpio_cbdata_list);
-
-static struct gpio_driver drv;
+/* *INDENT-ON* */
 
 /* Sane file stats for a directory */
 static struct inode_stat default_file_stat = {
@@ -75,13 +79,13 @@ add_gpio_inode(char *name, int nr, int mode)
        struct gpio *gpio;
 
        /* claim and configure the gpio */
-       if (drv.claim("gpiofs", nr, &gpio)) {
+       if (gpio_claim("gpiofs", nr, &gpio)) {
                log_warn(&log, "Failed to claim GPIO %d\n", nr);
                return EIO;
        }
        assert(gpio != NULL);
 
-       if (drv.pin_mode(gpio, mode)) {
+       if (gpio_pin_mode(gpio, mode)) {
                log_warn(&log, "Failed to switch GPIO %d to mode %d\n", nr,
                    mode);
                return EIO;
@@ -115,7 +119,7 @@ add_gpio_inode(char *name, int nr, int mode)
                cb->type = GPIO_CB_ON;
                cb->gpio = gpio;
 
-               snprintf(tmpname, 200, "%son", name);
+               snprintf(tmpname, 200, "%sOn", name);
                add_inode(get_root_inode(), tmpname, NO_INDEX,
                    &default_file_stat, 0, (cbdata_t) cb);
                TAILQ_INSERT_HEAD(&gpio_cbdata_list, cb, next);
@@ -130,7 +134,22 @@ add_gpio_inode(char *name, int nr, int mode)
                cb->type = GPIO_CB_OFF;
                cb->gpio = gpio;
 
-               snprintf(tmpname, 200, "%soff", name);
+               snprintf(tmpname, 200, "%sOff", name);
+               add_inode(get_root_inode(), tmpname, NO_INDEX,
+                   &default_file_stat, 0, (cbdata_t) cb);
+               TAILQ_INSERT_HEAD(&gpio_cbdata_list, cb, next);
+       } else {
+               /* read interrupt */
+               cb = malloc(sizeof(struct gpio_cbdata));
+               if (cb == NULL) {
+                       return ENOMEM;
+               }
+               memset(cb, 0, sizeof(*cb));
+
+               cb->type = GPIO_CB_INTR_READ;
+               cb->gpio = gpio;
+
+               snprintf(tmpname, 200, "%sIntr", name);
                add_inode(get_root_inode(), tmpname, NO_INDEX,
                    &default_file_stat, 0, (cbdata_t) cb);
                TAILQ_INSERT_HEAD(&gpio_cbdata_list, cb, next);
@@ -142,17 +161,30 @@ static void
 init_hook(void)
 {
        /* This hook will be called once, after VTreeFS has initialized. */
-       if (omap_gpio_init(&drv)) {
+       if (gpio_init()) {
                log_warn(&log, "Failed to init gpio driver\n");
        }
+
        add_gpio_inode("USR0", 149, GPIO_MODE_OUTPUT);
        add_gpio_inode("USR1", 150, GPIO_MODE_OUTPUT);
        add_gpio_inode("Button", 4, GPIO_MODE_INPUT);
 
-#if 0
-       add_gpio_inode("input1", 139, GPIO_MODE_INPUT);
-       add_gpio_inode("input2", 144, GPIO_MODE_INPUT);
-#endif
+       /* configure the padconf */
+       padconf_init();
+
+       /* configure GPIO_144 to be exported */
+       padconf_set(CONTROL_PADCONF_UART2_CTS, 0xff,
+           PADCONF_MUXMODE(4) | PADCONF_PULL_MODE_PD_EN |
+           PADCONF_INPUT_ENABLE(1));
+       padconf_set(CONTROL_PADCONF_MMC2_DAT6, 0xff00,
+           (PADCONF_MUXMODE(4) | PADCONF_PULL_MODE_PD_EN |
+               PADCONF_INPUT_ENABLE(1)) << 16);
+
+       padconf_release();
+       /* Added for demo purposes */
+       add_gpio_inode("BigRedButton", 144, GPIO_MODE_INPUT);
+       add_gpio_inode("BigRedButtonLed", 139, GPIO_MODE_OUTPUT);
+
 }
 
 static int
@@ -167,28 +199,30 @@ static int
        struct gpio_cbdata *gpio_cbdata = (struct gpio_cbdata *) cbdata;
        assert(gpio_cbdata->gpio != NULL);
 
-       if (gpio_cbdata->type == GPIO_CB_ON) {
-               /* turn on */
-               if (drv.set(gpio_cbdata->gpio, 1)) {
+       if (gpio_cbdata->type == GPIO_CB_ON
+           || gpio_cbdata->type == GPIO_CB_OFF) {
+               /* turn on or of */
+               if (gpio_set(gpio_cbdata->gpio,
+                       (gpio_cbdata->type == GPIO_CB_ON) ? 1 : 0)) {
                        *len = 0;
                        return EIO;
                }
                *len = 0;
                return OK;
-       } else if (gpio_cbdata->type == GPIO_CB_OFF) {
-               /* turn off */
-               if (drv.set(gpio_cbdata->gpio, 0)) {
+       }
+
+       if (gpio_cbdata->type == GPIO_CB_INTR_READ) {
+               /* reading interrupt */
+               if (gpio_intr_read(gpio_cbdata->gpio, &value)) {
+                       *len = 0;
+                       return EIO;
+               }
+       } else {
+               /* reading */
+               if (gpio_read(gpio_cbdata->gpio, &value)) {
                        *len = 0;
                        return EIO;
                }
-               *len = 0;
-               return OK;
-       }
-
-       /* reading */
-       if (drv.read(gpio_cbdata->gpio, &value)) {
-               *len = 0;
-               return EIO;
        }
        snprintf(data, 26, "%d\n", value);
 
@@ -211,6 +245,13 @@ static int
        return OK;
 }
 
+static int
+message_hook(message * m)
+{
+       gpio_intr_message(m);
+       return OK;
+}
+
 int
 main(int argc, char **argv)
 {
@@ -225,6 +266,7 @@ main(int argc, char **argv)
        memset(&hooks, 0, sizeof(hooks));
        hooks.init_hook = init_hook;
        hooks.read_hook = read_hook;
+       hooks.message_hook = message_hook;
 
        root_stat.mode = S_IFDIR | S_IRUSR | S_IRGRP | S_IROTH;
        root_stat.uid = 0;
@@ -233,7 +275,7 @@ main(int argc, char **argv)
        root_stat.dev = NO_DEV;
 
        /* limit the number of indexed entries */
-       start_vtreefs(&hooks, 10, &root_stat, 0);
+       start_vtreefs(&hooks, 30, &root_stat, 0);
 
        return EXIT_SUCCESS;
 }
diff --git a/drivers/gpio/gpio.h b/drivers/gpio/gpio.h
deleted file mode 100644 (file)
index 5984ca8..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-#ifndef __INCLUDE_GPIO_H__
-#define __INCLUDE_GPIO_H__
-
-struct gpio
-{
-       int nr;                 /* GPIO number */
-       int mode;               /* GPIO mode (input=0/output=1) */
-       void *data;             /* data pointer (not used in the omap driver) */
-};
-
-#define GPIO_MODE_INPUT 0
-#define GPIO_MODE_OUTPUT 1
-
-struct gpio_driver
-{
-       /* request access to a gpio */
-       int (*claim) (char *owner, int nr, struct gpio ** gpio);
-
-       /* Configure the GPIO for a certain purpose */
-       int (*pin_mode) (struct gpio * gpio, int mode);
-
-       /* Set the value for a GPIO */
-       int (*set) (struct gpio * gpio, int value);
-
-       /* Read the value of the GPIO */
-       int (*read) (struct gpio * gpio, int *value);
-};
-
-int omap_gpio_init(struct gpio_driver *gpio_driver);
-#endif /* __INCLUDE_GPIO_H__ */
diff --git a/drivers/gpio/gpio_omap.c b/drivers/gpio/gpio_omap.c
deleted file mode 100644 (file)
index e2063a7..0000000
+++ /dev/null
@@ -1,236 +0,0 @@
-/* kernel headers */
-#include <minix/syslib.h>
-#include <minix/drvlib.h>
-
-/* system headers */
-#include <sys/mman.h>
-#include <sys/types.h>
-
-/* usr headers */
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <errno.h>
-#include <assert.h>
-
-/* local headers */
-#include "log.h"
-#include "mmio.h"
-#include "gpio.h"
-
-/* used for logging */
-static struct log log = {
-       .name = "gpio_omap",
-       .log_level = LEVEL_INFO,
-       .log_func = default_log
-};
-
-struct omap_gpio_bank
-{
-       const char *name;
-       uint32_t register_address;
-       uint32_t base_address;
-       uint32_t disabled;
-};
-
-static struct omap_gpio_bank omap_gpio_banks[] = {
-       {"GPIO1", 0x48310000, 0, 0},
-       {"GPIO2", 0x49050000, 0, 0},
-       {"GPIO3", 0x49052000, 0, 0},
-       {"GPIO4", 0x49054000, 0, 0},
-       {"GPIO5", 0x49056000, 0, 0},
-       {"GPIO6", 0x49058000, 0, 0},
-       {NULL, 0, 0}
-};
-
-#define GPIO_REVISION 0x00
-#define GPIO_REVISION_MAJOR(X) ((X & 0xF0) >> 4)
-#define GPIO_REVISION_MINOR(X) (X & 0XF)
-
-#define GPIO_DATAOUT 0x3c
-#define GPIO_DATAIN 0x38
-#define GPIO_OE 0x34           /* Output Data Enable */
-#define GPIO_CLEARDATAOUT 0x90
-#define GPIO_SETDATAOUT 0x94
-
-#define LED_USR0 (1 << 21)
-#define LED_USR1 (1 << 22)
-
-struct omap_gpio_bank *
-omap_gpio_bank_get(int gpio_nr)
-{
-       struct omap_gpio_bank *bank;
-       assert(gpio_nr >= 0 && gpio_nr <= 32 * 6);
-       bank = &omap_gpio_banks[gpio_nr / 32];
-       return bank;
-}
-
-int
-omap_gpio_claim(char *owner, int nr, struct gpio **gpio)
-{
-       log_trace(&log, "%s s claiming %d\n", owner, nr);
-
-       if (nr < 0 && nr >= 32 * 6) {
-               log_warn(&log, "%s is claiming unknown GPIO number %d\n", owner,
-                   nr);
-               return EINVAL;
-       }
-
-       if ( omap_gpio_bank_get(nr)->disabled == 1) {
-               log_warn(&log, "%s is claiming GPIO %d from disabled bank\n", owner,
-                   nr);
-               return EINVAL;
-       }
-
-       struct gpio *tmp = malloc(sizeof(struct gpio));
-       memset(tmp, 0, sizeof(*tmp));
-
-       tmp->nr = nr;
-       *gpio = tmp;
-       return OK;
-}
-
-int
-omap_gpio_pin_mode(struct gpio *gpio, int mode)
-{
-       struct omap_gpio_bank *bank;
-       assert(gpio != NULL);
-       gpio->mode = mode;
-
-       bank = omap_gpio_bank_get(gpio->nr);
-       log_debug(&log,
-           "pin mode bank %s, base address 0x%x -> register address (0x%x,0x%x,0x%x)\n",
-           bank->name, bank->base_address, bank->register_address, GPIO_OE,
-           bank->register_address + GPIO_OE);
-
-       if (mode == GPIO_MODE_OUTPUT) {
-               set32(bank->base_address + GPIO_OE, BIT(gpio->nr % 32), 0);
-       } else {
-               set32(bank->base_address + GPIO_OE, BIT(gpio->nr % 32),
-                   0xffffffff);
-       }
-       return 0;
-}
-
-int
-omap_gpio_set(struct gpio *gpio, int value)
-{
-       struct omap_gpio_bank *bank;
-       assert(gpio != NULL);
-       assert(gpio->nr >= 0 && gpio->nr <= 32 * 6);
-
-       bank = omap_gpio_bank_get(gpio->nr);
-       if (value == 1) {
-               write32(bank->base_address + GPIO_SETDATAOUT,
-                   BIT(gpio->nr % 32));
-       } else {
-               write32(bank->base_address + GPIO_CLEARDATAOUT,
-                   BIT(gpio->nr % 32));
-       }
-       return OK;
-}
-
-int
-omap_gpio_read(struct gpio *gpio, int *value)
-{
-       struct omap_gpio_bank *bank;
-       assert(gpio != NULL);
-       assert(gpio->nr >= 0 && gpio->nr <= 32 * 6);
-
-       bank = omap_gpio_bank_get(gpio->nr);
-       log_trace(&log, "mode=%d OU/IN 0x%08x 0x%08x\n", gpio->mode,
-           read32(bank->base_address + GPIO_DATAIN),
-           read32(bank->base_address + GPIO_DATAOUT));
-
-       if (gpio->mode == GPIO_MODE_INPUT) {
-               *value =
-                   (read32(bank->base_address +
-                       GPIO_DATAIN) >> (gpio->nr % 32)) & 0x1;
-       } else {
-               *value =
-                   (read32(bank->base_address +
-                       GPIO_DATAOUT) >> (gpio->nr % 32)) & 0x1;
-       }
-
-       return OK;
-}
-
-int
-omap_gpio_init(struct gpio_driver *drv)
-{
-       u32_t revision;
-       int i;
-       struct minix_mem_range mr;
-       struct omap_gpio_bank *bank;
-
-       bank = &omap_gpio_banks[0];
-       for (i = 0; omap_gpio_banks[i].name != NULL; i++) {
-               bank = &omap_gpio_banks[i];
-               mr.mr_base = bank->register_address;
-               mr.mr_limit = bank->register_address + 0x400;
-
-               if (sys_privctl(SELF, SYS_PRIV_ADD_MEM, &mr) != 0) {
-                       log_warn(&log,
-                           "Unable to request permission to map memory\n");
-                       return EPERM;   /* fixme */
-               }
-
-               /* Set the base address to use */
-               bank->base_address =
-                   (uint32_t) vm_map_phys(SELF,
-                   (void *) bank->register_address, 0x400);
-
-               if (bank->base_address == (uint32_t) MAP_FAILED) {
-                       log_warn(&log, "Unable to map GPIO memory\n");
-                       return EPERM;   /* fixme */
-               }
-
-               revision = 0;
-               revision = read32(bank->base_address + GPIO_REVISION);
-               /* test if we can access it */
-               if (GPIO_REVISION_MAJOR(revision) != 2
-                   || GPIO_REVISION_MINOR(revision) != 5) {
-                       log_warn(&log,
-                           "Failed to read the revision of GPIO bank %s.. disabling\n",
-                           bank->name);
-                       bank->disabled = 1;
-               }
-               bank->disabled = 0;
-               log_trace(&log, "bank %s mapped on 0x%x\n", bank->name,
-                   bank->base_address);
-       }
-
-/* the following code need to move to a power management/clock service */
-#define CM_BASE 0x48004000
-#define CM_FCLKEN_WKUP 0xC00
-#define CM_ICLKEN_WKUP 0xC10
-
-       u32_t base;
-       mr.mr_base = CM_BASE;
-       mr.mr_limit = CM_BASE + 0x1000;
-
-       if (sys_privctl(SELF, SYS_PRIV_ADD_MEM, &mr) != 0) {
-               log_warn(&log, "Unable to request permission to map memory\n");
-               return EPERM;
-       }
-
-       base = (uint32_t) vm_map_phys(SELF, (void *) CM_BASE, 0x1000);
-
-       if (base == (uint32_t) MAP_FAILED) {
-               log_warn(&log, "Unable to map GPIO memory\n");
-               return EPERM;
-       }
-
-       /* enable the interface and functional clock on GPIO bank 1 */
-       set32(base + CM_FCLKEN_WKUP, BIT(3), 0xffffffff);
-       set32(base + CM_ICLKEN_WKUP, BIT(3), 0xffffffff);
-/* end power management/clock service stuff */
-
-
-       drv->claim = omap_gpio_claim;
-       drv->pin_mode = omap_gpio_pin_mode;
-       drv->set = omap_gpio_set;
-       drv->read = omap_gpio_read;
-       return 0;
-}
index 154e940ace731b5f007195cede081d2c1f2363bf..9f8fe394eadd7760fab7fe8375f6dd63f3163996 100644 (file)
@@ -552,14 +552,23 @@ service mmc
                IRQCTL          # 19
        ;
        irq     83;             # IRQ 83 allowed
-       ;
 };
 
 service gpio
 {
        system
                PRIVCTL         #  4
+               IRQCTL          # 19
        ;
+       irq     
+               29      # GPIO module 1
+               30      # GPIO module 2
+               31      # GPIO module 3 
+               32      # GPIO module 4 
+               33      # GPIO module 5 
+               34      # GPIO module 6
+       ;               
+
 };
 
 service vbox
index 4aaea7319ba22c3eb96124aab060598560681b7b..b72b9814391ef92e3d4a6246a5f14a416dddec1d 100644 (file)
@@ -10,10 +10,10 @@ INCS+=      acpi.h audio_fw.h bitmap.h \
        config.h const.h cpufeature.h crtso.h \
        debug.h devio.h devman.h dmap.h \
        driver.h drivers.h drvlib.h ds.h \
-       endpoint.h fslib.h gcov.h hash.h \
+       endpoint.h fslib.h gpio.h gcov.h hash.h \
        hgfs.h ioctl.h input.h ipc.h ipcconst.h \
-       keymap.h limits.h mount.h mthread.h minlib.h \
-       netdriver.h optset.h partition.h portio.h \
+       keymap.h limits.h log.h mmio.h mount.h mthread.h minlib.h \
+       netdriver.h optset.h padconf.h partition.h portio.h \
        priv.h procfs.h profile.h queryparam.h \
        rs.h safecopies.h sched.h sef.h sffs.h \
        sound.h spin.h sys_config.h sysinfo.h \
diff --git a/include/minix/gpio.h b/include/minix/gpio.h
new file mode 100644 (file)
index 0000000..d07e9f3
--- /dev/null
@@ -0,0 +1,34 @@
+#ifndef __INCLUDE_GPIO_H__
+#define __INCLUDE_GPIO_H__
+
+struct gpio
+{
+       int nr;                 /* GPIO number */
+       int mode;               /* GPIO mode (input=0/output=1) */
+};
+
+#define GPIO_MODE_INPUT 0
+#define GPIO_MODE_OUTPUT 1
+
+int gpio_init();
+
+/* request access to a gpio */
+int gpio_claim(char *owner, int nr, struct gpio **gpio);
+
+/* Configure the GPIO for a certain purpose */
+int gpio_pin_mode(struct gpio *gpio, int mode);
+
+/* Set the value for a GPIO */
+int gpio_set(struct gpio *gpio, int value);
+
+/* Read the current value of the GPIO */
+int gpio_read(struct gpio *gpio, int *value);
+
+/* Read and clear the value interrupt value of the GPIO */
+int gpio_intr_read(struct gpio *gpio, int *value);
+
+/* Interrupt hook */
+int gpio_intr_message(message * m);
+
+int gpio_release();
+#endif /* __INCLUDE_GPIO_H__ */
similarity index 97%
rename from drivers/gpio/log.h
rename to include/minix/log.h
index b3d0c17689b3ea21257e750d4402957a32717b8e..a68f36b7c68c48636cdf7838e73bf73a22deec70 100644 (file)
@@ -4,6 +4,8 @@
  * Simple logging functions
  */
 
+#include <stdarg.h>
+
 /*
  * LEVEL_NONE  do not log anything.
  * LEVEL_WARN  Information that needs to be known.
@@ -41,7 +43,10 @@ static const char *level_string[5] = {
  * requested log level is debug or trace the method , file and line number will
  * be printed to the steam.
  */
-struct log { const char *name; int log_level;
+struct log
+{
+       const char *name;
+       int log_level;
 
        /* the logging function itself */
        void (*log_func) (struct log * driver,
similarity index 90%
rename from drivers/gpio/mmio.h
rename to include/minix/mmio.h
index f40262a967ab5459721bad9b45a99fab52590a9e..8c23a352006c82344c88b57769fdd081e08f3e8e 100644 (file)
@@ -1,3 +1,6 @@
+#ifndef __MMIO_H__
+#define __MMIO_H__
+
 #define REG(x)(*((volatile uint32_t *)(x)))
 #define BIT(x)(0x1 << x)
 
@@ -12,7 +15,6 @@ write32(uint32_t address, uint32_t value)
 static inline uint32_t
 read32(uint32_t address)
 {
-
        return REG(address);
 }
 
@@ -28,3 +30,4 @@ set32(uint32_t address, uint32_t mask, uint32_t value)
        val |= (value & mask);
        write32(address, val);
 }
+#endif /* __MMIO_H__ */
diff --git a/include/minix/padconf.h b/include/minix/padconf.h
new file mode 100644 (file)
index 0000000..8d8f7cc
--- /dev/null
@@ -0,0 +1,184 @@
+#ifndef __PADCONF_H__
+#define __PADCONF_H__
+
+#define PADCONF_REGISTERS_BASE 0x48002030
+
+#define PADCONF_MUXMODE(X)  (X & 0x7)  /* mode 1 til 7 [2:0] */
+#define PADCONF_PULL_MODE(X)  ((X & 0x3) << 3) /* 2 bits[4:3] */
+#define PADCONF_PULL_MODE_PD_DIS PADCONF_PULL_MODE(0)  /* pull down disabled */
+#define PADCONF_PULL_MODE_PD_EN PADCONF_PULL_MODE(1)   /* pull down enabled */
+#define PADCONF_PULL_MODE_PU_DIS PADCONF_PULL_MODE(2)  /* pull up enabled */
+#define PADCONF_PULL_MODE_PU_EN PADCONF_PULL_MODE(3)   /* pull up enabled */
+#define PADCONF_INPUT_ENABLE(X)  ((X & 0x1) << 8)      /* 1 bits[8] */
+#define PADCONF_OFF_MODE(X)  ((X & 0xFE) << 9) /* 5 bits[13:9] */
+
+/* padconf pin definitions */
+#define CONTROL_PADCONF_SDRC_D0 (0x00000000)
+#define CONTROL_PADCONF_SDRC_D2 (0x00000004)
+#define CONTROL_PADCONF_SDRC_D4 (0x00000008)
+#define CONTROL_PADCONF_SDRC_D6 (0x0000000C)
+#define CONTROL_PADCONF_SDRC_D8 (0x00000010)
+#define CONTROL_PADCONF_SDRC_D10 (0x00000014)
+#define CONTROL_PADCONF_SDRC_D12 (0x00000018)
+#define CONTROL_PADCONF_SDRC_D14 (0x0000001C)
+#define CONTROL_PADCONF_SDRC_D16 (0x00000020)
+#define CONTROL_PADCONF_SDRC_D18 (0x00000024)
+#define CONTROL_PADCONF_SDRC_D20 (0x00000028)
+#define CONTROL_PADCONF_SDRC_D22 (0x0000002C)
+#define CONTROL_PADCONF_SDRC_D24 (0x00000030)
+#define CONTROL_PADCONF_SDRC_D26 (0x00000034)
+#define CONTROL_PADCONF_SDRC_D28 (0x00000038)
+#define CONTROL_PADCONF_SDRC_D30 (0x0000003C)
+#define CONTROL_PADCONF_SDRC_CLK (0x00000040)
+#define CONTROL_PADCONF_SDRC_DQS1 (0x00000044)
+#define CONTROL_PADCONF_SDRC_DQS3 (0x00000048)
+#define CONTROL_PADCONF_GPMC_A2 (0x0000004C)
+#define CONTROL_PADCONF_GPMC_A4 (0x00000050)
+#define CONTROL_PADCONF_GPMC_A6 (0x00000054)
+#define CONTROL_PADCONF_GPMC_A8 (0x00000058)
+#define CONTROL_PADCONF_GPMC_A10 (0x0000005C)
+#define CONTROL_PADCONF_GPMC_D1 (0x00000060)
+#define CONTROL_PADCONF_GPMC_D3 (0x00000064)
+#define CONTROL_PADCONF_GPMC_D5 (0x00000068)
+#define CONTROL_PADCONF_GPMC_D7 (0x0000006C)
+#define CONTROL_PADCONF_GPMC_D9 (0x00000070)
+#define CONTROL_PADCONF_GPMC_D11 (0x00000074)
+#define CONTROL_PADCONF_GPMC_D13 (0x00000078)
+#define CONTROL_PADCONF_GPMC_D15 (0x0000007C)
+#define CONTROL_PADCONF_GPMC_NCS1 (0x00000080)
+#define CONTROL_PADCONF_GPMC_NCS3 (0x00000084)
+#define CONTROL_PADCONF_GPMC_NCS5 (0x00000088)
+#define CONTROL_PADCONF_GPMC_NCS7 (0x0000008C)
+#define CONTROL_PADCONF_GPMC_NADV_ALE (0x00000090)
+#define CONTROL_PADCONF_GPMC_NWE (0x00000094)
+#define CONTROL_PADCONF_GPMC_NBE1 (0x00000098)
+#define CONTROL_PADCONF_GPMC_WAIT0 (0x0000009C)
+#define CONTROL_PADCONF_GPMC_WAIT2 (0x000000A0)
+#define CONTROL_PADCONF_DSS_PCLK (0x000000A4)
+#define CONTROL_PADCONF_DSS_VSYNC (0x000000A8)
+#define CONTROL_PADCONF_DSS_DATA0 (0x000000AC)
+#define CONTROL_PADCONF_DSS_DATA2 (0x000000B0)
+#define CONTROL_PADCONF_DSS_DATA4 (0x000000B4)
+#define CONTROL_PADCONF_DSS_DATA6 (0x000000B8)
+#define CONTROL_PADCONF_DSS_DATA8 (0x000000BC)
+#define CONTROL_PADCONF_DSS_DATA10 (0x000000C0)
+#define CONTROL_PADCONF_DSS_DATA12 (0x000000C4)
+#define CONTROL_PADCONF_DSS_DATA14 (0x000000C8)
+#define CONTROL_PADCONF_DSS_DATA16 (0x000000CC)
+#define CONTROL_PADCONF_DSS_DATA18 (0x000000D0)
+#define CONTROL_PADCONF_DSS_DATA20 (0x000000D4)
+#define CONTROL_PADCONF_DSS_DATA22 (0x000000D8)
+#define CONTROL_PADCONF_CAM_HS (0x000000DC)
+#define CONTROL_PADCONF_CAM_XCLKA (0x000000E0)
+#define CONTROL_PADCONF_CAM_FLD (0x000000E4)
+#define CONTROL_PADCONF_CAM_D1 (0x000000E8)
+#define CONTROL_PADCONF_CAM_D3 (0x000000EC)
+#define CONTROL_PADCONF_CAM_D5 (0x000000F0)
+#define CONTROL_PADCONF_CAM_D7 (0x000000F4)
+#define CONTROL_PADCONF_CAM_D9 (0x000000F8)
+#define CONTROL_PADCONF_CAM_D11 (0x000000FC)
+#define CONTROL_PADCONF_CAM_WEN (0x00000100)
+#define CONTROL_PADCONF_CSI2_DX0 (0x00000104)
+#define CONTROL_PADCONF_CSI2_DX1 (0x00000108)
+#define CONTROL_PADCONF_MCBSP2_FSX (0x0000010C)
+#define CONTROL_PADCONF_MCBSP2_DR (0x00000110)
+#define CONTROL_PADCONF_MMC1_CLK (0x00000114)
+#define CONTROL_PADCONF_MMC1_DAT0 (0x00000118)
+#define CONTROL_PADCONF_MMC1_DAT2 (0x0000011C)
+#define CONTROL_PADCONF_MMC2_CLK (0x00000128)
+#define CONTROL_PADCONF_MMC2_DAT0 (0x0000012C)
+#define CONTROL_PADCONF_MMC2_DAT2 (0x00000130)
+#define CONTROL_PADCONF_MMC2_DAT4 (0x00000134)
+#define CONTROL_PADCONF_MMC2_DAT6 (0x00000138)
+#define CONTROL_PADCONF_MCBSP3_DX (0x0000013C)
+#define CONTROL_PADCONF_MCBSP3_CLKX (0x00000140)
+#define CONTROL_PADCONF_UART2_CTS (0x00000144)
+#define CONTROL_PADCONF_UART2_TX (0x00000148)
+#define CONTROL_PADCONF_UART1_TX (0x0000014C)
+#define CONTROL_PADCONF_UART1_CTS (0x00000150)
+#define CONTROL_PADCONF_MCBSP4_CLKX (0x00000154)
+#define CONTROL_PADCONF_MCBSP4_DX (0x00000158)
+#define CONTROL_PADCONF_MCBSP1_CLKR (0x0000015C)
+#define CONTROL_PADCONF_MCBSP1_DX (0x00000160)
+#define CONTROL_PADCONF_MCBSP_CLKS (0x00000164)
+#define CONTROL_PADCONF_MCBSP1_CLKX (0x00000168)
+#define CONTROL_PADCONF_UART3_RTS_SD (0x0000016C)
+#define CONTROL_PADCONF_UART3_TX_IRTX (0x00000170)
+#define CONTROL_PADCONF_HSUSB0_STP (0x00000174)
+#define CONTROL_PADCONF_HSUSB0_NXT (0x00000178)
+#define CONTROL_PADCONF_HSUSB0_DATA1 (0x0000017C)
+#define CONTROL_PADCONF_HSUSB0_DATA3 (0x00000180)
+#define CONTROL_PADCONF_HSUSB0_DATA5 (0x00000184)
+#define CONTROL_PADCONF_HSUSB0_DATA7 (0x00000188)
+#define CONTROL_PADCONF_I2C1_SDA (0x0000018C)
+#define CONTROL_PADCONF_I2C2_SDA (0x00000190)
+#define CONTROL_PADCONF_I2C3_SDA (0x00000194)
+#define CONTROL_PADCONF_MCSPI1_CLK (0x00000198)
+#define CONTROL_PADCONF_MCSPI1_SOMI (0x0000019C)
+#define CONTROL_PADCONF_MCSPI1_CS1 (0x000001A0)
+#define CONTROL_PADCONF_MCSPI1_CS3 (0x000001A4)
+#define CONTROL_PADCONF_MCSPI2_SIMO (0x000001A8)
+#define CONTROL_PADCONF_MCSPI2_CS0 (0x000001AC)
+#define CONTROL_PADCONF_SYS_NIRQ (0x000001B0)
+#define CONTROL_PADCONF_SAD2D_MCAD0 (0x000001B4)
+#define CONTROL_PADCONF_SAD2D_MCAD2 (0x000001B8)
+#define CONTROL_PADCONF_SAD2D_MCAD4 (0x000001BC)
+#define CONTROL_PADCONF_SAD2D_MCAD6 (0x000001C0)
+#define CONTROL_PADCONF_SAD2D_MCAD8 (0x000001C4)
+#define CONTROL_PADCONF_SAD2D_MCAD10 (0x000001C8)
+#define CONTROL_PADCONF_SAD2D_MCAD12 (0x000001CC)
+#define CONTROL_PADCONF_SAD2D_MCAD14 (0x000001D0)
+#define CONTROL_PADCONF_SAD2D_MCAD16 (0x000001D4)
+#define CONTROL_PADCONF_SAD2D_MCAD18 (0x000001D8)
+#define CONTROL_PADCONF_SAD2D_MCAD20 (0x000001DC)
+#define CONTROL_PADCONF_SAD2D_MCAD22 (0x000001E0)
+#define CONTROL_PADCONF_SAD2D_MCAD24 (0x000001E4)
+#define CONTROL_PADCONF_SAD2D_MCAD26 (0x000001E8)
+#define CONTROL_PADCONF_SAD2D_MCAD28 (0x000001EC)
+#define CONTROL_PADCONF_SAD2D_MCAD30 (0x000001F0)
+#define CONTROL_PADCONF_SAD2D_MCAD32 (0x000001F4)
+#define CONTROL_PADCONF_SAD2D_MCAD34 (0x000001F8)
+#define CONTROL_PADCONF_SAD2D_MCAD36 (0x000001FC)
+#define CONTROL_PADCONF_SAD2D_NRESPWRON (0x00000200)
+#define CONTROL_PADCONF_SAD2D_ARMNIRQ (0x00000204)
+#define CONTROL_PADCONF_SAD2D_SPINT (0x00000208)
+#define CONTROL_PADCONF_SAD2D_DMAREQ0 (0x0000020C)
+#define CONTROL_PADCONF_SAD2D_DMAREQ2 (0x00000210)
+#define CONTROL_PADCONF_SAD2D_NTRST (0x00000214)
+#define CONTROL_PADCONF_SAD2D_TDO (0x00000218)
+#define CONTROL_PADCONF_SAD2D_TCK (0x0000021C)
+#define CONTROL_PADCONF_SAD2D_MSTDBY (0x00000220)
+#define CONTROL_PADCONF_SAD2D_IDLEACK (0x00000224)
+#define CONTROL_PADCONF_SAD2D_SWRITE (0x00000228)
+#define CONTROL_PADCONF_SAD2D_SREAD (0x0000022C)
+#define CONTROL_PADCONF_SAD2D_SBUSFLAG (0x00000230)
+#define CONTROL_PADCONF_SDRC_CKE1 (0x00000234)
+#define CONTROL_PADCONF_SDRC_BA0 (0x00000570)
+#define CONTROL_PADCONF_SDRC_A0 (0x00000574)
+#define CONTROL_PADCONF_SDRC_A2 (0x00000578)
+#define CONTROL_PADCONF_SDRC_A4 (0x0000057C)
+#define CONTROL_PADCONF_SDRC_A6 (0x00000580)
+#define CONTROL_PADCONF_SDRC_A8 (0x00000584)
+#define CONTROL_PADCONF_SDRC_A10 (0x00000588)
+#define CONTROL_PADCONF_SDRC_A12 (0x0000058C)
+#define CONTROL_PADCONF_SDRC_A14 (0x00000590)
+#define CONTROL_PADCONF_SDRC_NCS1 (0x00000594)
+#define CONTROL_PADCONF_SDRC_NRAS (0x00000598)
+#define CONTROL_PADCONF_SDRC_NWE (0x0000059C)
+#define CONTROL_PADCONF_SDRC_DM1 (0x000005A0)
+#define CONTROL_PADCONF_SDRC_DM3 (0x000005A4)
+#define CONTROL_PADCONF_ETK_CLK (0x000005A8)
+#define CONTROL_PADCONF_ETK_D0 (0x000005AC)
+#define CONTROL_PADCONF_ETK_D2 (0x000005B0)
+#define CONTROL_PADCONF_ETK_D4 (0x000005B4)
+#define CONTROL_PADCONF_ETK_D6 (0x000005B8)
+#define CONTROL_PADCONF_ETK_D8 (0x000005BC)
+#define CONTROL_PADCONF_ETK_D10 (0x000005C0)
+#define CONTROL_PADCONF_ETK_D12 (0x000005C4)
+#define CONTROL_PADCONF_ETK_D14 (0x000005C8)
+
+int padconf_init();
+int padconf_set(u32_t padconf, u32_t mask, u32_t value);
+int padconf_release();
+
+#endif /* __PADCONF_H__ */
index da4349856a1f59d3b4c385e1295ad76791f46c89..92ab849418a39cbf6b13357d6a900a2593cb3fda 100644 (file)
@@ -45,10 +45,14 @@ SUBDIR+= libcompat_minix libblockdriver libchardriver     \
        libutil libbz2 libprop \
        libnetsock libpuffs libsffs
 
-.if (${MACHINE} == "i386")
+.if (${MACHINE_ARCH} == "i386")
 SUBDIR += libvassert libhgfs libvboxfs libvirtio
 .endif
 
+.if (${MACHINE_ARCH} == "earm")
+SUBDIR += libgpio libpadconf
+.endif
+
 .if (${MKRUMP} != "no")
 SUBDIR+=       librumpclient
 .endif
diff --git a/lib/libgpio/Makefile b/lib/libgpio/Makefile
new file mode 100644 (file)
index 0000000..4e27eb3
--- /dev/null
@@ -0,0 +1,10 @@
+# Makefile for libmthread
+
+CPPFLAGS+=-O -D_MINIX -D_POSIX_SOURCE -Wall -Werror -D_SYSTEM
+
+LIB=   gpio
+
+SRCS=  \
+       gpio_omap.c  clkconf.c
+
+.include <bsd.lib.mk>
diff --git a/lib/libgpio/clkconf.c b/lib/libgpio/clkconf.c
new file mode 100644 (file)
index 0000000..7fb73cd
--- /dev/null
@@ -0,0 +1,78 @@
+/* kernel headers */
+#include <minix/syslib.h>
+#include <minix/drvlib.h>
+#include <minix/log.h>
+#include <minix/mmio.h>
+
+/* system headers */
+#include <sys/mman.h>
+#include <sys/types.h>
+
+/* usr headers */
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+
+/* local headers */
+#include "clkconf.h"
+
+/* used for logging */
+static struct log log = {
+       .name = "omap_clkconf",
+       .log_level = LEVEL_INFO,
+       .log_func = default_log
+};
+
+#define CM_BASE 0x48004000
+static u32_t base = 0;
+static u32_t use_count = 0;
+
+int
+clkconf_init()
+{
+       use_count++;
+
+       if (base != 0) {
+               /* when used in a library we can't guaranty we only call this
+                * method once */
+               log_trace(&log, "Called %d times\n", use_count);
+               return OK;
+       }
+       struct minix_mem_range mr;
+       mr.mr_base = CM_BASE;
+       mr.mr_limit = CM_BASE + 0x1000;
+
+       if (sys_privctl(SELF, SYS_PRIV_ADD_MEM, &mr) != 0) {
+               log_warn(&log, "Unable to request permission to map memory\n");
+               return EPERM;
+       }
+
+       base = (uint32_t) vm_map_phys(SELF, (void *) CM_BASE, 0x1000);
+
+       if (base == (uint32_t) MAP_FAILED) {
+               log_warn(&log, "Unable to map GPIO memory\n");
+               return EPERM;
+       }
+       return OK;
+}
+
+int
+clkconf_set(u32_t clk, u32_t mask, u32_t value)
+{
+       set32(base + clk, mask, value);
+       return OK;
+}
+
+int
+clkconf_release()
+{
+       assert(use_count > 0);
+       use_count--;
+       if (use_count == 0) {
+               vm_unmap_phys(SELF, (void *) base, 0x1000);
+       }
+       return OK;
+}
diff --git a/lib/libgpio/clkconf.h b/lib/libgpio/clkconf.h
new file mode 100644 (file)
index 0000000..deba8a2
--- /dev/null
@@ -0,0 +1,7 @@
+/* Clock configuration */
+#define CM_FCLKEN_WKUP 0xC00
+#define CM_ICLKEN_WKUP 0xC10
+
+int clkconf_init();
+int clkconf_set(u32_t clk, u32_t mask, u32_t value);
+int clkconf_release();
diff --git a/lib/libgpio/gpio_omap.c b/lib/libgpio/gpio_omap.c
new file mode 100644 (file)
index 0000000..dcfc10a
--- /dev/null
@@ -0,0 +1,447 @@
+/* kernel headers */
+#include <minix/syslib.h>
+#include <minix/drvlib.h>
+#include <minix/log.h>
+#include <minix/mmio.h>
+#include <minix/gpio.h>
+
+/* system headers */
+#include <sys/mman.h>
+#include <sys/types.h>
+
+/* usr headers */
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+
+#include "clkconf.h"
+
+/* local headers */
+
+/* used for logging */
+static struct log log = {
+       .name = "gpio_omap",
+       .log_level = LEVEL_INFO,
+       .log_func = default_log
+};
+
+struct gpio_driver
+{
+       /* request access to a gpio */
+       int (*claim) (char *owner, int nr, struct gpio ** gpio);
+
+       /* Configure the GPIO for a certain purpose */
+       int (*pin_mode) (struct gpio * gpio, int mode);
+
+       /* Set the value for a GPIO */
+       int (*set) (struct gpio * gpio, int value);
+
+       /* Read the current value of the GPIO */
+       int (*read) (struct gpio * gpio, int *value);
+
+       /* Read and clear the value interrupt value of the GPIO */
+       int (*intr_read) (struct gpio * gpio, int *value);
+
+       /* Interrupt hook */
+       int (*message_hook) (message * m);
+};
+
+static struct gpio_driver drv;
+
+struct omap_gpio_bank
+{
+       const char *name;
+       uint32_t register_address;
+       uint32_t irq_nr;        /* irq number */
+       uint32_t base_address;
+       int32_t disabled;
+       int irq_id;             /* orignhal hook id??? */
+       int irq_hook_id;        /* hook id */
+       uint32_t inter_values;  /* values when the interrupt was called */
+};
+
+#define GPIO1_BASE (0x48310000)
+#define GPIO2_BASE (0x49050000)
+#define GPIO3_BASE (0x49052000)
+#define GPIO4_BASE (0x49054000)
+#define GPIO5_BASE (0x49056000)
+#define GPIO6_BASE (0x49058000)
+#define GPIO1_IRQ  29          /* GPIO module 1 */
+#define GPIO2_IRQ  30          /* GPIO module 2 */
+#define GPIO3_IRQ  31          /* GPIO module 3 */
+#define GPIO4_IRQ  32          /* GPIO module 4 */
+#define GPIO5_IRQ  33          /* GPIO module 5 */
+#define GPIO6_IRQ  34          /* GPIO module 6 */
+#define GPIO1_IRQ_HOOK_ID 0
+#define GPIO2_IRQ_HOOK_ID 1
+#define GPIO3_IRQ_HOOK_ID 2
+#define GPIO4_IRQ_HOOK_ID 3
+#define GPIO5_IRQ_HOOK_ID 4
+#define GPIO6_IRQ_HOOK_ID 5
+
+#define GPIO_IRQSTATUS1 (0x18)
+#define GPIO_IRQENABLE1 (0x01C)
+#define GPIO_DATAOUT (0x3c)
+#define GPIO_DATAIN (0x38)
+#define GPIO_OE    (0x34)      /* Output Data Enable */
+#define GPIO_RISINGDETECT1 (0x048)
+#define GPIO_FALLINGDETECT1 (0x04c)
+#define GPIO_CLEARDATAOUT (0x90)
+#define GPIO_SETDATAOUT (0x94)
+
+static struct omap_gpio_bank omap_gpio_banks[] = {
+       {
+                   .name = "GPIO1",
+                   .register_address = GPIO1_BASE,
+                   .irq_nr = GPIO1_IRQ,
+                   .base_address = 0,
+                   .disabled = 0,
+                   .irq_id = GPIO1_IRQ_HOOK_ID,
+                   .irq_hook_id = GPIO1_IRQ_HOOK_ID,
+           },
+       {
+                   .name = "GPIO2",
+                   .register_address = GPIO2_BASE,
+                   .irq_nr = GPIO2_IRQ,
+                   .base_address = 0,
+                   .disabled = 0,
+                   .irq_id = GPIO2_IRQ_HOOK_ID,
+                   .irq_hook_id = GPIO2_IRQ_HOOK_ID,
+           },
+       {
+                   .name = "GPIO3",
+                   .register_address = GPIO3_BASE,
+                   .irq_nr = GPIO3_IRQ,
+                   .base_address = 0,
+                   .disabled = 0,
+                   .irq_id = GPIO3_IRQ_HOOK_ID,
+                   .irq_hook_id = GPIO3_IRQ_HOOK_ID,
+           },
+       {
+                   .name = "GPIO4",
+                   .register_address = GPIO4_BASE,
+                   .irq_nr = GPIO4_IRQ,
+                   .base_address = 0,
+                   .disabled = 0,
+                   .irq_id = GPIO4_IRQ_HOOK_ID,
+                   .irq_hook_id = GPIO4_IRQ_HOOK_ID,
+           },
+       {
+                   .name = "GPIO5",
+                   .register_address = GPIO5_BASE,
+                   .irq_nr = GPIO5_IRQ,
+                   .base_address = 0,
+                   .disabled = 0,
+                   .irq_id = GPIO5_IRQ_HOOK_ID,
+                   .irq_hook_id = GPIO5_IRQ_HOOK_ID,
+           },
+       {
+                   .name = "GPIO6",
+                   .register_address = GPIO6_BASE,
+                   .irq_nr = GPIO6_IRQ,
+                   .base_address = 0,
+                   .disabled = 0,
+                   .irq_id = GPIO6_IRQ_HOOK_ID,
+                   .irq_hook_id = GPIO6_IRQ_HOOK_ID,
+           },
+       {NULL, 0, 0}
+};
+
+#define GPIO_REVISION 0x00
+#define GPIO_REVISION_MAJOR(X) ((X & 0xF0) >> 4)
+#define GPIO_REVISION_MINOR(X) (X & 0XF)
+
+struct omap_gpio_bank *
+omap_gpio_bank_get(int gpio_nr)
+{
+       struct omap_gpio_bank *bank;
+       assert(gpio_nr >= 0 && gpio_nr <= 32 * 6);
+       bank = &omap_gpio_banks[gpio_nr / 32];
+       return bank;
+}
+
+int
+omap_gpio_claim(char *owner, int nr, struct gpio **gpio)
+{
+       log_trace(&log, "%s s claiming %d\n", owner, nr);
+
+       if (nr < 0 && nr >= 32 * 6) {
+               log_warn(&log, "%s is claiming unknown GPIO number %d\n",
+                   owner, nr);
+               return EINVAL;
+       }
+
+       if (omap_gpio_bank_get(nr)->disabled == 1) {
+               log_warn(&log, "%s is claiming GPIO %d from disabled bank\n",
+                   owner, nr);
+               return EINVAL;
+       }
+
+       struct gpio *tmp = malloc(sizeof(struct gpio));
+       memset(tmp, 0, sizeof(*tmp));
+
+       tmp->nr = nr;
+       *gpio = tmp;
+       return OK;
+}
+
+int
+omap_gpio_pin_mode(struct gpio *gpio, int mode)
+{
+       struct omap_gpio_bank *bank;
+       assert(gpio != NULL);
+       gpio->mode = mode;
+
+       bank = omap_gpio_bank_get(gpio->nr);
+       log_debug(&log,
+           "pin mode bank %s, base address 0x%x -> register address (0x%x,0x%x,0x%x)\n",
+           bank->name, bank->base_address, bank->register_address, GPIO_OE,
+           bank->register_address + GPIO_OE);
+
+       if (mode == GPIO_MODE_OUTPUT) {
+               set32(bank->base_address + GPIO_OE, BIT(gpio->nr % 32), 0);
+       } else {
+               set32(bank->base_address + GPIO_FALLINGDETECT1,
+                   BIT(gpio->nr % 32), 0xffffffff);
+               set32(bank->base_address + GPIO_IRQENABLE1, BIT(gpio->nr % 32),
+                   0xffffffff);
+               set32(bank->base_address + GPIO_OE, BIT(gpio->nr % 32),
+                   0xffffffff);
+       }
+       return 0;
+}
+
+int
+omap_gpio_set(struct gpio *gpio, int value)
+{
+       struct omap_gpio_bank *bank;
+       assert(gpio != NULL);
+       assert(gpio->nr >= 0 && gpio->nr <= 32 * 6);
+
+       bank = omap_gpio_bank_get(gpio->nr);
+       if (value == 1) {
+               write32(bank->base_address + GPIO_SETDATAOUT,
+                   BIT(gpio->nr % 32));
+       } else {
+               write32(bank->base_address + GPIO_CLEARDATAOUT,
+                   BIT(gpio->nr % 32));
+       }
+       return OK;
+}
+
+int
+omap_gpio_read(struct gpio *gpio, int *value)
+{
+       struct omap_gpio_bank *bank;
+       assert(gpio != NULL);
+       assert(gpio->nr >= 0 && gpio->nr <= 32 * 6);
+
+       bank = omap_gpio_bank_get(gpio->nr);
+       log_trace(&log, "mode=%d OU/IN 0x%08x 0x%08x\n", gpio->mode,
+           read32(bank->base_address + GPIO_DATAIN),
+           read32(bank->base_address + GPIO_DATAOUT));
+
+       if (gpio->mode == GPIO_MODE_INPUT) {
+               *value =
+                   (read32(bank->base_address +
+                       GPIO_DATAIN) >> (gpio->nr % 32)) & 0x1;
+       } else {
+               *value =
+                   (read32(bank->base_address +
+                       GPIO_DATAOUT) >> (gpio->nr % 32)) & 0x1;
+       }
+
+       return OK;
+}
+
+int
+omap_gpio_intr_read(struct gpio *gpio, int *value)
+{
+       struct omap_gpio_bank *bank;
+       assert(gpio != NULL);
+       assert(gpio->nr >= 0 && gpio->nr <= 32 * 6);
+
+       bank = omap_gpio_bank_get(gpio->nr);
+       /* TODO: check if interrupt where enabled?? */
+
+       *value = (bank->inter_values >> (gpio->nr % 32)) & 0x1;
+       /* clear the data */
+       bank->inter_values &= ~(1 << (gpio->nr % 32));
+
+       return OK;
+}
+
+int
+omap_message_hook(message * m)
+{
+       unsigned long irq_set, i;
+       struct omap_gpio_bank *bank;
+
+       switch (_ENDPOINT_P(m->m_source)) {
+       case HARDWARE:
+               /* Hardware interrupt return a "set" if pending interrupts */
+               irq_set = m->NOTIFY_ARG;
+               log_debug(&log, "HW message 0X%08x\n", m->NOTIFY_ARG);
+               bank = &omap_gpio_banks[0];
+               for (i = 0; omap_gpio_banks[i].name != NULL; i++) {
+                       bank = &omap_gpio_banks[i];
+
+                       if (irq_set & (1 << (bank->irq_id))) {
+                               log_trace(&log, "Interrupt for bank %s\n",
+                                   bank->name);
+                               bank->inter_values |=
+                                   read32(bank->base_address +
+                                   GPIO_IRQSTATUS1);
+                               /* clear the interrupts */
+                               write32(bank->base_address + GPIO_IRQSTATUS1,
+                                   0xffffffff);
+                               if (sys_irqenable(&bank->irq_hook_id) != OK) {
+                                       log_warn(&log,
+                                           "Failed to enable irq for bank %s\n",
+                                           bank->name);
+                               }
+                       }
+               }
+               return OK;
+       default:
+               log_warn(&log, "Unknown message\n");
+               break;
+       }
+       return OK;
+}
+
+int
+omap_gpio_init(struct gpio_driver *drv)
+{
+       u32_t revision;
+       int i;
+       struct minix_mem_range mr;
+       struct omap_gpio_bank *bank;
+
+       bank = &omap_gpio_banks[0];
+       for (i = 0; omap_gpio_banks[i].name != NULL; i++) {
+               bank = &omap_gpio_banks[i];
+               mr.mr_base = bank->register_address;
+               mr.mr_limit = bank->register_address + 0x400;
+
+               if (sys_privctl(SELF, SYS_PRIV_ADD_MEM, &mr) != 0) {
+                       log_warn(&log,
+                           "Unable to request permission to map memory\n");
+                       return EPERM;   /* fixme */
+               }
+
+               /* Set the base address to use */
+               bank->base_address =
+                   (uint32_t) vm_map_phys(SELF,
+                   (void *) bank->register_address, 0x400);
+
+               if (bank->base_address == (uint32_t) MAP_FAILED) {
+                       log_warn(&log, "Unable to map GPIO memory\n");
+                       return EPERM;   /* fixme */
+               }
+
+               revision = 0;
+               revision = read32(bank->base_address + GPIO_REVISION);
+               /* test if we can access it */
+               if (GPIO_REVISION_MAJOR(revision) != 2
+                   || GPIO_REVISION_MINOR(revision) != 5) {
+                       log_warn(&log,
+                           "Failed to read the revision of GPIO bank %s.. disabling\n",
+                           bank->name);
+                       bank->disabled = 1;
+               }
+               bank->disabled = 0;
+
+               if (sys_irqsetpolicy(bank->irq_nr, 0,
+                       &bank->irq_hook_id) != OK) {
+                       log_warn(&log,
+                           "GPIO: couldn't set IRQ policy for bank %s\n",
+                           bank->name);
+                       continue;
+               };
+               if (bank->irq_id != bank->irq_hook_id) {
+                       log_debug(&log, "requested id %d but got id %d\n",
+                           bank->irq_id, bank->irq_hook_id);
+               }
+               if (sys_irqenable(&bank->irq_hook_id) != OK) {
+                       log_warn(&log,
+                           "GPIO: couldn't enable interrupt for %s\n",
+                           bank->name);
+               };
+               log_trace(&log, "bank %s mapped on 0x%x with irq hook id %d\n",
+                   bank->name, bank->base_address, bank->irq_hook_id);
+
+       };
+
+       clkconf_init();
+       /* enable the interface and functional clock on GPIO bank 1 */
+       clkconf_set(CM_FCLKEN_WKUP, BIT(3), 0xffffffff);
+       clkconf_set(CM_ICLKEN_WKUP, BIT(3), 0xffffffff);
+       clkconf_release();
+
+
+       drv->claim = omap_gpio_claim;
+       drv->pin_mode = omap_gpio_pin_mode;
+       drv->set = omap_gpio_set;
+       drv->read = omap_gpio_read;
+       drv->intr_read = omap_gpio_intr_read;
+       drv->message_hook = omap_message_hook;
+       return 0;
+}
+
+int
+gpio_init()
+{
+       return omap_gpio_init(&drv);
+}
+
+/* request access to a gpio */
+int
+gpio_claim(char *owner, int nr, struct gpio **gpio)
+{
+       return drv.claim(owner, nr, gpio);
+}
+
+/* Configure the GPIO for a certain purpose */
+int
+gpio_pin_mode(struct gpio *gpio, int mode)
+{
+       return drv.pin_mode(gpio, mode);
+}
+
+/* Set the value for a GPIO */
+int
+gpio_set(struct gpio *gpio, int value)
+{
+       return drv.set(gpio, value);
+}
+
+/* Read the current value of the GPIO */
+int
+gpio_read(struct gpio *gpio, int *value)
+{
+       return drv.read(gpio, value);
+}
+
+/* Read and clear the value interrupt value of the GPIO */
+int
+gpio_intr_read(struct gpio *gpio, int *value)
+{
+       return drv.intr_read(gpio, value);
+}
+
+/* Interrupt hook */
+int
+gpio_intr_message(message * m)
+{
+       return drv.message_hook(m);
+}
+
+int
+gpio_release()
+{
+       return OK;
+}
diff --git a/lib/libpadconf/Makefile b/lib/libpadconf/Makefile
new file mode 100644 (file)
index 0000000..fd2c713
--- /dev/null
@@ -0,0 +1,10 @@
+# Makefile for libpadconf
+
+CPPFLAGS+=-O -D_MINIX -D_POSIX_SOURCE -Wall -Werror -D_SYSTEM
+
+LIB=   padconf
+
+SRCS=  \
+       padconf.c 
+
+.include <bsd.lib.mk>
diff --git a/lib/libpadconf/padconf.c b/lib/libpadconf/padconf.c
new file mode 100644 (file)
index 0000000..c1b4d80
--- /dev/null
@@ -0,0 +1,100 @@
+/* kernel headers */
+#include <minix/syslib.h>
+#include <minix/drvlib.h>
+#include <minix/log.h>
+#include <minix/padconf.h>
+#include <minix/mmio.h>
+
+/* system headers */
+#include <sys/mman.h>
+#include <sys/types.h>
+
+/* usr headers */
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+
+/* local headers */
+
+/* used for logging */
+static struct log log = {
+       .name = "omap_padconf",
+       .log_level = LEVEL_INFO,
+       .log_func = default_log
+};
+
+static u32_t base = 0;
+static u32_t use_count = 0;
+
+int
+padconf_init()
+{
+       struct minix_mem_range mr;
+
+       use_count++;
+
+       if (base != 0) {
+               /* when used in a library we can't guaranty we only call this
+                * method once */
+               log_trace(&log, "Called %d times\n", use_count);
+               return OK;
+       }
+       mr.mr_base = PADCONF_REGISTERS_BASE;
+       mr.mr_limit = PADCONF_REGISTERS_BASE + 0x1000;
+
+       if (sys_privctl(SELF, SYS_PRIV_ADD_MEM, &mr) != 0) {
+               log_warn(&log, "Unable to request permission to map memory\n");
+               return EPERM;
+       }
+
+       base =
+           (uint32_t) vm_map_phys(SELF, (void *) PADCONF_REGISTERS_BASE,
+           0x1000);
+
+       if (base == (uint32_t) MAP_FAILED) {
+               log_warn(&log, "Unable to map GPIO memory\n");
+               return EPERM;
+       }
+
+       mr.mr_base = PADCONF_REGISTERS_BASE;
+       mr.mr_limit = PADCONF_REGISTERS_BASE + 0x1000;
+
+       if (sys_privctl(SELF, SYS_PRIV_ADD_MEM, &mr) != 0) {
+               log_warn(&log, "Unable to request permission to map memory\n");
+               return EPERM;
+       }
+
+       base =
+           (uint32_t) vm_map_phys(SELF, (void *) PADCONF_REGISTERS_BASE,
+           0x1000);
+
+       if (base == (uint32_t) MAP_FAILED) {
+               log_warn(&log, "Unable to map GPIO memory\n");
+               return EPERM;
+       }
+       return OK;
+}
+
+int
+padconf_set(u32_t padconf, u32_t mask, u32_t value)
+{
+       assert(padconf <= CONTROL_PADCONF_ETK_D14);
+       set32(base + padconf, mask, value);
+       return OK;
+}
+
+int
+padconf_release()
+{
+       assert(use_count > 0);
+       use_count--;
+
+       if (use_count == 0) {
+               vm_unmap_phys(SELF, (void *) base, 0x1000);
+       }
+       base = 0;
+       return OK;
+}