Драйвер gpio-am35 для ЗОСРВ "Нейтрино" редакции 2020
Этот коммит содержится в:
Коммит
5782deaa07
3
Makefile
Обычный файл
3
Makefile
Обычный файл
@ -0,0 +1,3 @@
|
||||
LIST=ALL
|
||||
LATE_DIRS=utils
|
||||
include recurse.mk
|
58
README.md
Обычный файл
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
Обычный файл
2
hardware/Makefile
Обычный файл
@ -0,0 +1,2 @@
|
||||
LIST=hardware
|
||||
include recurse.mk
|
2
hardware/gpio/Makefile
Обычный файл
2
hardware/gpio/Makefile
Обычный файл
@ -0,0 +1,2 @@
|
||||
LIST=gpio
|
||||
include recurse.mk
|
8
hardware/gpio/am35/Makefile
Исполняемый файл
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
Обычный файл
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
Обычный файл
1
hardware/gpio/am35/arm/le.v7/Makefile
Обычный файл
@ -0,0 +1 @@
|
||||
include ../../common.mk
|
17
hardware/gpio/am35/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
Исполняемый файл
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
Исполняемый файл
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
Исполняемый файл
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
Исполняемый файл
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
Исполняемый файл
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
Исполняемый файл
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
Обычный файл
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
Исполняемый файл
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
Обычный файл
2
utils/Makefile
Обычный файл
@ -0,0 +1,2 @@
|
||||
LIST=utils
|
||||
include recurse.mk
|
2
utils/gpio-ctrl/Makefile
Обычный файл
2
utils/gpio-ctrl/Makefile
Обычный файл
@ -0,0 +1,2 @@
|
||||
LIST=CPU
|
||||
include recurse.mk
|
2
utils/gpio-ctrl/arm/Makefile
Обычный файл
2
utils/gpio-ctrl/arm/Makefile
Обычный файл
@ -0,0 +1,2 @@
|
||||
LIST=VARIANT
|
||||
include recurse.mk
|
1
utils/gpio-ctrl/arm/le.v7/Makefile
Обычный файл
1
utils/gpio-ctrl/arm/le.v7/Makefile
Обычный файл
@ -0,0 +1 @@
|
||||
include ../../common.mk
|
16
utils/gpio-ctrl/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
Обычный файл
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
Обычный файл
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
|
Загрузка…
x
Ссылка в новой задаче
Block a user