|
From: Leblanc f. <fle...@us...> - 2002-06-13 12:57:36
|
Update of /cvsroot/linux-mips/linux/drivers/char
In directory usw-pr-cvs1:/tmp/cvs-serv2868/drivers/char
Modified Files:
Makefile
Added Files:
adif.c
Log Message:
Correct CONFIG_PM conflict in config.in and move misplaced files.
--- NEW FILE: adif.c ---
/*
* linux/arch/mips/vr41xx/adif.c
*
* VR41xx Lvl A/D driver
*
* Parts Copyright (C) 2001 Chris AtLee <ca...@ca...>
* Parts Copyright (C) 2001 Paul Jimenez <pj...@ag...>
* Parts Copyright (C) 2001 Alexandre d'Alton <ale...@ya...>
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/major.h>
#include <linux/sched.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <asm/irq.h>
#include <asm/vr41xx.h>
#define VR41XX_ADIF_MINOR 15
static wait_queue_head_t wait;
static void
adif_irq_handler (int irq, void *dev_id, struct pt_regs *regs)
{
wake_up_interruptible (&wait);
}
static int
adif_open (struct inode *inode, struct file *file)
{
/* Readonly, sure they can all be open */
return 0;
}
static int
adif_close (struct inode *inode, struct file *file)
{
return 0;
}
static ssize_t
adif_read (struct file *file, char *buf, size_t count, loff_t * offset)
{
int original_stable;
unsigned short adin[4];
ssize_t retval;
unsigned long flags;
unsigned int j;
if (count < 4 * sizeof (short))
{
printk ("adif: Invalid count(%d) specified (must be at least %d)\n",
count, 4 * sizeof (short));
return 0;
}
/*** get battery readings here */
/** wait til we get into one of Standby, WaitPenTouch, or Interval state per
VR4181.pdf 19.4 */
/* If the pen is down, we can't use the PIU, so we wait. */
cli();
while(*VR41XX_PIUCNTREG & 0x2000){
sti();
j = jiffies + 100;
while(jiffies < j)
schedule();
}
save_and_cli (flags);
/* We need to activate the PIU clocks. */
*VR41XX_CMUCLKMSK |= (VR41XX_CMUCLKMSK_MSKKIU|
VR41XX_CMUCLKMSK_MSKSIU);
barrier ();
/* All these step are probably not needed, but they were for debugging */
*VR41XX_PIUCNTREG = 1;
*VR41XX_PIUCNTREG = 0x2; /* Power up the PIU */
#define PIU_IN_STANDBY ((*VR41XX_PIUCNTREG & 0x1c00) == 0x0400)
while (!PIU_IN_STANDBY)
*VR41XX_PIUCNTREG &= ~0x2; /* Go in standby state */
barrier ();
*VR41XX_PIUAMSKREG = 0xFF0F; /* Mask ADIN[0-2] & MIC pins */
barrier ();
restore_flags (flags);
/* set irq */
/* When we share IRQ we have to differentiate between two handlers
for the same IRQ, that's why we put the address ow the wait queue
as last argument to request_irq. */
if (retval = request_irq (VR41XX_IRQ_PIU, adif_irq_handler, SA_SHIRQ,
"vr41xx_battery_level", &wait))
{
/* restore PIUSTBLREG */
// *VR41XX_PIUSTBLREG = original_stable;
printk ("adif: unable to request_irq (%d)\n", retval);
return -retval;
}
barrier ();
save_and_cli (flags);
/* start the process */
*VR41XX_PIUASCNREG = 0x1;
barrier ();
*VR41XX_PIUCNTREG |= 0x0004;
barrier ();
restore_flags (flags);
/* sleep until the value is ready */
interruptible_sleep_on (&wait);
save_and_cli (flags);
*VR41XX_PIUAMSKREG = 0xFFF0;
*VR41XX_PIUASCNREG = 0x2;
barrier ();
/* read values */
adin[0] = *VR41XX_PIUAB0REG;
adin[1] = *VR41XX_PIUAB1REG;
adin[2] = *VR41XX_PIUAB2REG;
adin[3] = *VR41XX_PIUAB3REG;
/* Reset the PIU Controler in its default state */
*VR41XX_PIUCNTREG = 1;
barrier();
*VR41XX_PIUCNTREG = 0x2; /* Power up the PIU */
barrier();
while (!PIU_IN_STANDBY)
*VR41XX_PIUCNTREG &= ~0x2; /* Go in standby state */
*VR41XX_PIUCNTREG = 0x0322;
barrier ();
*VR41XX_PIUSIVLREG = 333; // set interval to .01 sec default
*VR41XX_PIUSTBLREG = 0x10;
barrier ();
*VR41XX_MPIUINTREG = 0x007d;
barrier ();
*VR41XX_PIUCNTREG = 0x0326; // resume autoscan
barrier ();
/* Shut down the clocks. */
*VR41XX_CMUCLKMSK &= ~(VR41XX_CMUCLKMSK_MSKKIU |
VR41XX_CMUCLKMSK_MSKSIU);
restore_flags (flags);
free_irq (VR41XX_IRQ_PIU, &wait);
// printk ("adif: returning %d, %d, %d, %d\n", adin[0], adin[1], adin[2],
// adin[3]);
if (!access_ok(VERIFY_WRITE, buf, 8))
return -EFAULT;
__put_user (adin[0], (short *) (buf));
__put_user (adin[1], (short *) (buf + 2));
__put_user (adin[2], (short *) (buf + 4));
__put_user (adin[3], (short *) (buf + 6));
return 4 * sizeof (short);
}
static struct file_operations adif_fops;
static struct miscdevice adif_device;
static int
adif_init (void)
{
int retval;
init_waitqueue_head (&wait);
/* NULL out the data structure before filling it */
memset (&adif_fops, 0, sizeof (struct file_operations));
adif_fops.read = adif_read;
adif_fops.open = adif_open;
adif_fops.release = adif_close;
/* NULL out the data structure before filling it */
memset (&adif_device, 0, sizeof (struct miscdevice));
adif_device.minor = VR41XX_ADIF_MINOR;
adif_device.name = "adif";
adif_device.fops = &adif_fops;
/* register it */
retval = misc_register (&adif_device);
if (retval < 0)
{
printk ("Failed to register A/D interface driver\n");
return retval;
}
printk ("A/D interface driver registered on %i,%i\n", MISC_MAJOR,
VR41XX_ADIF_MINOR);
return 0;
}
static void
adif_exit (void)
{
if (0 > misc_deregister (&adif_device))
printk ("Error unregistering A/D interface driver\n");
}
module_init (adif_init);
module_exit (adif_exit);
Index: Makefile
===================================================================
RCS file: /cvsroot/linux-mips/linux/drivers/char/Makefile,v
retrieving revision 1.31
retrieving revision 1.32
diff -u -d -r1.31 -r1.32
--- Makefile 31 May 2002 20:12:20 -0000 1.31
+++ Makefile 13 Jun 2002 12:57:33 -0000 1.32
@@ -270,6 +270,7 @@
obj-$(CONFIG_VR41XX_GPIO_BUTTONS) += gpiobtns.o
obj-$(CONFIG_VR41XX_E105_BUTTONS) += e105btns.o
obj-$(CONFIG_TOUCH_PANEL) += tpanel.o
+obj-$(CONFIG_ADIF) += adif.o
subdir-$(CONFIG_MWAVE) += mwave
ifeq ($(CONFIG_MWAVE),y)
|