Line 50... |
Line 50... |
memset( gpios, 0, sizeof(gpios) );
|
memset( gpios, 0, sizeof(gpios) );
|
first_time = 0;
|
first_time = 0;
|
}
|
}
|
|
|
|
|
for ( i = 0; i < MAX_GPIOS; ++ i ) {
|
for ( i = 0; i < config.ngpios; ++ i ) {
|
struct gpio_device *gpio = &(gpios[i]);
|
struct gpio_device *gpio = &(gpios[i]);
|
|
|
gpio->gpio_number = i;
|
gpio->gpio_number = i;
|
gpio->baseaddr = config.gpios[i].baseaddr;
|
gpio->baseaddr = config.gpios[i].baseaddr;
|
|
|
Line 64... |
Line 64... |
|
|
/* Register memory range */
|
/* Register memory range */
|
register_memoryarea( gpio->baseaddr, GPIO_ADDR_SPACE, 4, gpio_read32, gpio_write32 );
|
register_memoryarea( gpio->baseaddr, GPIO_ADDR_SPACE, 4, gpio_read32, gpio_write32 );
|
|
|
/* Possibly connect to VAPI */
|
/* Possibly connect to VAPI */
|
gpio->vapi_ids[GPIO_VAPI_DATA] = config.gpios[i].vapi_id;
|
if ( config.gpios[i].base_vapi_id ) {
|
gpio->vapi_ids[GPIO_VAPI_AUX] = config.gpios[i].aux_vapi_id;
|
gpio->base_vapi_id = config.gpios[i].base_vapi_id;
|
gpio->vapi_ids[GPIO_VAPI_CLOCK] = config.gpios[i].clk_vapi_id;
|
vapi_install_multi_handler( gpio->base_vapi_id, GPIO_NUM_VAPI_IDS, gpio_vapi_read );
|
gpio->vapi_ids[GPIO_VAPI_CONFIG] = config.gpios[i].cfg_vapi_id;
|
}
|
for ( j = 0; j < GPIO_NUM_VAPI_IDS; ++ j )
|
|
if ( gpio->vapi_ids[j] )
|
|
vapi_install_handler( gpio->vapi_ids[j], gpio_vapi_read );
|
|
}
|
}
|
}
|
}
|
}
|
}
|
|
|
|
|
/* Dump status */
|
/* Dump status */
|
void gpio_status( void )
|
void gpio_status( void )
|
{
|
{
|
unsigned i;
|
unsigned i;
|
|
|
for ( i = 0; i < MAX_GPIOS; ++ i ) {
|
for ( i = 0; i < config.ngpios; ++ i ) {
|
struct gpio_device *gpio = &(gpios[i]);
|
struct gpio_device *gpio = &(gpios[i]);
|
|
|
if ( gpio->baseaddr == 0 )
|
if ( gpio->baseaddr == 0 )
|
continue;
|
continue;
|
|
|
Line 106... |
Line 103... |
int gpio_find_device( unsigned long addr, struct gpio_device **gpio, unsigned long *reladdr )
|
int gpio_find_device( unsigned long addr, struct gpio_device **gpio, unsigned long *reladdr )
|
{
|
{
|
unsigned i;
|
unsigned i;
|
*gpio = NULL;
|
*gpio = NULL;
|
|
|
for ( i = 0; i < MAX_GPIOS && *gpio == NULL; ++ i ) {
|
for ( i = 0; i < config.ngpios && *gpio == NULL; ++ i ) {
|
if ( (addr >= gpios[i].baseaddr) && (addr < gpios[i].baseaddr + GPIO_ADDR_SPACE) )
|
if ( (addr >= gpios[i].baseaddr) && (addr < gpios[i].baseaddr + GPIO_ADDR_SPACE) )
|
*gpio = &(gpios[i]);
|
*gpio = &(gpios[i]);
|
}
|
}
|
|
|
/* verify we found a device */
|
/* verify we found a device */
|
Line 129... |
Line 126... |
/* Find device by vapi id */
|
/* Find device by vapi id */
|
struct gpio_device *gpio_find_vapi_device( unsigned long id, unsigned *which )
|
struct gpio_device *gpio_find_vapi_device( unsigned long id, unsigned *which )
|
{
|
{
|
unsigned i, j;
|
unsigned i, j;
|
|
|
for ( i = 0; i < MAX_GPIOS; ++ i )
|
for ( i = 0; i < config.ngpios; ++ i )
|
for ( j = 0; j < GPIO_NUM_VAPI_IDS; ++ j )
|
if ( (id >= gpios[i].base_vapi_id) && (id < gpios[i].base_vapi_id + GPIO_NUM_VAPI_IDS) ) {
|
if ( id == gpios[i].vapi_ids[j] )
|
*which = id - gpios[i].base_vapi_id;
|
return &(gpios[i]);
|
return &(gpios[i]);
|
|
}
|
|
|
return NULL;
|
return NULL;
|
}
|
}
|
|
|
|
|
Line 148... |
Line 146... |
printf( "gpio_read32( 0x%08lX ): Not in registered range(s)\n", addr );
|
printf( "gpio_read32( 0x%08lX ): Not in registered range(s)\n", addr );
|
return 0;
|
return 0;
|
}
|
}
|
|
|
switch( addr ) {
|
switch( addr ) {
|
case RGPIO_IN: gpio->next.ctrl &= ~RGPIO_CTRL_INT; return gpio->curr.in | gpio->curr.out;
|
case RGPIO_IN:
|
|
gpio->next.ctrl &= ~RGPIO_CTRL_INT;
|
|
return gpio->curr.in | gpio->curr.out;
|
case RGPIO_OUT: return gpio->curr.out;
|
case RGPIO_OUT: return gpio->curr.out;
|
case RGPIO_OE: return gpio->curr.oe;
|
case RGPIO_OE: return gpio->curr.oe;
|
case RGPIO_INTE: return gpio->curr.inte;
|
case RGPIO_INTE: return gpio->curr.inte;
|
case RGPIO_PTRIG: return gpio->curr.ptrig;
|
case RGPIO_PTRIG: return gpio->curr.ptrig;
|
case RGPIO_AUX: return gpio->curr.aux;
|
case RGPIO_AUX: return gpio->curr.aux;
|
Line 169... |
Line 169... |
printf( "gpio_write32( 0x%08lX ): Not in registered range(s)\n", addr );
|
printf( "gpio_write32( 0x%08lX ): Not in registered range(s)\n", addr );
|
return;
|
return;
|
}
|
}
|
|
|
switch( addr ) {
|
switch( addr ) {
|
case RGPIO_IN: debug( 3, "GPIO: Cannot write to RGPIO_IN\n" ); break;
|
case RGPIO_IN: debug( 2, "GPIO: Cannot write to RGPIO_IN\n" ); break;
|
case RGPIO_OUT: gpio->next.out = value; break;
|
case RGPIO_OUT: gpio->next.out = value; break;
|
case RGPIO_OE: gpio->next.oe = value; break;
|
case RGPIO_OE: gpio->next.oe = value; break;
|
case RGPIO_INTE: gpio->next.inte = value; break;
|
case RGPIO_INTE: gpio->next.inte = value; break;
|
case RGPIO_PTRIG: gpio->next.ptrig = value; break;
|
case RGPIO_PTRIG: gpio->next.ptrig = value; break;
|
case RGPIO_AUX: gpio->next.aux = value; break;
|
case RGPIO_AUX: gpio->next.aux = value; break;
|
Line 186... |
Line 186... |
void gpio_vapi_read( unsigned long id, unsigned long data )
|
void gpio_vapi_read( unsigned long id, unsigned long data )
|
{
|
{
|
unsigned which;
|
unsigned which;
|
struct gpio_device *gpio = gpio_find_vapi_device( id, &which );
|
struct gpio_device *gpio = gpio_find_vapi_device( id, &which );
|
|
|
debug( 4, "GPIO: id %08x, data %08x\n", id, data );
|
debug( 5, "GPIO: id %08x, data %08x\n", id, data );
|
|
|
if ( !gpio ) {
|
if ( !gpio ) {
|
debug( 1, "GPIO: VAPI ID %08x is not ours!\n", id );
|
debug( 1, "GPIO: VAPI ID %08x is not ours!\n", id );
|
return;
|
return;
|
}
|
}
|
|
|
switch( which ) {
|
switch( which ) {
|
case GPIO_VAPI_DATA: gpio->next.in = data; break;
|
case GPIO_VAPI_DATA:
|
case GPIO_VAPI_AUX: gpio->auxiliary_inputs = data; break;
|
debug( 3, "GPIO: Next input from VAPI = 0x%08x\n", data );
|
case GPIO_VAPI_CLOCK: gpio_external_clock( data ); break;
|
gpio->next.in = data;
|
case GPIO_VAPI_CONFIG: /* Currently no configuration commands supported */ break;
|
break;
|
|
case GPIO_VAPI_AUX:
|
|
gpio->auxiliary_inputs = data;
|
|
break;
|
|
case GPIO_VAPI_RGPIO_OE:
|
|
gpio->next.oe = data;
|
|
break;
|
|
case GPIO_VAPI_RGPIO_INTE:
|
|
gpio->next.inte = data;
|
|
break;
|
|
case GPIO_VAPI_RGPIO_PTRIG:
|
|
gpio->next.ptrig = data;
|
|
break;
|
|
case GPIO_VAPI_RGPIO_AUX:
|
|
gpio->next.aux = data;
|
|
break;
|
|
case GPIO_VAPI_RGPIO_CTRL:
|
|
gpio->next.ctrl = data;
|
|
break;
|
|
case GPIO_VAPI_CLOCK:
|
|
gpio_external_clock( data );
|
|
break;
|
}
|
}
|
}
|
}
|
|
|
/* System Clock. */
|
/* System Clock. */
|
void gpio_clock( void )
|
void gpio_clock( void )
|
{
|
{
|
unsigned i;
|
unsigned i;
|
|
|
for ( i = 0; i < MAX_GPIOS; ++ i )
|
for ( i = 0; i < config.ngpios; ++ i )
|
if ( !(gpios[i].curr.ctrl & RGPIO_CTRL_ECLK) )
|
if ( !(gpios[i].curr.ctrl & RGPIO_CTRL_ECLK) )
|
gpio_device_clock( &(gpios[i]) );
|
gpio_device_clock( &(gpios[i]) );
|
}
|
}
|
|
|
/* External Clock. */
|
/* External Clock. */
|
void gpio_external_clock( unsigned long value )
|
void gpio_external_clock( unsigned long value )
|
{
|
{
|
unsigned i;
|
unsigned i;
|
|
|
|
/* "Normalize" clock value */
|
value = (value != 0);
|
value = (value != 0);
|
|
|
for ( i = 0; i < MAX_GPIOS; ++ i ) {
|
for ( i = 0; i < config.ngpios; ++ i ) {
|
struct gpio_device *gpio = &(gpios[i]);
|
struct gpio_device *gpio = &(gpios[i]);
|
|
|
int eclk = ((gpio->curr.ctrl & RGPIO_CTRL_ECLK) == RGPIO_CTRL_ECLK);
|
int use_external_clock = ((gpio->curr.ctrl & RGPIO_CTRL_ECLK) == RGPIO_CTRL_ECLK);
|
int nec = ((gpio->curr.ctrl & RGPIO_CTRL_NEC) == RGPIO_CTRL_NEC);
|
int negative_edge = ((gpio->curr.ctrl & RGPIO_CTRL_NEC) == RGPIO_CTRL_NEC);
|
|
|
gpio->next.external_clock = value;
|
gpio->next.external_clock = value;
|
|
|
if ( eclk && (gpio->next.external_clock != gpio->curr.external_clock) && (value != nec) )
|
if ( use_external_clock && (gpio->next.external_clock != gpio->curr.external_clock) && (value != negative_edge) )
|
gpio_device_clock( gpio );
|
gpio_device_clock( gpio );
|
}
|
}
|
}
|
}
|
|
|
|
|
/* Clock as handld by one device. */
|
/* Clock as handld by one device. */
|
void gpio_device_clock( struct gpio_device *gpio )
|
void gpio_device_clock( struct gpio_device *gpio )
|
{
|
{
|
/* Calculate new inputs and outputs */
|
/* Calculate new inputs and outputs */
|
gpio->next.in &= ~gpio->next.oe; /* Only input bits */
|
gpio->next.in &= ~gpio->next.oe; /* Only input bits */
|
/* Replace requested output bits with aux input */
|
/* Replace requested output bits with aux input */
|
gpio->next.out = (gpio->next.out & ~gpio->next.aux) | (gpio->auxiliary_inputs & gpio->next.aux);
|
gpio->next.out = (gpio->next.out & ~gpio->next.aux) | (gpio->auxiliary_inputs & gpio->next.aux);
|
gpio->next.out &= gpio->next.oe; /* Only output-enabled bits */
|
gpio->next.out &= gpio->next.oe; /* Only output-enabled bits */
|
|
|
/* If any outputs changed, notify the world (i.e. vapi) */
|
/* If any outputs changed, notify the world (i.e. vapi) */
|
if ( gpio->next.out != gpio->curr.out )
|
if ( gpio->next.out != gpio->curr.out ) {
|
if ( gpio->vapi_ids[GPIO_VAPI_DATA] != 0 )
|
debug( 3, "GPIO: New output 0x%08x\n", gpio->next.out );
|
vapi_send( gpio->vapi_ids[GPIO_VAPI_DATA], gpio->next.out );
|
if ( gpio->base_vapi_id )
|
|
vapi_send( gpio->base_vapi_id + GPIO_VAPI_DATA, gpio->next.out );
|
|
}
|
|
|
/* If any inputs changed and interrupt enabled, generate interrupt */
|
/* If any inputs changed and interrupt enabled, generate interrupt */
|
if ( (gpio->next.in != gpio->curr.in) && (gpio->next.ctrl & RGPIO_CTRL_INTE) ) {
|
if ( gpio->next.in != gpio->curr.in ) {
|
|
debug( 3, "GPIO: New input 0x%08x\n", gpio->next.out );
|
|
|
|
if ( gpio->next.ctrl & RGPIO_CTRL_INTE ) {
|
unsigned changed_bits = gpio->next.in ^ gpio->curr.in; /* inputs that have changed */
|
unsigned changed_bits = gpio->next.in ^ gpio->curr.in; /* inputs that have changed */
|
unsigned set_bits = changed_bits & gpio->next.in; /* inputs that have been set */
|
unsigned set_bits = changed_bits & gpio->next.in; /* inputs that have been set */
|
unsigned cleared_bits = changed_bits & gpio->curr.in; /* inputs that have been cleared */
|
unsigned cleared_bits = changed_bits & gpio->curr.in; /* inputs that have been cleared */
|
unsigned relevant_bits = (gpio->next.ptrig & set_bits) | (~gpio->next.ptrig & cleared_bits);
|
unsigned relevant_bits = (gpio->next.ptrig & set_bits) | (~gpio->next.ptrig & cleared_bits);
|
|
|
if ( relevant_bits & gpio->next.inte ) {
|
if ( relevant_bits & gpio->next.inte ) {
|
report_interrupt( gpio->irq );
|
report_interrupt( gpio->irq );
|
gpio->next.ctrl |= RGPIO_CTRL_INT;
|
gpio->next.ctrl |= RGPIO_CTRL_INT;
|
}
|
}
|
}
|
}
|
|
}
|
|
|
/* Switch to values for next clock */
|
/* Switch to values for next clock */
|
memcpy( &(gpio->curr), &(gpio->next), sizeof(gpio->curr) );
|
memcpy( &(gpio->curr), &(gpio->next), sizeof(gpio->curr) );
|
}
|
}
|
|
|
No newline at end of file
|
No newline at end of file
|