gpio: add support for Raspberry Pi 2 and 3

Co-Authored-By: Benjamin Dauphin <benjamin.dauphin@live.fr>
Co-Authored-By: Gilles Henaux <gill.henaux@gmail.com>
This commit is contained in:
Jean-Baptiste Boric
2016-05-29 14:20:41 +02:00
parent 1e7d6ee8a7
commit b76b176eaf
4 changed files with 246 additions and 2 deletions

View File

@@ -205,7 +205,16 @@ init_hook(void)
CONTROL_CONF_PUDEN | CONTROL_CONF_MUXMODE(7)));
add_gpio_inode("RIGHT", (32 * 1) + 17, GPIO_MODE_INPUT);
} else if (BOARD_IS_RPI_2_B(machine.board_id) || BOARD_IS_RPI_3_B(machine.board_id)) {
/* Export GPIO 26 as SLIDE_PREV */
add_gpio_inode("SLIDE_PREV", 26, GPIO_MODE_INPUT);
/* Export GPIO 21 as SLIDE_NEXT */
add_gpio_inode("SLIDE_NEXT", 21, GPIO_MODE_INPUT);
/* Put both of them in pull-up */
sys_padconf(0x94, 0x3, 2);
sys_padconf(0x98, 0xffffffff, (1<<26)|(1<<21));
sys_padconf(0x98, 0xffffffff, 0);
}
}

View File

@@ -9,6 +9,12 @@ struct gpio
#define GPIO_MODE_INPUT 0
#define GPIO_MODE_OUTPUT 1
#define GPIO_MODE_ALT0 2
#define GPIO_MODE_ALT1 3
#define GPIO_MODE_ALT2 4
#define GPIO_MODE_ALT3 5
#define GPIO_MODE_ALT4 6
#define GPIO_MODE_ALT5 7
int gpio_init(void);

View File

@@ -4,8 +4,13 @@ CPPFLAGS+= -D_SYSTEM -D_MINIX_SYSTEM
LIB= gpio
SRCS= \
gpio_omap.c
.if ${BSP_NAME} == omap
SRCS= gpio_omap.c
.elif ${BSP_NAME} == rpi
SRCS= gpio_rpi.c
.else
.error Unknown bsp ${BSP_NAME}
.endif
WARNS?= 5

View File

@@ -0,0 +1,224 @@
/* kernel headers */
#include <minix/syslib.h>
#include <minix/drvlib.h>
#include <minix/log.h>
#include <minix/mmio.h>
#include <minix/gpio.h>
#include <minix/clkconf.h>
#include <minix/type.h>
#include <minix/board.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 <minix/padconf.h>
/* used for logging */
static struct log log = {
.name = "gpio_rpi",
.log_level = LEVEL_INFO,
.log_func = default_log
};
static uint32_t rpi_gpio_base_address;
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;
static int
rpi_gpio_claim(char *owner, int nr, struct gpio **gpio)
{
log_trace(&log, "%s s claiming %d\n", owner, nr);
if (nr < 0 && nr > 53) {
log_warn(&log, "%s is claiming unknown GPIO number %d\n",
owner, nr);
return EINVAL;
}
struct gpio *tmp = malloc(sizeof(struct gpio));
memset(tmp, 0, sizeof(*tmp));
tmp->nr = nr;
*gpio = tmp;
return OK;
}
static int
rpi_gpio_pin_mode(struct gpio *gpio, int mode)
{
assert(gpio != NULL);
gpio->mode = mode;
log_debug(&log, "pin %d mode %d\n", gpio->nr, mode);
int gpio_reg = gpio->nr / 10;
int gpio_offset = (gpio->nr % 10) * 3;
set32(rpi_gpio_base_address + 4*gpio_reg, 0x7 << gpio_offset, mode << gpio_offset);
return 0;
}
static int
rpi_gpio_set(struct gpio *gpio, int value)
{
assert(gpio != NULL);
assert(gpio->nr >= 0 && gpio->nr <= 53);
int gpio_reg = gpio->nr / 32;
if (value == 1) {
write32(rpi_gpio_base_address + 0x1c + 4*gpio_reg,
BIT(gpio->nr % 32));
} else {
write32(rpi_gpio_base_address + 0x28 + 4*gpio_reg,
BIT(gpio->nr % 32));
}
return OK;
}
static int
rpi_gpio_read(struct gpio *gpio, int *value)
{
assert(gpio != NULL);
assert(gpio->nr >= 0 && gpio->nr <= 53);
int gpio_reg = gpio->nr / 32;
*value = (read32(rpi_gpio_base_address + 0x34 + 4*gpio_reg) >>
(gpio->nr % 32)) & 0x1;
return OK;
}
static int
rpi_gpio_intr_read(struct gpio *gpio, int *value)
{
/* No interrupts yet */
return OK;
}
static int
rpi_message_hook(message * m)
{
/* No interrupts yet */
return OK;
}
static int
rpi_gpio_init(struct gpio_driver *gpdrv)
{
struct minix_mem_range mr;
mr.mr_base = PADCONF_RPI2_REGISTERS_BASE;
mr.mr_limit = mr.mr_base + PADCONF_RPI2_REGISTERS_SIZE;
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 */
rpi_gpio_base_address =
(uint32_t) vm_map_phys(SELF,
(void *) PADCONF_RPI2_REGISTERS_BASE, PADCONF_RPI2_REGISTERS_SIZE);
if (rpi_gpio_base_address == (uint32_t) MAP_FAILED) {
log_warn(&log, "Unable to map GPIO memory\n");
return EPERM; /* fixme */
}
gpdrv->claim = rpi_gpio_claim;
gpdrv->pin_mode = rpi_gpio_pin_mode;
gpdrv->set = rpi_gpio_set;
gpdrv->read = rpi_gpio_read;
gpdrv->intr_read = rpi_gpio_intr_read;
gpdrv->message_hook = rpi_message_hook;
return 0;
}
int
gpio_init()
{
return rpi_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(void)
{
return OK;
}