2007-09-30 20:35:09 +01:00
/*
* arch / arm / mach - ns9xxx / gpio . c
*
2008-02-15 08:41:06 +01:00
* Copyright ( C ) 2006 , 2007 by Digi International Inc .
2007-09-30 20:35:09 +01:00
* All rights reserved .
*
* This program is free software ; you can redistribute it and / or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation .
*/
2008-10-29 14:14:54 -07:00
# include <linux/kernel.h>
2007-09-30 20:35:09 +01:00
# include <linux/compiler.h>
# include <linux/init.h>
# include <linux/spinlock.h>
# include <linux/module.h>
2008-09-06 12:13:59 +01:00
# include <linux/bitops.h>
2007-09-30 20:35:09 +01:00
2008-08-05 16:14:15 +01:00
# include <mach/gpio.h>
# include <mach/processor.h>
# include <mach/processor-ns9360.h>
2007-09-30 20:35:09 +01:00
# include <asm/bug.h>
# include <asm/types.h>
2008-02-15 08:41:06 +01:00
# include "gpio-ns9360.h"
2007-09-30 20:35:09 +01:00
# if defined(CONFIG_PROCESSOR_NS9360)
# define GPIO_MAX 72
# elif defined(CONFIG_PROCESSOR_NS9750)
# define GPIO_MAX 49
# endif
/* protects BBU_GCONFx and BBU_GCTRLx */
static spinlock_t gpio_lock = __SPIN_LOCK_UNLOCKED ( gpio_lock ) ;
/* only access gpiores with atomic ops */
2008-03-06 16:21:42 +01:00
static DECLARE_BITMAP ( gpiores , GPIO_MAX + 1 ) ;
2007-09-30 20:35:09 +01:00
static inline int ns9xxx_valid_gpio ( unsigned gpio )
{
# if defined(CONFIG_PROCESSOR_NS9360)
if ( processor_is_ns9360 ( ) )
return gpio < = 72 ;
else
# endif
# if defined(CONFIG_PROCESSOR_NS9750)
if ( processor_is_ns9750 ( ) )
return gpio < = 49 ;
else
# endif
2008-02-15 08:41:06 +01:00
{
2007-09-30 20:35:09 +01:00
BUG ( ) ;
2008-02-15 08:41:06 +01:00
return 0 ;
}
2007-09-30 20:35:09 +01:00
}
int gpio_request ( unsigned gpio , const char * label )
{
if ( likely ( ns9xxx_valid_gpio ( gpio ) ) )
return test_and_set_bit ( gpio , gpiores ) ? - EBUSY : 0 ;
else
return - EINVAL ;
}
EXPORT_SYMBOL ( gpio_request ) ;
void gpio_free ( unsigned gpio )
{
2008-10-29 14:14:54 -07:00
might_sleep ( ) ;
2007-09-30 20:35:09 +01:00
clear_bit ( gpio , gpiores ) ;
return ;
}
EXPORT_SYMBOL ( gpio_free ) ;
2008-02-15 08:41:06 +01:00
int gpio_direction_input ( unsigned gpio )
2007-09-30 20:35:09 +01:00
{
2008-02-15 08:41:06 +01:00
if ( likely ( ns9xxx_valid_gpio ( gpio ) ) ) {
int ret = - EINVAL ;
unsigned long flags ;
2007-09-30 20:35:09 +01:00
2008-02-15 08:41:06 +01:00
spin_lock_irqsave ( & gpio_lock , flags ) ;
# if defined(CONFIG_PROCESSOR_NS9360)
if ( processor_is_ns9360 ( ) )
ret = __ns9360_gpio_configure ( gpio , 0 , 0 , 3 ) ;
else
# endif
BUG ( ) ;
2007-09-30 20:35:09 +01:00
2008-02-15 08:41:06 +01:00
spin_unlock_irqrestore ( & gpio_lock , flags ) ;
2007-09-30 20:35:09 +01:00
2008-02-15 08:41:06 +01:00
return ret ;
2007-09-30 20:35:09 +01:00
} else
return - EINVAL ;
}
EXPORT_SYMBOL ( gpio_direction_input ) ;
int gpio_direction_output ( unsigned gpio , int value )
{
if ( likely ( ns9xxx_valid_gpio ( gpio ) ) ) {
2008-02-15 08:41:06 +01:00
int ret = - EINVAL ;
unsigned long flags ;
2007-09-30 20:35:09 +01:00
gpio_set_value ( gpio , value ) ;
2008-02-15 08:41:06 +01:00
spin_lock_irqsave ( & gpio_lock , flags ) ;
# if defined(CONFIG_PROCESSOR_NS9360)
if ( processor_is_ns9360 ( ) )
ret = __ns9360_gpio_configure ( gpio , 1 , 0 , 3 ) ;
else
# endif
BUG ( ) ;
spin_unlock_irqrestore ( & gpio_lock , flags ) ;
return ret ;
2007-09-30 20:35:09 +01:00
} else
return - EINVAL ;
}
EXPORT_SYMBOL ( gpio_direction_output ) ;
int gpio_get_value ( unsigned gpio )
{
2008-02-15 08:41:06 +01:00
# if defined(CONFIG_PROCESSOR_NS9360)
if ( processor_is_ns9360 ( ) )
return ns9360_gpio_get_value ( gpio ) ;
else
# endif
{
BUG ( ) ;
return - EINVAL ;
}
2007-09-30 20:35:09 +01:00
}
EXPORT_SYMBOL ( gpio_get_value ) ;
void gpio_set_value ( unsigned gpio , int value )
{
unsigned long flags ;
spin_lock_irqsave ( & gpio_lock , flags ) ;
2008-02-15 08:41:06 +01:00
# if defined(CONFIG_PROCESSOR_NS9360)
if ( processor_is_ns9360 ( ) )
ns9360_gpio_set_value ( gpio , value ) ;
2007-09-30 20:35:09 +01:00
else
2008-02-15 08:41:06 +01:00
# endif
BUG ( ) ;
2007-09-30 20:35:09 +01:00
spin_unlock_irqrestore ( & gpio_lock , flags ) ;
}
EXPORT_SYMBOL ( gpio_set_value ) ;