2006-06-27 13:54:19 +04:00
/* linux/drivers/char/nsc_gpio.c
National Semiconductor common GPIO device - file / VFS methods .
Allows a user space process to control the GPIO pins .
Copyright ( c ) 2001 , 2002 Christer Weinigel < wingel @ nano - system . com >
Copyright ( c ) 2005 Jim Cromie < jim . cromie @ gmail . com >
*/
# include <linux/fs.h>
# include <linux/module.h>
# include <linux/errno.h>
# include <linux/kernel.h>
# include <linux/init.h>
# include <linux/nsc_gpio.h>
2006-06-27 13:54:23 +04:00
# include <linux/platform_device.h>
2016-12-24 22:46:01 +03:00
# include <linux/uaccess.h>
2006-06-27 13:54:19 +04:00
# include <asm/io.h>
# define NAME "nsc_gpio"
2006-06-27 13:54:23 +04:00
void nsc_gpio_dump ( struct nsc_gpio_ops * amp , unsigned index )
2006-06-27 13:54:20 +04:00
{
2006-06-27 13:54:23 +04:00
/* retrieve current config w/o changing it */
u32 config = amp - > gpio_config ( index , ~ 0 , 0 ) ;
/* user requested via 'v' command, so its INFO */
2006-06-27 13:54:26 +04:00
dev_info ( amp - > dev , " io%02u: 0x%04x %s %s %s %s %s %s %s \t io:%d/%d \n " ,
2006-06-27 13:54:23 +04:00
index , config ,
( config & 1 ) ? " OE " : " TS " , /* output-enabled/tristate */
( config & 2 ) ? " PP " : " OD " , /* push pull / open drain */
( config & 4 ) ? " PUE " : " PUD " , /* pull up enabled/disabled */
( config & 8 ) ? " LOCKED " : " " , /* locked / unlocked */
( config & 16 ) ? " LEVEL " : " EDGE " , /* level/edge input */
( config & 32 ) ? " HI " : " LO " , /* trigger on rise/fall edge */
2006-06-27 13:54:26 +04:00
( config & 64 ) ? " DEBOUNCE " : " " , /* debounce */
amp - > gpio_get ( index ) , amp - > gpio_current ( index ) ) ;
2006-06-27 13:54:20 +04:00
}
2006-06-27 13:54:20 +04:00
ssize_t nsc_gpio_write ( struct file * file , const char __user * data ,
size_t len , loff_t * ppos )
{
2013-01-24 02:07:38 +04:00
unsigned m = iminor ( file_inode ( file ) ) ;
2006-06-27 13:54:20 +04:00
struct nsc_gpio_ops * amp = file - > private_data ;
2006-06-27 13:54:23 +04:00
struct device * dev = amp - > dev ;
2006-06-27 13:54:20 +04:00
size_t i ;
int err = 0 ;
for ( i = 0 ; i < len ; + + i ) {
char c ;
if ( get_user ( c , data + i ) )
return - EFAULT ;
switch ( c ) {
case ' 0 ' :
amp - > gpio_set ( m , 0 ) ;
break ;
case ' 1 ' :
amp - > gpio_set ( m , 1 ) ;
break ;
case ' O ' :
2006-06-27 13:54:23 +04:00
dev_dbg ( dev , " GPIO%d output enabled \n " , m ) ;
2006-06-27 13:54:20 +04:00
amp - > gpio_config ( m , ~ 1 , 1 ) ;
break ;
case ' o ' :
2006-06-27 13:54:23 +04:00
dev_dbg ( dev , " GPIO%d output disabled \n " , m ) ;
2006-06-27 13:54:20 +04:00
amp - > gpio_config ( m , ~ 1 , 0 ) ;
break ;
case ' T ' :
2006-07-14 11:24:26 +04:00
dev_dbg ( dev , " GPIO%d output is push pull \n " , m ) ;
2006-06-27 13:54:20 +04:00
amp - > gpio_config ( m , ~ 2 , 2 ) ;
break ;
case ' t ' :
2006-07-14 11:24:26 +04:00
dev_dbg ( dev , " GPIO%d output is open drain \n " , m ) ;
2006-06-27 13:54:20 +04:00
amp - > gpio_config ( m , ~ 2 , 0 ) ;
break ;
case ' P ' :
2006-06-27 13:54:23 +04:00
dev_dbg ( dev , " GPIO%d pull up enabled \n " , m ) ;
2006-06-27 13:54:20 +04:00
amp - > gpio_config ( m , ~ 4 , 4 ) ;
break ;
case ' p ' :
2006-06-27 13:54:23 +04:00
dev_dbg ( dev , " GPIO%d pull up disabled \n " , m ) ;
2006-06-27 13:54:20 +04:00
amp - > gpio_config ( m , ~ 4 , 0 ) ;
break ;
case ' v ' :
/* View Current pin settings */
2006-06-27 13:54:23 +04:00
amp - > gpio_dump ( amp , m ) ;
2006-06-27 13:54:20 +04:00
break ;
case ' \n ' :
/* end of settings string, do nothing */
break ;
default :
2006-06-27 13:54:23 +04:00
dev_err ( dev , " io%2d bad setting: chr<0x%2x> \n " ,
m , ( int ) c ) ;
2006-06-27 13:54:20 +04:00
err + + ;
}
}
if ( err )
return - EINVAL ; /* full string handled, report error */
return len ;
}
ssize_t nsc_gpio_read ( struct file * file , char __user * buf ,
size_t len , loff_t * ppos )
{
2013-01-24 02:07:38 +04:00
unsigned m = iminor ( file_inode ( file ) ) ;
2006-06-27 13:54:20 +04:00
int value ;
struct nsc_gpio_ops * amp = file - > private_data ;
value = amp - > gpio_get ( m ) ;
if ( put_user ( value ? ' 1 ' : ' 0 ' , buf ) )
return - EFAULT ;
return 1 ;
}
2006-06-27 13:54:20 +04:00
/* common file-ops routines for both scx200_gpio and pc87360_gpio */
2006-06-27 13:54:20 +04:00
EXPORT_SYMBOL ( nsc_gpio_write ) ;
EXPORT_SYMBOL ( nsc_gpio_read ) ;
2006-06-27 13:54:20 +04:00
EXPORT_SYMBOL ( nsc_gpio_dump ) ;
2006-06-27 13:54:19 +04:00
static int __init nsc_gpio_init ( void )
{
printk ( KERN_DEBUG NAME " initializing \n " ) ;
return 0 ;
}
static void __exit nsc_gpio_cleanup ( void )
{
printk ( KERN_DEBUG NAME " cleanup \n " ) ;
}
module_init ( nsc_gpio_init ) ;
module_exit ( nsc_gpio_cleanup ) ;
2006-06-27 13:54:20 +04:00
MODULE_AUTHOR ( " Jim Cromie <jim.cromie@gmail.com> " ) ;
MODULE_DESCRIPTION ( " NatSemi GPIO Common Methods " ) ;
MODULE_LICENSE ( " GPL " ) ;