* Generalize GPIO handling.
* Add libs to configure gpio's clocks and pads
* Add Interrupt handling.
* Introduce mmio.h and log.h
Change-Id: I928e4c807d15031de2eede4b3ecff62df795f8ac
./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
./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
# 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.
#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>
#include <string.h>
/* local headers */
-#include "log.h"
-#include "mmio.h"
-#include "gpio.h"
/* used for logging */
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
};
/* 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 = {
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;
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);
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);
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
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);
return OK;
}
+static int
+message_hook(message * m)
+{
+ gpio_intr_message(m);
+ return OK;
+}
+
int
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;
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;
}
+++ /dev/null
-#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__ */
+++ /dev/null
-/* 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;
-}
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
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 \
--- /dev/null
+#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__ */
* Simple logging functions
*/
+#include <stdarg.h>
+
/*
* LEVEL_NONE do not log anything.
* LEVEL_WARN Information that needs to be known.
* 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,
+#ifndef __MMIO_H__
+#define __MMIO_H__
+
#define REG(x)(*((volatile uint32_t *)(x)))
#define BIT(x)(0x1 << x)
static inline uint32_t
read32(uint32_t address)
{
-
return REG(address);
}
val |= (value & mask);
write32(address, val);
}
+#endif /* __MMIO_H__ */
--- /dev/null
+#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__ */
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
--- /dev/null
+# 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>
--- /dev/null
+/* 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;
+}
--- /dev/null
+/* 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();
--- /dev/null
+/* 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;
+}
--- /dev/null
+# Makefile for libpadconf
+
+CPPFLAGS+=-O -D_MINIX -D_POSIX_SOURCE -Wall -Werror -D_SYSTEM
+
+LIB= padconf
+
+SRCS= \
+ padconf.c
+
+.include <bsd.lib.mk>
--- /dev/null
+/* 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;
+}