1
1
Форкнуть 0

Драйвер gpio-am35 для ЗОСРВ "Нейтрино" редакции 2020

Этот коммит содержится в:
Коммит 5782deaa07
23 изменённых файлов: 1971 добавлений и 0 удалений

3
Makefile Обычный файл
Просмотреть файл

@ -0,0 +1,3 @@
LIST=ALL
LATE_DIRS=utils
include recurse.mk

58
README.md Обычный файл
Просмотреть файл

@ -0,0 +1,58 @@
## Общая структура GPIO драйвера
```
┌───────────────────────────┐
│ │
│ Устройство │
│ │
└─────────────▴─────────────┘
┌─────────────┴─────────────┐ ┌───────────────────────────┐
│ │ │ │
│ Драйвер (gpio-*) ◂───▸ /dev/gpio ◂── * ──┤ Клиентское приложение │
│ │ │ │
└───────────────────────────┘ └───────────────────────────┘
```
## Дерево исходных кодов
```
|- hardware/gpio/am35/
| |- *.* - Исходный код GPIO-драйвера для TI AM3517
| |- common.mk - Параметры сборки драйверов
| `- Makefile - Правила сборки дерева исходников
|
|- utils/gpio-ctrl/ - Исходный код типового клиентского приложения GPIO-драйвера
|
`- Makefile - Правила сборки дерева исходников
```
## Сборка драйвера
- Установить и настроить [комплект разработчика](https://help.kpda.ru/help/topic/ru.kpda.doc.dev_tools_ru/html/devkit/devkit.html) для [ЗОСРВ "Нейтрино" редакции 2020](https://help.kpda.ru/help/index.jsp).
- Выполнить команду:
```
make
```
## Запуск драйвера и обращение к нему
Общая схема запуска драйвера:
```
gpio-am35 &
```
Пример вызова клиентской утилиты:
```
gpio-ctrl -n /dev/gpio -p3 -d0 -o1
```

2
hardware/Makefile Обычный файл
Просмотреть файл

@ -0,0 +1,2 @@
LIST=hardware
include recurse.mk

2
hardware/gpio/Makefile Обычный файл
Просмотреть файл

@ -0,0 +1,2 @@
LIST=gpio
include recurse.mk

8
hardware/gpio/am35/Makefile Исполняемый файл
Просмотреть файл

@ -0,0 +1,8 @@
LIST=CPU
ifndef QRECURSE
QRECURSE=recurse.mk
ifdef QCONFIG
QRDIR=$(dir $(QCONFIG))
endif
endif
include $(QRDIR)$(QRECURSE)

8
hardware/gpio/am35/arm/Makefile Обычный файл
Просмотреть файл

@ -0,0 +1,8 @@
LIST=VARIANT
ifndef QRECURSE
QRECURSE=recurse.mk
ifdef QCONFIG
QRDIR=$(dir $(QCONFIG))
endif
endif
include $(QRDIR)$(QRECURSE)

1
hardware/gpio/am35/arm/le.v7/Makefile Обычный файл
Просмотреть файл

@ -0,0 +1 @@
include ../../common.mk

17
hardware/gpio/am35/common.mk Обычный файл
Просмотреть файл

@ -0,0 +1,17 @@
ifndef QCONFIG
QCONFIG=qconfig.mk
endif
include $(QCONFIG)
include $(MKFILES_ROOT)/qmacros.mk
-include $(PROJECT_ROOT)/roots.mk
define PINFO
PINFO DESCRIPTION=GPIO driver
endef
NAME := gpio-$(NAME)
USEFILE=$(PROJECT_ROOT)/$(NAME).use
INSTALLDIR = sbin
include $(MKFILES_ROOT)/qtargets.mk

126
hardware/gpio/am35/devctl.c Исполняемый файл
Просмотреть файл

@ -0,0 +1,126 @@
/*
* (c) 2017, SWD Embedded Systems Limited, http://www.kpda.ru
*/
#include "proto.h"
extern int verbose;
int pulse_coid = -1; // who to deliver the pulse to
int rcvid = -1; // who to deliver the pulse to
struct sigevent pulse_event; // will contain the pulse to be delivered
int gpio_devctl( resmgr_context_t *ctp, io_devctl_t *msg, gpio_ocb_t *ocb )
{
int status;
int nbytes = 0;
gpio_devctl_t *devmsg_ptr = NULL;
uint8_t pin;
gpio_dev_t *dev = ocb->hdr.attr;
if ( (status = iofunc_devctl_default( ctp, msg, &ocb->hdr )) != _RESMGR_DEFAULT )
return (_RESMGR_ERRNO( status ));
status=0;
switch ( msg->i.dcmd )
{
case DCMD_SET_INPUT:
// get a pointer to the structure
devmsg_ptr = (gpio_devctl_t*)_DEVCTL_DATA( msg->i );
pin = devmsg_ptr->set_input.pin_num;
status = hw_set_input( dev->hdl, pin );
if ( status < 0 )
return (EINVAL);
break;
case DCMD_SET_OUTPUT:
// get a pointer to the structure
devmsg_ptr = (gpio_devctl_t*)_DEVCTL_DATA( msg->i );
pin = devmsg_ptr->set_output.pin_num;
status = hw_set_output( dev->hdl, pin );
if ( status < 0 )
return (EINVAL);
break;
case DCMD_READ:
// get a pointer to the structure
devmsg_ptr = (gpio_devctl_t*)_DEVCTL_DATA( msg->i );
status = hw_cmd_read( dev->hdl, (void *)devmsg_ptr );
if ( status != 1 )
return (EINVAL);
msg->o.ret_val = 0;
return (_RESMGR_PTR( ctp, &msg->o, sizeof( msg->o ) + sizeof( gpio_devctl_read_t ) ));
break;
case DCMD_WRITE:
// get a pointer to the structure
devmsg_ptr = (gpio_devctl_t*)_DEVCTL_DATA( msg->i );
status = hw_cmd_write( dev->hdl, (void*)devmsg_ptr );
if ( status != 1 )
return (EINVAL);
msg->o.ret_val = 0;
return (_RESMGR_PTR( ctp, &msg->o, sizeof( msg->o ) + sizeof( gpio_devctl_write_t ) ));
break;
case DCMD_INT_ENABLE:
// get a pointer to the structure
devmsg_ptr = (gpio_devctl_t*)_DEVCTL_DATA( msg->i );
pin = devmsg_ptr->cmd_intterupt.pin_num;
// status = hw_int_enable_wlevel( dev->hdl, pin, devmsg_ptr->cmd_intterupt.level );
if ( hw_int_enable_wlevel( dev->hdl, pin, devmsg_ptr->cmd_intterupt.level ) != 0 )
return (EINVAL);
break;
case DCMD_INT_DISABLE:
// get a pointer to the structure
devmsg_ptr = (gpio_devctl_t*)_DEVCTL_DATA( msg->i );
pin = devmsg_ptr->cmd_intterupt.pin_num;
if ( hw_set_output( dev->hdl, pin ) < 0 )
{
gpio_slogf( "GPIO RM: GPIO pin %d interrupt disable failed ", pin );
return (EINVAL);
}
if ( hw_int_disable( dev->hdl, pin ) < 0 )
{
gpio_slogf( "GPIO RM: GPIO pin %d interrupt disable failed ", pin );
return (EINVAL);
}
break;
case DCMD_INT_ENABLE_WAIT_PULSE:
devmsg_ptr = (gpio_devctl_t*)_DEVCTL_DATA( msg->i );
rcvid = ctp->rcvid;
pulse_coid = devmsg_ptr->cmd_intterupt.coid;
pin = devmsg_ptr->cmd_intterupt.pin_num;
if ( hw_int_enable_wlevel( dev->hdl, pin, devmsg_ptr->cmd_intterupt.level ) != 0 )
{
gpio_slogf( "GPIO RM: GPIO pin %d interrupt enable failed ", pin );
return (EINVAL);
}
if ( verbose )
gpio_slogf( "GPIO RM: Interrupt PIN %d recived pulse_coid %d rcvid %d ",
pin, pulse_coid, rcvid );
return (_RESMGR_NPARTS( 0 ));
break;
default:
return (ENOSYS);
}
_IO_SET_WRITE_NBYTES( ctp, nbytes );
return (_RESMGR_NPARTS( 0 ));
}

7
hardware/gpio/am35/gpio-am35.use Исполняемый файл
Просмотреть файл

@ -0,0 +1,7 @@
%C - GPIO resource manager.
Syntax:
%C [options]
Options:
-v verbose level

385
hardware/gpio/am35/init.c Исполняемый файл
Просмотреть файл

@ -0,0 +1,385 @@
/*
* (c) 2017, SWD Embedded Systems Limited, http://www.kpda.ru
*/
#include "proto.h"
extern int verbose;
uint32_t gpio_pbase[] = { OMAP3530_GPIO1_BASE,
OMAP3530_GPIO2_BASE,
OMAP3530_GPIO3_BASE,
OMAP3530_GPIO4_BASE,
OMAP3530_GPIO5_BASE,
OMAP3530_GPIO6_BASE };
#define GPIO_PIN_NUM (pin_num - (gpio_num * 32))
gpio_dev_t * am35_hw_init( gpio_dev_t *dev )
{
am35_gpio_t *am35;
int i, j;
if ( -1 == ThreadCtl( _NTO_TCTL_IO, 0 ) )
{
gpio_slogf( "ThreadCtl" );
return (NULL);
}
am35 = calloc( 1, sizeof( am35_gpio_t ) );
if ( !am35 )
return (NULL);
for ( i = 0; i <= 5; i++ )
{
am35->gpiobase[i] = mmap_device_io( OMAP3530_GPIO_SIZE, gpio_pbase[i] );
if ( am35->gpiobase[i] == (uintptr_t)MAP_FAILED )
{
gpio_slogf( "mmap_device_io GPIO%d failed.", i );
for( j = 0; j < i; j++ )
munmap_device_io( am35->gpiobase[j], OMAP3530_GPIO_SIZE );
free( am35 );
return (NULL);
}
// Disable interrupts
out32( am35->gpiobase[i] + GPIO_IRQENABLE_1, 0 );
out32( am35->gpiobase[i] + GPIO_IRQENABLE_2, 0 );
// Disable interrupt High/Low level detect
out32( am35->gpiobase[i] + GPIO_LEVELDETECT0, 0 );
out32( am35->gpiobase[i] + GPIO_LEVELDETECT1, 0 );
out32( am35->gpiobase[i] + GPIO_RISINGDETECT, 0 );
out32( am35->gpiobase[i] + GPIO_FALLINGDETECT, 0 );
// Reset interrupt status
out32( am35->gpiobase[i] + GPIO_IRQSTATUS_1, 0xFFFFFFFF );
out32( am35->gpiobase[i] + GPIO_IRQSTATUS_2, 0xFFFFFFFF );
}
dev->hdl = am35;
return dev;
}
void am35_hw_fini( gpio_dev_t *dev )
{
am35_gpio_t *am35 = dev->hdl;
int i;
for ( i = 0; i <= 5; i++ )
munmap_device_io( am35->gpiobase[i], OMAP3530_GPIO_SIZE );
dev->hdl = NULL;
free( am35 );
}
int hw_cmd_read( void *hdl, void *buf )
{
am35_gpio_t *am35 = hdl;
int bytes = 1;
uint8_t pin_num;
uint8_t gpio_num;
gpio_devctl_t *devmsg_ptr = (gpio_devctl_t *)buf;
pin_num = devmsg_ptr->cmd_read.pin_num;
if ( pin_num > 191 )
{
gpio_slogf( "GPIO error: Valid GPIO pin number is from range 0 ~ 191." );
return (0);
}
gpio_num = pin_num / 32;
// check if it's input or output
if ( in32( am35->gpiobase[gpio_num] + GPIO_OE ) & (1 << GPIO_PIN_NUM) ) // GPIO set as input
{
if ( verbose )
gpio_slogf( "GPIO pin_num %d set as input ", pin_num );
if ( in32( am35->gpiobase[gpio_num] + GPIO_DATAIN ) & (1 << GPIO_PIN_NUM) )
devmsg_ptr->cmd_read.data = 1;
else
devmsg_ptr->cmd_read.data = 0;
} else {
// GPIO set as output
if ( verbose )
gpio_slogf( "GPIO pin_num %d set as output ", pin_num );
if ( in32( am35->gpiobase[gpio_num] + GPIO_DATAOUT ) & (1 << GPIO_PIN_NUM) )
devmsg_ptr->cmd_read.data = 1;
else
devmsg_ptr->cmd_read.data = 0;
}
if ( verbose )
{
gpio_slogf( "GPIO%d DATAIN REG 0x%X ", (gpio_num + 1), in32( am35->gpiobase[gpio_num] + GPIO_DATAIN ) );
gpio_slogf( "GPIO%d PIN %d [%d] data %d ", (gpio_num + 1), GPIO_PIN_NUM, pin_num, devmsg_ptr->cmd_read.data );
}
return bytes;
}
int hw_cmd_write( void *hdl, void *buf )
{
am35_gpio_t *am35 = hdl;
int bytes = 1;
uint8_t pin_num;
uint8_t gpio_num;
uint8_t value;
gpio_devctl_t *devmsg_ptr = (gpio_devctl_t *)buf;
pin_num = devmsg_ptr->cmd_write.pin_num;
value = devmsg_ptr->cmd_write.data;
if ( pin_num > 191 )
{
gpio_slogf( "GPIO error: Valid GPIO pin number is from range 0 ~ 191." );
return (0);
}
/* NOTE: we need to set the pins to GPIO mode for below operation.
* This is done in startup or the individual drivers by setting the
* conf_<module>_<pin> register */
gpio_num = pin_num / 32;
// check if it's input or output
if ( in32( am35->gpiobase[gpio_num] + GPIO_OE ) & (1 << GPIO_PIN_NUM) ) // GPIO set as input
{
gpio_slogf( "GPIO pin set as input, invalid for write." );
return (0);
}
if ( value )
out32( am35->gpiobase[gpio_num] + GPIO_SETDATAOUT, (1 << GPIO_PIN_NUM) );
else
out32( am35->gpiobase[gpio_num] + GPIO_CLEARDATAOUT, (1 << GPIO_PIN_NUM) );
return bytes;
}
int hw_set_input( void *hdl, uint8_t data )
{
am35_gpio_t *am35 = hdl;
uint8_t pin_num = data;
uint8_t gpio_num;
uint32_t temp;
if ( (pin_num > 191) || (pin_num < 0) )
{
gpio_slogf( "GPIO error: Valid GPIO pin number is from range 0 ~ 191." );
return (0);
}
gpio_num = pin_num / 32;
temp = in32( am35->gpiobase[gpio_num] + GPIO_OE );
out32( am35->gpiobase[gpio_num] + GPIO_OE, temp | (1 << GPIO_PIN_NUM) );
if ( verbose )
gpio_slogf( "GPIO%d PIN %d (%d) configured as input.", gpio_num, GPIO_PIN_NUM, pin_num );
return (0);
}
int hw_set_output( void *hdl, uint8_t data )
{
uint32_t temp;
am35_gpio_t *am35 = hdl;
uint8_t pin_num = data;
uint8_t gpio_num;
if ( (pin_num > 191) || (pin_num < 0) )
{
gpio_slogf( "GPIO error: Valid GPIO pin number is from range 0 ~ 191." );
return (-1);
}
gpio_num = pin_num / 32;
// check if it's input or output
if ( !(in32( am35->gpiobase[gpio_num] + GPIO_OE ) & (1 << GPIO_PIN_NUM)) ) // GPIO set as output
{
if ( verbose )
gpio_slogf( "GPIO pin already set as output." );
return (0);
} else {
temp = in32( am35->gpiobase[gpio_num] + GPIO_OE );
out32( am35->gpiobase[gpio_num] + GPIO_OE, temp & (~(1 << GPIO_PIN_NUM)) );
}
return (0);
}
int hw_int_enable_wlevel( void *hdl, uint8_t data, uint8_t int_level )
{
uint32_t temp;
am35_gpio_t *am35 = hdl;
uint8_t pin_num = data;
uint8_t gpio_num;
if ( (pin_num > 191) || (pin_num < 0) )
{
gpio_slogf( "GPIO error: Valid GPIO pin number is from range 0 ~ 191." );
return (-1);
}
gpio_num = pin_num / 32;
if ( int_level == GPIO_INT_LEVEL_LOW )
{
temp = in32( am35->gpiobase[gpio_num] + GPIO_LEVELDETECT0 );
out32( am35->gpiobase[gpio_num] + GPIO_LEVELDETECT0, temp | (1 << GPIO_PIN_NUM) );
} else
if ( int_level == GPIO_INT_LEVEL_HIGH )
{
temp = in32( am35->gpiobase[gpio_num] + GPIO_LEVELDETECT1 );
out32( am35->gpiobase[gpio_num] + GPIO_LEVELDETECT1, temp | (1 << GPIO_PIN_NUM) );
}
// Reset interrupt status
out32( am35->gpiobase[gpio_num] + GPIO_IRQSTATUS_1, (1 << GPIO_PIN_NUM) );
out32( am35->gpiobase[gpio_num] + GPIO_IRQSTATUS_2, (1 << GPIO_PIN_NUM) );
out32( am35->gpiobase[gpio_num] + GPIO_SETIRQENABLE1, (1 << GPIO_PIN_NUM) );
if ( verbose )
gpio_slogf( "GPIO%d PIN %d (%d) interrupt is enabled.", gpio_num, GPIO_PIN_NUM, pin_num );
if ( InterruptUnmask( OMAP3530_GPIO_6_IRQ, 0 ) == -1 )
{
gpio_slogf( "GPIO%d PIN %d (%d) interrupt enable failed.", gpio_num, GPIO_PIN_NUM, pin_num );
if ( verbose )
perror( "InterruptUnmask" );
return (-1);
}
return (0);
}
int hw_int_enable( void *hdl, uint8_t data )
{
am35_gpio_t *am35 = hdl;
uint8_t pin_num = data;
uint8_t gpio_num;
if ( (pin_num > 191) || (pin_num < 0) )
{
gpio_slogf( "GPIO error: Valid GPIO pin number is from range 0 ~ 191." );
return (-1);
}
gpio_num = pin_num / 32;
out32( am35->gpiobase[gpio_num] + GPIO_SETIRQENABLE1, (1 << GPIO_PIN_NUM) );
if ( verbose )
gpio_slogf( "GPIO%d PIN %d (%d) interrupt is enabled.", gpio_num, GPIO_PIN_NUM, pin_num );
if ( InterruptUnmask( OMAP3530_GPIO_6_IRQ, 0 ) == -1 )
{
gpio_slogf( "GPIO%d PIN %d (%d) interrupt unmask failed.", gpio_num, GPIO_PIN_NUM, pin_num );
if ( verbose )
perror( "GPIO RM: InterruptUnmask" );
return (-1);
}
return (0);
}
int hw_int_disable( void *hdl, uint8_t pin_num )
{
am35_gpio_t *am35 = hdl;
uint8_t gpio_num;
unsigned temp;
if ( (pin_num > 191) || (pin_num < 0) )
{
gpio_slogf( "GPIO error: Valid GPIO pin number is from range 0 ~ 191." );
return (-1);
}
gpio_num = pin_num / 32;
// Disable interrupt
out32( am35->gpiobase[gpio_num] + GPIO_CLEARIRQENABLE1, (1 << GPIO_PIN_NUM) );
// Disable interrupt High/Low level detect
temp = in32( am35->gpiobase[gpio_num] + GPIO_LEVELDETECT0 );
out32( am35->gpiobase[gpio_num] + GPIO_LEVELDETECT0, temp & (~(1 << GPIO_PIN_NUM)) );
temp = in32( am35->gpiobase[gpio_num] + GPIO_LEVELDETECT1 );
out32( am35->gpiobase[gpio_num] + GPIO_LEVELDETECT1, temp & (~(1 << GPIO_PIN_NUM)) );
// Reset interrupt status
out32( am35->gpiobase[gpio_num] + GPIO_IRQSTATUS_1, (1 << GPIO_PIN_NUM) );
out32( am35->gpiobase[gpio_num] + GPIO_IRQSTATUS_2, (1 << GPIO_PIN_NUM) );
if ( verbose )
gpio_slogf( "GPIO%d PIN %d (%d) interrupt is disabled.", gpio_num, GPIO_PIN_NUM, pin_num );
return (0);
}
int hw_irq_status( void *hdl, gpio_interrupt_t *gpio_int )
{
am35_gpio_t *am35 = hdl;
uint32_t temp,
i,
j;
uint8_t pin = 0,
level = 0;
for ( i = 0; i < 6; i++ )
{
temp = in32( am35->gpiobase[i] + GPIO_IRQSTATUS_1 );
if ( temp != 0x0 )
{
if ( verbose )
gpio_slogf( "GPIO IRQ status 0x%X ", temp );
// out32( am35->gpiobase[i] + GPIO_IRQSTATUS_1, temp );
for ( j = 0; j < 32; j++ )
{
if ( (temp & 0x1) == 0x1 )
{
pin = j;
break;
} else
temp = temp >> 1;
}
if ( in32( am35->gpiobase[i] + GPIO_LEVELDETECT0 ) & (1 << pin) )
level = GPIO_INT_LEVEL_LOW;
else if ( in32( am35->gpiobase[i] + GPIO_LEVELDETECT1 ) & (1 << pin) )
level = GPIO_INT_LEVEL_HIGH;
else
level = -1;
// out32( am35->gpiobase[i] + GPIO_IRQSTATUS_1, 1 << pin );
pin = pin + (i * 32);
hw_int_disable( hdl, pin);
gpio_int->pin = pin;
gpio_int->level = level;
return pin;
}
}
return (-1);
}

279
hardware/gpio/am35/main.c Исполняемый файл
Просмотреть файл

@ -0,0 +1,279 @@
/*
* (c) 2017, SWD Embedded Systems Limited, http://www.kpda.ru
*/
#include "proto.h"
int verbose = 0;
static volatile unsigned done = 0;
static gpio_dev_t *Dev;
extern gpio_dev_t *am35_hw_init( gpio_dev_t *dev );
void am35_hw_fini( gpio_dev_t *dev );
void *interrupt_thread( void *data );
struct sigevent int_event; // the SIGEV_INTR event the ISR will return
extern int pulse_coid; // who to deliver the pulse to
extern int rcvid; // who to deliver the pulse to
extern struct sigevent pulse_event; // will contain the pulse to be delivered
int gpio_slogf( const char *fmt, ... )
{
int status;
va_list arglist;
if ( verbose > 2 )
{
va_start( arglist, fmt );
vfprintf( stderr, fmt, arglist );
va_end( arglist );
fprintf( stderr, "\n" );
}
va_start( arglist, fmt );
status = vslogf( _SLOGC_GPIO, _SLOG_INFO, fmt, arglist );
va_end( arglist );
return status;
}
static void gpio_exit( int signo )
{
atomic_set( &done, 1 );
dispatch_unblock( Dev->ctp );
}
static int gpio_main( gpio_dev_t *dev )
{
resmgr_connect_funcs_t connect_funcs;
resmgr_io_funcs_t io_funcs;
resmgr_attr_t rattr;
iofunc_funcs_t ocb_funcs = { _IOFUNC_NFUNCS, gpio_ocb_calloc, gpio_ocb_free };
iofunc_mount_t mount = { 0, 0, 0, 0, &ocb_funcs };
dispatch_context_t *ctp;
char devname[PATH_MAX + 1];
struct sigaction sa;
if ( !dev )
return (-1);
Dev = dev;
if ( NULL == (dev->dpp = dispatch_create()) )
{
gpio_slogf( "GPIO RM: dispatch_create failed: %s", strerror( errno ) );
perror( "GPIO RM: dispatch_create() failed" );
return (-1);
}
/* set up i/o handler functions */
memset( &rattr, 0, sizeof( rattr ) );
rattr.nparts_max = GPIO_RESMGR_NPARTS_MIN;
rattr.msg_max_size = GPIO_RESMGR_MSGSIZE_MIN;
iofunc_func_init( _RESMGR_CONNECT_NFUNCS, &connect_funcs, _RESMGR_IO_NFUNCS, &io_funcs );
io_funcs.devctl = gpio_devctl;
iofunc_attr_init( &dev->hdr, S_IFCHR | 0666, NULL, NULL );
dev->hdr.mount = &mount;
/* register device name */
snprintf( devname, PATH_MAX, GPIO_DEVICE_NAME );
if ( -1 == (dev->id = resmgr_attach( dev->dpp, &rattr, devname, _FTYPE_ANY, 0,
&connect_funcs, &io_funcs, dev )) )
{
gpio_slogf( "GPIO RM: resmgr_attach failed: %s", strerror( errno ) );
perror( "GPIO RM: resmgr_attach() failed" );
return (-1);
}
if ( NULL == (dev->ctp = dispatch_context_alloc( dev->dpp )) )
{
gpio_slogf( "GPIO RM: dispatch_context_alloc failed: %s", strerror( errno ) );
perror( "GPIO RM: dispatch_context_alloc() failed" );
return (-1);
}
/* register exit handler */
sigemptyset( &sa.sa_mask );
sigaddset( &sa.sa_mask, SIGTERM );
sa.sa_handler = gpio_exit;
sa.sa_flags = 0;
sigaction( SIGTERM, &sa, NULL );
if ( -1 == pthread_create( NULL, NULL, interrupt_thread, NULL ) )
{
gpio_slogf( "GPIO RM: pthread_create failed: %s", strerror( errno ) );
perror( "GPIO RM: pthread_create() failed" );
return (-1);
}
/* background the process */
procmgr_daemon( 0, PROCMGR_DAEMON_NOCLOSE | PROCMGR_DAEMON_NODEVNULL );
/* wait for messages */
while ( !done )
{
if ( ctp = dispatch_block( dev->ctp ) )
{
dev->ctp = ctp;
dispatch_handler( dev->ctp );
} else
if ( errno != EFAULT )
atomic_set( &done, 1 );
}
/* Received SIGTERM: clean up */
resmgr_detach( dev->dpp, dev->id, _RESMGR_DETACH_ALL );
return (0);
}
void * interrupt_thread( void *data )
{
struct sigevent event; // pulse
gpio_dev_t *dev = Dev;
gpio_interrupt_t gpio_int;
int pin = -1;
struct sigevent gpio1_int_event;
struct sigevent gpio2_int_event;
struct sigevent gpio3_int_event;
struct sigevent gpio4_int_event;
struct sigevent gpio5_int_event;
struct sigevent gpio6_int_event;
if ( ThreadCtl( _NTO_TCTL_IO, 0 ) == -1 )
{
gpio_slogf( "GPIO RM: ThreadCtl failed: %s", strerror( errno ) );
perror( "GPIO RM: ThreadCtl" );
exit( EXIT_FAILURE );
}
// set up a SIGEV_INTR event structure to for the ISR to return, the ISR
// will deliver this event after every 1000th interrupt. When
// it does, InterruptWait() will unblock.
// this macro fills in the event structure with SIGEV_INTR
SIGEV_INTR_INIT( &gpio1_int_event );
SIGEV_INTR_INIT( &gpio2_int_event );
SIGEV_INTR_INIT( &gpio3_int_event );
SIGEV_INTR_INIT( &gpio4_int_event );
SIGEV_INTR_INIT( &gpio5_int_event );
SIGEV_INTR_INIT( &gpio6_int_event );
if ( InterruptAttachEvent( OMAP3530_GPIO_6_IRQ, &gpio6_int_event, 0 ) == -1 )
{
gpio_slogf( "GPIO RM: InterruptAttachEvent failed: %s", strerror( errno ) );
exit( EXIT_FAILURE );
}
if ( InterruptAttachEvent( OMAP3530_GPIO_1_IRQ, &gpio1_int_event, 0 ) == -1 )
{
gpio_slogf( "GPIO RM: InterruptAttachEvent failed: %s", strerror( errno ) );
exit( EXIT_FAILURE );
}
if ( InterruptAttachEvent( OMAP3530_GPIO_2_IRQ, &gpio2_int_event, 0 ) == -1 )
{
gpio_slogf( "GPIO RM: InterruptAttachEvent failed: %s", strerror( errno ) );
exit( EXIT_FAILURE );
}
if ( InterruptAttachEvent( OMAP3530_GPIO_3_IRQ, &gpio3_int_event, 0 ) == -1 )
{
gpio_slogf( "GPIO RM: InterruptAttachEvent failed: %s", strerror( errno ) );
exit( EXIT_FAILURE );
}
if ( InterruptAttachEvent( OMAP3530_GPIO_4_IRQ, &gpio4_int_event, 0 ) == -1 )
{
gpio_slogf( "GPIO RM: InterruptAttachEvent failed: %s", strerror( errno ) );
exit( EXIT_FAILURE );
}
if ( InterruptAttachEvent( OMAP3530_GPIO_5_IRQ, &gpio5_int_event, 0 ) == -1 )
{
gpio_slogf( "GPIO RM: InterruptAttachEvent failed: %s", strerror( errno ) );
exit( EXIT_FAILURE );
}
while ( 1 )
{
InterruptWait( 0, NULL );
gpio_slogf( "GPIO RM: unblocked from InterruptWait()" );
pin = hw_irq_status( dev->hdl, &gpio_int );
if ( pin != -1 )
gpio_slogf( "GPIO RM: Interrupt from PIN %d (level = %d)", gpio_int.pin, gpio_int.level );
else
continue;
if ( rcvid != -1 )
{
if ( verbose > 2 )
{
gpio_slogf( "GPIO RM delivering pulse" );
gpio_slogf( "GPIO RM: pulse_coid %d rcvid %d", pulse_coid, rcvid );
}
// fill in the event structure for a pulse
SIGEV_PULSE_INIT( &event, pulse_coid, SIGEV_PULSE_PRIO_INHERIT, _PULSE_CODE_MINAVAIL, pin );
if ( MsgDeliverEvent( rcvid, &event ) == -1 )
{
gpio_slogf( "GPIO RM: MsgDeliverEvent failed: %s", strerror( errno ) );
perror( "GPIO RM: MsgDeliverEvent" );
rcvid = -1;
}
// if ( MsgSendPulse( pulse_coid, -1, _PULSE_CODE_MINAVAIL, 0 ) == -1 )
// {
// gpio_slogf( "GPIO RM: MsgSendPulse failed: %s", strerror( errno ) );
// perror( "GPIO RM: MsgSendPulse" );
// }
if ( verbose > 2 )
gpio_slogf( "GPIO RM: pulse sent" );
if ( hw_int_enable_wlevel( dev->hdl, gpio_int.pin, gpio_int.level ) != 0 )
gpio_slogf( "GPIO RM GPIO pin %d interrupt enable failed", gpio_int.pin );
if ( InterruptUnmask( OMAP3530_GPIO_6_IRQ, 0 ) == -1 )
{
gpio_slogf( "GPIO RM: InterruptUnmask failed: %s", strerror( errno ) );
perror( "GPIO RM: InterruptUnmask" );
}
}
}
}
int main( int argc, char *argv[] )
{
int status;
int opt;
gpio_dev_t dev;
memset( &dev, 0, sizeof( dev ) );
while ( (opt = getopt( argc, argv, "v" )) != -1 )
{
switch ( opt )
{
case 'v':
verbose++;
break;
}
}
gpio_slogf( "GPIO RM: starting GPIO resource manager" );
am35_hw_init( &dev );
status = gpio_main( &dev );
am35_hw_fini( &dev );
return status;
}

22
hardware/gpio/am35/ocb.c Исполняемый файл
Просмотреть файл

@ -0,0 +1,22 @@
/*
* (c) 2017, SWD Embedded Systems Limited, http://www.kpda.ru
*/
#include "proto.h"
gpio_ocb_t * gpio_ocb_calloc( resmgr_context_t *ctp, gpio_dev_t *dev )
{
gpio_ocb_t *ocb;
if ( NULL == (ocb = calloc( 1, sizeof( *ocb ) )) )
return NULL;
return ocb;
}
void
gpio_ocb_free( gpio_ocb_t *ocb )
{
free( ocb );
}

77
hardware/gpio/am35/proto.h Исполняемый файл
Просмотреть файл

@ -0,0 +1,77 @@
/*
* (c) 2017, SWD Embedded Systems Limited, http://www.kpda.ru
*/
#ifndef _PROTO_H_INCLUDED
#define _PROTO_H_INCLUDED
#define PRINT_FUNCTIONNAME
struct gpio_dev;
struct gpio_ocb;
#define IOFUNC_ATTR_T struct gpio_dev
#define IOFUNC_OCB_T struct gpio_ocb
#define THREAD_POOL_PARAM_T dispatch_context_t
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <stdarg.h>
#include <hw/inout.h>
#include <sys/iofunc.h>
#include <sys/dispatch.h>
#include <devctl.h>
#include <atomic.h>
#include <sys/neutrino.h>
#include <sys/procmgr.h>
#include <sys/mman.h>
#include <time.h>
#include <sys/slog.h>
#include <arm/omap3530.h>
#include <hw/gpio_am35.h>
#define _SLOGC_GPIO 40
typedef struct gpio_dev {
iofunc_attr_t hdr;
dispatch_t *dpp;
dispatch_context_t *ctp;
int id;
iofunc_notify_t notify[3];
void *hdl;
} gpio_dev_t;
typedef struct gpio_ocb {
iofunc_ocb_t hdr;
} gpio_ocb_t;
typedef struct {
uintptr_t gpiobase[6];
} am35_gpio_t;
gpio_ocb_t *gpio_ocb_calloc( resmgr_context_t *ctp, gpio_dev_t *dev );
void gpio_ocb_free( gpio_ocb_t *ocb );
int gpio_devctl( resmgr_context_t *ctp, io_devctl_t *msg, gpio_ocb_t *ocb );
int gpio_slogf( const char *fmt, ... );
int hw_cmd_write( void *hdl, void *buf );
int hw_cmd_read( void *hdl, void *buf );
int hw_set_output( void *hdl, uint8_t data );
int hw_set_input( void *hdl, uint8_t data );
int hw_int_enable_wlevel( void *hdl, uint8_t data, uint8_t level );
int hw_int_enable( void *hdl, uint8_t data );
int hw_int_disable( void *hdl, uint8_t data );
int hw_irq_status( void *hdl, gpio_interrupt_t *gpio_int );
#endif

667
hardware/gpio/am35/public/arm/omap3530.h Обычный файл
Просмотреть файл

@ -0,0 +1,667 @@
/*
* (c) 2017, SWD Embedded Systems Limited, http://www.kpda.ru
*/
/*
* TI OMAP3530 processor with ARMv7 Cortex-A8 core
*/
#ifndef __ARM_OMAP3530_H_INCLUDED
#define __ARM_OMAP3530_H_INCLUDED
#define L4_35XX_BASE 0x48000000
#define L4_WK_35XX_BASE 0x48300000
#define L4_WK_OMAP_BASE L4_WK_OMAP_BASE
#define L4_PER_35XX_BASE 0x49000000
#define L4_PER_OMAP_BASE L4_PER_35XX_BASE
#define L4_35XX_EMU_BASE 0x54000000
#define L4_EMU_BASE L4_35XX_EMU_BASE
#define L3_35XX_BASE 0x68000000
#define L3_OMAP_BASE L3_35XX_BASE
#define OMAP3530_32KSYNCT_BASE 0x48320000
#define OMAP3530_CM_BASE 0x48004800
#define OMAP3530_PRM_BASE 0x48306800
#define OMAP353X_SMS_BASE 0x6C000000
#define OMAP353X_SDRC_BASE 0x6D000000
#define OMAP35XX_GPMC_BASE 0x6E000000
#define OMAP3530_SCM_BASE 0x48002000
#define OMAP3530_CTRL_BASE OMAP3530_SCM_BASE
#define OMAP35XX_IC_BASE 0x48200000
#define OMAP35XX_IVA_INTC_BASE 0x40000000
#define IRQ_SIR_IRQ 0x0040
#define OMAP35XX_DSP_BASE 0x58000000
#define OMAP35XX_DSP_MEM_BASE (OMAP35XX_DSP_BASE + 0x0)
#define OMAP35XX_DSP_IPI_BASE (OMAP35XX_DSP_BASE + 0x1000000)
#define OMAP35XX_DSP_MMU_BASE (OMAP35XX_DSP_BASE + 0x2000000)
/*
* System Control module
*/
#define OMAP3530_SYSCTL_BASE 0x48002000
#define OMAP3530_SYSCTL_SIZE 0x1000
/*
* System Control Registers, offset from base
*/
#define OMAP3530_SYSCTL_REVISION 0x000
#define OMAP3530_SYSCTL_SYSCONFIG 0x010
#define OMAP3530_SYSCTL_PADCONF(x) (0x030 + (x) * 4)
#define OMAP3530_SYSCTL_PADCONF_OFF 0x270
#define OMAP3530_SYSCTL_DEVCONF0 0x274
#define OMAP3530_SYSCTL_MEM_DFTRW0 0x278
#define OMAP3530_SYSCTL_MEM_DFTRW1 0x27C
#define OMAP3530_SYSCTL_MSUSPENDMUX_0 0x290
#define OMAP3530_SYSCTL_MSUSPENDMUX_1 0x294
#define OMAP3530_SYSCTL_MSUSPENDMUX_2 0x298
#define OMAP3530_SYSCTL_MSUSPENDMUX_3 0x29C
#define OMAP3530_SYSCTL_MSUSPENDMUX_4 0x2A0
#define OMAP3530_SYSCTL_MSUSPENDMUX_5 0x2A4
#define OMAP3530_SYSCTL_SEC_CTRL 0x2B0
#define OMAP3530_SYSCTL_DEVCONF1 0x2D8
#define OMAP3530_SYSCTL_CSIRXFE 0x2DC
#define OMAP3530_SYSCTL_SEC_STATUS 0x2E0
#define OMAP3530_SYSCTL_SEC_ERR_STATUS 0x2E4
#define OMAP3530_SYSCTL_SEC_ERR_STATUS_DEBUG 0x2E8
#define OMAP3530_SYSCTL_STATUS 0x2F0
#define OMAP3530_SYSCTL_GENERAL_PURPOSE_STATUS 0x2F4
#define OMAP3530_SYSCTL_RPUB_KEY_H_0 0x300
#define OMAP3530_SYSCTL_RPUB_KEY_H_1 0x304
#define OMAP3530_SYSCTL_RPUB_KEY_H_2 0x308
#define OMAP3530_SYSCTL_RPUB_KEY_H_3 0x30C
#define OMAP3530_SYSCTL_RPUB_KEY_H_4 0x310
#define OMAP3530_SYSCTL_RAND_KEY_0 0x318
#define OMAP3530_SYSCTL_RAND_KEY_1 0x31C
#define OMAP3530_SYSCTL_RAND_KEY_2 0x320
#define OMAP3530_SYSCTL_RAND_KEY_3 0x324
#define OMAP3530_SYSCTL_CUST_KEY_0 0x328
#define OMAP3530_SYSCTL_CUST_KEY_1 0x32C
#define OMAP3530_SYSCTL_CUST_KEY_2 0x330
#define OMAP3530_SYSCTL_CUST_KEY_3 0x334
#define OMAP3530_SYSCTL_TEST_KEY_0 0x338
#define OMAP3530_SYSCTL_TEST_KEY_1 0x33C
#define OMAP3530_SYSCTL_TEST_KEY_2 0x340
#define OMAP3530_SYSCTL_TEST_KEY_3 0x344
#define OMAP3530_SYSCTL_TEST_KEY_4 0x348
#define OMAP3530_SYSCTL_TEST_KEY_5 0x34C
#define OMAP3530_SYSCTL_TEST_KEY_6 0x350
#define OMAP3530_SYSCTL_TEST_KEY_7 0x354
#define OMAP3530_SYSCTL_TEST_KEY_8 0x358
#define OMAP3530_SYSCTL_TEST_KEY_9 0x35C
#define OMAP3530_SYSCTL_TEST_KEY_10 0x360
#define OMAP3530_SYSCTL_TEST_KEY_11 0x364
#define OMAP3530_SYSCTL_TEST_KEY_12 0x368
#define OMAP3530_SYSCTL_TEST_KEY_13 0x36C
/*
* Power, reset and clock management module
*/
#define OMAP3530_PRCM_BASE 0x48004000
#define OMAP3530_PRCM_SIZE 0x2000
/*
* Power, reset and Clock management Registers
*/
#define OMAP3530_PRCM_IVA2_CM 0x48004000
#define OMAP3530_PRCM_OCP_SYSREGS_CM 0x48004800
#define OMAP3530_PRCM_MPU_CM 0x48004900
#define OMAP3530_PRCM_CORE_CM 0x48004A00
#define OMAP3530_PRCM_SGX_CM 0x48004B00
#define OMAP3530_PRCM_WKUP_CM 0x48004C00
#define OMAP3530_PRCM_CCR_CM 0x48004D00
#define OMAP3530_PRCM_DSS_CM 0x48004E00
#define OMAP3530_PRCM_CAM_CM 0x48004F00
#define OMAP3530_PRCM_PER_CM 0x48005000
#define OMAP3530_PRCM_EMU_CM 0x48005100
#define OMAP3530_PRCM_GR_CM 0x48005200
#define OMAP3530_PRCM_NEON_CM 0x48005300
#define OMAP3530_PRCM_USBHOST_CM 0x48005400
/* Turn all Clocks ON */
#define OMAP3530_FCK_IVA2_ON 0x00000001
#define OMAP3530_FCK_CORE1_ON 0x43fffe00
#define OMAP3530_FCK_CORE3_ON 0x00000007
#define OMAP3530_ICK_CORE1_ON 0x7ffffed2
#define OMAP3530_ICK_CORE2_ON 0x0000001f
#define OMAP3530_ICK_CORE3_ON 0x00000004
#define OMAP3530_FCK_WKUP_ON 0x000002e9
#define OMAP3530_ICK_WKUP_ON 0x0000023f
#define OMAP3530_FCK_DSS_ON 0x00000005 /* tv+dss1 (not dss2) */
#define OMAP3530_ICK_DSS_ON 0x00000001
#define OMAP3530_FCK_CAM_ON 0x00000001
#define OMAP3530_ICK_CAM_ON 0x00000001
#define OMAP3530_FCK_PER_ON 0x0003ffff
#define OMAP3530_ICK_PER_ON 0x0003ffff
/* Module offsets from both CM_BASE & PRM_BASE */
/* Technically OCP_MOD is 35xx only, and PLL_MOD is CCR_MOD on 3530 */
#define OMAP3530_OCP_MOD 0x000
#define OMAP3530_MPU_MOD 0x100
#define OMAP3530_CORE_MOD 0x200
#define OMAP3530_GFX_MOD 0x300
#define OMAP3530_WKUP_MOD 0x400
#define OMAP3530_PLL_MOD 0x500
/* IVA2_CM Register */
#define OMAP3530_CM_FCLKEN_IVA2 0x0000
#define OMAP3530_CM_CLKEN_PLL_IVA2 0x0004
#define OMAP3530_CM_IDLEST_IVA2 0x0020
#define OMAP3530_CM_IDLEST_PLL_IVA2 0x0024
#define OMAP3530_CM_AUTOIDLE_PLL_IVA2 0x0034
#define OMAP3530_CM_CLKSEL1_PLL_IVA2 0x0040
#define OMAP3530_CM_CLKSEL2_PLL_IVA2 0x0044
#define OMAP3530_CM_CLKSTCTRL_IVA2 0x0048
#define OMAP3530_CM_CLKSTST_IVA2 0x004C
/* OCP_System_Registers_CM Register */
#define OMAP3530_CM_REVISION 0x0000
#define OMAP3530_CM_SYSCONFIG 0x0010
/* MPU_CM Register */
#define OMAP3530_CM_CLKEN_PLL_MPU 0x0004
#define OMAP3530_CM_IDLEST_MPU 0x0020
#define OMAP3530_CM_IDLEST_PLL_MPU 0x0024
#define OMAP3530_CM_AUTOIDLE_PLL_MPU 0x0034
#define OMAP3530_CM_CLKSEL1_PLL_MPU 0x0040
#define OMAP3530_CM_CLKSEL2_PLL_MPU 0x0044
#define OMAP3530_CM_CLKSTCTRL_MPU 0x0048
#define OMAP3530_CM_CLKSTST_MPU 0x004C
/* CORE_CM Register */
#define OMAP3530_CM_FCLKEN1_CORE 0x0000
#define OMAP3530_CM_FCLKEN3_CORE 0x0008
#define OMAP3530_CM_ICLKEN1_CORE 0x0010
#define OMAP3530_CM_ICLKEN2_CORE 0x0014
#define OMAP3530_CM_ICLKEN3_CORE 0x0018
#define OMAP3530_CM_IDLEST1_CORE 0x0020
#define OMAP3530_CM_IDLEST2_CORE 0x0024
#define OMAP3530_CM_IDLEST3_CORE 0x0028
#define OMAP3530_CM_AUTOIDLE1_CORE 0x0030
#define OMAP3530_CM_AUTOIDLE2_CORE 0x0034
#define OMAP3530_CM_AUTOIDLE3_CORE 0x0038
#define OMAP3530_CM_CLKSEL_CORE RW 0x0040
#define OMAP3530_CM_CLKSTCTRL_CORE 0x0048
#define OMAP3530_CM_CLKSTST_CORE 0x004C
/* SGX_CM Register */
#define OMAP3530_CM_FCLKEN_SGX 0x0000
#define OMAP3530_CM_ICLKEN_SGX 0x0010
#define OMAP3530_CM_IDLEST_SGX 0x0020
#define OMAP3530_CM_CLKSEL_SGX 0x0040
#define OMAP3530_CM_SLEEPDEP_SGX 0x0044
#define OMAP3530_CM_CLKSTCTRL_SGX 0x0048
#define OMAP3530_CM_CLKSTST_SGX 0x004C
/* WKUP_CM Register */
#define OMAP3530_CM_FCLKEN_WKUP 0x0000
#define OMAP3530_CM_ICLKEN_WKUP 0x0010
#define OMAP3530_CM_IDLEST_WKUP 0x0020
#define OMAP3530_CM_AUTOIDLE_WKUP 0x0030
#define OMAP3530_CM_CLKSEL_WKUP 0x0040
/* Clock_Control_Registers_CM Register */
#define OMAP3530_CM_CLKEN_PLL 0x0000
#define OMAP3530_CM_CLKEN2_PLL 0x0004
#define OMAP3530_CM_IDLEST_CKGEN 0x0020
#define OMAP3530_CM_IDLEST2_CKGEN 0x0024
#define OMAP3530_CM_AUTOIDLE_PLL 0x0030
#define OMAP3530_CM_AUTOIDLE2_PLL 0x0034
#define OMAP3530_CM_CLKSEL1_PLL 0x0040
#define OMAP3530_CM_CLKSEL2_PLL 0x0044
#define OMAP3530_CM_CLKSEL3_PLL 0x0048
#define OMAP3530_CM_CLKSEL4_PLL 0x004C
#define OMAP3530_CM_CLKSEL5_PLL 0x0050
#define OMAP3530_CM_CLKOUT_CTRL 0x0070
/* DSS_CM Register */
#define OMAP3530_CM_FCLKEN_DSS 0x0000
#define OMAP3530_CM_ICLKEN_DSS 0x0010
#define OMAP3530_CM_IDLEST_DSS 0x0020
#define OMAP3530_CM_AUTOIDLE_DSS 0x0030
#define OMAP3530_CM_CLKSEL_DSS 0x0040
#define OMAP3530_CM_SLEEPDEP_DSS 0x0044
#define OMAP3530_CM_CLKSTCTRL_DSS 0x0048
#define OMAP3530_CM_CLKSTST_DSS 0x004C
/* CAM_CM Register */
#define OMAP3530_CM_FCLKEN_CAM 0x0000
#define OMAP3530_CM_ICLKEN_CAM 0x0010
#define OMAP3530_CM_IDLEST_CAM 0x0020
#define OMAP3530_CM_AUTOIDLE_CAM 0x0030
#define OMAP3530_CM_CLKSEL_CAM 0x0040
#define OMAP3530_CM_SLEEPDEP_CAM 0x0044
#define OMAP3530_CM_CLKSTCTRL_CAM 0x0048
#define OMAP3530_CM_CLKSTST_CAM 0x004C
/* PER_CM Register */
#define OMAP3530_CM_FCLKEN_PER 0x0000
#define OMAP3530_CM_ICLKEN_PER 0x0010
#define OMAP3530_CM_IDLEST_PER 0x0020
#define OMAP3530_CM_AUTOIDLE_PER 0x0030
#define OMAP3530_CM_CLKSEL_PER 0x0040
#define OMAP3530_CM_SLEEPDEP_PER 0x0044
#define OMAP3530_CM_CLKSTCTRL_PER 0x0048
#define OMAP3530_CM_CLKSTST_PER 0x004C
/* EMU_CM Register */
#define OMAP3530_CM_CLKSEL1_EMU 0x0040
#define OMAP3530_CM_CLKSTCTRL_EMU 0x0048
#define OMAP3530_CM_CLKSTST_EMU 0x004C
#define OMAP3530_CM_CLKSEL2_EMU 0x0050
#define OMAP3530_CM_CLKSEL3_EMU 0x0054
/* Global_Registers_CM Register */
#define OMAP3530_CM_POLCTRL 0x009C
/* NEON_CM Register */
#define OMAP3530_CM_IDLEST_NEON 0x0020
#define OMAP3530_CM_CLKSTCTRL_NEON 0x0048
/* USBHOST_CM Register */
#define OMAP3530_CM_FCLKEN_USBHOST 0x0000
#define OMAP3530_CM_ICLKEN_USBHOST 0x0010
#define OMAP3530_CM_IDLEST_USBHOST 0x0020
#define OMAP3530_CM_AUTOIDLE_USBHOST 0x0030
#define OMAP3530_CM_SLEEPDEP_USBHOST 0x0044
#define OMAP3530_CM_CLKSTCTRL_USBHOST 0x0048
#define OMAP3530_CM_CLKSTST_USBHOST 0x004C
/* PRCM */
#define OMAP35XX_CM_FCLKEN_IVA2 0x48004000
#define OMAP35XX_CM_CLKEN_PLL_IVA2 0x48004004
#define OMAP35XX_CM_IDLEST_PLL_IVA2 0x48004024
#define OMAP35XX_CM_CLKSEL1_PLL_IVA2 0x48004040
#define OMAP35XX_CM_CLKSEL2_PLL_IVA2 0x48004044
#define OMAP35XX_CM_CLKEN_PLL_MPU 0x48004904
#define OMAP35XX_CM_IDLEST_PLL_MPU 0x48004924
#define OMAP35XX_CM_CLKSEL1_PLL_MPU 0x48004940
#define OMAP35XX_CM_CLKSEL2_PLL_MPU 0x48004944
#define OMAP35XX_CM_FCLKEN1_CORE 0x48004a00
#define OMAP35XX_CM_FCLKEN3_CORE 0x48004a08
#define OMAP35XX_CM_ICLKEN1_CORE 0x48004a10
#define OMAP35XX_CM_ICLKEN2_CORE 0x48004a14
#define OMAP35XX_CM_ICLKEN3_CORE 0x48004a18
#define OMAP35XX_CM_CLKSEL_CORE 0x48004a40
#define OMAP35XX_CM_FCLKEN_GFX 0x48004b00
#define OMAP35XX_CM_ICLKEN_GFX 0x48004b10
#define OMAP35XX_CM_CLKSEL_GFX 0x48004b40
#define OMAP35XX_CM_FCLKEN_WKUP 0x48004c00
#define OMAP35XX_CM_ICLKEN_WKUP 0x48004c10
#define OMAP35XX_CM_CLKSEL_WKUP 0x48004c40
#define OMAP35XX_CM_IDLEST_WKUP 0x48004c20
#define OMAP35XX_CM_CLKEN_PLL 0x48004d00
#define OMAP35XX_CM_IDLEST_CKGEN 0x48004d20
#define OMAP35XX_CM_CLKSEL1_PLL 0x48004d40
#define OMAP35XX_CM_CLKSEL2_PLL 0x48004d44
#define OMAP35XX_CM_CLKSEL3_PLL 0x48004d48
#define OMAP35XX_CM_FCLKEN_DSS 0x48004e00
#define OMAP35XX_CM_ICLKEN_DSS 0x48004e10
#define OMAP35XX_CM_CLKSEL_DSS 0x48004e40
#define OMAP35XX_CM_FCLKEN_CAM 0x48004f00
#define OMAP35XX_CM_ICLKEN_CAM 0x48004f10
#define OMAP35XX_CM_CLKSEL_CAM 0x48004F40
#define OMAP35XX_CM_FCLKEN_PER 0x48005000
#define OMAP35XX_CM_ICLKEN_PER 0x48005010
#define OMAP35XX_CM_CLKSEL_PER 0x48005040
#define OMAP35XX_CM_CLKSEL1_EMU 0x48005140
/* CM_IDLEST_MPU */
#define OMAP3530_ST_MPU (1 << 0)
/* CM_CLKSEL1_PLL_MPU */
#define OMAP3530_MPU_CLK_SRC_SHIFT 19
#define OMAP3530_MPU_CLK_SRC_MASK (0x3 << 19)
#define OMAP3530_MPU_DPLL_MULT_SHIFT 8
#define OMAP3530_MPU_DPLL_MULT_MASK (0x7ff << 8)
#define OMAP3530_MPU_DPLL_DIV_SHIFT 0
#define OMAP3530_MPU_DPLL_DIV_MASK (0x7f << 0)
/* CM_CLKSEL2_PLL_MPU */
#define OMAP3530_MPU_DPLL_CLKOUT_DIV_SHIFT 0
#define OMAP3530_MPU_DPLL_CLKOUT_DIV_MASK (0x1f << 0)
/* CM_CLKSEL1_PLL */
#define OMAP35XX_DPLL_CLKOUT_DIV_SHIFT 27
#define OMAP35XX_DPLL_CLKOUT_DIV_MASK (0x1f << 27)
#define OMAP35XX_DPLL_MULT_SHIFT 16
#define OMAP35XX_DPLL_MULT_MASK (0x7ff << 12)
#define OMAP35XX_DPLL_DIV_SHIFT 8
#define OMAP35XX_DPLL_DIV_MASK (0x7f << 8)
#define OMAP35XX_96M_SOURCE_SHIFT 6
#define OMAP35XX_96M_SOURCE (1 << 6)
#define OMAP35XX_54M_SOURCE_SHIFT 5
#define OMAP35XX_54M_SOURCE (1 << 5)
#define OMAP35XX_48M_SOURCE_SHIFT 3
#define OMAP35XX_48M_SOURCE (1 << 3)
/*
* Watchdog Timer
*/
#define OMAP3530_WDT1_BASE 0x4830C000
#define OMAP3530_WDT2_BASE 0x48314000
#define OMAP3530_WDT3_BASE 0x49030000
#define OMAP3530_WDT2_WKUP_BASE 0x54714000
#define OMAP3530_WDT_SIZE 0x1000
/*
* Watchdog Timer Registers, offset from base
*/
#define OMAP3530_WD_SYSCONFIG 0x10
#define OMAP3530_WD_SYSSTATUS 0x14
#define OMAP3530_WD_WISR 0x18
#define OMAP3530_WD_WIER 0x1C
#define OMAP3530_WCLR 0x24
#define OMAP3530_WCRR 0x28
#define OMAP3530_WLDR 0x2C
#define OMAP3530_WTGR 0x30
#define OMAP3530_WWPS 0x34
#define OMAP3530_WSPR 0x48
/*
* General-Purpose Timer
*/
#define OMAP3530_GPT1_BASE 0x48318000
#define OMAP3530_GPT2_BASE 0x49032000
#define OMAP3530_GPT3_BASE 0x49034000
#define OMAP3530_GPT4_BASE 0x49036000
#define OMAP3530_GPT5_BASE 0x49038000
#define OMAP3530_GPT6_BASE 0x4903A000
#define OMAP3530_GPT7_BASE 0x4903C000
#define OMAP3530_GPT8_BASE 0x4903E000
#define OMAP3530_GPT9_BASE 0x49040000
#define OMAP3530_GPT10_BASE 0x48086000
#define OMAP3530_GPT11_BASE 0x48088000
#define OMAP3530_GPT12_BASE 0x48304000
#define OMAP3530_GPT1_WKUP_BASE 0x54718000
#define OMAP3530_GPT_SIZE 0x1000
/*
* General-Purpose Timer Registers, offset from base
*/
/* Defs for GPTIMER5 to GPTIMER8 */
#define OMAP3530_GPT_TIOCP_CFG 0x10
#define OMAP3530_GPT_TISTAT 0x14
#define OMAP3530_GPT_TISR 0x18
#define OMAP3530_GPT_TIER 0x1C
#define OMAP3530_GPT_TWER 0x20
#define OMAP3530_GPT_TCLR 0x24
#define OMAP3530_GPT_TCRR 0x28
#define OMAP3530_GPT_TLDR 0x2C
#define OMAP3530_GPT_TTGR 0x30
#define OMAP3530_GPT_TWPS 0x34
#define OMAP3530_GPT_TMAR 0x38
#define OMAP3530_GPT_TCAR1 0x3C
#define OMAP3530_GPT_TSICR 0x40
#define OMAP3530_GPT_TCAR2 0x44
/* Extra defs for GPTIMER1 to GPTIMER4 Register, and for GPTIMER9 to GPTIMER12 */
#define OMAP3530_GPT_TPIR 0x048
#define OMAP3530_GPT_TNIR 0x04C
#define OMAP3530_GPT_TCVR 0x050
#define OMAP3530_GPT_TOCR 0x054
#define OMAP3530_GPT_TOWR 0x058
/*
* SDMA4
*/
#define OMAP3530_DMA4_GENERAL_BASE 0x48056000
#define OMAP3530_DMA4_GENERAL_REGION_LEN 0x80
#define OMAP3530_DMA4_IRQSTATUS_L0 0x08
#define OMAP3530_DMA4_IRQSTATUS_L1 0x0c
#define OMAP3530_DMA4_IRQSTATUS_L2 0x10
#define OMAP3530_DMA4_IRQSTATUS_L3 0x14
#define OMAP3530_DMA4_IRQENABLE_L0 0x18
#define OMAP3530_DMA4_IRQENABLE_L1 0x1c
#define OMAP3530_DMA4_IRQENABLE_L2 0x20
#define OMAP3530_DMA4_IRQENABLE_L3 0x24
#define OMAP3530_DMA4_SYSSTATUS 0x28
#define OMAP3530_DMA4_OCP_SYSCONFIG 0x2C
#define OMAP3530_DMA4_CAPS_0_REG 0x64
#define OMAP3530_DMA4_CAPS_2_REG 0x6c
#define OMAP3530_DMA4_CAPS_3_REG 0x70
#define OMAP3530_DMA4_CAPS_4_REG 0x74
#define OMAP3530_DMA4_GCR_REG 0x78
#define GCR_ARBITRATION_RATE 0xff0000
#define DMA_DEFAULT_FIFO_DEPTH 0x10
#define OMAP3530_SDMA_IRQ 256
/*
* USB
*/
#define OMAP3530_USB_BASE 0x48064000
#define OMAP3530_USB_SIZE 0x1000
/*
* UARTs
*/
#define OMAP3530_UART1_BASE 0x4806A000
#define OMAP3530_UART2_BASE 0x4806C000
#define OMAP3530_UART3_BASE 0x49020000 /* UART/IrDA/CIR */
#define OMAP3530_UART_SIZE 0x1000
/*
* Interrupt Controller
*/
#define OMAP3530_INTC_BASE 0x48200000
#define OMAP3530_INTC_SIZE 0x280
/*
* Interrupt controller registers,
* offset from base
*/
#define OMAP3530_INTC_IRQ_PRIORITY 0x060
#define OMAP3530_INTC_FIQ_PRIORITY 0x064
#define OMAP3530_INTC_THRESHOLD 0x068
/*
* GPIOs
*/
#define OMAP3530_GPIO1_BASE 0x48310000
#define OMAP3530_GPIO2_BASE 0x49050000
#define OMAP3530_GPIO3_BASE 0x49052000
#define OMAP3530_GPIO4_BASE 0x49054000
#define OMAP3530_GPIO5_BASE 0x49056000
#define OMAP3530_GPIO6_BASE 0x49058000
#define OMAP3530_GPIO_SIZE 0x1000
#define GPIO_REVISION 0x000
#define GPIO_SYSCONFIG 0x010
#define GPIO_SYSSTATUS 0x014
#define GPIO_IRQSTATUS_1 0x018
#define GPIO_IRQENABLE_1 0x01C
#define GPIO_WAKEUPUNABLE 0x020
#define GPIO_IRQSTATUS_2 0x028
#define GPIO_IRQENABLE_2 0x02C
#define GPIO_CTRL 0x030
#define GPIO_OE 0x034
#define GPIO_DATAIN 0x038
#define GPIO_DATAOUT 0x03C
#define GPIO_LEVELDETECT0 0x040
#define GPIO_LEVELDETECT1 0x044
#define GPIO_RISINGDETECT 0x048
#define GPIO_FALLINGDETECT 0x04C
#define GPIO_DEBOUNCENABLE 0x050
#define GPIO_DEBOUNCINGTIME 0x054
#define GPIO_CLEARIRQENABLE1 0x060
#define GPIO_SETIRQENABLE1 0x064
#define GPIO_CLEARIRQENABLE2 0x070
#define GPIO_SETIRQENABLE2 0x074
#define GPIO_CLEARWKUENA 0x080
#define GPIO_SETWKUENA 0x084
#define GPIO_CLEARDATAOUT 0x090
#define GPIO_SETDATAOUT 0x094
#define OMAP3530_GPIO_1_IRQ 29 /*Interrupt numbers for GPIO 1-6 */
#define OMAP3530_GPIO_2_IRQ 30
#define OMAP3530_GPIO_3_IRQ 31
#define OMAP3530_GPIO_4_IRQ 32
#define OMAP3530_GPIO_5_IRQ 33
#define OMAP3530_GPIO_6_IRQ 34
/*
* SMS
*/
#define OMAP3530_SMS_BASE 0x68008000
#define OMAP3530_SMS_SIZE 0x10000
/*
* SDRC
*/
#define OMAP3530_SDRC_BASE 0x6D000000
#define OMAP3530_SDRC_SIZE 0x10000
/*
* GPMC
*/
#define OMAP3530_GPMC_BASE 0x6E000000
#define OMAP3530_GPMC_SIZE 0x1000000
/*
* GPMC registers, offset from base address
*/
#define OMAP3530_GPMC_BCH_RESULT0_0 0x240
#define OMAP3530_GPMC_BCH_RESULT0_1 0x250
#define OMAP3530_GPMC_BCH_RESULT0_2 0x260
#define OMAP3530_GPMC_BCH_RESULT0_3 0x270
#define OMAP3530_GPMC_BCH_RESULT0_4 0x280
#define OMAP3530_GPMC_BCH_RESULT0_5 0x290
#define OMAP3530_GPMC_BCH_RESULT0_6 0x2A0
#define OMAP3530_GPMC_BCH_RESULT0_7 0x2B0
#define OMAP3530_GPMC_BCH_RESULT1_0 0x244
#define OMAP3530_GPMC_BCH_RESULT1_1 0x254
#define OMAP3530_GPMC_BCH_RESULT1_2 0x264
#define OMAP3530_GPMC_BCH_RESULT1_3 0x274
#define OMAP3530_GPMC_BCH_RESULT1_4 0x284
#define OMAP3530_GPMC_BCH_RESULT1_5 0x294
#define OMAP3530_GPMC_BCH_RESULT1_6 0x2A4
#define OMAP3530_GPMC_BCH_RESULT1_7 0x2B4
#define OMAP3530_GPMC_BCH_RESULT2_0 0x248
#define OMAP3530_GPMC_BCH_RESULT2_1 0x258
#define OMAP3530_GPMC_BCH_RESULT2_2 0x268
#define OMAP3530_GPMC_BCH_RESULT2_3 0x278
#define OMAP3530_GPMC_BCH_RESULT2_4 0x288
#define OMAP3530_GPMC_BCH_RESULT2_5 0x298
#define OMAP3530_GPMC_BCH_RESULT2_6 0x2A8
#define OMAP3530_GPMC_BCH_RESULT2_7 0x2B8
#define OMAP3530_GPMC_BCH_RESULT3_0 0x24C
#define OMAP3530_GPMC_BCH_RESULT3_1 0x25C
#define OMAP3530_GPMC_BCH_RESULT3_2 0x26C
#define OMAP3530_GPMC_BCH_RESULT3_3 0x27C
#define OMAP3530_GPMC_BCH_RESULT3_4 0x28C
#define OMAP3530_GPMC_BCH_RESULT3_5 0x29C
#define OMAP3530_GPMC_BCH_RESULT3_6 0x2AC
#define OMAP3530_GPMC_BCH_RESULT3_7 0x2BC
#define OMAP3530_GPMC_BCH_SWDATA 0x2D0
/*
* L4 Peripherals - L4 Wakeup and L4 Core now
*/
#define OMAP35XX_CORE_L4_IO_BASE 0x48000000
#define OMAP35XX_WAKEUP_L4_IO_BASE 0x48300000
/* Clock_Control_Registers_PRM */
#define OMAP35XX_PRM_CLKSEL 0x48306d40
/* Global_Registers_PRM */
#define OMAP35XX_GR_PRM_BASE 0x48307200
#define OMAP35XX_GR_PRM_SIZE 0x100
#define OMAP35XX_GR_PRM_RSTCTRL 0x50
#define OMAP35XX_PRM_RSTCTRL 0x48307250
#define OMAP35XX_PRM_CLKSRC_CTRL 0x48307270
#define OMAP35XX_L4_PER 0x49000000
#define OMAP35XX_L4_IO_BASE OMAP35XX_CORE_L4_IO_BASE
/* Fuse bits indicating max clock rate */
#define OMAP35XX_720M_DEVICE_ID 0x4830a20c
#define OMAP35XX_720M_DEVICE_ID_SKUID_MASK 0x0f
#define OMAP35XX_DEVICE_IS_720M_CAPABLE 0x08
/* omap37xx device id registers */
#define OMAP_CONTROL_ID_CODE 0x4830a204
#define OMAP37XX_DEVICE_FAMILY 0x0b89102f
#define OMAP37XX_DEVICE_FAMILY_MASK 0x0fffffff
#define OMAP37XX_CONT_DEV_STAT_REG 0x4800244c
#define OMAP37XX_DEVICE_ID_MASK 0x0f00
#define OMAP37XX_1000M_CAPABLE 0x0e00
#define OMAP37XX_800M_CAPABLE 0x0c00
/* 32KTIMER */
#define OMAP35XX_SYNC_32KTIMER_BASE 0x48320000
/* I2C base */
#define OMAP35XX_I2C_BASE1 (OMAP35XX_CORE_L4_IO_BASE + 0x70000)
#define OMAP35XX_I2C_BASE2 (OMAP35XX_CORE_L4_IO_BASE + 0x72000)
#define OMAP35XX_I2C_BASE3 (OMAP35XX_CORE_L4_IO_BASE + 0x60000)
#define OMAP3530_I2C_1_IRQ 56 /*Interrupt number for I2C 1 */
#define OMAP3530_I2C_2_IRQ 57 /*Interrupt number for I2C 2 */
#define OMAP3530_I2C_3_IRQ 61 /*Interrupt number for I2C 3 */
/* Stuff on L3 Interconnect */
#define OMAP35XX_OMAP35XX_SMX_APE_BASE 0x68000000
/* SMX-APE */
#define OMAP35XX_PM_RT_APE_BASE_ADDR_ARM (OMAP35XX_SMX_APE_BASE + 0x10000)
#define OMAP35XX_PM_GPMC_BASE_ADDR_ARM (OMAP35XX_SMX_APE_BASE + 0x12400)
#define OMAP35XX_PM_OCM_RAM_BASE_ADDR_ARM (OMAP35XX_SMX_APE_BASE + 0x12800)
#define OMAP35XX_PM_OCM_ROM_BASE_ADDR_ARM (OMAP35XX_SMX_APE_BASE + 0x12C00)
#define OMAP35XX_PM_IVA2_BASE_ADDR_ARM (OMAP35XX_SMX_APE_BASE + 0x14000)
#define OMAP35XX_RT_REQ_INFO_PERMISSION_1 (OMAP35XX_PM_RT_APE_BASE_ADDR_ARM + 0x68)
#define OMAP35XX_RT_READ_PERMISSION_0 (OMAP35XX_PM_RT_APE_BASE_ADDR_ARM + 0x50)
#define OMAP35XX_RT_WRITE_PERMISSION_0 (OMAP35XX_PM_RT_APE_BASE_ADDR_ARM + 0x58)
#define OMAP35XX_RT_ADDR_MATCH_1 (OMAP35XX_PM_RT_APE_BASE_ADDR_ARM + 0x60)
#define OMAP35XX_GPMC_REQ_INFO_PERMISSION_0 (OMAP35XX_PM_GPMC_BASE_ADDR_ARM + 0x48)
#define OMAP35XX_GPMC_READ_PERMISSION_0 (OMAP35XX_PM_GPMC_BASE_ADDR_ARM + 0x50)
#define OMAP35XX_GPMC_WRITE_PERMISSION_0 (OMAP35XX_PM_GPMC_BASE_ADDR_ARM + 0x58)
#define OMAP35XX_OCM_REQ_INFO_PERMISSION_0 (OMAP35XX_PM_OCM_RAM_BASE_ADDR_ARM + 0x48)
#define OMAP35XX_OCM_READ_PERMISSION_0 (OMAP35XX_PM_OCM_RAM_BASE_ADDR_ARM + 0x50)
#define OMAP35XX_OCM_WRITE_PERMISSION_0 (OMAP35XX_PM_OCM_RAM_BASE_ADDR_ARM + 0x58)
#define OMAP35XX_OCM_ADDR_MATCH_2 (OMAP35XX_PM_OCM_RAM_BASE_ADDR_ARM + 0x80)
#define OMAP35XX_IVA2_REQ_INFO_PERMISSION_0 (OMAP35XX_PM_IVA2_BASE_ADDR_ARM + 0x48)
#define OMAP35XX_IVA2_READ_PERMISSION_0 (OMAP35XX_PM_IVA2_BASE_ADDR_ARM + 0x50)
#define OMAP35XX_IVA2_WRITE_PERMISSION_0 (OMAP35XX_PM_IVA2_BASE_ADDR_ARM + 0x58)
#define OMAP35XX_IVA2_REQ_INFO_PERMISSION_1 (OMAP35XX_PM_IVA2_BASE_ADDR_ARM + 0x68)
#define OMAP35XX_IVA2_READ_PERMISSION_1 (OMAP35XX_PM_IVA2_BASE_ADDR_ARM + 0x70)
#define OMAP35XX_IVA2_WRITE_PERMISSION_1 (OMAP35XX_PM_IVA2_BASE_ADDR_ARM + 0x78)
#define OMAP35XX_IVA2_REQ_INFO_PERMISSION_2 (OMAP35XX_PM_IVA2_BASE_ADDR_ARM + 0x88)
#define OMAP35XX_IVA2_READ_PERMISSION_2 (OMAP35XX_PM_IVA2_BASE_ADDR_ARM + 0x90)
#define OMAP35XX_IVA2_WRITE_PERMISSION_2 (OMAP35XX_PM_IVA2_BASE_ADDR_ARM + 0x98)
#define OMAP35XX_IVA2_REQ_INFO_PERMISSION_3 (OMAP35XX_PM_IVA2_BASE_ADDR_ARM + 0xA8)
#define OMAP35XX_IVA2_READ_PERMISSION_3 (OMAP35XX_PM_IVA2_BASE_ADDR_ARM + 0xB0)
#define OMAP35XX_IVA2_WRITE_PERMISSION_3 (OMAP35XX_PM_IVA2_BASE_ADDR_ARM + 0xB8)
/* CONTROL */
#define OMAP35XX_CTRL_BASE (OMAP35XX_L4_IO_BASE + 0x2000)
/* Register offsets of common modules */
/* Control */
#define OMAP35XX_CONTROL_STATUS (OMAP35XX_CTRL_BASE + 0x2F0)
#define OMAP35XX_MCR (OMAP35XX_CTRL_BASE + 0x8C)
#define OMAP35XX_CONTROL_SCALABLE_OMAP_STATUS (OMAP35XX_CTRL_BASE + 0x44C)
#define OMAP35XX_CONTROL_SCALABLE_OMAP_OCP (OMAP35XX_CTRL_BASE + 0x534)
#endif

78
hardware/gpio/am35/public/hw/gpio_am35.h Исполняемый файл
Просмотреть файл

@ -0,0 +1,78 @@
/*
* (c) 2017, SWD Embedded Systems Limited, http://www.kpda.ru
*/
#ifndef _GPIO_AM35_H_INCLUDED
#define _GPIO_AM35_H_INCLUDED
#define GPIO_DEVICE_NAME "/dev/gpio"
#define GPIO_INPUT 0
#define GPIO_OUTPUT 1
#define GPIO_INT_LEVEL_UNCHANGED 0
#define GPIO_INT_LEVEL_LOW 1
#define GPIO_INT_LEVEL_HIGH 2
#define GPIO_RESMGR_NPARTS_MIN 2
#define GPIO_RESMGR_MSGSIZE_MIN 16
#define GPIO_CLIENTS_MAX 32
typedef struct {
uint8_t pin_num;
} gpio_devctl_input_t;
typedef struct {
uint8_t pin_num;
} gpio_devctl_output_t;
typedef struct {
uint8_t pin_num;
uint8_t data;
} gpio_devctl_read_t;
typedef struct {
uint8_t pin_num;
uint8_t data;
} gpio_devctl_write_t;
typedef struct {
uint8_t pin_num;
uint8_t level;
int coid;
} gpio_devctl_int_t;
// A union of all devctl messages
typedef union {
gpio_devctl_input_t set_input;
gpio_devctl_output_t set_output;
gpio_devctl_read_t cmd_read;
gpio_devctl_write_t cmd_write;
gpio_devctl_int_t cmd_intterupt;
} gpio_devctl_t;
typedef struct {
uint8_t pin;
uint8_t level;
} gpio_interrupt_t;
#define GPIO_SET_INPUT 0
#define GPIO_SET_OUTPUT 1
#define GPIO_READ 2
#define GPIO_WRITE 3
#define GPIO_INT_ENABLE 4
#define GPIO_INT_DISABLE 5
#define GPIO_INT_WAIT_PULSE 6
#define DCMD_SET_INPUT __DIOT(_DCMD_MISC, GPIO_SET_INPUT, gpio_devctl_input_t)
#define DCMD_SET_OUTPUT __DIOT(_DCMD_MISC, GPIO_SET_OUTPUT, gpio_devctl_output_t)
#define DCMD_READ __DIOTF(_DCMD_MISC, GPIO_READ, gpio_devctl_read_t)
#define DCMD_WRITE __DIOTF(_DCMD_MISC, GPIO_WRITE, gpio_devctl_write_t)
#define DCMD_INT_ENABLE __DIOTF(_DCMD_MISC, GPIO_INT_ENABLE, gpio_devctl_int_t)
#define DCMD_INT_DISABLE __DIOTF(_DCMD_MISC, GPIO_INT_DISABLE, gpio_devctl_int_t)
#define DCMD_INT_ENABLE_WAIT_PULSE __DIOTF(_DCMD_MISC, GPIO_INT_WAIT_PULSE, gpio_devctl_int_t)
#endif

2
utils/Makefile Обычный файл
Просмотреть файл

@ -0,0 +1,2 @@
LIST=utils
include recurse.mk

2
utils/gpio-ctrl/Makefile Обычный файл
Просмотреть файл

@ -0,0 +1,2 @@
LIST=CPU
include recurse.mk

2
utils/gpio-ctrl/arm/Makefile Обычный файл
Просмотреть файл

@ -0,0 +1,2 @@
LIST=VARIANT
include recurse.mk

1
utils/gpio-ctrl/arm/le.v7/Makefile Обычный файл
Просмотреть файл

@ -0,0 +1 @@
include ../../common.mk

16
utils/gpio-ctrl/common.mk Обычный файл
Просмотреть файл

@ -0,0 +1,16 @@
ifndef QCONFIG
QCONFIG=qconfig.mk
endif
include $(QCONFIG)
INSTALLDIR=sbin
define PINFO
PINFO DESCRIPTION=gpio-ctrl
endef
CCFLAGS = -I ../../../../hardware/gpio/am35/public
USEFILE=$(PROJECT_ROOT)/gpio-ctrl.use
include $(MKFILES_ROOT)/qtargets.mk

196
utils/gpio-ctrl/gpio-ctrl.c Обычный файл
Просмотреть файл

@ -0,0 +1,196 @@
/*
* (c) 2017, SWD Embedded Systems Limited, http://www.kpda.ru
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <devctl.h>
#include <fcntl.h>
#include <devctl.h>
#include <inttypes.h>
#include <sys/iomsg.h>
#include <hw/gpio_am35.h>
typedef struct _gpio_ctrl {
char *devname; /* port prefix */
uint8_t pin; /* pin num or reg mask depending on mode */
uint16_t dir; /* pins direction ( 0 for input, 1 for output ) */
uint16_t outval; /* output pin state */
uint8_t chwait; /* wait for pin change pulse events */
uint8_t verbose;
} gpio_ctrl_t;
void parse_options( int argc, char *argv[], gpio_ctrl_t *gc )
{
int c;
unsigned gpio_pin;
while ( (c = getopt( argc, argv, "n:p:d:o:Wv" ) ) != -1 )
{
switch ( c )
{
case 'n':
gc->devname = optarg;
break;
case 'p':
gpio_pin = strtoul( optarg, NULL, 0 );
if ( (gpio_pin > 191) || (gpio_pin < 0) )
{
printf( "GPIO control: Error! Valid GPIO pin number is from range 0 ~ 191.\n" );
exit( -1 );
}
gc->pin = gpio_pin;
break;
case 'd':
gc->dir = strtoul( optarg, NULL, 0 );
if ( gc->dir != 0 )
gc->dir = GPIO_OUTPUT;
else
gc->dir = GPIO_INPUT;
break;
case 'o':
gc->outval = strtoul( optarg, NULL, 0 );
if ( gc->outval != 0 )
gc->outval = 1;
else
gc->outval = 0;
break;
case 'W':
gc->chwait = 1;
break;
case 'v':
gc->verbose++;
break;
}
}
}
int main( int argc, char *argv[] )
{
gpio_ctrl_t gpio_ctrl;
gpio_devctl_t msg;
int fd;
int status;
memset( &gpio_ctrl, 0 , sizeof( gpio_ctrl_t ) );
gpio_ctrl.devname = GPIO_DEVICE_NAME;
gpio_ctrl.dir = -1;
gpio_ctrl.outval = 0;
gpio_ctrl.verbose = 1;
gpio_ctrl.pin = 178;
parse_options( argc, argv, &gpio_ctrl );
fd = open( gpio_ctrl.devname, O_RDWR );
if ( fd == -1 )
{
printf( "GPIO control: Error! Failed to open %s: %s\n", gpio_ctrl.devname, strerror( errno ) );
return (-1);
}
if ( gpio_ctrl.dir == GPIO_INPUT )
{
printf( "GPIO control: Reading GPIO pin %d \n", gpio_ctrl.pin );
msg.set_input.pin_num = gpio_ctrl.pin;
// Set pin direction
if ( ( status = devctl( fd, DCMD_SET_INPUT, &msg, sizeof( msg ), NULL ) ) )
printf( "GPIO control: Error! GPIO DCMD_SET_INPUT devctl failed; status = %d\n", status );
else
printf( "GPIO control: Pin %d direction: INPUT\n", gpio_ctrl.pin );
if ( ( status = devctl( fd, DCMD_READ, &msg, sizeof( msg ), NULL ) ) )
{
printf( "GPIO control: Error! GPIO DCMD_READ devctl failed; status = %d\n", status );
return (-1);
} else {
printf( "GPIO control: Pin %d value: %d\n", msg.cmd_read.pin_num, msg.cmd_read.data );
return (msg.cmd_read.data);
}
} else
if ( gpio_ctrl.dir == GPIO_OUTPUT )
{
printf( "GPIO control: Setting GPIO pin %d value %d\n", gpio_ctrl.pin, gpio_ctrl.outval );
msg.set_output.pin_num = gpio_ctrl.pin;
// Set pin direction
if ( ( status = devctl( fd, DCMD_SET_OUTPUT, &msg, sizeof( msg ), NULL ) ) )
printf( "GPIO control: Error! GPIO DCMD_SET_OUTPUT devctl failed; status = %d\n", status );
else
printf( "GPIO control: Pin %d direction: OUTPUT\n", gpio_ctrl.pin );
msg.cmd_write.pin_num = gpio_ctrl.pin;
msg.cmd_write.data = gpio_ctrl.outval;
if ( ( status = devctl( fd, DCMD_WRITE, &msg, sizeof( msg ), NULL ) ) )
printf( "GPIO control: Error! GPIO DCMD_WRITE devctl failed; status = %d\n", status );
else
printf( "GPIO control: Pin %d value: %d\n", msg.cmd_write.pin_num, msg.cmd_write.data );
}
if ( gpio_ctrl.chwait )
{
int chid;
int coid;
struct _pulse pulse;
// we need a channel to receive the pulse notification on
chid = ChannelCreate( 0 );
// and we need a connection to that channel for the pulse to be delivered on
coid = ConnectAttach( 0, 0, chid, _NTO_SIDE_CHANNEL, 0 );
msg.cmd_intterupt.pin_num = gpio_ctrl.pin;
msg.cmd_intterupt.level = GPIO_INT_LEVEL_LOW;
msg.cmd_intterupt.coid = coid;
// Set pin direction
if ( ( status = devctl( fd, DCMD_SET_INPUT, &msg, sizeof( msg ), NULL ) ) )
printf( "GPIO control: Error! GPIO DCMD_SET_INPUT devctl failed; status = %d\n", status );
else
printf( "GPIO control: Pin %d direction: INPUT\n", gpio_ctrl.pin );
printf( "GPIO control: Client: enable interrupts from GPIO pin %d \n", msg.cmd_intterupt.pin_num );
if ( ( status = devctl( fd, DCMD_INT_ENABLE_WAIT_PULSE, &msg, sizeof( msg ), NULL ) ) )
printf( "GPIO control: Error! GPIO DCMD_PULSE devctl failed; status = %d\n", status );
else
{
printf( "GPIO control: Client is waiting for pulses...\n" );
printf( "GPIO control: Client: chid %d coid %d \n", chid, coid );
while ( 1 )
{
// wait for the pulse from the resource manager
MsgReceivePulse( chid, &pulse, sizeof( pulse ), NULL );
printf( "GPIO control: Client pulse code %d recieved. GPIO interrupt from PIN %u \n\n", pulse.code, pulse.value.sival_int );
// break;
}
if ( ( status = devctl( fd, DCMD_INT_DISABLE, &msg, sizeof( msg ), NULL ) ) )
printf( "GPIO control: Error! GPIO DCMD_INT_DISABLE devctl failed; status = %d\n", status );
else
printf( "GPIO control: GPIO Interrupt test complete \n" );
}
}
close( fd );
return (EXIT_SUCCESS);
}

12
utils/gpio-ctrl/gpio-ctrl.use Обычный файл
Просмотреть файл

@ -0,0 +1,12 @@
%C - A sample application for controlling individual pins of GPIO port.
Syntax:
%C [options]
Options:
-n name GPIO device name (default: /dev/gpio)
-p pin pin number
-d direction set pin direction (0 for input, 1 for output)
-o output set output pin state
-W register and wait for pin change pulse events
-v verbose level