Line 34... |
Line 34... |
#include "pic.h"
|
#include "pic.h"
|
#include "vapi.h"
|
#include "vapi.h"
|
#include "debug.h"
|
#include "debug.h"
|
#include "sched.h"
|
#include "sched.h"
|
|
|
|
DEFAULT_DEBUG_CHANNEL(gpio);
|
|
|
static void gpio_vapi_read( unsigned long id, unsigned long data, void *dat );
|
static void gpio_vapi_read( unsigned long id, unsigned long data, void *dat );
|
static uint32_t gpio_read32( oraddr_t addr, void *dat );
|
static uint32_t gpio_read32( oraddr_t addr, void *dat );
|
static void gpio_write32( oraddr_t addr, uint32_t value, void *dat );
|
static void gpio_write32( oraddr_t addr, uint32_t value, void *dat );
|
|
|
static void gpio_external_clock( unsigned long value, struct gpio_device *gpio );
|
static void gpio_external_clock( unsigned long value, struct gpio_device *gpio );
|
Line 101... |
Line 103... |
void gpio_write32( oraddr_t addr, uint32_t value, void *dat )
|
void gpio_write32( oraddr_t addr, uint32_t value, void *dat )
|
{
|
{
|
struct gpio_device *gpio = dat;
|
struct gpio_device *gpio = dat;
|
|
|
switch( addr ) {
|
switch( addr ) {
|
case RGPIO_IN: debug( 5, "GPIO: Cannot write to RGPIO_IN\n" ); break;
|
case RGPIO_IN: TRACE( "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 119... |
Line 121... |
void gpio_vapi_read( unsigned long id, unsigned long data, void *dat )
|
void gpio_vapi_read( unsigned long id, unsigned long data, void *dat )
|
{
|
{
|
unsigned which;
|
unsigned which;
|
struct gpio_device *gpio = dat;
|
struct gpio_device *gpio = dat;
|
|
|
debug( 5, "GPIO: id %08lx, data %08lx\n", id, data );
|
TRACE( "GPIO: id %08lx, data %08lx\n", id, data );
|
|
|
which = id - gpio->base_vapi_id;
|
which = id - gpio->base_vapi_id;
|
|
|
switch( which ) {
|
switch( which ) {
|
case GPIO_VAPI_DATA:
|
case GPIO_VAPI_DATA:
|
debug( 4, "GPIO: Next input from VAPI = 0x%08lx (RGPIO_OE = 0x%08lx)\n",
|
TRACE( "GPIO: Next input from VAPI = 0x%08lx (RGPIO_OE = 0x%08lx)\n",
|
data, gpio->next.oe );
|
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;
|
Line 193... |
Line 195... |
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%08lx, RGPIO_OE = 0x%08lx\n", gpio->next.out,
|
TRACE( "GPIO: New output 0x%08lx, RGPIO_OE = 0x%08lx\n", gpio->next.out,
|
gpio->next.oe );
|
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%08lx\n", gpio->next.in );
|
TRACE( "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 */
|
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 ) {
|
debug( 3, "GPIO: Reporting interrupt %d\n", gpio->irq );
|
TRACE( "GPIO: Reporting interrupt %d\n", gpio->irq );
|
gpio->next.ctrl |= RGPIO_CTRL_INTS;
|
gpio->next.ctrl |= RGPIO_CTRL_INTS;
|
gpio->next.ints |= relevant_bits & gpio->next.inte;
|
gpio->next.ints |= relevant_bits & gpio->next.inte;
|
/* Since we can't report an interrupt during a readmem/writemem
|
/* Since we can't report an interrupt during a readmem/writemem
|
* schedule the scheduler to do it. Read the comment above
|
* schedule the scheduler to do it. Read the comment above
|
* report_interrupt in pic/pic.c */
|
* report_interrupt in pic/pic.c */
|