GPIO:further development
* Generalize GPIO handling. * Add libs to configure gpio's clocks and pads * Add Interrupt handling. * Introduce mmio.h and log.h Change-Id: I928e4c807d15031de2eede4b3ecff62df795f8ac
This commit is contained in:
		
							parent
							
								
									47e47cfdd6
								
							
						
					
					
						commit
						3357fcb24a
					
				@ -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
 | 
			
		||||
 | 
			
		||||
@ -577,6 +577,7 @@
 | 
			
		||||
./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
 | 
			
		||||
@ -586,13 +587,16 @@
 | 
			
		||||
./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
 | 
			
		||||
 | 
			
		||||
@ -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.
 | 
			
		||||
 | 
			
		||||
@ -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,17 +199,11 @@ 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)) {
 | 
			
		||||
			*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_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;
 | 
			
		||||
		}
 | 
			
		||||
@ -185,10 +211,18 @@ static int
 | 
			
		||||
		return OK;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* reading */
 | 
			
		||||
	if (drv.read(gpio_cbdata->gpio, &value)) {
 | 
			
		||||
		*len = 0;
 | 
			
		||||
		return EIO;
 | 
			
		||||
	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;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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__ */
 | 
			
		||||
@ -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;
 | 
			
		||||
}
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -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 \
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										34
									
								
								include/minix/gpio.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								include/minix/gpio.h
									
									
									
									
									
										Normal file
									
								
							@ -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__ */
 | 
			
		||||
@ -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,
 | 
			
		||||
@ -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__ */
 | 
			
		||||
							
								
								
									
										184
									
								
								include/minix/padconf.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										184
									
								
								include/minix/padconf.h
									
									
									
									
									
										Normal file
									
								
							@ -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__ */
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										10
									
								
								lib/libgpio/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								lib/libgpio/Makefile
									
									
									
									
									
										Normal file
									
								
							@ -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>
 | 
			
		||||
							
								
								
									
										78
									
								
								lib/libgpio/clkconf.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								lib/libgpio/clkconf.c
									
									
									
									
									
										Normal file
									
								
							@ -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;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										7
									
								
								lib/libgpio/clkconf.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								lib/libgpio/clkconf.h
									
									
									
									
									
										Normal file
									
								
							@ -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();
 | 
			
		||||
							
								
								
									
										447
									
								
								lib/libgpio/gpio_omap.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										447
									
								
								lib/libgpio/gpio_omap.c
									
									
									
									
									
										Normal file
									
								
							@ -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;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										10
									
								
								lib/libpadconf/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								lib/libpadconf/Makefile
									
									
									
									
									
										Normal file
									
								
							@ -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>
 | 
			
		||||
							
								
								
									
										100
									
								
								lib/libpadconf/padconf.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								lib/libpadconf/padconf.c
									
									
									
									
									
										Normal file
									
								
							@ -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;
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user