gpio: port to am335x
* port libgpio to am335x. * increase NR_IRQ to 16 to avoid too many IRQs requested error. * move gpio binary to /sbin (that's where mount looks for drivers). * fix bug that re-enabled banks that were disabled due to bad revision. * fix padconf masks for dm37xx in gpio driver (should be 16-bit). * fix a few typos in README.txt and comments. Change-Id: I32374415a97135174c5224f76374a870909fa90c
This commit is contained in:
parent
74bc88581c
commit
0a9eab0bb6
8 changed files with 303 additions and 109 deletions
|
@ -13,6 +13,7 @@
|
||||||
./multiboot/mod10_vm minix-sys
|
./multiboot/mod10_vm minix-sys
|
||||||
./multiboot/mod11_pfs minix-sys
|
./multiboot/mod11_pfs minix-sys
|
||||||
./multiboot/mod12_init minix-sys
|
./multiboot/mod12_init minix-sys
|
||||||
|
./sbin/gpio minix-sys
|
||||||
./usr/bin/eepromread minix-sys
|
./usr/bin/eepromread minix-sys
|
||||||
./usr/include/arm minix-sys
|
./usr/include/arm minix-sys
|
||||||
./usr/include/arm/aeabi.h minix-sys
|
./usr/include/arm/aeabi.h minix-sys
|
||||||
|
@ -108,7 +109,6 @@
|
||||||
./usr/sbin/bmp085 minix-sys
|
./usr/sbin/bmp085 minix-sys
|
||||||
./usr/sbin/cat24c256 minix-sys
|
./usr/sbin/cat24c256 minix-sys
|
||||||
./usr/sbin/fb minix-sys
|
./usr/sbin/fb minix-sys
|
||||||
./usr/sbin/gpio minix-sys
|
|
||||||
./usr/sbin/i2c minix-sys
|
./usr/sbin/i2c minix-sys
|
||||||
./usr/sbin/lan8710a minix-sys
|
./usr/sbin/lan8710a minix-sys
|
||||||
./usr/sbin/random minix-sys
|
./usr/sbin/random minix-sys
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
PROG= gpio
|
PROG= gpio
|
||||||
SRCS= gpio.c
|
SRCS= gpio.c
|
||||||
|
|
||||||
DPADD+= ${LIBBLOCKDRIVER} ${LIBSYS}
|
DPADD+= ${LIBBLOCKDRIVER} ${LIBSYS} ${LIBGPIO} ${LIBCLKCONF}
|
||||||
LDADD+= -lvtreefs -lsys -lgpio -lclkconf
|
LDADD+= -lvtreefs -lsys -lgpio -lclkconf
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -11,6 +11,6 @@ CPPFLAGS+= -D_SYSTEM=1
|
||||||
|
|
||||||
MAN=
|
MAN=
|
||||||
|
|
||||||
BINDIR?= /usr/sbin
|
BINDIR?= /sbin
|
||||||
|
|
||||||
.include <minix.service.mk>
|
.include <minix.service.mk>
|
||||||
|
|
|
@ -1,35 +1,35 @@
|
||||||
General Purpose Input and Output
|
General Purpose Input and Output
|
||||||
|
|
||||||
To make MINIX more usable on embedded hardware we need some way to access the
|
To make MINIX more usable on embedded hardware, we need some way to access the
|
||||||
GPIO features of the system on chip’s. Generally System on Chips (SoC) designs
|
GPIO features of the system on a chip. Generally System on Chips (SoC) designs
|
||||||
provide some way configure pads to perform basic Input/Output configuration on
|
provide some way to configure pads to perform basic Input/Output operations on
|
||||||
selected ports. These ports are also usually grouped into a bank. The end
|
selected ports. These ports are also usually grouped into banks. The end
|
||||||
result is that you have a functional general input output block where you need
|
result is that you have a functional general input output block where you need
|
||||||
to configure some the following functions.
|
to configure some the following functions.
|
||||||
|
|
||||||
Functional requirements
|
Functional Requirements
|
||||||
|
|
||||||
We envision that the short term usage of the GPIO library will be booth input
|
We envision that the short term usage of the GPIO library will be both input
|
||||||
and output handling. Input handling as we want to be able to listen to button
|
and output handling. Input handling as we want to be able to listen to button
|
||||||
presses and genrate key events and output handling because we want to be able
|
presses and generate key events, and output handling because we want to be able
|
||||||
to control leds.
|
to control LEDs.
|
||||||
|
|
||||||
GPIO required functionality
|
GPIO required functionality
|
||||||
-Configure pins as input or output.
|
-Configure pins as input or output.
|
||||||
-Configure the impedance of the pins.
|
-Configure the impedance of the pins.
|
||||||
-Get or set the values of the pins(possibly in a single call).
|
-Get or set the values of the pins (possibly in a single call).
|
||||||
-Configure interrupt levels for input pins.
|
-Configure interrupt levels for input pins.
|
||||||
|
-Configure debouncing of pins.
|
||||||
|
|
||||||
Configure debouncing of pins.
|
Additional kernel requirements:
|
||||||
|
|
||||||
Additional kernel requirements
|
|
||||||
-Manage the GPIO resources (who may access what)
|
-Manage the GPIO resources (who may access what)
|
||||||
-Access the GPIO pins from within driver (for the keyboard)
|
-Access the GPIO pins from within driver (for the keyboard)
|
||||||
-Access the GPIO pins from within userland (for toggeling leds)
|
-Access the GPIO pins from within userland (for toggling LEDs)
|
||||||
|
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
You have to manualy mount the gpio fs using the following command
|
You have to manually mount the gpio fs using the following command
|
||||||
|
|
||||||
|
# mkdir -p /gpio
|
||||||
# mount -t gpio none /gpio
|
# mount -t gpio none /gpio
|
||||||
|
|
||||||
|
|
|
@ -165,15 +165,34 @@ init_hook(void)
|
||||||
log_warn(&log, "Failed to init gpio driver\n");
|
log_warn(&log, "Failed to init gpio driver\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef AM335X
|
||||||
|
|
||||||
|
/* Export GPIO3_19 (P9-27 on BBB) output as LCD_EN */
|
||||||
|
|
||||||
|
sys_padconf(CONTROL_CONF_MCASP0_FSR, 0xffffffff,
|
||||||
|
(CONTROL_CONF_PUTYPESEL | CONTROL_CONF_MUXMODE(7)));
|
||||||
|
|
||||||
|
add_gpio_inode("LCD_EN", (32 * 3) + 19, GPIO_MODE_OUTPUT);
|
||||||
|
|
||||||
|
/* Export GPIO1_17 (P9-23 on BBB) input as RIGHT */
|
||||||
|
|
||||||
|
/* assumes external pull-up resistor (10K) */
|
||||||
|
sys_padconf(CONTROL_CONF_SPI0_D0, 0xffffffff, (CONTROL_CONF_RXACTIVE |
|
||||||
|
CONTROL_CONF_PUDEN | CONTROL_CONF_MUXMODE(7)));
|
||||||
|
|
||||||
|
add_gpio_inode("RIGHT", (32 * 1) + 17, GPIO_MODE_INPUT);
|
||||||
|
|
||||||
|
#elif DM37XX
|
||||||
|
|
||||||
add_gpio_inode("USR0", 149, GPIO_MODE_OUTPUT);
|
add_gpio_inode("USR0", 149, GPIO_MODE_OUTPUT);
|
||||||
add_gpio_inode("USR1", 150, GPIO_MODE_OUTPUT);
|
add_gpio_inode("USR1", 150, GPIO_MODE_OUTPUT);
|
||||||
add_gpio_inode("Button", 4, GPIO_MODE_INPUT);
|
add_gpio_inode("Button", 4, GPIO_MODE_INPUT);
|
||||||
|
|
||||||
/* configure GPIO_144 to be exported */
|
/* configure GPIO_144 to be exported */
|
||||||
sys_padconf(CONTROL_PADCONF_UART2_CTS, 0xff,
|
sys_padconf(CONTROL_PADCONF_UART2_CTS, 0x0000ffff,
|
||||||
PADCONF_MUXMODE(4) | PADCONF_PULL_MODE_PD_EN |
|
PADCONF_MUXMODE(4) | PADCONF_PULL_MODE_PD_EN |
|
||||||
PADCONF_INPUT_ENABLE(1));
|
PADCONF_INPUT_ENABLE(1));
|
||||||
sys_padconf(CONTROL_PADCONF_MMC2_DAT6, 0xff00,
|
sys_padconf(CONTROL_PADCONF_MMC2_DAT6, 0xffff0000,
|
||||||
(PADCONF_MUXMODE(4) | PADCONF_PULL_MODE_PD_EN |
|
(PADCONF_MUXMODE(4) | PADCONF_PULL_MODE_PD_EN |
|
||||||
PADCONF_INPUT_ENABLE(1)) << 16);
|
PADCONF_INPUT_ENABLE(1)) << 16);
|
||||||
|
|
||||||
|
@ -181,6 +200,8 @@ init_hook(void)
|
||||||
add_gpio_inode("BigRedButton", 144, GPIO_MODE_INPUT);
|
add_gpio_inode("BigRedButton", 144, GPIO_MODE_INPUT);
|
||||||
add_gpio_inode("BigRedButtonLed", 139, GPIO_MODE_OUTPUT);
|
add_gpio_inode("BigRedButtonLed", 139, GPIO_MODE_OUTPUT);
|
||||||
|
|
||||||
|
#endif /* DM37XX */
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -197,7 +218,7 @@ static int
|
||||||
|
|
||||||
if (gpio_cbdata->type == GPIO_CB_ON
|
if (gpio_cbdata->type == GPIO_CB_ON
|
||||||
|| gpio_cbdata->type == GPIO_CB_OFF) {
|
|| gpio_cbdata->type == GPIO_CB_OFF) {
|
||||||
/* turn on or of */
|
/* turn on or off */
|
||||||
if (gpio_set(gpio_cbdata->gpio,
|
if (gpio_set(gpio_cbdata->gpio,
|
||||||
(gpio_cbdata->type == GPIO_CB_ON) ? 1 : 0)) {
|
(gpio_cbdata->type == GPIO_CB_ON) ? 1 : 0)) {
|
||||||
*len = 0;
|
*len = 0;
|
||||||
|
|
|
@ -585,12 +585,18 @@ service gpio
|
||||||
PADCONF # 57
|
PADCONF # 57
|
||||||
;
|
;
|
||||||
irq
|
irq
|
||||||
29 # GPIO module 1
|
29 # GPIO module 1 (dm37xx)
|
||||||
30 # GPIO module 2
|
30 # GPIO module 2 (dm37xx)
|
||||||
31 # GPIO module 3
|
31 # GPIO module 3 (dm37xx)
|
||||||
32 # GPIO module 4
|
32 # GPIO module 4 (dm37xx) / module 2a (am335x)
|
||||||
33 # GPIO module 5
|
33 # GPIO module 5 (dm37xx) / module 2b (am335x)
|
||||||
34 # GPIO module 6
|
34 # GPIO module 6 (dm37xx)
|
||||||
|
62 # GPIO module 3a (am335x)
|
||||||
|
63 # GPIO module 3b (am335x)
|
||||||
|
96 # GPIO module 0a (am335x)
|
||||||
|
97 # GPIO module 0b (am335x)
|
||||||
|
98 # GPIO module 1a (am335x)
|
||||||
|
99 # GPIO module 1b (am335x)
|
||||||
;
|
;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -63,7 +63,7 @@
|
||||||
#define NR_MEM_RANGE 20
|
#define NR_MEM_RANGE 20
|
||||||
|
|
||||||
/* Max. number of IRQs that can be assigned to a process */
|
/* Max. number of IRQs that can be assigned to a process */
|
||||||
#define NR_IRQ 8
|
#define NR_IRQ 16
|
||||||
|
|
||||||
/* Scheduling priorities. Values must start at zero (highest
|
/* Scheduling priorities. Values must start at zero (highest
|
||||||
* priority) and increment.
|
* priority) and increment.
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include <minix/mmio.h>
|
#include <minix/mmio.h>
|
||||||
#include <minix/gpio.h>
|
#include <minix/gpio.h>
|
||||||
#include <minix/clkconf.h>
|
#include <minix/clkconf.h>
|
||||||
|
#include <minix/type.h>
|
||||||
|
|
||||||
/* system headers */
|
/* system headers */
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
@ -19,6 +20,7 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
/* local headers */
|
/* local headers */
|
||||||
|
#include "gpio_omap.h"
|
||||||
|
|
||||||
/* used for logging */
|
/* used for logging */
|
||||||
static struct log log = {
|
static struct log log = {
|
||||||
|
@ -57,107 +59,171 @@ struct omap_gpio_bank
|
||||||
uint32_t irq_nr; /* irq number */
|
uint32_t irq_nr; /* irq number */
|
||||||
uint32_t base_address;
|
uint32_t base_address;
|
||||||
int32_t disabled;
|
int32_t disabled;
|
||||||
int irq_id; /* orignhal hook id??? */
|
int irq_id; /* original hook id??? */
|
||||||
int irq_hook_id; /* hook id */
|
int irq_hook_id; /* hook id */
|
||||||
uint32_t inter_values; /* values when the interrupt was called */
|
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[] = {
|
static struct omap_gpio_bank omap_gpio_banks[] = {
|
||||||
|
#ifdef AM335X
|
||||||
{
|
{
|
||||||
.name = "GPIO1",
|
.name = "GPIO0",
|
||||||
.register_address = GPIO1_BASE,
|
.register_address = AM335X_GPIO0_BASE,
|
||||||
.irq_nr = GPIO1_IRQ,
|
.irq_nr = AM335X_GPIO0A_IRQ,
|
||||||
.base_address = 0,
|
.base_address = 0,
|
||||||
.disabled = 0,
|
.disabled = 0,
|
||||||
.irq_id = GPIO1_IRQ_HOOK_ID,
|
.irq_id = AM335X_GPIO0A_IRQ_HOOK_ID,
|
||||||
.irq_hook_id = GPIO1_IRQ_HOOK_ID,
|
.irq_hook_id = AM335X_GPIO0A_IRQ_HOOK_ID,
|
||||||
|
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "GPIO1",
|
||||||
|
.register_address = AM335X_GPIO1_BASE,
|
||||||
|
.irq_nr = AM335X_GPIO1A_IRQ,
|
||||||
|
.base_address = 0,
|
||||||
|
.disabled = 0,
|
||||||
|
.irq_id = AM335X_GPIO1A_IRQ_HOOK_ID,
|
||||||
|
.irq_hook_id = AM335X_GPIO1A_IRQ_HOOK_ID,
|
||||||
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.name = "GPIO2",
|
.name = "GPIO2",
|
||||||
.register_address = GPIO2_BASE,
|
.register_address = AM335X_GPIO2_BASE,
|
||||||
.irq_nr = GPIO2_IRQ,
|
.irq_nr = AM335X_GPIO2A_IRQ,
|
||||||
.base_address = 0,
|
.base_address = 0,
|
||||||
.disabled = 0,
|
.disabled = 0,
|
||||||
.irq_id = GPIO2_IRQ_HOOK_ID,
|
.irq_id = AM335X_GPIO2A_IRQ_HOOK_ID,
|
||||||
.irq_hook_id = GPIO2_IRQ_HOOK_ID,
|
.irq_hook_id = AM335X_GPIO2A_IRQ_HOOK_ID,
|
||||||
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.name = "GPIO3",
|
.name = "GPIO3",
|
||||||
.register_address = GPIO3_BASE,
|
.register_address = AM335X_GPIO3_BASE,
|
||||||
.irq_nr = GPIO3_IRQ,
|
.irq_nr = AM335X_GPIO3A_IRQ,
|
||||||
.base_address = 0,
|
.base_address = 0,
|
||||||
.disabled = 0,
|
.disabled = 0,
|
||||||
.irq_id = GPIO3_IRQ_HOOK_ID,
|
.irq_id = AM335X_GPIO3A_IRQ_HOOK_ID,
|
||||||
.irq_hook_id = GPIO3_IRQ_HOOK_ID,
|
.irq_hook_id = AM335X_GPIO3A_IRQ_HOOK_ID,
|
||||||
|
|
||||||
|
},
|
||||||
|
#elif DM37XX
|
||||||
|
{
|
||||||
|
.name = "GPIO1",
|
||||||
|
.register_address = DM37XX_GPIO1_BASE,
|
||||||
|
.irq_nr = DM37XX_GPIO1_IRQ,
|
||||||
|
.base_address = 0,
|
||||||
|
.disabled = 0,
|
||||||
|
.irq_id = DM37XX_GPIO1_IRQ_HOOK_ID,
|
||||||
|
.irq_hook_id = DM37XX_GPIO1_IRQ_HOOK_ID,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "GPIO2",
|
||||||
|
.register_address = DM37XX_GPIO2_BASE,
|
||||||
|
.irq_nr = DM37XX_GPIO2_IRQ,
|
||||||
|
.base_address = 0,
|
||||||
|
.disabled = 0,
|
||||||
|
.irq_id = DM37XX_GPIO2_IRQ_HOOK_ID,
|
||||||
|
.irq_hook_id = DM37XX_GPIO2_IRQ_HOOK_ID,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "GPIO3",
|
||||||
|
.register_address = DM37XX_GPIO3_BASE,
|
||||||
|
.irq_nr = DM37XX_GPIO3_IRQ,
|
||||||
|
.base_address = 0,
|
||||||
|
.disabled = 0,
|
||||||
|
.irq_id = DM37XX_GPIO3_IRQ_HOOK_ID,
|
||||||
|
.irq_hook_id = DM37XX_GPIO3_IRQ_HOOK_ID,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.name = "GPIO4",
|
.name = "GPIO4",
|
||||||
.register_address = GPIO4_BASE,
|
.register_address = DM37XX_GPIO4_BASE,
|
||||||
.irq_nr = GPIO4_IRQ,
|
.irq_nr = DM37XX_GPIO4_IRQ,
|
||||||
.base_address = 0,
|
.base_address = 0,
|
||||||
.disabled = 0,
|
.disabled = 0,
|
||||||
.irq_id = GPIO4_IRQ_HOOK_ID,
|
.irq_id = DM37XX_GPIO4_IRQ_HOOK_ID,
|
||||||
.irq_hook_id = GPIO4_IRQ_HOOK_ID,
|
.irq_hook_id = DM37XX_GPIO4_IRQ_HOOK_ID,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.name = "GPIO5",
|
.name = "GPIO5",
|
||||||
.register_address = GPIO5_BASE,
|
.register_address = DM37XX_GPIO5_BASE,
|
||||||
.irq_nr = GPIO5_IRQ,
|
.irq_nr = DM37XX_GPIO5_IRQ,
|
||||||
.base_address = 0,
|
.base_address = 0,
|
||||||
.disabled = 0,
|
.disabled = 0,
|
||||||
.irq_id = GPIO5_IRQ_HOOK_ID,
|
.irq_id = DM37XX_GPIO5_IRQ_HOOK_ID,
|
||||||
.irq_hook_id = GPIO5_IRQ_HOOK_ID,
|
.irq_hook_id = DM37XX_GPIO5_IRQ_HOOK_ID,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.name = "GPIO6",
|
.name = "GPIO6",
|
||||||
.register_address = GPIO6_BASE,
|
.register_address = DM37XX_GPIO6_BASE,
|
||||||
.irq_nr = GPIO6_IRQ,
|
.irq_nr = DM37XX_GPIO6_IRQ,
|
||||||
.base_address = 0,
|
.base_address = 0,
|
||||||
.disabled = 0,
|
.disabled = 0,
|
||||||
.irq_id = GPIO6_IRQ_HOOK_ID,
|
.irq_id = DM37XX_GPIO6_IRQ_HOOK_ID,
|
||||||
.irq_hook_id = GPIO6_IRQ_HOOK_ID,
|
.irq_hook_id = DM37XX_GPIO6_IRQ_HOOK_ID,
|
||||||
},
|
},
|
||||||
|
#endif /* DM37XX */
|
||||||
{NULL, 0, 0, 0, 0, 0, 0, 0 }
|
{NULL, 0, 0, 0, 0, 0, 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
#define GPIO_REVISION 0x00
|
#define NBANKS ((int)((sizeof(omap_gpio_banks)/sizeof(omap_gpio_banks[0])) - 1))
|
||||||
#define GPIO_REVISION_MAJOR(X) ((X & 0xF0) >> 4)
|
|
||||||
#define GPIO_REVISION_MINOR(X) (X & 0XF)
|
/*
|
||||||
|
* Defines the set of registers. There is a lot of commonality between the
|
||||||
|
* AM335X and DM37XX gpio registers. To avoid ifdefs everywhere, we define
|
||||||
|
* a central register set and only use ifdefs where they differ.
|
||||||
|
*/
|
||||||
|
typedef struct gpio_omap_registers {
|
||||||
|
vir_bytes REVISION;
|
||||||
|
vir_bytes IRQENABLE;
|
||||||
|
vir_bytes IRQSTATUS;
|
||||||
|
vir_bytes DATAOUT;
|
||||||
|
vir_bytes DATAIN;
|
||||||
|
vir_bytes OE;
|
||||||
|
vir_bytes RISINGDETECT;
|
||||||
|
vir_bytes FALLINGDETECT;
|
||||||
|
vir_bytes CLEARDATAOUT;
|
||||||
|
vir_bytes SETDATAOUT;
|
||||||
|
} gpio_omap_regs_t;
|
||||||
|
|
||||||
|
/* Define the registers for each chip */
|
||||||
|
|
||||||
|
gpio_omap_regs_t gpio_omap_dm37xx = {
|
||||||
|
.REVISION = DM37XX_GPIO_REVISION,
|
||||||
|
.IRQENABLE = DM37XX_GPIO_IRQENABLE1,
|
||||||
|
.IRQSTATUS = DM37XX_GPIO_IRQSTATUS1,
|
||||||
|
.DATAOUT = DM37XX_GPIO_DATAOUT,
|
||||||
|
.DATAIN = DM37XX_GPIO_DATAIN,
|
||||||
|
.OE = DM37XX_GPIO_OE,
|
||||||
|
.RISINGDETECT = DM37XX_GPIO_RISINGDETECT1,
|
||||||
|
.FALLINGDETECT = DM37XX_GPIO_FALLINGDETECT1,
|
||||||
|
.CLEARDATAOUT = DM37XX_GPIO_CLEARDATAOUT,
|
||||||
|
.SETDATAOUT = DM37XX_GPIO_SETDATAOUT
|
||||||
|
};
|
||||||
|
|
||||||
|
gpio_omap_regs_t gpio_omap_am335x = {
|
||||||
|
.REVISION = AM335X_GPIO_REVISION,
|
||||||
|
.IRQENABLE = AM335X_GPIO_IRQSTATUS_SET_0,
|
||||||
|
.IRQSTATUS = AM335X_GPIO_IRQSTATUS_0,
|
||||||
|
.DATAOUT = AM335X_GPIO_DATAOUT,
|
||||||
|
.DATAIN = AM335X_GPIO_DATAIN,
|
||||||
|
.OE = AM335X_GPIO_OE,
|
||||||
|
.RISINGDETECT = AM335X_GPIO_RISINGDETECT,
|
||||||
|
.FALLINGDETECT = AM335X_GPIO_FALLINGDETECT,
|
||||||
|
.CLEARDATAOUT = AM335X_GPIO_CLEARDATAOUT,
|
||||||
|
.SETDATAOUT = AM335X_GPIO_SETDATAOUT
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef AM335X
|
||||||
|
static gpio_omap_regs_t *regs = &gpio_omap_am335x;
|
||||||
|
#elif DM37XX
|
||||||
|
static gpio_omap_regs_t *regs = &gpio_omap_dm37xx;
|
||||||
|
#endif /* DM37XX */
|
||||||
|
|
||||||
static struct omap_gpio_bank *
|
static struct omap_gpio_bank *
|
||||||
omap_gpio_bank_get(int gpio_nr)
|
omap_gpio_bank_get(int gpio_nr)
|
||||||
{
|
{
|
||||||
struct omap_gpio_bank *bank;
|
struct omap_gpio_bank *bank;
|
||||||
assert(gpio_nr >= 0 && gpio_nr <= 32 * 6);
|
assert(gpio_nr >= 0 && gpio_nr <= 32 * NBANKS);
|
||||||
bank = &omap_gpio_banks[gpio_nr / 32];
|
bank = &omap_gpio_banks[gpio_nr / 32];
|
||||||
return bank;
|
return bank;
|
||||||
}
|
}
|
||||||
|
@ -167,7 +233,7 @@ omap_gpio_claim(char *owner, int nr, struct gpio **gpio)
|
||||||
{
|
{
|
||||||
log_trace(&log, "%s s claiming %d\n", owner, nr);
|
log_trace(&log, "%s s claiming %d\n", owner, nr);
|
||||||
|
|
||||||
if (nr < 0 && nr >= 32 * 6) {
|
if (nr < 0 && nr >= 32 * NBANKS) {
|
||||||
log_warn(&log, "%s is claiming unknown GPIO number %d\n",
|
log_warn(&log, "%s is claiming unknown GPIO number %d\n",
|
||||||
owner, nr);
|
owner, nr);
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
|
@ -197,17 +263,17 @@ omap_gpio_pin_mode(struct gpio *gpio, int mode)
|
||||||
bank = omap_gpio_bank_get(gpio->nr);
|
bank = omap_gpio_bank_get(gpio->nr);
|
||||||
log_debug(&log,
|
log_debug(&log,
|
||||||
"pin mode bank %s, base address 0x%x -> register address (0x%x,0x%x,0x%x)\n",
|
"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->name, bank->base_address, bank->register_address, regs->OE,
|
||||||
bank->register_address + GPIO_OE);
|
bank->register_address + regs->OE);
|
||||||
|
|
||||||
if (mode == GPIO_MODE_OUTPUT) {
|
if (mode == GPIO_MODE_OUTPUT) {
|
||||||
set32(bank->base_address + GPIO_OE, BIT(gpio->nr % 32), 0);
|
set32(bank->base_address + regs->OE, BIT(gpio->nr % 32), 0);
|
||||||
} else {
|
} else {
|
||||||
set32(bank->base_address + GPIO_FALLINGDETECT1,
|
set32(bank->base_address + regs->FALLINGDETECT,
|
||||||
BIT(gpio->nr % 32), 0xffffffff);
|
BIT(gpio->nr % 32), 0xffffffff);
|
||||||
set32(bank->base_address + GPIO_IRQENABLE1, BIT(gpio->nr % 32),
|
set32(bank->base_address + regs->IRQENABLE, BIT(gpio->nr % 32),
|
||||||
0xffffffff);
|
0xffffffff);
|
||||||
set32(bank->base_address + GPIO_OE, BIT(gpio->nr % 32),
|
set32(bank->base_address + regs->OE, BIT(gpio->nr % 32),
|
||||||
0xffffffff);
|
0xffffffff);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -218,14 +284,14 @@ omap_gpio_set(struct gpio *gpio, int value)
|
||||||
{
|
{
|
||||||
struct omap_gpio_bank *bank;
|
struct omap_gpio_bank *bank;
|
||||||
assert(gpio != NULL);
|
assert(gpio != NULL);
|
||||||
assert(gpio->nr >= 0 && gpio->nr <= 32 * 6);
|
assert(gpio->nr >= 0 && gpio->nr <= 32 * NBANKS);
|
||||||
|
|
||||||
bank = omap_gpio_bank_get(gpio->nr);
|
bank = omap_gpio_bank_get(gpio->nr);
|
||||||
if (value == 1) {
|
if (value == 1) {
|
||||||
write32(bank->base_address + GPIO_SETDATAOUT,
|
write32(bank->base_address + regs->SETDATAOUT,
|
||||||
BIT(gpio->nr % 32));
|
BIT(gpio->nr % 32));
|
||||||
} else {
|
} else {
|
||||||
write32(bank->base_address + GPIO_CLEARDATAOUT,
|
write32(bank->base_address + regs->CLEARDATAOUT,
|
||||||
BIT(gpio->nr % 32));
|
BIT(gpio->nr % 32));
|
||||||
}
|
}
|
||||||
return OK;
|
return OK;
|
||||||
|
@ -236,21 +302,21 @@ omap_gpio_read(struct gpio *gpio, int *value)
|
||||||
{
|
{
|
||||||
struct omap_gpio_bank *bank;
|
struct omap_gpio_bank *bank;
|
||||||
assert(gpio != NULL);
|
assert(gpio != NULL);
|
||||||
assert(gpio->nr >= 0 && gpio->nr <= 32 * 6);
|
assert(gpio->nr >= 0 && gpio->nr <= 32 * NBANKS);
|
||||||
|
|
||||||
bank = omap_gpio_bank_get(gpio->nr);
|
bank = omap_gpio_bank_get(gpio->nr);
|
||||||
log_trace(&log, "mode=%d OU/IN 0x%08x 0x%08x\n", gpio->mode,
|
log_trace(&log, "mode=%d OU/IN 0x%08x 0x%08x\n", gpio->mode,
|
||||||
read32(bank->base_address + GPIO_DATAIN),
|
read32(bank->base_address + regs->DATAIN),
|
||||||
read32(bank->base_address + GPIO_DATAOUT));
|
read32(bank->base_address + regs->DATAOUT));
|
||||||
|
|
||||||
if (gpio->mode == GPIO_MODE_INPUT) {
|
if (gpio->mode == GPIO_MODE_INPUT) {
|
||||||
*value =
|
*value =
|
||||||
(read32(bank->base_address +
|
(read32(bank->base_address +
|
||||||
GPIO_DATAIN) >> (gpio->nr % 32)) & 0x1;
|
regs->DATAIN) >> (gpio->nr % 32)) & 0x1;
|
||||||
} else {
|
} else {
|
||||||
*value =
|
*value =
|
||||||
(read32(bank->base_address +
|
(read32(bank->base_address +
|
||||||
GPIO_DATAOUT) >> (gpio->nr % 32)) & 0x1;
|
regs->DATAOUT) >> (gpio->nr % 32)) & 0x1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
|
@ -261,7 +327,7 @@ omap_gpio_intr_read(struct gpio *gpio, int *value)
|
||||||
{
|
{
|
||||||
struct omap_gpio_bank *bank;
|
struct omap_gpio_bank *bank;
|
||||||
assert(gpio != NULL);
|
assert(gpio != NULL);
|
||||||
assert(gpio->nr >= 0 && gpio->nr <= 32 * 6);
|
assert(gpio->nr >= 0 && gpio->nr <= 32 * NBANKS);
|
||||||
|
|
||||||
bank = omap_gpio_bank_get(gpio->nr);
|
bank = omap_gpio_bank_get(gpio->nr);
|
||||||
/* TODO: check if interrupt where enabled?? */
|
/* TODO: check if interrupt where enabled?? */
|
||||||
|
@ -293,9 +359,9 @@ omap_message_hook(message * m)
|
||||||
bank->name);
|
bank->name);
|
||||||
bank->inter_values |=
|
bank->inter_values |=
|
||||||
read32(bank->base_address +
|
read32(bank->base_address +
|
||||||
GPIO_IRQSTATUS1);
|
regs->IRQSTATUS);
|
||||||
/* clear the interrupts */
|
/* clear the interrupts */
|
||||||
write32(bank->base_address + GPIO_IRQSTATUS1,
|
write32(bank->base_address + regs->IRQSTATUS,
|
||||||
0xffffffff);
|
0xffffffff);
|
||||||
if (sys_irqenable(&bank->irq_hook_id) != OK) {
|
if (sys_irqenable(&bank->irq_hook_id) != OK) {
|
||||||
log_warn(&log,
|
log_warn(&log,
|
||||||
|
@ -306,7 +372,7 @@ omap_message_hook(message * m)
|
||||||
}
|
}
|
||||||
return OK;
|
return OK;
|
||||||
default:
|
default:
|
||||||
log_warn(&log, "Unknown message\n");
|
log_debug(&log, "Unknown message\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return OK;
|
return OK;
|
||||||
|
@ -343,16 +409,25 @@ omap_gpio_init(struct gpio_driver *gpdrv)
|
||||||
}
|
}
|
||||||
|
|
||||||
revision = 0;
|
revision = 0;
|
||||||
revision = read32(bank->base_address + GPIO_REVISION);
|
revision = read32(bank->base_address + regs->REVISION);
|
||||||
/* test if we can access it */
|
/* test if we can access it */
|
||||||
if (GPIO_REVISION_MAJOR(revision) != 2
|
if (
|
||||||
|| GPIO_REVISION_MINOR(revision) != 5) {
|
#ifdef AM335X
|
||||||
|
AM335X_GPIO_REVISION_MAJOR(revision) != 0
|
||||||
|
|| AM335X_GPIO_REVISION_MINOR(revision) != 1
|
||||||
|
#elif DM37XX
|
||||||
|
DM37XX_GPIO_REVISION_MAJOR(revision) != 2
|
||||||
|
|| DM37XX_GPIO_REVISION_MINOR(revision) != 5
|
||||||
|
#endif /* DM37XX */
|
||||||
|
) {
|
||||||
log_warn(&log,
|
log_warn(&log,
|
||||||
"Failed to read the revision of GPIO bank %s.. disabling\n",
|
"Failed to read the revision of GPIO bank %s.. disabling\n",
|
||||||
bank->name);
|
bank->name);
|
||||||
|
log_warn(&log, "Got 0x%x\n", revision);
|
||||||
bank->disabled = 1;
|
bank->disabled = 1;
|
||||||
|
} else {
|
||||||
|
bank->disabled = 0;
|
||||||
}
|
}
|
||||||
bank->disabled = 0;
|
|
||||||
|
|
||||||
if (sys_irqsetpolicy(bank->irq_nr, 0,
|
if (sys_irqsetpolicy(bank->irq_nr, 0,
|
||||||
&bank->irq_hook_id) != OK) {
|
&bank->irq_hook_id) != OK) {
|
||||||
|
@ -376,9 +451,13 @@ omap_gpio_init(struct gpio_driver *gpdrv)
|
||||||
};
|
};
|
||||||
|
|
||||||
clkconf_init();
|
clkconf_init();
|
||||||
|
#ifdef AM335X
|
||||||
|
/* Nothing to enable for GPIO on AM335X */
|
||||||
|
#elif DM37XX
|
||||||
/* enable the interface and functional clock on GPIO bank 1 */
|
/* enable the interface and functional clock on GPIO bank 1 */
|
||||||
clkconf_set(CM_FCLKEN_WKUP, BIT(3), 0xffffffff);
|
clkconf_set(CM_FCLKEN_WKUP, BIT(3), 0xffffffff);
|
||||||
clkconf_set(CM_ICLKEN_WKUP, BIT(3), 0xffffffff);
|
clkconf_set(CM_ICLKEN_WKUP, BIT(3), 0xffffffff);
|
||||||
|
#endif /* DM37XX */
|
||||||
clkconf_release();
|
clkconf_release();
|
||||||
|
|
||||||
|
|
||||||
|
|
88
lib/libgpio/gpio_omap.h
Normal file
88
lib/libgpio/gpio_omap.h
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
#ifndef __GPIO_OMAP_H
|
||||||
|
#define __GPIO_OMAP_H
|
||||||
|
|
||||||
|
#define AM335X_GPIO0_BASE (0x44e07000)
|
||||||
|
#define AM335X_GPIO1_BASE (0x4804c000)
|
||||||
|
#define AM335X_GPIO2_BASE (0x481ac000)
|
||||||
|
#define AM335X_GPIO3_BASE (0x481ae000)
|
||||||
|
#define AM335X_GPIO0A_IRQ 96
|
||||||
|
#define AM335X_GPIO0B_IRQ 97
|
||||||
|
#define AM335X_GPIO1A_IRQ 98
|
||||||
|
#define AM335X_GPIO1B_IRQ 99
|
||||||
|
#define AM335X_GPIO2A_IRQ 32
|
||||||
|
#define AM335X_GPIO2B_IRQ 33
|
||||||
|
#define AM335X_GPIO3A_IRQ 62
|
||||||
|
#define AM335X_GPIO3B_IRQ 63
|
||||||
|
#define AM335X_GPIO0A_IRQ_HOOK_ID 0
|
||||||
|
#define AM335X_GPIO0B_IRQ_HOOK_ID 1
|
||||||
|
#define AM335X_GPIO1A_IRQ_HOOK_ID 2
|
||||||
|
#define AM335X_GPIO1B_IRQ_HOOK_ID 3
|
||||||
|
#define AM335X_GPIO2A_IRQ_HOOK_ID 4
|
||||||
|
#define AM335X_GPIO2B_IRQ_HOOK_ID 5
|
||||||
|
#define AM335X_GPIO3A_IRQ_HOOK_ID 6
|
||||||
|
#define AM335X_GPIO3B_IRQ_HOOK_ID 7
|
||||||
|
|
||||||
|
#define AM335X_GPIO_REVISION 0x000
|
||||||
|
#define AM335X_GPIO_SYSCONFIG 0x010
|
||||||
|
#define AM335X_GPIO_EOI 0x020
|
||||||
|
#define AM335X_GPIO_IRQSTATUS_RAW_0 0x024
|
||||||
|
#define AM335X_GPIO_IRQSTATUS_RAW_1 0x028
|
||||||
|
#define AM335X_GPIO_IRQSTATUS_0 0x02C
|
||||||
|
#define AM335X_GPIO_IRQSTATUS_1 0x030
|
||||||
|
#define AM335X_GPIO_IRQSTATUS_SET_0 0x034
|
||||||
|
#define AM335X_GPIO_IRQSTATUS_SET_1 0x038
|
||||||
|
#define AM335X_GPIO_IRQSTATUS_CLR_0 0x03C
|
||||||
|
#define AM335X_GPIO_IRQSTATUS_CLR_1 0x040
|
||||||
|
#define AM335X_GPIO_IRQWAKEN_0 0x044
|
||||||
|
#define AM335X_GPIO_IRQWAKEN_1 0x048
|
||||||
|
#define AM335X_GPIO_SYSSTATUS 0x114
|
||||||
|
#define AM335X_GPIO_CTRL 0x130
|
||||||
|
#define AM335X_GPIO_OE 0x134
|
||||||
|
#define AM335X_GPIO_DATAIN 0x138
|
||||||
|
#define AM335X_GPIO_DATAOUT 0x13C
|
||||||
|
#define AM335X_GPIO_LEVELDETECT0 0x140
|
||||||
|
#define AM335X_GPIO_LEVELDETECT1 0x144
|
||||||
|
#define AM335X_GPIO_RISINGDETECT 0x148
|
||||||
|
#define AM335X_GPIO_FALLINGDETECT 0x14C
|
||||||
|
#define AM335X_GPIO_DEBOUNCENABLE 0x150
|
||||||
|
#define AM335X_GPIO_DEBOUNCINGTIME 0x154
|
||||||
|
#define AM335X_GPIO_CLEARDATAOUT 0x190
|
||||||
|
#define AM335X_GPIO_SETDATAOUT 0x194
|
||||||
|
|
||||||
|
#define AM335X_GPIO_REVISION_MAJOR(X) ((X >> 8) & 0x07)
|
||||||
|
#define AM335X_GPIO_REVISION_MINOR(X) (X & 0x3f)
|
||||||
|
|
||||||
|
#define DM37XX_GPIO1_BASE (0x48310000)
|
||||||
|
#define DM37XX_GPIO2_BASE (0x49050000)
|
||||||
|
#define DM37XX_GPIO3_BASE (0x49052000)
|
||||||
|
#define DM37XX_GPIO4_BASE (0x49054000)
|
||||||
|
#define DM37XX_GPIO5_BASE (0x49056000)
|
||||||
|
#define DM37XX_GPIO6_BASE (0x49058000)
|
||||||
|
#define DM37XX_GPIO1_IRQ 29 /* GPIO module 1 */
|
||||||
|
#define DM37XX_GPIO2_IRQ 30 /* GPIO module 2 */
|
||||||
|
#define DM37XX_GPIO3_IRQ 31 /* GPIO module 3 */
|
||||||
|
#define DM37XX_GPIO4_IRQ 32 /* GPIO module 4 */
|
||||||
|
#define DM37XX_GPIO5_IRQ 33 /* GPIO module 5 */
|
||||||
|
#define DM37XX_GPIO6_IRQ 34 /* GPIO module 6 */
|
||||||
|
#define DM37XX_GPIO1_IRQ_HOOK_ID 0
|
||||||
|
#define DM37XX_GPIO2_IRQ_HOOK_ID 1
|
||||||
|
#define DM37XX_GPIO3_IRQ_HOOK_ID 2
|
||||||
|
#define DM37XX_GPIO4_IRQ_HOOK_ID 3
|
||||||
|
#define DM37XX_GPIO5_IRQ_HOOK_ID 4
|
||||||
|
#define DM37XX_GPIO6_IRQ_HOOK_ID 5
|
||||||
|
|
||||||
|
#define DM37XX_GPIO_IRQSTATUS1 (0x18)
|
||||||
|
#define DM37XX_GPIO_IRQENABLE1 (0x01C)
|
||||||
|
#define DM37XX_GPIO_DATAOUT (0x3c)
|
||||||
|
#define DM37XX_GPIO_DATAIN (0x38)
|
||||||
|
#define DM37XX_GPIO_OE (0x34) /* Output Data Enable */
|
||||||
|
#define DM37XX_GPIO_RISINGDETECT1 (0x048)
|
||||||
|
#define DM37XX_GPIO_FALLINGDETECT1 (0x04c)
|
||||||
|
#define DM37XX_GPIO_CLEARDATAOUT (0x90)
|
||||||
|
#define DM37XX_GPIO_SETDATAOUT (0x94)
|
||||||
|
|
||||||
|
#define DM37XX_GPIO_REVISION 0x00
|
||||||
|
#define DM37XX_GPIO_REVISION_MAJOR(X) ((X & 0xF0) >> 4)
|
||||||
|
#define DM37XX_GPIO_REVISION_MINOR(X) (X & 0XF)
|
||||||
|
|
||||||
|
#endif /* __GPIO_OMAP_H */
|
Loading…
Reference in a new issue