Subversion Repositories shark

Rev

Blame | Last modification | View Log | RSS feed

//SHARK version by Giacomo Guidi <giacomo@gandalf.sssup.it>

#define __NO_VERSION__ 1

#include <sys/types.h>
#include "drivers/compbttv.h"
#include <asm/bitops.h>

#include "drivers/bt848.h"
#include "drivers/gpio.h"

#define printk cprintf
/*********************/
/* gpio_adapter ctor */
void init_gpio_adapter ( struct gpio_adapter *gpio )
{
    //ignore overlapped fields...they are configured elsewhere
   
    gpio->state = 0;
    gpio->sync_bits = 0;
    gpio->async_mask = ~0;  //assign everything to async control
    gpio->async_bits = 0;
   
    init_request_queue(&(gpio->request_queue));
    init_request_queue(&(gpio->free_queue));
   
    gpio->private_data = NULL;
}

/********************************************************************/
/* async bit methods...restricted to the bits allowed in async mode */
static void gpio_apply_bits ( struct gpio_adapter * );

void gpio_set ( struct gpio_adapter *gpio, __u32 data )
{
    //printk("gpio: set called with %08lX\n",(unsigned long)data);
    gpio->async_bits = data & gpio->async_mask;
    //printk("gpio: set to: %06lX\n",(long)(gpio->async_bits|gpio->sync_bits));
    gpio_apply_bits(gpio);
}

void gpio_and ( struct gpio_adapter *gpio, __u32 data )
{
    //printk("gpio: and called with &=%08lX\n",(unsigned long)data);
    gpio->async_bits &= data;   // disallowed bits are already zero...
    //printk("gpio: and to: %06lX\n",(long)(gpio->async_bits|gpio->sync_bits));
    gpio_apply_bits(gpio);
}

void gpio_or ( struct gpio_adapter *gpio, __u32 data )
{
    //printk("gpio: or called with |=%08lX\n",(unsigned long)data);
    gpio->async_bits |= data & gpio->async_mask;
    //printk("gpio:  or to: %06lX\n",(long)(gpio->async_bits|gpio->sync_bits));
    gpio_apply_bits(gpio);
}

/* placed here to (hopefully) allow near jumps (smaller/faster) */
static void gpio_apply_bits ( struct gpio_adapter *gpio )
{
    if (!test_bit(GPIO_HW_LOCKED,&(gpio->state))) {
        __u32 value = gpio->sync_bits|gpio->async_bits;
        *(__u32 *)(gpio->bt848_mem+BT848_GPIO_DATA) = value;
        //printk("gpio: %06lX\n",(long)value);
        //printk("gpio: out_en = %06lX\n",(long)readl(gpio->bt848_mem+BT848_GPIO_OUT_EN));
    } else {
        // can't update...leave it for task holding hardware lock
        set_bit(GPIO_ASYNC_MOD,&(gpio->state));
        // yes, that's correct...the sync task must up our async_lock
        // this prevents the next async write until this one hits the hardware
    }
   
}

void gpio_andor ( struct gpio_adapter *gpio, __u32 and_data, __u32 or_data )
{
    //printk("gpio: andor called with &=%08lX and |=%08lX\n",(unsigned long)and_data,(unsigned long)or_data);
    gpio->async_bits &= and_data;
    gpio->async_bits |= or_data & gpio->async_mask;
    //printk("gpio: aor to: %06lX\n",(long)(gpio->async_bits|gpio->sync_bits));
    gpio_apply_bits(gpio);
}

/***********************/
/* synchronous methods */
static inline void gpio_sync_write( struct gpio_adapter *gpio,
                             __u32 sync_bits,
                             __u32 *async_bits )
{
    if (test_and_clear_bit(GPIO_ASYNC_MOD,&((gpio)->state))) {
        *async_bits = (gpio)->async_bits;
    }
    *(__u32 *)(gpio->bt848_mem+BT848_GPIO_DATA) = (sync_bits)|(*async_bits);
}

static inline void gpio_sync_acquire_hardware( struct gpio_adapter *gpio )
{
    if (test_and_set_bit(GPIO_HW_LOCKED,&(gpio->state)))
            printk("gpio: acquire\n");;
}

static void gpio_sync_release_hardware ( struct gpio_adapter *gpio )
{
    if (test_and_clear_bit(GPIO_ASYNC_MOD,&(gpio->state))) {
        //we are responsible for a final update...do it here
        *(__u32 *)(gpio->bt848_mem+BT848_GPIO_DATA) = gpio->sync_bits|gpio->async_bits;
    }
    /* must have the hardware to release it */
    if (!test_and_clear_bit(GPIO_HW_LOCKED,&(gpio->state))) {
        printk("gpio: release\n");;
    }
}

/* request queue access */
void gpio_commit_request( struct gpio_adapter *gpio,
                                 struct gpio_request *request )
{
    list_add_tail(&(request->list),&(gpio->request_queue.list));
}

void gpio_commit_transaction( struct gpio_adapter *gpio,
                                     struct list_head *list )
{
    list_splice(list,gpio->request_queue.list.prev);
}