2005-04-16 15:20:36 -07:00
/*
* linux / arch / h8300 / kernel / gpio . c
*
* Yoshinori Sato < ysato @ users . sourceforge . jp >
*
*/
/*
* Internal I / O Port Management
*/
# include <linux/stddef.h>
# include <linux/proc_fs.h>
2013-04-11 02:32:46 +01:00
# include <linux/seq_file.h>
2005-04-16 15:20:36 -07:00
# include <linux/kernel.h>
# include <linux/string.h>
# include <linux/fs.h>
# include <linux/init.h>
# define _(addr) (volatile unsigned char *)(addr)
# if defined(CONFIG_H83007) || defined(CONFIG_H83068)
# include <asm/regs306x.h>
static volatile unsigned char * ddrs [ ] = {
_ ( P1DDR ) , _ ( P2DDR ) , _ ( P3DDR ) , _ ( P4DDR ) , _ ( P5DDR ) , _ ( P6DDR ) ,
NULL , _ ( P8DDR ) , _ ( P9DDR ) , _ ( PADDR ) , _ ( PBDDR ) ,
} ;
# define MAX_PORT 11
# endif
# if defined(CONFIG_H83002) || defined(CONFIG_H8048)
/* Fix me!! */
# include <asm/regs306x.h>
static volatile unsigned char * ddrs [ ] = {
_ ( P1DDR ) , _ ( P2DDR ) , _ ( P3DDR ) , _ ( P4DDR ) , _ ( P5DDR ) , _ ( P6DDR ) ,
NULL , _ ( P8DDR ) , _ ( P9DDR ) , _ ( PADDR ) , _ ( PBDDR ) ,
} ;
# define MAX_PORT 11
# endif
# if defined(CONFIG_H8S2678)
# include <asm/regs267x.h>
static volatile unsigned char * ddrs [ ] = {
_ ( P1DDR ) , _ ( P2DDR ) , _ ( P3DDR ) , NULL , _ ( P5DDR ) , _ ( P6DDR ) ,
_ ( P7DDR ) , _ ( P8DDR ) , NULL , _ ( PADDR ) , _ ( PBDDR ) , _ ( PCDDR ) ,
_ ( PDDDR ) , _ ( PEDDR ) , _ ( PFDDR ) , _ ( PGDDR ) , _ ( PHDDR ) ,
_ ( PADDR ) , _ ( PBDDR ) , _ ( PCDDR ) , _ ( PDDDR ) , _ ( PEDDR ) , _ ( PFDDR ) ,
_ ( PGDDR ) , _ ( PHDDR )
} ;
# define MAX_PORT 17
# endif
# undef _
# if !defined(P1DDR)
# error Unsuppoted CPU Selection
# endif
static struct {
unsigned char used ;
unsigned char ddr ;
} gpio_regs [ MAX_PORT ] ;
extern char * _platform_gpio_table ( int length ) ;
int h8300_reserved_gpio ( int port , unsigned int bits )
{
unsigned char * used ;
if ( port < 0 | | port > = MAX_PORT )
return - 1 ;
used = & ( gpio_regs [ port ] . used ) ;
if ( ( * used & bits ) ! = 0 )
return 0 ;
* used | = bits ;
return 1 ;
}
int h8300_free_gpio ( int port , unsigned int bits )
{
unsigned char * used ;
if ( port < 0 | | port > = MAX_PORT )
return - 1 ;
used = & ( gpio_regs [ port ] . used ) ;
if ( ( * used & bits ) ! = bits )
return 0 ;
* used & = ( ~ bits ) ;
return 1 ;
}
int h8300_set_gpio_dir ( int port_bit , int dir )
{
int port = ( port_bit > > 8 ) & 0xff ;
int bit = port_bit & 0xff ;
if ( ddrs [ port ] = = NULL )
return 0 ;
if ( gpio_regs [ port ] . used & bit ) {
if ( dir )
gpio_regs [ port ] . ddr | = bit ;
else
gpio_regs [ port ] . ddr & = ~ bit ;
* ddrs [ port ] = gpio_regs [ port ] . ddr ;
return 1 ;
} else
return 0 ;
}
int h8300_get_gpio_dir ( int port_bit )
{
int port = ( port_bit > > 8 ) & 0xff ;
int bit = port_bit & 0xff ;
if ( ddrs [ port ] = = NULL )
return 0 ;
if ( gpio_regs [ port ] . used & bit ) {
return ( gpio_regs [ port ] . ddr & bit ) ! = 0 ;
} else
return - 1 ;
}
# if defined(CONFIG_PROC_FS)
static char * port_status ( int portno )
{
static char result [ 10 ] ;
2006-01-09 20:54:01 -08:00
static const char io [ 2 ] = { ' I ' , ' O ' } ;
2005-04-16 15:20:36 -07:00
char * rp ;
int c ;
unsigned char used , ddr ;
used = gpio_regs [ portno ] . used ;
ddr = gpio_regs [ portno ] . ddr ;
result [ 8 ] = ' \0 ' ;
rp = result + 7 ;
for ( c = 8 ; c > 0 ; c - - , rp - - , used > > = 1 , ddr > > = 1 )
if ( used & 0x01 )
* rp = io [ ddr & 0x01 ] ;
else
* rp = ' - ' ;
return result ;
}
2013-04-11 02:32:46 +01:00
static int gpio_proc_show ( struct seq_file * m , void * v )
2005-04-16 15:20:36 -07:00
{
2006-01-09 20:54:01 -08:00
static const char port_name [ ] = " 123456789ABCDEFGH " ;
2013-04-11 02:32:46 +01:00
int c ;
2005-04-16 15:20:36 -07:00
for ( c = 0 ; c < MAX_PORT ; c + + ) {
if ( ddrs [ c ] = = NULL )
2013-04-11 02:32:46 +01:00
continue ;
seq_printf ( m , " P%c: %s \n " , port_name [ c ] , port_status ( c ) ) ;
2005-04-16 15:20:36 -07:00
}
2013-04-11 02:32:46 +01:00
return 0 ;
2005-04-16 15:20:36 -07:00
}
2013-04-11 02:32:46 +01:00
static int gpio_proc_open ( struct inode * inode , struct file * file )
2005-04-16 15:20:36 -07:00
{
2013-04-11 02:32:46 +01:00
return single_open ( file , gpio_proc_show , PDE_DATA ( inode ) ) ;
}
2005-04-16 15:20:36 -07:00
2013-04-11 02:32:46 +01:00
static const struct file_operations gpio_proc_fops = {
. open = gpio_proc_open ,
. read = seq_read ,
. llseek = seq_lseek ,
2013-05-05 00:08:26 -04:00
. release = single_release ,
2013-04-11 02:32:46 +01:00
} ;
static __init int register_proc ( void )
{
return proc_create ( " gpio " , S_IRUGO , NULL , & gpio_proc_fops ) ! = NULL ;
2005-04-16 15:20:36 -07:00
}
__initcall ( register_proc ) ;
# endif
void __init h8300_gpio_init ( void )
{
memcpy ( gpio_regs , _platform_gpio_table ( sizeof ( gpio_regs ) ) , sizeof ( gpio_regs ) ) ;
}