2012-07-12 19:35:02 +04:00
/*
* at91 pinctrl driver based on at91 pinmux core
*
* Copyright ( C ) 2011 - 2012 Jean - Christophe PLAGNIOL - VILLARD < plagnioj @ jcrosoft . com >
*
* Under GPLv2 only
*/
# include <linux/clk.h>
# include <linux/err.h>
# include <linux/init.h>
# include <linux/module.h>
# include <linux/of.h>
# include <linux/of_device.h>
# include <linux/of_address.h>
# include <linux/of_irq.h>
# include <linux/slab.h>
# include <linux/interrupt.h>
# include <linux/irq.h>
# include <linux/irqdomain.h>
2013-01-18 19:31:37 +04:00
# include <linux/irqchip/chained_irq.h>
2012-07-12 19:35:02 +04:00
# include <linux/io.h>
# include <linux/gpio.h>
# include <linux/pinctrl/machine.h>
# include <linux/pinctrl/pinconf.h>
# include <linux/pinctrl/pinctrl.h>
# include <linux/pinctrl/pinmux.h>
/* Since we request GPIOs from ourself */
# include <linux/pinctrl/consumer.h>
# include <mach/hardware.h>
# include <mach/at91_pio.h>
# include "core.h"
# define MAX_NB_GPIO_PER_BANK 32
struct at91_pinctrl_mux_ops ;
struct at91_gpio_chip {
struct gpio_chip chip ;
struct pinctrl_gpio_range range ;
struct at91_gpio_chip * next ; /* Bank sharing same clock */
int pioc_hwirq ; /* PIO bank interrupt identifier on AIC */
int pioc_virq ; /* PIO bank Linux virtual interrupt */
int pioc_idx ; /* PIO bank index */
void __iomem * regbase ; /* PIO bank virtual address */
struct clk * clock ; /* associated clock */
struct irq_domain * domain ; /* associated irq domain */
struct at91_pinctrl_mux_ops * ops ; /* ops */
} ;
# define to_at91_gpio_chip(c) container_of(c, struct at91_gpio_chip, chip)
static struct at91_gpio_chip * gpio_chips [ MAX_GPIO_BANKS ] ;
static int gpio_banks ;
2012-10-23 20:28:00 +04:00
# define PULL_UP (1 << 0)
2012-07-12 19:35:02 +04:00
# define MULTI_DRIVE (1 << 1)
2012-09-26 10:57:45 +04:00
# define DEGLITCH (1 << 2)
# define PULL_DOWN (1 << 3)
# define DIS_SCHMIT (1 << 4)
# define DEBOUNCE (1 << 16)
# define DEBOUNCE_VAL_SHIFT 17
# define DEBOUNCE_VAL (0x3fff << DEBOUNCE_VAL_SHIFT)
2012-07-12 19:35:02 +04:00
/**
* struct at91_pmx_func - describes AT91 pinmux functions
* @ name : the name of this specific function
* @ groups : corresponding pin groups
* @ ngroups : the number of groups
*/
struct at91_pmx_func {
const char * name ;
const char * * groups ;
unsigned ngroups ;
} ;
enum at91_mux {
AT91_MUX_GPIO = 0 ,
AT91_MUX_PERIPH_A = 1 ,
AT91_MUX_PERIPH_B = 2 ,
AT91_MUX_PERIPH_C = 3 ,
AT91_MUX_PERIPH_D = 4 ,
} ;
/**
* struct at91_pmx_pin - describes an At91 pin mux
* @ bank : the bank of the pin
* @ pin : the pin number in the @ bank
* @ mux : the mux mode : gpio or periph_x of the pin i . e . alternate function .
* @ conf : the configuration of the pin : PULL_UP , MULTIDRIVE etc . . .
*/
struct at91_pmx_pin {
uint32_t bank ;
uint32_t pin ;
enum at91_mux mux ;
unsigned long conf ;
} ;
/**
* struct at91_pin_group - describes an At91 pin group
* @ name : the name of this specific pin group
* @ pins_conf : the mux mode for each pin in this group . The size of this
* array is the same as pins .
* @ pins : an array of discrete physical pins used in this group , taken
* from the driver - local pin enumeration space
* @ npins : the number of pins in this group array , i . e . the number of
* elements in . pins so we can iterate over that array
*/
struct at91_pin_group {
const char * name ;
struct at91_pmx_pin * pins_conf ;
unsigned int * pins ;
unsigned npins ;
} ;
/**
* struct at91_pinctrl_mux_ops - describes an At91 mux ops group
* on new IP with support for periph C and D the way to mux in
* periph A and B has changed
* So provide the right call back
* if not present means the IP does not support it
* @ get_periph : return the periph mode configured
* @ mux_A_periph : mux as periph A
* @ mux_B_periph : mux as periph B
* @ mux_C_periph : mux as periph C
* @ mux_D_periph : mux as periph D
2012-09-26 10:57:45 +04:00
* @ get_deglitch : get deglitch status
* @ set_deglitch : enable / disable deglitch
* @ get_debounce : get debounce status
* @ set_debounce : enable / disable debounce
* @ get_pulldown : get pulldown status
* @ set_pulldown : enable / disable pulldown
* @ get_schmitt_trig : get schmitt trigger status
* @ disable_schmitt_trig : disable schmitt trigger
2012-07-12 19:35:02 +04:00
* @ irq_type : return irq type
*/
struct at91_pinctrl_mux_ops {
enum at91_mux ( * get_periph ) ( void __iomem * pio , unsigned mask ) ;
void ( * mux_A_periph ) ( void __iomem * pio , unsigned mask ) ;
void ( * mux_B_periph ) ( void __iomem * pio , unsigned mask ) ;
void ( * mux_C_periph ) ( void __iomem * pio , unsigned mask ) ;
void ( * mux_D_periph ) ( void __iomem * pio , unsigned mask ) ;
2012-09-26 10:57:45 +04:00
bool ( * get_deglitch ) ( void __iomem * pio , unsigned pin ) ;
2013-09-13 11:45:33 +04:00
void ( * set_deglitch ) ( void __iomem * pio , unsigned mask , bool is_on ) ;
2012-09-26 10:57:45 +04:00
bool ( * get_debounce ) ( void __iomem * pio , unsigned pin , u32 * div ) ;
2013-09-13 11:45:33 +04:00
void ( * set_debounce ) ( void __iomem * pio , unsigned mask , bool is_on , u32 div ) ;
2012-09-26 10:57:45 +04:00
bool ( * get_pulldown ) ( void __iomem * pio , unsigned pin ) ;
2013-09-13 11:45:33 +04:00
void ( * set_pulldown ) ( void __iomem * pio , unsigned mask , bool is_on ) ;
2012-09-26 10:57:45 +04:00
bool ( * get_schmitt_trig ) ( void __iomem * pio , unsigned pin ) ;
void ( * disable_schmitt_trig ) ( void __iomem * pio , unsigned mask ) ;
2012-07-12 19:35:02 +04:00
/* irq */
int ( * irq_type ) ( struct irq_data * d , unsigned type ) ;
} ;
static int gpio_irq_type ( struct irq_data * d , unsigned type ) ;
static int alt_gpio_irq_type ( struct irq_data * d , unsigned type ) ;
struct at91_pinctrl {
struct device * dev ;
struct pinctrl_dev * pctl ;
int nbanks ;
uint32_t * mux_mask ;
int nmux ;
struct at91_pmx_func * functions ;
int nfunctions ;
struct at91_pin_group * groups ;
int ngroups ;
struct at91_pinctrl_mux_ops * ops ;
} ;
static const inline struct at91_pin_group * at91_pinctrl_find_group_by_name (
const struct at91_pinctrl * info ,
const char * name )
{
const struct at91_pin_group * grp = NULL ;
int i ;
for ( i = 0 ; i < info - > ngroups ; i + + ) {
if ( strcmp ( info - > groups [ i ] . name , name ) )
continue ;
grp = & info - > groups [ i ] ;
dev_dbg ( info - > dev , " %s: %d 0:%d \n " , name , grp - > npins , grp - > pins [ 0 ] ) ;
break ;
}
return grp ;
}
static int at91_get_groups_count ( struct pinctrl_dev * pctldev )
{
struct at91_pinctrl * info = pinctrl_dev_get_drvdata ( pctldev ) ;
return info - > ngroups ;
}
static const char * at91_get_group_name ( struct pinctrl_dev * pctldev ,
unsigned selector )
{
struct at91_pinctrl * info = pinctrl_dev_get_drvdata ( pctldev ) ;
return info - > groups [ selector ] . name ;
}
static int at91_get_group_pins ( struct pinctrl_dev * pctldev , unsigned selector ,
const unsigned * * pins ,
unsigned * npins )
{
struct at91_pinctrl * info = pinctrl_dev_get_drvdata ( pctldev ) ;
if ( selector > = info - > ngroups )
return - EINVAL ;
* pins = info - > groups [ selector ] . pins ;
* npins = info - > groups [ selector ] . npins ;
return 0 ;
}
static void at91_pin_dbg_show ( struct pinctrl_dev * pctldev , struct seq_file * s ,
unsigned offset )
{
seq_printf ( s , " %s " , dev_name ( pctldev - > dev ) ) ;
}
static int at91_dt_node_to_map ( struct pinctrl_dev * pctldev ,
struct device_node * np ,
struct pinctrl_map * * map , unsigned * num_maps )
{
struct at91_pinctrl * info = pinctrl_dev_get_drvdata ( pctldev ) ;
const struct at91_pin_group * grp ;
struct pinctrl_map * new_map ;
struct device_node * parent ;
int map_num = 1 ;
int i ;
/*
2013-10-16 18:12:33 +04:00
* first find the group of this node and check if we need to create
2012-07-12 19:35:02 +04:00
* config maps for pins
*/
grp = at91_pinctrl_find_group_by_name ( info , np - > name ) ;
if ( ! grp ) {
dev_err ( info - > dev , " unable to find group for node %s \n " ,
np - > name ) ;
return - EINVAL ;
}
map_num + = grp - > npins ;
new_map = devm_kzalloc ( pctldev - > dev , sizeof ( * new_map ) * map_num , GFP_KERNEL ) ;
if ( ! new_map )
return - ENOMEM ;
* map = new_map ;
* num_maps = map_num ;
/* create mux map */
parent = of_get_parent ( np ) ;
if ( ! parent ) {
2012-12-12 18:22:44 +04:00
devm_kfree ( pctldev - > dev , new_map ) ;
2012-07-12 19:35:02 +04:00
return - EINVAL ;
}
new_map [ 0 ] . type = PIN_MAP_TYPE_MUX_GROUP ;
new_map [ 0 ] . data . mux . function = parent - > name ;
new_map [ 0 ] . data . mux . group = np - > name ;
of_node_put ( parent ) ;
/* create config map */
new_map + + ;
for ( i = 0 ; i < grp - > npins ; i + + ) {
new_map [ i ] . type = PIN_MAP_TYPE_CONFIGS_PIN ;
new_map [ i ] . data . configs . group_or_pin =
pin_get_name ( pctldev , grp - > pins [ i ] ) ;
new_map [ i ] . data . configs . configs = & grp - > pins_conf [ i ] . conf ;
new_map [ i ] . data . configs . num_configs = 1 ;
}
dev_dbg ( pctldev - > dev , " maps: function %s group %s num %d \n " ,
( * map ) - > data . mux . function , ( * map ) - > data . mux . group , map_num ) ;
return 0 ;
}
static void at91_dt_free_map ( struct pinctrl_dev * pctldev ,
struct pinctrl_map * map , unsigned num_maps )
{
}
2013-02-16 13:25:07 +04:00
static const struct pinctrl_ops at91_pctrl_ops = {
2012-07-12 19:35:02 +04:00
. get_groups_count = at91_get_groups_count ,
. get_group_name = at91_get_group_name ,
. get_group_pins = at91_get_group_pins ,
. pin_dbg_show = at91_pin_dbg_show ,
. dt_node_to_map = at91_dt_node_to_map ,
. dt_free_map = at91_dt_free_map ,
} ;
2013-03-15 08:37:03 +04:00
static void __iomem * pin_to_controller ( struct at91_pinctrl * info ,
2012-07-12 19:35:02 +04:00
unsigned int bank )
{
return gpio_chips [ bank ] - > regbase ;
}
static inline int pin_to_bank ( unsigned pin )
{
return pin / = MAX_NB_GPIO_PER_BANK ;
}
static unsigned pin_to_mask ( unsigned int pin )
{
return 1 < < pin ;
}
static void at91_mux_disable_interrupt ( void __iomem * pio , unsigned mask )
{
writel_relaxed ( mask , pio + PIO_IDR ) ;
}
static unsigned at91_mux_get_pullup ( void __iomem * pio , unsigned pin )
{
2013-08-27 17:19:21 +04:00
return ! ( ( readl_relaxed ( pio + PIO_PUSR ) > > pin ) & 0x1 ) ;
2012-07-12 19:35:02 +04:00
}
static void at91_mux_set_pullup ( void __iomem * pio , unsigned mask , bool on )
{
writel_relaxed ( mask , pio + ( on ? PIO_PUER : PIO_PUDR ) ) ;
}
static unsigned at91_mux_get_multidrive ( void __iomem * pio , unsigned pin )
{
return ( readl_relaxed ( pio + PIO_MDSR ) > > pin ) & 0x1 ;
}
static void at91_mux_set_multidrive ( void __iomem * pio , unsigned mask , bool on )
{
writel_relaxed ( mask , pio + ( on ? PIO_MDER : PIO_MDDR ) ) ;
}
static void at91_mux_set_A_periph ( void __iomem * pio , unsigned mask )
{
writel_relaxed ( mask , pio + PIO_ASR ) ;
}
static void at91_mux_set_B_periph ( void __iomem * pio , unsigned mask )
{
writel_relaxed ( mask , pio + PIO_BSR ) ;
}
static void at91_mux_pio3_set_A_periph ( void __iomem * pio , unsigned mask )
{
writel_relaxed ( readl_relaxed ( pio + PIO_ABCDSR1 ) & ~ mask ,
pio + PIO_ABCDSR1 ) ;
writel_relaxed ( readl_relaxed ( pio + PIO_ABCDSR2 ) & ~ mask ,
pio + PIO_ABCDSR2 ) ;
}
static void at91_mux_pio3_set_B_periph ( void __iomem * pio , unsigned mask )
{
writel_relaxed ( readl_relaxed ( pio + PIO_ABCDSR1 ) | mask ,
pio + PIO_ABCDSR1 ) ;
writel_relaxed ( readl_relaxed ( pio + PIO_ABCDSR2 ) & ~ mask ,
pio + PIO_ABCDSR2 ) ;
}
static void at91_mux_pio3_set_C_periph ( void __iomem * pio , unsigned mask )
{
writel_relaxed ( readl_relaxed ( pio + PIO_ABCDSR1 ) & ~ mask , pio + PIO_ABCDSR1 ) ;
writel_relaxed ( readl_relaxed ( pio + PIO_ABCDSR2 ) | mask , pio + PIO_ABCDSR2 ) ;
}
static void at91_mux_pio3_set_D_periph ( void __iomem * pio , unsigned mask )
{
writel_relaxed ( readl_relaxed ( pio + PIO_ABCDSR1 ) | mask , pio + PIO_ABCDSR1 ) ;
writel_relaxed ( readl_relaxed ( pio + PIO_ABCDSR2 ) | mask , pio + PIO_ABCDSR2 ) ;
}
static enum at91_mux at91_mux_pio3_get_periph ( void __iomem * pio , unsigned mask )
{
unsigned select ;
if ( readl_relaxed ( pio + PIO_PSR ) & mask )
return AT91_MUX_GPIO ;
select = ! ! ( readl_relaxed ( pio + PIO_ABCDSR1 ) & mask ) ;
select | = ( ! ! ( readl_relaxed ( pio + PIO_ABCDSR2 ) & mask ) < < 1 ) ;
return select + 1 ;
}
static enum at91_mux at91_mux_get_periph ( void __iomem * pio , unsigned mask )
{
unsigned select ;
if ( readl_relaxed ( pio + PIO_PSR ) & mask )
return AT91_MUX_GPIO ;
select = readl_relaxed ( pio + PIO_ABSR ) & mask ;
return select + 1 ;
}
2012-09-26 10:57:45 +04:00
static bool at91_mux_get_deglitch ( void __iomem * pio , unsigned pin )
{
return ( __raw_readl ( pio + PIO_IFSR ) > > pin ) & 0x1 ;
}
static void at91_mux_set_deglitch ( void __iomem * pio , unsigned mask , bool is_on )
{
__raw_writel ( mask , pio + ( is_on ? PIO_IFER : PIO_IFDR ) ) ;
}
2013-09-13 11:47:22 +04:00
static bool at91_mux_pio3_get_deglitch ( void __iomem * pio , unsigned pin )
{
if ( ( __raw_readl ( pio + PIO_IFSR ) > > pin ) & 0x1 )
return ! ( ( __raw_readl ( pio + PIO_IFSCSR ) > > pin ) & 0x1 ) ;
return false ;
}
2012-09-26 10:57:45 +04:00
static void at91_mux_pio3_set_deglitch ( void __iomem * pio , unsigned mask , bool is_on )
{
if ( is_on )
__raw_writel ( mask , pio + PIO_IFSCDR ) ;
at91_mux_set_deglitch ( pio , mask , is_on ) ;
}
static bool at91_mux_pio3_get_debounce ( void __iomem * pio , unsigned pin , u32 * div )
{
* div = __raw_readl ( pio + PIO_SCDR ) ;
2013-09-13 11:47:22 +04:00
return ( ( __raw_readl ( pio + PIO_IFSR ) > > pin ) & 0x1 ) & &
( ( __raw_readl ( pio + PIO_IFSCSR ) > > pin ) & 0x1 ) ;
2012-09-26 10:57:45 +04:00
}
static void at91_mux_pio3_set_debounce ( void __iomem * pio , unsigned mask ,
bool is_on , u32 div )
{
if ( is_on ) {
__raw_writel ( mask , pio + PIO_IFSCER ) ;
__raw_writel ( div & PIO_SCDR_DIV , pio + PIO_SCDR ) ;
__raw_writel ( mask , pio + PIO_IFER ) ;
2013-09-13 11:47:22 +04:00
} else
__raw_writel ( mask , pio + PIO_IFSCDR ) ;
2012-09-26 10:57:45 +04:00
}
static bool at91_mux_pio3_get_pulldown ( void __iomem * pio , unsigned pin )
{
2013-08-27 17:19:21 +04:00
return ! ( ( __raw_readl ( pio + PIO_PPDSR ) > > pin ) & 0x1 ) ;
2012-09-26 10:57:45 +04:00
}
static void at91_mux_pio3_set_pulldown ( void __iomem * pio , unsigned mask , bool is_on )
{
__raw_writel ( mask , pio + ( is_on ? PIO_PPDER : PIO_PPDDR ) ) ;
}
static void at91_mux_pio3_disable_schmitt_trig ( void __iomem * pio , unsigned mask )
{
__raw_writel ( __raw_readl ( pio + PIO_SCHMITT ) | mask , pio + PIO_SCHMITT ) ;
}
static bool at91_mux_pio3_get_schmitt_trig ( void __iomem * pio , unsigned pin )
{
return ( __raw_readl ( pio + PIO_SCHMITT ) > > pin ) & 0x1 ;
}
2012-07-12 19:35:02 +04:00
static struct at91_pinctrl_mux_ops at91rm9200_ops = {
. get_periph = at91_mux_get_periph ,
. mux_A_periph = at91_mux_set_A_periph ,
. mux_B_periph = at91_mux_set_B_periph ,
2012-09-26 10:57:45 +04:00
. get_deglitch = at91_mux_get_deglitch ,
. set_deglitch = at91_mux_set_deglitch ,
2012-07-12 19:35:02 +04:00
. irq_type = gpio_irq_type ,
} ;
static struct at91_pinctrl_mux_ops at91sam9x5_ops = {
. get_periph = at91_mux_pio3_get_periph ,
. mux_A_periph = at91_mux_pio3_set_A_periph ,
. mux_B_periph = at91_mux_pio3_set_B_periph ,
. mux_C_periph = at91_mux_pio3_set_C_periph ,
. mux_D_periph = at91_mux_pio3_set_D_periph ,
2013-09-13 11:47:22 +04:00
. get_deglitch = at91_mux_pio3_get_deglitch ,
2012-09-26 10:57:45 +04:00
. set_deglitch = at91_mux_pio3_set_deglitch ,
. get_debounce = at91_mux_pio3_get_debounce ,
. set_debounce = at91_mux_pio3_set_debounce ,
. get_pulldown = at91_mux_pio3_get_pulldown ,
. set_pulldown = at91_mux_pio3_set_pulldown ,
. get_schmitt_trig = at91_mux_pio3_get_schmitt_trig ,
. disable_schmitt_trig = at91_mux_pio3_disable_schmitt_trig ,
2012-07-12 19:35:02 +04:00
. irq_type = alt_gpio_irq_type ,
} ;
static void at91_pin_dbg ( const struct device * dev , const struct at91_pmx_pin * pin )
{
if ( pin - > mux ) {
dev_dbg ( dev , " pio%c%d configured as periph%c with conf = 0x%lu \n " ,
pin - > bank + ' A ' , pin - > pin , pin - > mux - 1 + ' A ' , pin - > conf ) ;
} else {
dev_dbg ( dev , " pio%c%d configured as gpio with conf = 0x%lu \n " ,
pin - > bank + ' A ' , pin - > pin , pin - > conf ) ;
}
}
2013-03-15 08:37:03 +04:00
static int pin_check_config ( struct at91_pinctrl * info , const char * name ,
2012-07-12 19:35:02 +04:00
int index , const struct at91_pmx_pin * pin )
{
int mux ;
/* check if it's a valid config */
if ( pin - > bank > = info - > nbanks ) {
dev_err ( info - > dev , " %s: pin conf %d bank_id %d >= nbanks %d \n " ,
name , index , pin - > bank , info - > nbanks ) ;
return - EINVAL ;
}
if ( pin - > pin > = MAX_NB_GPIO_PER_BANK ) {
dev_err ( info - > dev , " %s: pin conf %d pin_bank_id %d >= %d \n " ,
name , index , pin - > pin , MAX_NB_GPIO_PER_BANK ) ;
return - EINVAL ;
}
if ( ! pin - > mux )
return 0 ;
mux = pin - > mux - 1 ;
if ( mux > = info - > nmux ) {
dev_err ( info - > dev , " %s: pin conf %d mux_id %d >= nmux %d \n " ,
name , index , mux , info - > nmux ) ;
return - EINVAL ;
}
if ( ! ( info - > mux_mask [ pin - > bank * info - > nmux + mux ] & 1 < < pin - > pin ) ) {
dev_err ( info - > dev , " %s: pin conf %d mux_id %d not supported for pio%c%d \n " ,
name , index , mux , pin - > bank + ' A ' , pin - > pin ) ;
return - EINVAL ;
}
return 0 ;
}
static void at91_mux_gpio_disable ( void __iomem * pio , unsigned mask )
{
writel_relaxed ( mask , pio + PIO_PDR ) ;
}
static void at91_mux_gpio_enable ( void __iomem * pio , unsigned mask , bool input )
{
writel_relaxed ( mask , pio + PIO_PER ) ;
writel_relaxed ( mask , pio + ( input ? PIO_ODR : PIO_OER ) ) ;
}
static int at91_pmx_enable ( struct pinctrl_dev * pctldev , unsigned selector ,
unsigned group )
{
struct at91_pinctrl * info = pinctrl_dev_get_drvdata ( pctldev ) ;
const struct at91_pmx_pin * pins_conf = info - > groups [ group ] . pins_conf ;
const struct at91_pmx_pin * pin ;
uint32_t npins = info - > groups [ group ] . npins ;
int i , ret ;
unsigned mask ;
void __iomem * pio ;
dev_dbg ( info - > dev , " enable function %s group %s \n " ,
info - > functions [ selector ] . name , info - > groups [ group ] . name ) ;
/* first check that all the pins of the group are valid with a valid
2013-10-16 18:12:33 +04:00
* parameter */
2012-07-12 19:35:02 +04:00
for ( i = 0 ; i < npins ; i + + ) {
pin = & pins_conf [ i ] ;
ret = pin_check_config ( info , info - > groups [ group ] . name , i , pin ) ;
if ( ret )
return ret ;
}
for ( i = 0 ; i < npins ; i + + ) {
pin = & pins_conf [ i ] ;
at91_pin_dbg ( info - > dev , pin ) ;
pio = pin_to_controller ( info , pin - > bank ) ;
mask = pin_to_mask ( pin - > pin ) ;
at91_mux_disable_interrupt ( pio , mask ) ;
2013-03-15 08:37:03 +04:00
switch ( pin - > mux ) {
2012-07-12 19:35:02 +04:00
case AT91_MUX_GPIO :
at91_mux_gpio_enable ( pio , mask , 1 ) ;
break ;
case AT91_MUX_PERIPH_A :
info - > ops - > mux_A_periph ( pio , mask ) ;
break ;
case AT91_MUX_PERIPH_B :
info - > ops - > mux_B_periph ( pio , mask ) ;
break ;
case AT91_MUX_PERIPH_C :
if ( ! info - > ops - > mux_C_periph )
return - EINVAL ;
info - > ops - > mux_C_periph ( pio , mask ) ;
break ;
case AT91_MUX_PERIPH_D :
if ( ! info - > ops - > mux_D_periph )
return - EINVAL ;
info - > ops - > mux_D_periph ( pio , mask ) ;
break ;
}
if ( pin - > mux )
at91_mux_gpio_disable ( pio , mask ) ;
}
return 0 ;
}
static void at91_pmx_disable ( struct pinctrl_dev * pctldev , unsigned selector ,
unsigned group )
{
struct at91_pinctrl * info = pinctrl_dev_get_drvdata ( pctldev ) ;
const struct at91_pmx_pin * pins_conf = info - > groups [ group ] . pins_conf ;
const struct at91_pmx_pin * pin ;
uint32_t npins = info - > groups [ group ] . npins ;
int i ;
unsigned mask ;
void __iomem * pio ;
for ( i = 0 ; i < npins ; i + + ) {
pin = & pins_conf [ i ] ;
at91_pin_dbg ( info - > dev , pin ) ;
pio = pin_to_controller ( info , pin - > bank ) ;
mask = pin_to_mask ( pin - > pin ) ;
at91_mux_gpio_enable ( pio , mask , 1 ) ;
}
}
static int at91_pmx_get_funcs_count ( struct pinctrl_dev * pctldev )
{
struct at91_pinctrl * info = pinctrl_dev_get_drvdata ( pctldev ) ;
return info - > nfunctions ;
}
static const char * at91_pmx_get_func_name ( struct pinctrl_dev * pctldev ,
unsigned selector )
{
struct at91_pinctrl * info = pinctrl_dev_get_drvdata ( pctldev ) ;
return info - > functions [ selector ] . name ;
}
static int at91_pmx_get_groups ( struct pinctrl_dev * pctldev , unsigned selector ,
const char * const * * groups ,
unsigned * const num_groups )
{
struct at91_pinctrl * info = pinctrl_dev_get_drvdata ( pctldev ) ;
* groups = info - > functions [ selector ] . groups ;
* num_groups = info - > functions [ selector ] . ngroups ;
return 0 ;
}
2012-11-05 17:23:50 +04:00
static int at91_gpio_request_enable ( struct pinctrl_dev * pctldev ,
struct pinctrl_gpio_range * range ,
unsigned offset )
2012-07-12 19:35:02 +04:00
{
struct at91_pinctrl * npct = pinctrl_dev_get_drvdata ( pctldev ) ;
struct at91_gpio_chip * at91_chip ;
struct gpio_chip * chip ;
unsigned mask ;
if ( ! range ) {
dev_err ( npct - > dev , " invalid range \n " ) ;
return - EINVAL ;
}
if ( ! range - > gc ) {
dev_err ( npct - > dev , " missing GPIO chip in range \n " ) ;
return - EINVAL ;
}
chip = range - > gc ;
at91_chip = container_of ( chip , struct at91_gpio_chip , chip ) ;
dev_dbg ( npct - > dev , " enable pin %u as GPIO \n " , offset ) ;
mask = 1 < < ( offset - chip - > base ) ;
dev_dbg ( npct - > dev , " enable pin %u as PIO%c%d 0x%x \n " ,
offset , ' A ' + range - > id , offset - chip - > base , mask ) ;
writel_relaxed ( mask , at91_chip - > regbase + PIO_PER ) ;
return 0 ;
}
2012-11-05 17:23:50 +04:00
static void at91_gpio_disable_free ( struct pinctrl_dev * pctldev ,
struct pinctrl_gpio_range * range ,
unsigned offset )
2012-07-12 19:35:02 +04:00
{
struct at91_pinctrl * npct = pinctrl_dev_get_drvdata ( pctldev ) ;
dev_dbg ( npct - > dev , " disable pin %u as GPIO \n " , offset ) ;
/* Set the pin to some default state, GPIO is usually default */
}
2013-02-16 13:25:07 +04:00
static const struct pinmux_ops at91_pmx_ops = {
2012-07-12 19:35:02 +04:00
. get_functions_count = at91_pmx_get_funcs_count ,
. get_function_name = at91_pmx_get_func_name ,
. get_function_groups = at91_pmx_get_groups ,
. enable = at91_pmx_enable ,
. disable = at91_pmx_disable ,
. gpio_request_enable = at91_gpio_request_enable ,
. gpio_disable_free = at91_gpio_disable_free ,
} ;
static int at91_pinconf_get ( struct pinctrl_dev * pctldev ,
unsigned pin_id , unsigned long * config )
{
struct at91_pinctrl * info = pinctrl_dev_get_drvdata ( pctldev ) ;
void __iomem * pio ;
unsigned pin ;
2012-09-26 10:57:45 +04:00
int div ;
2012-07-12 19:35:02 +04:00
dev_dbg ( info - > dev , " %s:%d, pin_id=%d, config=0x%lx " , __func__ , __LINE__ , pin_id , * config ) ;
pio = pin_to_controller ( info , pin_to_bank ( pin_id ) ) ;
pin = pin_id % MAX_NB_GPIO_PER_BANK ;
if ( at91_mux_get_multidrive ( pio , pin ) )
* config | = MULTI_DRIVE ;
if ( at91_mux_get_pullup ( pio , pin ) )
* config | = PULL_UP ;
2012-09-26 10:57:45 +04:00
if ( info - > ops - > get_deglitch & & info - > ops - > get_deglitch ( pio , pin ) )
* config | = DEGLITCH ;
if ( info - > ops - > get_debounce & & info - > ops - > get_debounce ( pio , pin , & div ) )
* config | = DEBOUNCE | ( div < < DEBOUNCE_VAL_SHIFT ) ;
if ( info - > ops - > get_pulldown & & info - > ops - > get_pulldown ( pio , pin ) )
* config | = PULL_DOWN ;
if ( info - > ops - > get_schmitt_trig & & info - > ops - > get_schmitt_trig ( pio , pin ) )
* config | = DIS_SCHMIT ;
2012-07-12 19:35:02 +04:00
return 0 ;
}
static int at91_pinconf_set ( struct pinctrl_dev * pctldev ,
2013-08-27 22:32:12 +04:00
unsigned pin_id , unsigned long * configs ,
unsigned num_configs )
2012-07-12 19:35:02 +04:00
{
struct at91_pinctrl * info = pinctrl_dev_get_drvdata ( pctldev ) ;
unsigned mask ;
void __iomem * pio ;
2013-08-27 22:32:12 +04:00
int i ;
unsigned long config ;
for ( i = 0 ; i < num_configs ; i + + ) {
config = configs [ i ] ;
dev_dbg ( info - > dev ,
" %s:%d, pin_id=%d, config=0x%lx " ,
__func__ , __LINE__ , pin_id , config ) ;
pio = pin_to_controller ( info , pin_to_bank ( pin_id ) ) ;
mask = pin_to_mask ( pin_id % MAX_NB_GPIO_PER_BANK ) ;
if ( config & PULL_UP & & config & PULL_DOWN )
return - EINVAL ;
at91_mux_set_pullup ( pio , mask , config & PULL_UP ) ;
at91_mux_set_multidrive ( pio , mask , config & MULTI_DRIVE ) ;
if ( info - > ops - > set_deglitch )
info - > ops - > set_deglitch ( pio , mask , config & DEGLITCH ) ;
if ( info - > ops - > set_debounce )
info - > ops - > set_debounce ( pio , mask , config & DEBOUNCE ,
2012-09-26 10:57:45 +04:00
( config & DEBOUNCE_VAL ) > > DEBOUNCE_VAL_SHIFT ) ;
2013-08-27 22:32:12 +04:00
if ( info - > ops - > set_pulldown )
info - > ops - > set_pulldown ( pio , mask , config & PULL_DOWN ) ;
if ( info - > ops - > disable_schmitt_trig & & config & DIS_SCHMIT )
info - > ops - > disable_schmitt_trig ( pio , mask ) ;
} /* for each config */
2012-09-26 10:57:45 +04:00
2012-07-12 19:35:02 +04:00
return 0 ;
}
static void at91_pinconf_dbg_show ( struct pinctrl_dev * pctldev ,
struct seq_file * s , unsigned pin_id )
{
}
static void at91_pinconf_group_dbg_show ( struct pinctrl_dev * pctldev ,
struct seq_file * s , unsigned group )
{
}
2013-02-16 13:25:07 +04:00
static const struct pinconf_ops at91_pinconf_ops = {
2012-07-12 19:35:02 +04:00
. pin_config_get = at91_pinconf_get ,
. pin_config_set = at91_pinconf_set ,
. pin_config_dbg_show = at91_pinconf_dbg_show ,
. pin_config_group_dbg_show = at91_pinconf_group_dbg_show ,
} ;
static struct pinctrl_desc at91_pinctrl_desc = {
. pctlops = & at91_pctrl_ops ,
. pmxops = & at91_pmx_ops ,
. confops = & at91_pinconf_ops ,
. owner = THIS_MODULE ,
} ;
static const char * gpio_compat = " atmel,at91rm9200-gpio " ;
2012-12-22 01:10:23 +04:00
static void at91_pinctrl_child_count ( struct at91_pinctrl * info ,
struct device_node * np )
2012-07-12 19:35:02 +04:00
{
struct device_node * child ;
for_each_child_of_node ( np , child ) {
if ( of_device_is_compatible ( child , gpio_compat ) ) {
info - > nbanks + + ;
} else {
info - > nfunctions + + ;
info - > ngroups + = of_get_child_count ( child ) ;
}
}
}
2012-12-22 01:10:23 +04:00
static int at91_pinctrl_mux_mask ( struct at91_pinctrl * info ,
struct device_node * np )
2012-07-12 19:35:02 +04:00
{
int ret = 0 ;
int size ;
2013-03-15 08:37:02 +04:00
const __be32 * list ;
2012-07-12 19:35:02 +04:00
list = of_get_property ( np , " atmel,mux-mask " , & size ) ;
if ( ! list ) {
dev_err ( info - > dev , " can not read the mux-mask of %d \n " , size ) ;
return - EINVAL ;
}
size / = sizeof ( * list ) ;
if ( ! size | | size % info - > nbanks ) {
dev_err ( info - > dev , " wrong mux mask array should be by %d \n " , info - > nbanks ) ;
return - EINVAL ;
}
info - > nmux = size / info - > nbanks ;
info - > mux_mask = devm_kzalloc ( info - > dev , sizeof ( u32 ) * size , GFP_KERNEL ) ;
if ( ! info - > mux_mask ) {
dev_err ( info - > dev , " could not alloc mux_mask \n " ) ;
return - ENOMEM ;
}
ret = of_property_read_u32_array ( np , " atmel,mux-mask " ,
info - > mux_mask , size ) ;
if ( ret )
dev_err ( info - > dev , " can not read the mux-mask of %d \n " , size ) ;
return ret ;
}
2012-12-22 01:10:23 +04:00
static int at91_pinctrl_parse_groups ( struct device_node * np ,
struct at91_pin_group * grp ,
struct at91_pinctrl * info , u32 index )
2012-07-12 19:35:02 +04:00
{
struct at91_pmx_pin * pin ;
int size ;
2013-03-15 08:37:02 +04:00
const __be32 * list ;
2012-07-12 19:35:02 +04:00
int i , j ;
dev_dbg ( info - > dev , " group(%d): %s \n " , index , np - > name ) ;
/* Initialise group */
grp - > name = np - > name ;
/*
* the binding format is atmel , pins = < bank pin mux CONFIG . . . > ,
* do sanity check and calculate pins number
*/
list = of_get_property ( np , " atmel,pins " , & size ) ;
/* we do not check return since it's safe node passed down */
size / = sizeof ( * list ) ;
if ( ! size | | size % 4 ) {
dev_err ( info - > dev , " wrong pins number or pins and configs should be by 4 \n " ) ;
return - EINVAL ;
}
grp - > npins = size / 4 ;
pin = grp - > pins_conf = devm_kzalloc ( info - > dev , grp - > npins * sizeof ( struct at91_pmx_pin ) ,
GFP_KERNEL ) ;
grp - > pins = devm_kzalloc ( info - > dev , grp - > npins * sizeof ( unsigned int ) ,
GFP_KERNEL ) ;
if ( ! grp - > pins_conf | | ! grp - > pins )
return - ENOMEM ;
for ( i = 0 , j = 0 ; i < size ; i + = 4 , j + + ) {
pin - > bank = be32_to_cpu ( * list + + ) ;
pin - > pin = be32_to_cpu ( * list + + ) ;
grp - > pins [ j ] = pin - > bank * MAX_NB_GPIO_PER_BANK + pin - > pin ;
pin - > mux = be32_to_cpu ( * list + + ) ;
pin - > conf = be32_to_cpu ( * list + + ) ;
at91_pin_dbg ( info - > dev , pin ) ;
pin + + ;
}
return 0 ;
}
2012-12-22 01:10:23 +04:00
static int at91_pinctrl_parse_functions ( struct device_node * np ,
struct at91_pinctrl * info , u32 index )
2012-07-12 19:35:02 +04:00
{
struct device_node * child ;
struct at91_pmx_func * func ;
struct at91_pin_group * grp ;
int ret ;
static u32 grp_index ;
u32 i = 0 ;
dev_dbg ( info - > dev , " parse function(%d): %s \n " , index , np - > name ) ;
func = & info - > functions [ index ] ;
/* Initialise function */
func - > name = np - > name ;
func - > ngroups = of_get_child_count ( np ) ;
if ( func - > ngroups < = 0 ) {
dev_err ( info - > dev , " no groups defined \n " ) ;
return - EINVAL ;
}
func - > groups = devm_kzalloc ( info - > dev ,
func - > ngroups * sizeof ( char * ) , GFP_KERNEL ) ;
if ( ! func - > groups )
return - ENOMEM ;
for_each_child_of_node ( np , child ) {
func - > groups [ i ] = child - > name ;
grp = & info - > groups [ grp_index + + ] ;
ret = at91_pinctrl_parse_groups ( child , grp , info , i + + ) ;
if ( ret )
return ret ;
}
return 0 ;
}
2012-12-22 01:10:23 +04:00
static struct of_device_id at91_pinctrl_of_match [ ] = {
2012-07-12 19:35:02 +04:00
{ . compatible = " atmel,at91sam9x5-pinctrl " , . data = & at91sam9x5_ops } ,
{ . compatible = " atmel,at91rm9200-pinctrl " , . data = & at91rm9200_ops } ,
{ /* sentinel */ }
} ;
2012-12-22 01:10:23 +04:00
static int at91_pinctrl_probe_dt ( struct platform_device * pdev ,
struct at91_pinctrl * info )
2012-07-12 19:35:02 +04:00
{
int ret = 0 ;
int i , j ;
uint32_t * tmp ;
struct device_node * np = pdev - > dev . of_node ;
struct device_node * child ;
if ( ! np )
return - ENODEV ;
info - > dev = & pdev - > dev ;
2013-03-15 08:37:03 +04:00
info - > ops = ( struct at91_pinctrl_mux_ops * )
2012-07-12 19:35:02 +04:00
of_match_device ( at91_pinctrl_of_match , & pdev - > dev ) - > data ;
at91_pinctrl_child_count ( info , np ) ;
if ( info - > nbanks < 1 ) {
2013-10-16 18:12:33 +04:00
dev_err ( & pdev - > dev , " you need to specify at least one gpio-controller \n " ) ;
2012-07-12 19:35:02 +04:00
return - EINVAL ;
}
ret = at91_pinctrl_mux_mask ( info , np ) ;
if ( ret )
return ret ;
dev_dbg ( & pdev - > dev , " nmux = %d \n " , info - > nmux ) ;
dev_dbg ( & pdev - > dev , " mux-mask \n " ) ;
tmp = info - > mux_mask ;
for ( i = 0 ; i < info - > nbanks ; i + + ) {
for ( j = 0 ; j < info - > nmux ; j + + , tmp + + ) {
dev_dbg ( & pdev - > dev , " %d:%d \t 0x%x \n " , i , j , tmp [ 0 ] ) ;
}
}
dev_dbg ( & pdev - > dev , " nfunctions = %d \n " , info - > nfunctions ) ;
dev_dbg ( & pdev - > dev , " ngroups = %d \n " , info - > ngroups ) ;
info - > functions = devm_kzalloc ( & pdev - > dev , info - > nfunctions * sizeof ( struct at91_pmx_func ) ,
GFP_KERNEL ) ;
if ( ! info - > functions )
return - ENOMEM ;
info - > groups = devm_kzalloc ( & pdev - > dev , info - > ngroups * sizeof ( struct at91_pin_group ) ,
GFP_KERNEL ) ;
if ( ! info - > groups )
return - ENOMEM ;
dev_dbg ( & pdev - > dev , " nbanks = %d \n " , info - > nbanks ) ;
dev_dbg ( & pdev - > dev , " nfunctions = %d \n " , info - > nfunctions ) ;
dev_dbg ( & pdev - > dev , " ngroups = %d \n " , info - > ngroups ) ;
i = 0 ;
for_each_child_of_node ( np , child ) {
if ( of_device_is_compatible ( child , gpio_compat ) )
continue ;
ret = at91_pinctrl_parse_functions ( child , info , i + + ) ;
if ( ret ) {
dev_err ( & pdev - > dev , " failed to parse function \n " ) ;
return ret ;
}
}
return 0 ;
}
2012-12-22 01:10:23 +04:00
static int at91_pinctrl_probe ( struct platform_device * pdev )
2012-07-12 19:35:02 +04:00
{
struct at91_pinctrl * info ;
struct pinctrl_pin_desc * pdesc ;
2013-03-15 08:37:03 +04:00
int ret , i , j , k ;
2012-07-12 19:35:02 +04:00
info = devm_kzalloc ( & pdev - > dev , sizeof ( * info ) , GFP_KERNEL ) ;
if ( ! info )
return - ENOMEM ;
ret = at91_pinctrl_probe_dt ( pdev , info ) ;
if ( ret )
return ret ;
/*
* We need all the GPIO drivers to probe FIRST , or we will not be able
* to obtain references to the struct gpio_chip * for them , and we
* need this to proceed .
*/
for ( i = 0 ; i < info - > nbanks ; i + + ) {
if ( ! gpio_chips [ i ] ) {
dev_warn ( & pdev - > dev , " GPIO chip %d not registered yet \n " , i ) ;
devm_kfree ( & pdev - > dev , info ) ;
return - EPROBE_DEFER ;
}
}
at91_pinctrl_desc . name = dev_name ( & pdev - > dev ) ;
at91_pinctrl_desc . npins = info - > nbanks * MAX_NB_GPIO_PER_BANK ;
at91_pinctrl_desc . pins = pdesc =
devm_kzalloc ( & pdev - > dev , sizeof ( * pdesc ) * at91_pinctrl_desc . npins , GFP_KERNEL ) ;
if ( ! at91_pinctrl_desc . pins )
return - ENOMEM ;
for ( i = 0 , k = 0 ; i < info - > nbanks ; i + + ) {
for ( j = 0 ; j < MAX_NB_GPIO_PER_BANK ; j + + , k + + ) {
pdesc - > number = k ;
pdesc - > name = kasprintf ( GFP_KERNEL , " pio%c%d " , i + ' A ' , j ) ;
pdesc + + ;
}
}
platform_set_drvdata ( pdev , info ) ;
info - > pctl = pinctrl_register ( & at91_pinctrl_desc , & pdev - > dev , info ) ;
if ( ! info - > pctl ) {
dev_err ( & pdev - > dev , " could not register AT91 pinctrl driver \n " ) ;
ret = - EINVAL ;
goto err ;
}
/* We will handle a range of GPIO pins */
for ( i = 0 ; i < info - > nbanks ; i + + )
pinctrl_add_gpio_range ( info - > pctl , & gpio_chips [ i ] - > range ) ;
dev_info ( & pdev - > dev , " initialized AT91 pinctrl driver \n " ) ;
return 0 ;
err :
return ret ;
}
2012-12-22 01:10:23 +04:00
static int at91_pinctrl_remove ( struct platform_device * pdev )
2012-07-12 19:35:02 +04:00
{
struct at91_pinctrl * info = platform_get_drvdata ( pdev ) ;
pinctrl_unregister ( info - > pctl ) ;
return 0 ;
}
static int at91_gpio_request ( struct gpio_chip * chip , unsigned offset )
{
/*
* Map back to global GPIO space and request muxing , the direction
* parameter does not matter for this controller .
*/
int gpio = chip - > base + offset ;
int bank = chip - > base / chip - > ngpio ;
dev_dbg ( chip - > dev , " %s:%d pio%c%d(%d) \n " , __func__ , __LINE__ ,
' A ' + bank , offset , gpio ) ;
return pinctrl_request_gpio ( gpio ) ;
}
static void at91_gpio_free ( struct gpio_chip * chip , unsigned offset )
{
int gpio = chip - > base + offset ;
pinctrl_free_gpio ( gpio ) ;
}
static int at91_gpio_direction_input ( struct gpio_chip * chip , unsigned offset )
{
struct at91_gpio_chip * at91_gpio = to_at91_gpio_chip ( chip ) ;
void __iomem * pio = at91_gpio - > regbase ;
unsigned mask = 1 < < offset ;
writel_relaxed ( mask , pio + PIO_ODR ) ;
return 0 ;
}
static int at91_gpio_get ( struct gpio_chip * chip , unsigned offset )
{
struct at91_gpio_chip * at91_gpio = to_at91_gpio_chip ( chip ) ;
void __iomem * pio = at91_gpio - > regbase ;
unsigned mask = 1 < < offset ;
u32 pdsr ;
pdsr = readl_relaxed ( pio + PIO_PDSR ) ;
return ( pdsr & mask ) ! = 0 ;
}
static void at91_gpio_set ( struct gpio_chip * chip , unsigned offset ,
int val )
{
struct at91_gpio_chip * at91_gpio = to_at91_gpio_chip ( chip ) ;
void __iomem * pio = at91_gpio - > regbase ;
unsigned mask = 1 < < offset ;
writel_relaxed ( mask , pio + ( val ? PIO_SODR : PIO_CODR ) ) ;
}
static int at91_gpio_direction_output ( struct gpio_chip * chip , unsigned offset ,
int val )
{
struct at91_gpio_chip * at91_gpio = to_at91_gpio_chip ( chip ) ;
void __iomem * pio = at91_gpio - > regbase ;
unsigned mask = 1 < < offset ;
writel_relaxed ( mask , pio + ( val ? PIO_SODR : PIO_CODR ) ) ;
writel_relaxed ( mask , pio + PIO_OER ) ;
return 0 ;
}
static int at91_gpio_to_irq ( struct gpio_chip * chip , unsigned offset )
{
struct at91_gpio_chip * at91_gpio = to_at91_gpio_chip ( chip ) ;
int virq ;
if ( offset < chip - > ngpio )
virq = irq_create_mapping ( at91_gpio - > domain , offset ) ;
else
virq = - ENXIO ;
dev_dbg ( chip - > dev , " %s: request IRQ for GPIO %d, return %d \n " ,
chip - > label , offset + chip - > base , virq ) ;
return virq ;
}
# ifdef CONFIG_DEBUG_FS
static void at91_gpio_dbg_show ( struct seq_file * s , struct gpio_chip * chip )
{
enum at91_mux mode ;
int i ;
struct at91_gpio_chip * at91_gpio = to_at91_gpio_chip ( chip ) ;
void __iomem * pio = at91_gpio - > regbase ;
for ( i = 0 ; i < chip - > ngpio ; i + + ) {
unsigned pin = chip - > base + i ;
unsigned mask = pin_to_mask ( pin ) ;
const char * gpio_label ;
u32 pdsr ;
gpio_label = gpiochip_is_requested ( chip , i ) ;
if ( ! gpio_label )
continue ;
mode = at91_gpio - > ops - > get_periph ( pio , mask ) ;
seq_printf ( s , " [%s] GPIO%s%d: " ,
gpio_label , chip - > label , i ) ;
if ( mode = = AT91_MUX_GPIO ) {
pdsr = readl_relaxed ( pio + PIO_PDSR ) ;
seq_printf ( s , " [gpio] %s \n " ,
pdsr & mask ?
" set " : " clear " ) ;
} else {
seq_printf ( s , " [periph %c] \n " ,
mode + ' A ' - 1 ) ;
}
}
}
# else
# define at91_gpio_dbg_show NULL
# endif
/* 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 .
* First implementation always triggers on rising and falling edges
* whereas the newer PIO3 can be additionally configured to trigger on
* level , edge with any polarity .
*
* 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 ( struct irq_data * d )
{
struct at91_gpio_chip * at91_gpio = irq_data_get_irq_chip_data ( d ) ;
void __iomem * pio = at91_gpio - > regbase ;
unsigned mask = 1 < < d - > hwirq ;
if ( pio )
writel_relaxed ( mask , pio + PIO_IDR ) ;
}
static void gpio_irq_unmask ( struct irq_data * d )
{
struct at91_gpio_chip * at91_gpio = irq_data_get_irq_chip_data ( d ) ;
void __iomem * pio = at91_gpio - > regbase ;
unsigned mask = 1 < < d - > hwirq ;
if ( pio )
writel_relaxed ( mask , pio + PIO_IER ) ;
}
static int gpio_irq_type ( struct irq_data * d , unsigned type )
{
switch ( type ) {
case IRQ_TYPE_NONE :
case IRQ_TYPE_EDGE_BOTH :
return 0 ;
default :
return - EINVAL ;
}
}
/* Alternate irq type for PIO3 support */
static int alt_gpio_irq_type ( struct irq_data * d , unsigned type )
{
struct at91_gpio_chip * at91_gpio = irq_data_get_irq_chip_data ( d ) ;
void __iomem * pio = at91_gpio - > regbase ;
unsigned mask = 1 < < d - > hwirq ;
switch ( type ) {
case IRQ_TYPE_EDGE_RISING :
2013-07-20 18:51:33 +04:00
irq_set_handler ( d - > irq , handle_simple_irq ) ;
2012-07-12 19:35:02 +04:00
writel_relaxed ( mask , pio + PIO_ESR ) ;
writel_relaxed ( mask , pio + PIO_REHLSR ) ;
break ;
case IRQ_TYPE_EDGE_FALLING :
2013-07-20 18:51:33 +04:00
irq_set_handler ( d - > irq , handle_simple_irq ) ;
2012-07-12 19:35:02 +04:00
writel_relaxed ( mask , pio + PIO_ESR ) ;
writel_relaxed ( mask , pio + PIO_FELLSR ) ;
break ;
case IRQ_TYPE_LEVEL_LOW :
2013-07-20 18:51:33 +04:00
irq_set_handler ( d - > irq , handle_level_irq ) ;
2012-07-12 19:35:02 +04:00
writel_relaxed ( mask , pio + PIO_LSR ) ;
writel_relaxed ( mask , pio + PIO_FELLSR ) ;
break ;
case IRQ_TYPE_LEVEL_HIGH :
2013-07-20 18:51:33 +04:00
irq_set_handler ( d - > irq , handle_level_irq ) ;
2012-07-12 19:35:02 +04:00
writel_relaxed ( mask , pio + PIO_LSR ) ;
writel_relaxed ( mask , pio + PIO_REHLSR ) ;
break ;
case IRQ_TYPE_EDGE_BOTH :
/*
* disable additional interrupt modes :
* fall back to default behavior
*/
2013-07-20 18:51:33 +04:00
irq_set_handler ( d - > irq , handle_simple_irq ) ;
2012-07-12 19:35:02 +04:00
writel_relaxed ( mask , pio + PIO_AIMDR ) ;
return 0 ;
case IRQ_TYPE_NONE :
default :
pr_warn ( " AT91: No type for irq %d \n " , gpio_to_irq ( d - > irq ) ) ;
return - EINVAL ;
}
/* enable additional interrupt modes */
writel_relaxed ( mask , pio + PIO_AIMER ) ;
return 0 ;
}
# ifdef CONFIG_PM
2013-03-08 19:18:21 +04:00
static u32 wakeups [ MAX_GPIO_BANKS ] ;
static u32 backups [ MAX_GPIO_BANKS ] ;
2012-07-12 19:35:02 +04:00
static int gpio_irq_set_wake ( struct irq_data * d , unsigned state )
{
struct at91_gpio_chip * at91_gpio = irq_data_get_irq_chip_data ( d ) ;
unsigned bank = at91_gpio - > pioc_idx ;
2013-03-08 19:18:21 +04:00
unsigned mask = 1 < < d - > hwirq ;
2012-07-12 19:35:02 +04:00
if ( unlikely ( bank > = MAX_GPIO_BANKS ) )
return - EINVAL ;
2013-03-08 19:18:21 +04:00
if ( state )
wakeups [ bank ] | = mask ;
else
wakeups [ bank ] & = ~ mask ;
2012-07-12 19:35:02 +04:00
irq_set_irq_wake ( at91_gpio - > pioc_virq , state ) ;
return 0 ;
}
2013-03-08 19:18:21 +04:00
void at91_pinctrl_gpio_suspend ( void )
{
int i ;
for ( i = 0 ; i < gpio_banks ; i + + ) {
void __iomem * pio ;
if ( ! gpio_chips [ i ] )
continue ;
pio = gpio_chips [ i ] - > regbase ;
backups [ i ] = __raw_readl ( pio + PIO_IMR ) ;
__raw_writel ( backups [ i ] , pio + PIO_IDR ) ;
__raw_writel ( wakeups [ i ] , pio + PIO_IER ) ;
if ( ! wakeups [ i ] ) {
clk_unprepare ( gpio_chips [ i ] - > clock ) ;
clk_disable ( gpio_chips [ i ] - > clock ) ;
} else {
printk ( KERN_DEBUG " GPIO-%c may wake for %08x \n " ,
' A ' + i , wakeups [ i ] ) ;
}
}
}
void at91_pinctrl_gpio_resume ( void )
{
int i ;
for ( i = 0 ; i < gpio_banks ; i + + ) {
void __iomem * pio ;
if ( ! gpio_chips [ i ] )
continue ;
pio = gpio_chips [ i ] - > regbase ;
if ( ! wakeups [ i ] ) {
if ( clk_prepare ( gpio_chips [ i ] - > clock ) = = 0 )
clk_enable ( gpio_chips [ i ] - > clock ) ;
}
__raw_writel ( wakeups [ i ] , pio + PIO_IDR ) ;
__raw_writel ( backups [ i ] , pio + PIO_IER ) ;
}
}
2012-07-12 19:35:02 +04:00
# else
# define gpio_irq_set_wake NULL
2013-03-08 19:18:21 +04:00
# endif /* CONFIG_PM */
2012-07-12 19:35:02 +04:00
static struct irq_chip gpio_irqchip = {
. name = " GPIO " ,
. irq_disable = gpio_irq_mask ,
. irq_mask = gpio_irq_mask ,
. irq_unmask = gpio_irq_unmask ,
/* .irq_set_type is set dynamically */
. irq_set_wake = gpio_irq_set_wake ,
} ;
static void gpio_irq_handler ( unsigned irq , struct irq_desc * desc )
{
struct irq_chip * chip = irq_desc_get_chip ( desc ) ;
struct irq_data * idata = irq_desc_get_irq_data ( desc ) ;
struct at91_gpio_chip * at91_gpio = irq_data_get_irq_chip_data ( idata ) ;
void __iomem * pio = at91_gpio - > regbase ;
unsigned long isr ;
int n ;
chained_irq_enter ( chip , desc ) ;
for ( ; ; ) {
/* 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 ) .
*/
isr = readl_relaxed ( pio + PIO_ISR ) & readl_relaxed ( pio + PIO_IMR ) ;
if ( ! isr ) {
if ( ! at91_gpio - > next )
break ;
at91_gpio = at91_gpio - > next ;
pio = at91_gpio - > regbase ;
continue ;
}
2012-10-26 18:50:54 +04:00
for_each_set_bit ( n , & isr , BITS_PER_LONG ) {
2012-07-12 19:35:02 +04:00
generic_handle_irq ( irq_find_mapping ( at91_gpio - > domain , n ) ) ;
}
}
chained_irq_exit ( chip , desc ) ;
/* now it may re-trigger */
}
/*
* 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 ;
static int at91_gpio_irq_map ( struct irq_domain * h , unsigned int virq ,
irq_hw_number_t hw )
{
struct at91_gpio_chip * at91_gpio = h - > host_data ;
2013-07-20 18:51:33 +04:00
void __iomem * pio = at91_gpio - > regbase ;
u32 mask = 1 < < hw ;
2012-07-12 19:35:02 +04:00
irq_set_lockdep_class ( virq , & gpio_lock_class ) ;
/*
* Can use the " simple " and not " edge " handler since it ' s
* shorter , and the AIC handles interrupts sanely .
*/
2013-07-20 18:51:33 +04:00
irq_set_chip ( virq , & gpio_irqchip ) ;
if ( ( at91_gpio - > ops = = & at91sam9x5_ops ) & &
( readl_relaxed ( pio + PIO_AIMMR ) & mask ) & &
( readl_relaxed ( pio + PIO_ELSR ) & mask ) )
irq_set_handler ( virq , handle_level_irq ) ;
else
irq_set_handler ( virq , handle_simple_irq ) ;
2012-07-12 19:35:02 +04:00
set_irq_flags ( virq , IRQF_VALID ) ;
irq_set_chip_data ( virq , at91_gpio ) ;
return 0 ;
}
2012-11-05 17:23:50 +04:00
static int at91_gpio_irq_domain_xlate ( struct irq_domain * d ,
struct device_node * ctrlr ,
const u32 * intspec , unsigned int intsize ,
irq_hw_number_t * out_hwirq ,
unsigned int * out_type )
2012-10-23 17:56:41 +04:00
{
struct at91_gpio_chip * at91_gpio = d - > host_data ;
int ret ;
int pin = at91_gpio - > chip . base + intspec [ 0 ] ;
if ( WARN_ON ( intsize < 2 ) )
return - EINVAL ;
* out_hwirq = intspec [ 0 ] ;
* out_type = intspec [ 1 ] & IRQ_TYPE_SENSE_MASK ;
ret = gpio_request ( pin , ctrlr - > full_name ) ;
if ( ret )
return ret ;
ret = gpio_direction_input ( pin ) ;
if ( ret )
return ret ;
return 0 ;
}
2012-07-12 19:35:02 +04:00
static struct irq_domain_ops at91_gpio_ops = {
. map = at91_gpio_irq_map ,
2012-10-23 17:56:41 +04:00
. xlate = at91_gpio_irq_domain_xlate ,
2012-07-12 19:35:02 +04:00
} ;
static int at91_gpio_of_irq_setup ( struct device_node * node ,
struct at91_gpio_chip * at91_gpio )
{
struct at91_gpio_chip * prev = NULL ;
struct irq_data * d = irq_get_irq_data ( at91_gpio - > pioc_virq ) ;
at91_gpio - > pioc_hwirq = irqd_to_hwirq ( d ) ;
/* Setup proper .irq_set_type function */
gpio_irqchip . irq_set_type = at91_gpio - > ops - > irq_type ;
/* Disable irqs of this PIO controller */
writel_relaxed ( ~ 0 , at91_gpio - > regbase + PIO_IDR ) ;
/* Setup irq domain */
at91_gpio - > domain = irq_domain_add_linear ( node , at91_gpio - > chip . ngpio ,
& at91_gpio_ops , at91_gpio ) ;
if ( ! at91_gpio - > domain )
panic ( " at91_gpio.%d: couldn't allocate irq domain (DT). \n " ,
at91_gpio - > pioc_idx ) ;
/* Setup chained handler */
if ( at91_gpio - > pioc_idx )
prev = gpio_chips [ at91_gpio - > pioc_idx - 1 ] ;
2013-10-16 18:12:33 +04:00
/* The top level handler handles one bank of GPIOs, except
2012-07-12 19:35:02 +04:00
* on some SoC it can handles up to three . . .
* We only set up the handler for the first of the list .
*/
if ( prev & & prev - > next = = at91_gpio )
return 0 ;
irq_set_chip_data ( at91_gpio - > pioc_virq , at91_gpio ) ;
irq_set_chained_handler ( at91_gpio - > pioc_virq , gpio_irq_handler ) ;
return 0 ;
}
/* This structure is replicated for each GPIO block allocated at probe time */
static struct gpio_chip at91_gpio_template = {
. request = at91_gpio_request ,
. free = at91_gpio_free ,
. direction_input = at91_gpio_direction_input ,
. get = at91_gpio_get ,
. direction_output = at91_gpio_direction_output ,
. set = at91_gpio_set ,
. to_irq = at91_gpio_to_irq ,
. dbg_show = at91_gpio_dbg_show ,
. can_sleep = 0 ,
. ngpio = MAX_NB_GPIO_PER_BANK ,
} ;
2012-12-22 01:10:23 +04:00
static void at91_gpio_probe_fixup ( void )
2012-07-12 19:35:02 +04:00
{
unsigned i ;
struct at91_gpio_chip * at91_gpio , * last = NULL ;
for ( i = 0 ; i < gpio_banks ; i + + ) {
at91_gpio = gpio_chips [ i ] ;
/*
* GPIO controller are grouped on some SoC :
* PIOC , PIOD and PIOE can share the same IRQ line
*/
if ( last & & last - > pioc_virq = = at91_gpio - > pioc_virq )
last - > next = at91_gpio ;
last = at91_gpio ;
}
}
2012-12-22 01:10:23 +04:00
static struct of_device_id at91_gpio_of_match [ ] = {
2012-07-12 19:35:02 +04:00
{ . compatible = " atmel,at91sam9x5-gpio " , . data = & at91sam9x5_ops , } ,
{ . compatible = " atmel,at91rm9200-gpio " , . data = & at91rm9200_ops } ,
{ /* sentinel */ }
} ;
2012-12-22 01:10:23 +04:00
static int at91_gpio_probe ( struct platform_device * pdev )
2012-07-12 19:35:02 +04:00
{
struct device_node * np = pdev - > dev . of_node ;
struct resource * res ;
struct at91_gpio_chip * at91_chip = NULL ;
struct gpio_chip * chip ;
struct pinctrl_gpio_range * range ;
int ret = 0 ;
2012-11-06 20:33:34 +04:00
int irq , i ;
2012-07-12 19:35:02 +04:00
int alias_idx = of_alias_get_id ( np , " gpio " ) ;
uint32_t ngpio ;
2012-11-06 20:33:34 +04:00
char * * names ;
2012-07-12 19:35:02 +04:00
BUG_ON ( alias_idx > = ARRAY_SIZE ( gpio_chips ) ) ;
if ( gpio_chips [ alias_idx ] ) {
ret = - EBUSY ;
goto err ;
}
irq = platform_get_irq ( pdev , 0 ) ;
if ( irq < 0 ) {
ret = irq ;
goto err ;
}
at91_chip = devm_kzalloc ( & pdev - > dev , sizeof ( * at91_chip ) , GFP_KERNEL ) ;
if ( ! at91_chip ) {
ret = - ENOMEM ;
goto err ;
}
2013-05-10 12:17:03 +04:00
res = platform_get_resource ( pdev , IORESOURCE_MEM , 0 ) ;
2013-01-21 14:09:14 +04:00
at91_chip - > regbase = devm_ioremap_resource ( & pdev - > dev , res ) ;
if ( IS_ERR ( at91_chip - > regbase ) ) {
ret = PTR_ERR ( at91_chip - > regbase ) ;
2012-07-12 19:35:02 +04:00
goto err ;
}
2013-03-15 08:37:03 +04:00
at91_chip - > ops = ( struct at91_pinctrl_mux_ops * )
2012-07-12 19:35:02 +04:00
of_match_device ( at91_gpio_of_match , & pdev - > dev ) - > data ;
at91_chip - > pioc_virq = irq ;
at91_chip - > pioc_idx = alias_idx ;
at91_chip - > clock = clk_get ( & pdev - > dev , NULL ) ;
if ( IS_ERR ( at91_chip - > clock ) ) {
dev_err ( & pdev - > dev , " failed to get clock, ignoring. \n " ) ;
goto err ;
}
if ( clk_prepare ( at91_chip - > clock ) )
goto clk_prep_err ;
/* enable PIO controller's clock */
if ( clk_enable ( at91_chip - > clock ) ) {
dev_err ( & pdev - > dev , " failed to enable clock, ignoring. \n " ) ;
goto clk_err ;
}
at91_chip - > chip = at91_gpio_template ;
chip = & at91_chip - > chip ;
chip - > of_node = np ;
chip - > label = dev_name ( & pdev - > dev ) ;
chip - > dev = & pdev - > dev ;
chip - > owner = THIS_MODULE ;
chip - > base = alias_idx * MAX_NB_GPIO_PER_BANK ;
if ( ! of_property_read_u32 ( np , " #gpio-lines " , & ngpio ) ) {
if ( ngpio > = MAX_NB_GPIO_PER_BANK )
pr_err ( " at91_gpio.%d, gpio-nb >= %d failback to %d \n " ,
alias_idx , MAX_NB_GPIO_PER_BANK , MAX_NB_GPIO_PER_BANK ) ;
else
chip - > ngpio = ngpio ;
}
2013-03-15 08:37:03 +04:00
names = devm_kzalloc ( & pdev - > dev , sizeof ( char * ) * chip - > ngpio ,
GFP_KERNEL ) ;
2012-11-06 20:33:34 +04:00
if ( ! names ) {
ret = - ENOMEM ;
goto clk_err ;
}
for ( i = 0 ; i < chip - > ngpio ; i + + )
names [ i ] = kasprintf ( GFP_KERNEL , " pio%c%d " , alias_idx + ' A ' , i ) ;
2013-03-15 08:37:03 +04:00
chip - > names = ( const char * const * ) names ;
2012-11-06 20:33:34 +04:00
2012-07-12 19:35:02 +04:00
range = & at91_chip - > range ;
range - > name = chip - > label ;
range - > id = alias_idx ;
range - > pin_base = range - > base = range - > id * MAX_NB_GPIO_PER_BANK ;
range - > npins = chip - > ngpio ;
range - > gc = chip ;
ret = gpiochip_add ( chip ) ;
if ( ret )
goto clk_err ;
gpio_chips [ alias_idx ] = at91_chip ;
gpio_banks = max ( gpio_banks , alias_idx + 1 ) ;
at91_gpio_probe_fixup ( ) ;
at91_gpio_of_irq_setup ( np , at91_chip ) ;
dev_info ( & pdev - > dev , " at address %p \n " , at91_chip - > regbase ) ;
return 0 ;
clk_err :
clk_unprepare ( at91_chip - > clock ) ;
clk_prep_err :
clk_put ( at91_chip - > clock ) ;
err :
dev_err ( & pdev - > dev , " Failure %i for GPIO %i \n " , ret , alias_idx ) ;
return ret ;
}
static struct platform_driver at91_gpio_driver = {
. driver = {
. name = " gpio-at91 " ,
. owner = THIS_MODULE ,
2013-09-28 16:08:48 +04:00
. of_match_table = at91_gpio_of_match ,
2012-07-12 19:35:02 +04:00
} ,
. probe = at91_gpio_probe ,
} ;
static struct platform_driver at91_pinctrl_driver = {
. driver = {
. name = " pinctrl-at91 " ,
. owner = THIS_MODULE ,
2013-09-28 16:08:48 +04:00
. of_match_table = at91_pinctrl_of_match ,
2012-07-12 19:35:02 +04:00
} ,
. probe = at91_pinctrl_probe ,
2012-12-22 01:10:23 +04:00
. remove = at91_pinctrl_remove ,
2012-07-12 19:35:02 +04:00
} ;
static int __init at91_pinctrl_init ( void )
{
int ret ;
ret = platform_driver_register ( & at91_gpio_driver ) ;
if ( ret )
return ret ;
return platform_driver_register ( & at91_pinctrl_driver ) ;
}
arch_initcall ( at91_pinctrl_init ) ;
static void __exit at91_pinctrl_exit ( void )
{
platform_driver_unregister ( & at91_pinctrl_driver ) ;
}
module_exit ( at91_pinctrl_exit ) ;
MODULE_AUTHOR ( " Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> " ) ;
MODULE_DESCRIPTION ( " Atmel AT91 pinctrl driver " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;