2006-01-09 17:05:41 +00:00
/*
2007-02-05 11:42:07 +01:00
* linux / arch / arm / mach - at91 / gpio . c
2006-01-09 17:05:41 +00:00
*
* Copyright ( C ) 2005 HP Labs
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*/
2006-09-27 13:23:00 +01:00
# include <linux/clk.h>
2006-01-09 17:05:41 +00:00
# include <linux/errno.h>
2006-07-01 23:01:50 +01:00
# include <linux/interrupt.h>
# include <linux/irq.h>
2007-11-23 16:09:10 +01:00
# include <linux/debugfs.h>
# include <linux/seq_file.h>
2006-01-09 17:05:41 +00:00
# include <linux/kernel.h>
# include <linux/list.h>
# include <linux/module.h>
2008-09-06 12:10:45 +01:00
# include <linux/io.h>
2006-01-09 17:05:41 +00:00
2008-08-05 16:14:15 +01:00
# include <mach/hardware.h>
# include <mach/at91_pio.h>
# include <mach/gpio.h>
2006-01-09 17:05:41 +00:00
2006-09-27 13:23:00 +01:00
# include "generic.h"
static struct at91_gpio_bank * gpio ;
static int gpio_banks ;
2006-01-09 17:05:41 +00:00
static inline void __iomem * pin_to_controller ( unsigned pin )
{
pin - = PIN_BASE ;
pin / = 32 ;
2006-09-27 13:23:00 +01:00
if ( likely ( pin < gpio_banks ) )
2008-01-04 18:30:24 +01:00
return gpio [ pin ] . regbase ;
2006-01-09 17:05:41 +00:00
return NULL ;
}
static inline unsigned pin_to_mask ( unsigned pin )
{
pin - = PIN_BASE ;
return 1 < < ( pin % 32 ) ;
}
/*--------------------------------------------------------------------------*/
/* Not all hardware capabilities are exposed through these calls; they
* only encapsulate the most common features and modes . ( So if you
* want to change signals in groups , do it directly . )
*
* Bootloaders will usually handle some of the pin multiplexing setup .
* The intent is certainly that by the time Linux is fully booted , all
* pins should have been fully initialized . These setup calls should
* only be used by board setup routines , or possibly in driver probe ( ) .
*
* For bootloaders doing all that setup , these calls could be inlined
* as NOPs so Linux won ' t duplicate any setup code
*/
2007-02-12 00:53:13 -08:00
/*
* mux the pin to the " GPIO " peripheral role .
*/
int __init_or_module at91_set_GPIO_periph ( unsigned pin , int use_pullup )
{
void __iomem * pio = pin_to_controller ( pin ) ;
unsigned mask = pin_to_mask ( pin ) ;
if ( ! pio )
return - EINVAL ;
__raw_writel ( mask , pio + PIO_IDR ) ;
__raw_writel ( mask , pio + ( use_pullup ? PIO_PUER : PIO_PUDR ) ) ;
__raw_writel ( mask , pio + PIO_PER ) ;
return 0 ;
}
EXPORT_SYMBOL ( at91_set_GPIO_periph ) ;
2006-01-09 17:05:41 +00:00
/*
* mux the pin to the " A " internal peripheral role .
*/
int __init_or_module at91_set_A_periph ( unsigned pin , int use_pullup )
{
void __iomem * pio = pin_to_controller ( pin ) ;
unsigned mask = pin_to_mask ( pin ) ;
if ( ! pio )
return - EINVAL ;
__raw_writel ( mask , pio + PIO_IDR ) ;
__raw_writel ( mask , pio + ( use_pullup ? PIO_PUER : PIO_PUDR ) ) ;
__raw_writel ( mask , pio + PIO_ASR ) ;
__raw_writel ( mask , pio + PIO_PDR ) ;
return 0 ;
}
EXPORT_SYMBOL ( at91_set_A_periph ) ;
/*
* mux the pin to the " B " internal peripheral role .
*/
int __init_or_module at91_set_B_periph ( unsigned pin , int use_pullup )
{
void __iomem * pio = pin_to_controller ( pin ) ;
unsigned mask = pin_to_mask ( pin ) ;
if ( ! pio )
return - EINVAL ;
__raw_writel ( mask , pio + PIO_IDR ) ;
__raw_writel ( mask , pio + ( use_pullup ? PIO_PUER : PIO_PUDR ) ) ;
__raw_writel ( mask , pio + PIO_BSR ) ;
__raw_writel ( mask , pio + PIO_PDR ) ;
return 0 ;
}
EXPORT_SYMBOL ( at91_set_B_periph ) ;
/*
* mux the pin to the gpio controller ( instead of " A " or " B " peripheral ) , and
* configure it for an input .
*/
int __init_or_module at91_set_gpio_input ( unsigned pin , int use_pullup )
{
void __iomem * pio = pin_to_controller ( pin ) ;
unsigned mask = pin_to_mask ( pin ) ;
if ( ! pio )
return - EINVAL ;
__raw_writel ( mask , pio + PIO_IDR ) ;
__raw_writel ( mask , pio + ( use_pullup ? PIO_PUER : PIO_PUDR ) ) ;
__raw_writel ( mask , pio + PIO_ODR ) ;
__raw_writel ( mask , pio + PIO_PER ) ;
return 0 ;
}
EXPORT_SYMBOL ( at91_set_gpio_input ) ;
/*
* mux the pin to the gpio controller ( instead of " A " or " B " peripheral ) ,
* and configure it for an output .
*/
int __init_or_module at91_set_gpio_output ( unsigned pin , int value )
{
void __iomem * pio = pin_to_controller ( pin ) ;
unsigned mask = pin_to_mask ( pin ) ;
if ( ! pio )
return - EINVAL ;
__raw_writel ( mask , pio + PIO_IDR ) ;
__raw_writel ( mask , pio + PIO_PUDR ) ;
__raw_writel ( mask , pio + ( value ? PIO_SODR : PIO_CODR ) ) ;
__raw_writel ( mask , pio + PIO_OER ) ;
__raw_writel ( mask , pio + PIO_PER ) ;
return 0 ;
}
EXPORT_SYMBOL ( at91_set_gpio_output ) ;
/*
* enable / disable the glitch filter ; mostly used with IRQ handling .
*/
int __init_or_module at91_set_deglitch ( unsigned pin , int is_on )
{
void __iomem * pio = pin_to_controller ( pin ) ;
unsigned mask = pin_to_mask ( pin ) ;
if ( ! pio )
return - EINVAL ;
__raw_writel ( mask , pio + ( is_on ? PIO_IFER : PIO_IFDR ) ) ;
return 0 ;
}
EXPORT_SYMBOL ( at91_set_deglitch ) ;
2006-02-22 21:23:35 +00:00
/*
* enable / disable the multi - driver ; This is only valid for output and
* allows the output pin to run as an open collector output .
*/
int __init_or_module at91_set_multi_drive ( unsigned pin , int is_on )
{
void __iomem * pio = pin_to_controller ( pin ) ;
unsigned mask = pin_to_mask ( pin ) ;
if ( ! pio )
return - EINVAL ;
__raw_writel ( mask , pio + ( is_on ? PIO_MDER : PIO_MDDR ) ) ;
return 0 ;
}
EXPORT_SYMBOL ( at91_set_multi_drive ) ;
2006-01-09 17:05:41 +00:00
/*--------------------------------------------------------------------------*/
2007-02-12 00:53:13 -08:00
/* new-style GPIO calls; these expect at91_set_GPIO_periph to have been
* called , and maybe at91_set_multi_drive ( ) for putout pins .
*/
int gpio_direction_input ( unsigned pin )
{
void __iomem * pio = pin_to_controller ( pin ) ;
unsigned mask = pin_to_mask ( pin ) ;
if ( ! pio | | ! ( __raw_readl ( pio + PIO_PSR ) & mask ) )
return - EINVAL ;
2007-02-22 09:38:52 +01:00
__raw_writel ( mask , pio + PIO_ODR ) ;
2007-02-12 00:53:13 -08:00
return 0 ;
}
EXPORT_SYMBOL ( gpio_direction_input ) ;
2007-03-16 13:38:14 -08:00
int gpio_direction_output ( unsigned pin , int value )
2007-02-12 00:53:13 -08:00
{
void __iomem * pio = pin_to_controller ( pin ) ;
unsigned mask = pin_to_mask ( pin ) ;
if ( ! pio | | ! ( __raw_readl ( pio + PIO_PSR ) & mask ) )
return - EINVAL ;
2007-03-16 13:38:14 -08:00
__raw_writel ( mask , pio + ( value ? PIO_SODR : PIO_CODR ) ) ;
2007-02-12 00:53:13 -08:00
__raw_writel ( mask , pio + PIO_OER ) ;
return 0 ;
}
EXPORT_SYMBOL ( gpio_direction_output ) ;
/*--------------------------------------------------------------------------*/
2006-01-09 17:05:41 +00:00
/*
* assuming the pin is muxed as a gpio output , set its value .
*/
int at91_set_gpio_value ( unsigned pin , int value )
{
void __iomem * pio = pin_to_controller ( pin ) ;
unsigned mask = pin_to_mask ( pin ) ;
if ( ! pio )
return - EINVAL ;
__raw_writel ( mask , pio + ( value ? PIO_SODR : PIO_CODR ) ) ;
return 0 ;
}
EXPORT_SYMBOL ( at91_set_gpio_value ) ;
/*
* read the pin ' s value ( works even if it ' s not muxed as a gpio ) .
*/
int at91_get_gpio_value ( unsigned pin )
{
void __iomem * pio = pin_to_controller ( pin ) ;
unsigned mask = pin_to_mask ( pin ) ;
u32 pdsr ;
if ( ! pio )
return - EINVAL ;
pdsr = __raw_readl ( pio + PIO_PDSR ) ;
return ( pdsr & mask ) ! = 0 ;
}
EXPORT_SYMBOL ( at91_get_gpio_value ) ;
/*--------------------------------------------------------------------------*/
2006-06-19 15:26:54 +01:00
# ifdef CONFIG_PM
2006-09-27 13:23:00 +01:00
static u32 wakeups [ MAX_GPIO_BANKS ] ;
static u32 backups [ MAX_GPIO_BANKS ] ;
2006-06-19 15:26:54 +01:00
static int gpio_irq_set_wake ( unsigned pin , unsigned state )
{
unsigned mask = pin_to_mask ( pin ) ;
2007-01-09 13:47:29 +01:00
unsigned bank = ( pin - PIN_BASE ) / 32 ;
2006-06-19 15:26:54 +01:00
2007-01-09 13:47:29 +01:00
if ( unlikely ( bank > = MAX_GPIO_BANKS ) )
2006-06-19 15:26:54 +01:00
return - EINVAL ;
if ( state )
2007-01-09 13:47:29 +01:00
wakeups [ bank ] | = mask ;
2006-06-19 15:26:54 +01:00
else
2007-01-09 13:47:29 +01:00
wakeups [ bank ] & = ~ mask ;
set_irq_wake ( gpio [ bank ] . id , state ) ;
2006-06-19 15:26:54 +01:00
return 0 ;
}
void at91_gpio_suspend ( void )
{
int i ;
2006-09-27 13:23:00 +01:00
for ( i = 0 ; i < gpio_banks ; i + + ) {
2008-01-04 18:30:24 +01:00
void __iomem * pio = gpio [ i ] . regbase ;
2006-06-19 15:26:54 +01:00
2008-01-04 18:30:24 +01:00
backups [ i ] = __raw_readl ( pio + PIO_IMR ) ;
__raw_writel ( backups [ i ] , pio + PIO_IDR ) ;
__raw_writel ( wakeups [ i ] , pio + PIO_IER ) ;
2006-06-19 15:26:54 +01:00
2007-01-09 13:47:29 +01:00
if ( ! wakeups [ i ] )
clk_disable ( gpio [ i ] . clock ) ;
else {
2006-06-19 15:26:54 +01:00
# ifdef CONFIG_PM_DEBUG
2007-01-09 13:47:29 +01:00
printk ( KERN_DEBUG " GPIO-%c may wake for %08x \n " , ' A ' + i , wakeups [ i ] ) ;
2006-06-19 15:26:54 +01:00
# endif
}
}
}
void at91_gpio_resume ( void )
{
int i ;
2006-09-27 13:23:00 +01:00
for ( i = 0 ; i < gpio_banks ; i + + ) {
2008-01-04 18:30:24 +01:00
void __iomem * pio = gpio [ i ] . regbase ;
2006-06-19 15:26:54 +01:00
2007-01-09 13:47:29 +01:00
if ( ! wakeups [ i ] )
clk_enable ( gpio [ i ] . clock ) ;
2008-01-04 18:30:24 +01:00
__raw_writel ( wakeups [ i ] , pio + PIO_IDR ) ;
__raw_writel ( backups [ i ] , pio + PIO_IER ) ;
2006-09-27 13:23:00 +01:00
}
2006-06-19 15:26:54 +01:00
}
# else
# define gpio_irq_set_wake NULL
# endif
2006-01-09 17:05:41 +00:00
/* Several AIC controller irqs are dispatched through this GPIO handler.
* To use any AT91_PIN_ * as an externally triggered IRQ , first call
* at91_set_gpio_input ( ) then maybe enable its glitch filter .
* Then just request_irq ( ) with the pin ID ; it works like any ARM IRQ
* handler , though it always triggers on rising and falling edges .
*
* Alternatively , certain pins may be used directly as IRQ0 . . IRQ6 after
* configuring them with at91_set_a_periph ( ) or at91_set_b_periph ( ) .
* IRQ0 . . IRQ6 should be configurable , e . g . level vs edge triggering .
*/
static void gpio_irq_mask ( unsigned pin )
{
void __iomem * pio = pin_to_controller ( pin ) ;
unsigned mask = pin_to_mask ( pin ) ;
if ( pio )
__raw_writel ( mask , pio + PIO_IDR ) ;
}
static void gpio_irq_unmask ( unsigned pin )
{
void __iomem * pio = pin_to_controller ( pin ) ;
unsigned mask = pin_to_mask ( pin ) ;
if ( pio )
__raw_writel ( mask , pio + PIO_IER ) ;
}
static int gpio_irq_type ( unsigned pin , unsigned type )
{
2008-01-04 18:30:24 +01:00
switch ( type ) {
case IRQ_TYPE_NONE :
case IRQ_TYPE_EDGE_BOTH :
return 0 ;
default :
return - EINVAL ;
}
2006-01-09 17:05:41 +00:00
}
2006-08-01 22:26:25 +01:00
static struct irq_chip gpio_irqchip = {
. name = " GPIO " ,
2006-01-09 17:05:41 +00:00
. mask = gpio_irq_mask ,
. unmask = gpio_irq_unmask ,
. set_type = gpio_irq_type ,
2006-06-19 15:26:54 +01:00
. set_wake = gpio_irq_set_wake ,
2006-01-09 17:05:41 +00:00
} ;
2006-11-23 11:41:32 +00:00
static void gpio_irq_handler ( unsigned irq , struct irq_desc * desc )
2006-01-09 17:05:41 +00:00
{
unsigned pin ;
2006-11-23 11:41:32 +00:00
struct irq_desc * gpio ;
2008-01-04 18:30:24 +01:00
struct at91_gpio_bank * bank ;
2006-01-09 17:05:41 +00:00
void __iomem * pio ;
u32 isr ;
2008-01-04 18:30:24 +01:00
bank = get_irq_chip_data ( irq ) ;
pio = bank - > regbase ;
2006-01-09 17:05:41 +00:00
/* temporarily mask (level sensitive) parent IRQ */
desc - > chip - > ack ( irq ) ;
for ( ; ; ) {
2008-01-04 18:30:24 +01:00
/* Reading ISR acks pending (edge triggered) GPIO interrupts.
* When there none are pending , we ' re finished unless we need
* to process multiple banks ( like ID_PIOCDE on sam9263 ) .
*/
2006-01-09 17:05:41 +00:00
isr = __raw_readl ( pio + PIO_ISR ) & __raw_readl ( pio + PIO_IMR ) ;
2008-01-04 18:30:24 +01:00
if ( ! isr ) {
if ( ! bank - > next )
break ;
bank = bank - > next ;
pio = bank - > regbase ;
continue ;
}
2006-01-09 17:05:41 +00:00
2008-01-04 18:30:24 +01:00
pin = bank - > chipbase ;
2006-01-09 17:05:41 +00:00
while ( isr ) {
2006-02-24 22:27:50 +00:00
if ( isr & 1 ) {
2006-07-01 23:01:50 +01:00
if ( unlikely ( gpio - > depth ) ) {
2006-02-24 22:27:50 +00:00
/*
* The core ARM interrupt handler lazily disables IRQs so
* another IRQ must be generated before it actually gets
* here to be disabled on the GPIO controller .
*/
gpio_irq_mask ( pin ) ;
}
else
2008-10-09 13:36:24 +01:00
generic_handle_irq ( pin ) ;
2006-02-24 22:27:50 +00:00
}
2006-01-09 17:05:41 +00:00
pin + + ;
gpio + + ;
isr > > = 1 ;
}
}
desc - > chip - > unmask ( irq ) ;
/* now it may re-trigger */
}
2006-09-27 13:23:00 +01:00
/*--------------------------------------------------------------------------*/
2007-11-23 16:09:10 +01:00
# ifdef CONFIG_DEBUG_FS
static int at91_gpio_show ( struct seq_file * s , void * unused )
{
int bank , j ;
/* print heading */
seq_printf ( s , " Pin \t " ) ;
for ( bank = 0 ; bank < gpio_banks ; bank + + ) {
seq_printf ( s , " PIO%c \t " , ' A ' + bank ) ;
} ;
seq_printf ( s , " \n \n " ) ;
/* print pin status */
for ( j = 0 ; j < 32 ; j + + ) {
seq_printf ( s , " %i: \t " , j ) ;
for ( bank = 0 ; bank < gpio_banks ; bank + + ) {
unsigned pin = PIN_BASE + ( 32 * bank ) + j ;
void __iomem * pio = pin_to_controller ( pin ) ;
unsigned mask = pin_to_mask ( pin ) ;
if ( __raw_readl ( pio + PIO_PSR ) & mask )
seq_printf ( s , " GPIO:%s " , __raw_readl ( pio + PIO_PDSR ) & mask ? " 1 " : " 0 " ) ;
else
seq_printf ( s , " %s " , __raw_readl ( pio + PIO_ABSR ) & mask ? " B " : " A " ) ;
seq_printf ( s , " \t " ) ;
}
seq_printf ( s , " \n " ) ;
}
return 0 ;
}
static int at91_gpio_open ( struct inode * inode , struct file * file )
{
return single_open ( file , at91_gpio_show , NULL ) ;
}
static const struct file_operations at91_gpio_operations = {
. open = at91_gpio_open ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = single_release ,
} ;
static int __init at91_gpio_debugfs_init ( void )
{
/* /sys/kernel/debug/at91_gpio */
( void ) debugfs_create_file ( " at91_gpio " , S_IFREG | S_IRUGO , NULL , NULL , & at91_gpio_operations ) ;
return 0 ;
}
postcore_initcall ( at91_gpio_debugfs_init ) ;
# endif
/*--------------------------------------------------------------------------*/
2008-03-05 00:08:29 +01:00
/* This lock class tells lockdep that GPIO irqs are in a different
* category than their parents , so it won ' t report false recursion .
*/
static struct lock_class_key gpio_lock_class ;
2006-09-27 13:23:00 +01:00
/*
* Called from the processor - specific init to enable GPIO interrupt support .
*/
void __init at91_gpio_irq_setup ( void )
2006-01-09 17:05:41 +00:00
{
2008-01-04 18:30:24 +01:00
unsigned pioc , pin ;
struct at91_gpio_bank * this , * prev ;
2006-01-09 17:05:41 +00:00
2008-01-04 18:30:24 +01:00
for ( pioc = 0 , pin = PIN_BASE , this = gpio , prev = NULL ;
pioc + + < gpio_banks ;
prev = this , this + + ) {
unsigned id = this - > id ;
2006-01-09 17:05:41 +00:00
unsigned i ;
2008-01-04 18:30:24 +01:00
/* enable PIO controller's clock */
clk_enable ( this - > clock ) ;
2006-01-09 17:05:41 +00:00
2008-01-04 18:30:24 +01:00
__raw_writel ( ~ 0 , this - > regbase + PIO_IDR ) ;
2006-01-09 17:05:41 +00:00
2008-01-04 18:30:24 +01:00
for ( i = 0 , pin = this - > chipbase ; i < 32 ; i + + , pin + + ) {
2008-03-05 00:08:29 +01:00
lockdep_set_class ( & irq_desc [ pin ] . lock , & gpio_lock_class ) ;
2006-06-19 15:26:54 +01:00
/*
* Can use the " simple " and not " edge " handler since it ' s
2007-10-19 23:10:43 +02:00
* shorter , and the AIC handles interrupts sanely .
2006-06-19 15:26:54 +01:00
*/
2006-01-09 17:05:41 +00:00
set_irq_chip ( pin , & gpio_irqchip ) ;
2006-11-23 11:41:32 +00:00
set_irq_handler ( pin , handle_simple_irq ) ;
2006-01-09 17:05:41 +00:00
set_irq_flags ( pin , IRQF_VALID ) ;
}
2008-01-04 18:30:24 +01:00
/* The toplevel handler handles one bank of GPIOs, except
* AT91SAM9263_ID_PIOCDE handles three . . . PIOC is first in
* the list , so we only set up that handler .
*/
if ( prev & & prev - > next = = this )
continue ;
set_irq_chip_data ( id , this ) ;
2006-01-09 17:05:41 +00:00
set_irq_chained_handler ( id , gpio_irq_handler ) ;
}
2006-09-27 13:23:00 +01:00
pr_info ( " AT91: %d gpio irqs in %d banks \n " , pin - PIN_BASE , gpio_banks ) ;
}
/*
* Called from the processor - specific init to enable GPIO pin support .
*/
void __init at91_gpio_init ( struct at91_gpio_bank * data , int nr_banks )
{
2008-01-04 18:30:24 +01:00
unsigned i ;
struct at91_gpio_bank * last ;
2006-09-27 13:23:00 +01:00
BUG_ON ( nr_banks > MAX_GPIO_BANKS ) ;
gpio = data ;
gpio_banks = nr_banks ;
2008-01-04 18:30:24 +01:00
for ( i = 0 , last = NULL ; i < nr_banks ; i + + , last = data , data + + ) {
data - > chipbase = PIN_BASE + i * 32 ;
data - > regbase = data - > offset + ( void __iomem * ) AT91_VA_BASE_SYS ;
/* AT91SAM9263_ID_PIOCDE groups PIOC, PIOD, PIOE */
if ( last & & last - > id = = data - > id )
last - > next = data ;
}
2006-01-09 17:05:41 +00:00
}