Line 17... |
Line 17... |
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
*/
|
*/
|
#include <string.h>
|
#include <string.h>
|
|
|
|
#include "config.h"
|
|
|
|
#ifdef HAVE_INTTYPES_H
|
|
#include <inttypes.h>
|
|
#endif
|
|
|
|
#include "port.h"
|
|
#include "arch.h"
|
#include "abstract.h"
|
#include "abstract.h"
|
#include "gpio.h"
|
#include "gpio.h"
|
#include "gpio_i.h"
|
#include "gpio_i.h"
|
#include "sim-config.h"
|
#include "sim-config.h"
|
#include "pic.h"
|
#include "pic.h"
|
Line 28... |
Line 36... |
#include "debug.h"
|
#include "debug.h"
|
|
|
static struct gpio_device gpios[MAX_GPIOS];
|
static struct gpio_device gpios[MAX_GPIOS];
|
|
|
static void gpio_vapi_read( unsigned long id, unsigned long data );
|
static void gpio_vapi_read( unsigned long id, unsigned long data );
|
static unsigned long gpio_read32( unsigned long addr );
|
static uint32_t gpio_read32( oraddr_t addr );
|
static void gpio_write32( unsigned long addr, unsigned long value );
|
static void gpio_write32( oraddr_t addr, uint32_t value );
|
|
|
static void gpio_external_clock( unsigned long value );
|
static void gpio_external_clock( unsigned long value );
|
static void gpio_device_clock( struct gpio_device *gpio );
|
static void gpio_device_clock( struct gpio_device *gpio );
|
static int gpio_find_device( unsigned long addr, struct gpio_device **gpio, unsigned long *reladdr );
|
static int gpio_find_device( oraddr_t addr, struct gpio_device **gpio, oraddr_t *reladdr );
|
static struct gpio_device *gpio_find_vapi_device( unsigned long id, unsigned *which_vapi );
|
static struct gpio_device *gpio_find_vapi_device( unsigned long id, unsigned *which_vapi );
|
|
|
/* Initialize all parameters and state */
|
/* Initialize all parameters and state */
|
void gpio_reset( void )
|
void gpio_reset( void )
|
{
|
{
|
Line 81... |
Line 89... |
struct gpio_device *gpio = &(gpios[i]);
|
struct gpio_device *gpio = &(gpios[i]);
|
|
|
if ( gpio->baseaddr == 0 )
|
if ( gpio->baseaddr == 0 )
|
continue;
|
continue;
|
|
|
PRINTF( "\nGPIO %u at 0x%08lX:\n", i, gpio->baseaddr );
|
PRINTF( "\nGPIO %u at 0x%"PRIxADDR":\n", i, gpio->baseaddr );
|
PRINTF( "RGPIO_IN : 0x%08lX\n", gpio->curr.in );
|
PRINTF( "RGPIO_IN : 0x%08lX\n", gpio->curr.in );
|
PRINTF( "RGPIO_OUT : 0x%08lX\n", gpio->curr.out );
|
PRINTF( "RGPIO_OUT : 0x%08lX\n", gpio->curr.out );
|
PRINTF( "RGPIO_OE : 0x%08lX\n", gpio->curr.oe );
|
PRINTF( "RGPIO_OE : 0x%08lX\n", gpio->curr.oe );
|
PRINTF( "RGPIO_INTE : 0x%08lX\n", gpio->curr.inte );
|
PRINTF( "RGPIO_INTE : 0x%08lX\n", gpio->curr.inte );
|
PRINTF( "RGPIO_PTRIG : 0x%08lX\n", gpio->curr.ptrig );
|
PRINTF( "RGPIO_PTRIG : 0x%08lX\n", gpio->curr.ptrig );
|
Line 96... |
Line 104... |
}
|
}
|
|
|
|
|
/* Convert a memory address to a device struct and relative address.
|
/* Convert a memory address to a device struct and relative address.
|
* Return nonzero on success */
|
* Return nonzero on success */
|
int gpio_find_device( unsigned long addr, struct gpio_device **gpio, unsigned long *reladdr )
|
int gpio_find_device( oraddr_t addr, struct gpio_device **gpio, oraddr_t *reladdr )
|
{
|
{
|
unsigned i;
|
unsigned i;
|
*gpio = NULL;
|
*gpio = NULL;
|
|
|
for ( i = 0; i < config.ngpios && *gpio == NULL; ++ i ) {
|
for ( i = 0; i < config.ngpios && *gpio == NULL; ++ i ) {
|
Line 135... |
Line 143... |
return NULL;
|
return NULL;
|
}
|
}
|
|
|
|
|
/* Wishbone read */
|
/* Wishbone read */
|
unsigned long gpio_read32( unsigned long addr )
|
uint32_t gpio_read32( oraddr_t addr )
|
{
|
{
|
struct gpio_device *gpio;
|
struct gpio_device *gpio;
|
if ( !gpio_find_device( addr, &gpio, &addr ) ) {
|
if ( !gpio_find_device( addr, &gpio, &addr ) ) {
|
debug( 2, "gpio_read32( 0x%08lX ): Not in registered range(s)\n", addr );
|
debug( 2, "gpio_read32( 0x%"PRIxADDR" ): Not in registered range(s)\n", addr );
|
return 0;
|
return 0;
|
}
|
}
|
|
|
switch( addr ) {
|
switch( addr ) {
|
case RGPIO_IN: return gpio->curr.in | gpio->curr.out;
|
case RGPIO_IN: return gpio->curr.in | gpio->curr.out;
|
Line 157... |
Line 165... |
}
|
}
|
}
|
}
|
|
|
|
|
/* Wishbone write */
|
/* Wishbone write */
|
void gpio_write32( unsigned long addr, unsigned long value )
|
void gpio_write32( oraddr_t addr, uint32_t value )
|
{
|
{
|
struct gpio_device *gpio;
|
struct gpio_device *gpio;
|
if ( !gpio_find_device( addr, &gpio, &addr ) ) {
|
if ( !gpio_find_device( addr, &gpio, &addr ) ) {
|
debug( 2, "gpio_write32( 0x%08lX ): Not in registered range(s)\n", addr );
|
debug( 2, "gpio_write32( 0x%"PRIxADDR" ): Not in registered range(s)\n", addr );
|
return;
|
return;
|
}
|
}
|
|
|
switch( addr ) {
|
switch( addr ) {
|
case RGPIO_IN: debug( 5, "GPIO: Cannot write to RGPIO_IN\n" ); break;
|
case RGPIO_IN: debug( 5, "GPIO: Cannot write to RGPIO_IN\n" ); break;
|
Line 184... |
Line 192... |
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( 5, "GPIO: id %08x, data %08x\n", id, data );
|
debug( 5, "GPIO: id %08lx, data %08lx\n", id, data );
|
|
|
if ( !gpio ) {
|
if ( !gpio ) {
|
debug( 1, "GPIO: VAPI ID %08x is not ours!\n", id );
|
debug( 1, "GPIO: VAPI ID %08lx is not ours!\n", id );
|
return;
|
return;
|
}
|
}
|
|
|
switch( which ) {
|
switch( which ) {
|
case GPIO_VAPI_DATA:
|
case GPIO_VAPI_DATA:
|
debug( 4, "GPIO: Next input from VAPI = 0x%08x (RGPIO_OE = 0x%08x)\n", data, gpio->next.oe );
|
debug( 4, "GPIO: Next input from VAPI = 0x%08lx (RGPIO_OE = 0x%08lx)\n",
|
|
data, gpio->next.oe );
|
gpio->next.in = data;
|
gpio->next.in = data;
|
break;
|
break;
|
case GPIO_VAPI_AUX:
|
case GPIO_VAPI_AUX:
|
gpio->auxiliary_inputs = data;
|
gpio->auxiliary_inputs = data;
|
break;
|
break;
|
Line 263... |
Line 272... |
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 ) {
|
debug( 4, "GPIO: New output 0x%08x, RGPIO_OE = 0x%08x\n", gpio->next.out, gpio->next.oe );
|
debug( 4, "GPIO: New output 0x%08lx, RGPIO_OE = 0x%08lx\n", gpio->next.out,
|
|
gpio->next.oe );
|
if ( gpio->base_vapi_id )
|
if ( gpio->base_vapi_id )
|
vapi_send( gpio->base_vapi_id + GPIO_VAPI_DATA, gpio->next.out );
|
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 ) {
|
if ( gpio->next.in != gpio->curr.in ) {
|
debug( 4, "GPIO: New input 0x%08x\n", gpio->next.in );
|
debug( 4, "GPIO: New input 0x%08lx\n", gpio->next.in );
|
|
|
if ( gpio->next.ctrl & RGPIO_CTRL_INTE ) {
|
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 */
|