/* 
 ************************************************************************
 *  sa1100_gpio.c 
 *
 *  Author: Nikita Saxena
 *  Date created: 4/1/2000
 * 
 *  This software may be used and distributed according to the terms
 *  of the GNU Public License, incorporated herein by reference.
 *
 *  Description:
 *
 *  The purpose of this driver is to enable simple GPIO read and write
 *  capability using a character driver interface.  This driver allows
 *  access to GPIO lines 24 through 27 on the ADS Graphics Client.
 *
 ************************************************************************
 */

#include <linux/module.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/kernel.h>

#include <asm/segment.h>
#include <asm/hardware.h>



/* Administratrivia */
 #ifndef GPIO_MAJOR
 #define GPIO_MAJOR 59
 #endif


/* Hardware related stuff */
 #define END_IO     3
 #define START_IO   0


 #define GPIO_OFFSET   24

 static void set_gpiobit(unsigned int minor);
 static void clear_gpiobit(unsigned int minor);


/*
 *********************************************************************  
 * Function:  	gpio_write 
 * Author:      Nikita Saxena 
 * 
 * Description: General I/O output routine.
 * 
 *
 **********************************************************************
 */

 static ssize_t gpio_write(struct file * file, 
                           const char * buf, 
                           size_t count,
                           loff_t * ppos)
 {
   struct inode *inode = file->f_dentry->d_inode;
   unsigned int minor = MINOR(inode->i_rdev);
 
   printk("Test Message1, buf[0]=%d\n", buf[0]);
   
   if ( (*buf) == '1')
        set_gpiobit (minor);
   else
      if ( (*buf) == '0')
          clear_gpiobit (minor);

   return(1);       
    
 }


/*
 *********************************************************************  
 * Function:  	set_gpiobit
 * Author:      Nikita Saxena 
 * 
 * Description: Set GPIO bit routine.
 * 
 *
 **********************************************************************
 */


 static void set_gpiobit(unsigned int minor)

 {
       
    if (minor <= END_IO && minor >= START_IO)
    {         

        printk("Test Message 2, minor=%d\n", minor);
        
        GPDR |= GPIO_GPIO(minor + GPIO_OFFSET);         
        GPSR = GPIO_GPIO(minor + GPIO_OFFSET);

    }

 }


/*
 *********************************************************************  
 * Function:  	clear_gpiobit
 * Author:      Nikita Saxena 
 * 
 * Description: Clear GPIO bit routine.
 * 
 *
 **********************************************************************
 */


 static void clear_gpiobit(unsigned int minor)

 {
   
    if (minor <= END_IO && minor >= START_IO)
    {

        printk("Test Message 3, minor=%d\n", minor);
        
        GPDR |= GPIO_GPIO(minor + GPIO_OFFSET);         
        GPCR = GPIO_GPIO(minor + GPIO_OFFSET);

    }

 }


/*
 *********************************************************************  
 * Function:  	gpio_read
 * Author:      Nikita Saxena 
 * 
 * Description: General I/O read routine.
 * 
 *
 **********************************************************************
 */


 static ssize_t gpio_read(struct file * file, 
                          char * buf, 
                          size_t count,
                          loff_t * ppos) 
 {
   struct inode *inode = file->f_dentry->d_inode;
   unsigned int minor = MINOR(inode->i_rdev);
   int bitstate, ret;

   ret = -1;
  
   if (minor <= END_IO && minor >= START_IO)
   {
         
        GPDR &= (~GPIO_GPIO(minor + GPIO_OFFSET)); 
        
        bitstate = (GPLR & GPIO_GPIO(minor + GPIO_OFFSET)) >> (minor + GPIO_OFFSET);
        printk ("The bit state for %d is %d", minor, bitstate);        

        *buf = (char)bitstate;
        ret = 1;
   }  
       
   return ret;
 }


/*
 *********************************************************************  
 * Structure:  	file operations structure
 * Author:      Nikita Saxena 
 * 
 * Description: General I/O file operations functions.
 * 
 *
 **********************************************************************
 */
 

 static struct file_operations gpio_fops = 
 {
   NULL,              /* gio_lseek    */
   gpio_read,	      /* gio_read     */
   gpio_write,        /* gio_write    */
   NULL,		      /* gio_readdir  */
   NULL,	          /* gio_select   */
   NULL,              /* gio_ioctl    */
   NULL,		      /* gio_mmap     */
   NULL,              /* gio_open     */
   NULL               /* gio_release  */
 };


/*
 *********************************************************************  
 * Function:  	init_gpio
 * Author:      Nikita Saxena 
 * 
 * Description: General I/O read initialization routine.
 * 
 *
 **********************************************************************
 */
 

 int init_gpio (void)
 {
  
   if (register_chrdev(GPIO_MAJOR,"gio",&gpio_fops)) 
   {
       printk("gio: unable to get major %d\n", GPIO_MAJOR);
       return -EIO;
   }
   else
       printk("gpio driver initialised\n");
       
   return 0;
 }


/*
 *********************************************************************  
 * Function:  	unregister_giodriver
 * Author:      Nikita Saxena 
 * 
 * Description: General I/O deregister routine.
 * 
 *
 **********************************************************************
 */


 void unregister_giodriver(void)
 {
      
      unregister_chrdev(GPIO_MAJOR,"gio");
  
 }


/*
 * Local variables:
 * compile-command: "cc -DMODULE -D__KERNEL__ -Wall -O2 -DEBUG -c par.c 
 * tab-width: 8
 * End:
 */

