2008-10-08 15:41:43 +04:00
/*
2012-06-20 12:29:04 +04:00
* SuperH Pin Function Controller support .
2008-10-08 15:41:43 +04:00
*
* Copyright ( C ) 2008 Magnus Damm
2012-06-20 12:29:04 +04:00
* Copyright ( C ) 2009 - 2012 Paul Mundt
2008-10-08 15:41:43 +04:00
*
* This file is subject to the terms and conditions of the GNU General Public
* License . See the file " COPYING " in the main directory of this archive
* for more details .
*/
2012-12-16 02:50:47 +04:00
# define DRV_NAME "sh-pfc"
2012-12-16 02:50:45 +04:00
# define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
2010-10-03 22:54:56 +04:00
2008-10-08 15:41:43 +04:00
# include <linux/errno.h>
# include <linux/kernel.h>
2012-06-20 12:29:04 +04:00
# include <linux/sh_pfc.h>
2008-10-08 15:41:43 +04:00
# include <linux/module.h>
# include <linux/err.h>
# include <linux/io.h>
# include <linux/bitops.h>
2011-12-09 07:14:27 +04:00
# include <linux/slab.h>
# include <linux/ioport.h>
2012-07-10 07:08:14 +04:00
# include <linux/pinctrl/machine.h>
2012-12-16 02:50:47 +04:00
# include <linux/platform_device.h>
2011-12-09 07:14:27 +04:00
2012-12-16 02:50:44 +04:00
# include "core.h"
2012-06-20 12:29:04 +04:00
static int pfc_ioremap ( struct sh_pfc * pfc )
2011-12-09 07:14:27 +04:00
{
struct resource * res ;
int k ;
2012-12-16 02:50:43 +04:00
if ( ! pfc - > pdata - > num_resources )
2011-12-09 07:14:27 +04:00
return 0 ;
2012-12-16 02:50:48 +04:00
pfc - > window = devm_kzalloc ( pfc - > dev , pfc - > pdata - > num_resources *
sizeof ( * pfc - > window ) , GFP_NOWAIT ) ;
2012-06-20 12:29:04 +04:00
if ( ! pfc - > window )
2012-12-16 02:50:48 +04:00
return - ENOMEM ;
2011-12-09 07:14:27 +04:00
2012-12-16 02:50:43 +04:00
for ( k = 0 ; k < pfc - > pdata - > num_resources ; k + + ) {
res = pfc - > pdata - > resource + k ;
2011-12-09 07:14:27 +04:00
WARN_ON ( resource_type ( res ) ! = IORESOURCE_MEM ) ;
2012-06-20 12:29:04 +04:00
pfc - > window [ k ] . phys = res - > start ;
pfc - > window [ k ] . size = resource_size ( res ) ;
2012-12-16 02:50:49 +04:00
pfc - > window [ k ] . virt = devm_ioremap_nocache ( pfc - > dev , res - > start ,
resource_size ( res ) ) ;
if ( ! pfc - > window [ k ] . virt )
2012-12-16 02:50:48 +04:00
return - ENOMEM ;
2011-12-09 07:14:27 +04:00
}
return 0 ;
}
2012-06-20 12:29:04 +04:00
static void __iomem * pfc_phys_to_virt ( struct sh_pfc * pfc ,
2011-12-09 07:14:27 +04:00
unsigned long address )
{
struct pfc_window * window ;
int k ;
/* scan through physical windows and convert address */
2012-12-16 02:50:43 +04:00
for ( k = 0 ; k < pfc - > pdata - > num_resources ; k + + ) {
2012-06-20 12:29:04 +04:00
window = pfc - > window + k ;
2011-12-09 07:14:27 +04:00
if ( address < window - > phys )
continue ;
if ( address > = ( window - > phys + window - > size ) )
continue ;
return window - > virt + ( address - window - > phys ) ;
}
/* no windows defined, register must be 1:1 mapped virt:phys */
return ( void __iomem * ) address ;
}
2008-10-08 15:41:43 +04:00
static int enum_in_range ( pinmux_enum_t enum_id , struct pinmux_range * r )
{
if ( enum_id < r - > begin )
return 0 ;
if ( enum_id > r - > end )
return 0 ;
return 1 ;
}
2011-12-09 07:14:27 +04:00
static unsigned long gpio_read_raw_reg ( void __iomem * mapped_reg ,
2008-12-25 12:17:26 +03:00
unsigned long reg_width )
{
switch ( reg_width ) {
case 8 :
2011-12-09 07:14:27 +04:00
return ioread8 ( mapped_reg ) ;
2008-12-25 12:17:26 +03:00
case 16 :
2011-12-09 07:14:27 +04:00
return ioread16 ( mapped_reg ) ;
2008-12-25 12:17:26 +03:00
case 32 :
2011-12-09 07:14:27 +04:00
return ioread32 ( mapped_reg ) ;
2008-12-25 12:17:26 +03:00
}
BUG ( ) ;
return 0 ;
}
2011-12-09 07:14:27 +04:00
static void gpio_write_raw_reg ( void __iomem * mapped_reg ,
2008-12-25 12:17:26 +03:00
unsigned long reg_width ,
unsigned long data )
{
switch ( reg_width ) {
case 8 :
2011-12-09 07:14:27 +04:00
iowrite8 ( data , mapped_reg ) ;
2008-12-25 12:17:26 +03:00
return ;
case 16 :
2011-12-09 07:14:27 +04:00
iowrite16 ( data , mapped_reg ) ;
2008-12-25 12:17:26 +03:00
return ;
case 32 :
2011-12-09 07:14:27 +04:00
iowrite32 ( data , mapped_reg ) ;
2008-12-25 12:17:26 +03:00
return ;
}
BUG ( ) ;
}
2012-06-20 12:29:04 +04:00
int sh_pfc_read_bit ( struct pinmux_data_reg * dr , unsigned long in_pos )
2011-12-13 20:00:37 +04:00
{
unsigned long pos ;
pos = dr - > reg_width - ( in_pos + 1 ) ;
pr_debug ( " read_bit: addr = %lx, pos = %ld, "
" r_width = %ld \n " , dr - > reg , pos , dr - > reg_width ) ;
return ( gpio_read_raw_reg ( dr - > mapped_reg , dr - > reg_width ) > > pos ) & 1 ;
}
2012-06-20 12:29:04 +04:00
void sh_pfc_write_bit ( struct pinmux_data_reg * dr , unsigned long in_pos ,
unsigned long value )
2008-12-25 12:17:26 +03:00
{
unsigned long pos ;
pos = dr - > reg_width - ( in_pos + 1 ) ;
2009-12-09 09:51:27 +03:00
pr_debug ( " write_bit addr = %lx, value = %d, pos = %ld, "
2009-11-30 06:15:04 +03:00
" r_width = %ld \n " ,
dr - > reg , ! ! value , pos , dr - > reg_width ) ;
2008-12-25 12:17:26 +03:00
if ( value )
set_bit ( pos , & dr - > reg_shadow ) ;
else
clear_bit ( pos , & dr - > reg_shadow ) ;
2011-12-09 07:14:27 +04:00
gpio_write_raw_reg ( dr - > mapped_reg , dr - > reg_width , dr - > reg_shadow ) ;
2008-12-25 12:17:26 +03:00
}
2012-06-20 12:29:04 +04:00
static void config_reg_helper ( struct sh_pfc * pfc ,
2011-12-13 20:00:55 +04:00
struct pinmux_cfg_reg * crp ,
unsigned long in_pos ,
void __iomem * * mapped_regp ,
unsigned long * maskp ,
unsigned long * posp )
2008-10-08 15:41:43 +04:00
{
2011-12-13 20:01:05 +04:00
int k ;
2012-06-20 12:29:04 +04:00
* mapped_regp = pfc_phys_to_virt ( pfc , crp - > reg ) ;
2008-10-08 15:41:43 +04:00
2011-12-13 20:01:05 +04:00
if ( crp - > field_width ) {
* maskp = ( 1 < < crp - > field_width ) - 1 ;
* posp = crp - > reg_width - ( ( in_pos + 1 ) * crp - > field_width ) ;
} else {
* maskp = ( 1 < < crp - > var_field_width [ in_pos ] ) - 1 ;
* posp = crp - > reg_width ;
for ( k = 0 ; k < = in_pos ; k + + )
* posp - = crp - > var_field_width [ k ] ;
}
2011-12-13 20:00:55 +04:00
}
2012-06-20 12:29:04 +04:00
static int read_config_reg ( struct sh_pfc * pfc ,
2011-12-13 20:00:55 +04:00
struct pinmux_cfg_reg * crp ,
unsigned long field )
{
void __iomem * mapped_reg ;
unsigned long mask , pos ;
2012-06-20 12:29:04 +04:00
config_reg_helper ( pfc , crp , field , & mapped_reg , & mask , & pos ) ;
2008-10-08 15:41:43 +04:00
2011-12-13 20:00:55 +04:00
pr_debug ( " read_reg: addr = %lx, field = %ld, "
2009-11-30 06:15:04 +03:00
" r_width = %ld, f_width = %ld \n " ,
2011-12-13 20:00:55 +04:00
crp - > reg , field , crp - > reg_width , crp - > field_width ) ;
2008-10-08 15:41:43 +04:00
2011-12-13 20:00:55 +04:00
return ( gpio_read_raw_reg ( mapped_reg , crp - > reg_width ) > > pos ) & mask ;
2008-12-25 12:17:18 +03:00
}
2012-06-20 12:29:04 +04:00
static void write_config_reg ( struct sh_pfc * pfc ,
2011-12-13 20:00:55 +04:00
struct pinmux_cfg_reg * crp ,
unsigned long field , unsigned long value )
2008-12-25 12:17:18 +03:00
{
2011-12-13 20:00:55 +04:00
void __iomem * mapped_reg ;
2011-12-13 20:01:14 +04:00
unsigned long mask , pos , data ;
2008-12-25 12:17:18 +03:00
2012-06-20 12:29:04 +04:00
config_reg_helper ( pfc , crp , field , & mapped_reg , & mask , & pos ) ;
2008-10-08 15:41:43 +04:00
2011-12-13 20:00:55 +04:00
pr_debug ( " write_reg addr = %lx, value = %ld, field = %ld, "
2009-11-30 06:15:04 +03:00
" r_width = %ld, f_width = %ld \n " ,
2011-12-13 20:00:55 +04:00
crp - > reg , value , field , crp - > reg_width , crp - > field_width ) ;
2008-12-25 12:17:18 +03:00
mask = ~ ( mask < < pos ) ;
value = value < < pos ;
2008-10-08 15:41:43 +04:00
2011-12-13 20:01:14 +04:00
data = gpio_read_raw_reg ( mapped_reg , crp - > reg_width ) ;
data & = mask ;
data | = value ;
2012-12-16 02:50:43 +04:00
if ( pfc - > pdata - > unlock_reg )
gpio_write_raw_reg ( pfc_phys_to_virt ( pfc , pfc - > pdata - > unlock_reg ) ,
2011-12-13 20:01:14 +04:00
32 , ~ data ) ;
gpio_write_raw_reg ( mapped_reg , crp - > reg_width , data ) ;
2008-10-08 15:41:43 +04:00
}
2012-06-20 12:29:04 +04:00
static int setup_data_reg ( struct sh_pfc * pfc , unsigned gpio )
2008-10-08 15:41:43 +04:00
{
2012-12-16 02:50:43 +04:00
struct pinmux_gpio * gpiop = & pfc - > pdata - > gpios [ gpio ] ;
2008-10-08 15:41:43 +04:00
struct pinmux_data_reg * data_reg ;
int k , n ;
2012-12-16 02:50:43 +04:00
if ( ! enum_in_range ( gpiop - > enum_id , & pfc - > pdata - > data ) )
2008-10-08 15:41:43 +04:00
return - 1 ;
k = 0 ;
while ( 1 ) {
2012-12-16 02:50:43 +04:00
data_reg = pfc - > pdata - > data_regs + k ;
2008-10-08 15:41:43 +04:00
if ( ! data_reg - > reg_width )
break ;
2012-06-20 12:29:04 +04:00
data_reg - > mapped_reg = pfc_phys_to_virt ( pfc , data_reg - > reg ) ;
2011-12-09 07:14:27 +04:00
2008-10-08 15:41:43 +04:00
for ( n = 0 ; n < data_reg - > reg_width ; n + + ) {
2008-12-25 12:17:09 +03:00
if ( data_reg - > enum_ids [ n ] = = gpiop - > enum_id ) {
gpiop - > flags & = ~ PINMUX_FLAG_DREG ;
gpiop - > flags | = ( k < < PINMUX_FLAG_DREG_SHIFT ) ;
gpiop - > flags & = ~ PINMUX_FLAG_DBIT ;
gpiop - > flags | = ( n < < PINMUX_FLAG_DBIT_SHIFT ) ;
2008-10-08 15:41:43 +04:00
return 0 ;
}
}
k + + ;
}
2008-12-25 12:17:09 +03:00
BUG ( ) ;
2008-10-08 15:41:43 +04:00
return - 1 ;
}
2012-06-20 12:29:04 +04:00
static void setup_data_regs ( struct sh_pfc * pfc )
2008-12-25 12:17:26 +03:00
{
struct pinmux_data_reg * drp ;
int k ;
2012-12-16 02:50:43 +04:00
for ( k = pfc - > pdata - > first_gpio ; k < = pfc - > pdata - > last_gpio ; k + + )
2012-06-20 12:29:04 +04:00
setup_data_reg ( pfc , k ) ;
2008-12-25 12:17:26 +03:00
k = 0 ;
while ( 1 ) {
2012-12-16 02:50:43 +04:00
drp = pfc - > pdata - > data_regs + k ;
2008-12-25 12:17:26 +03:00
if ( ! drp - > reg_width )
break ;
2011-12-09 07:14:27 +04:00
drp - > reg_shadow = gpio_read_raw_reg ( drp - > mapped_reg ,
drp - > reg_width ) ;
2008-12-25 12:17:26 +03:00
k + + ;
}
}
2012-06-20 12:29:04 +04:00
int sh_pfc_get_data_reg ( struct sh_pfc * pfc , unsigned gpio ,
2008-12-25 12:17:09 +03:00
struct pinmux_data_reg * * drp , int * bitp )
{
2012-12-16 02:50:43 +04:00
struct pinmux_gpio * gpiop = & pfc - > pdata - > gpios [ gpio ] ;
2008-12-25 12:17:09 +03:00
int k , n ;
2012-12-16 02:50:43 +04:00
if ( ! enum_in_range ( gpiop - > enum_id , & pfc - > pdata - > data ) )
2008-12-25 12:17:09 +03:00
return - 1 ;
k = ( gpiop - > flags & PINMUX_FLAG_DREG ) > > PINMUX_FLAG_DREG_SHIFT ;
n = ( gpiop - > flags & PINMUX_FLAG_DBIT ) > > PINMUX_FLAG_DBIT_SHIFT ;
2012-12-16 02:50:43 +04:00
* drp = pfc - > pdata - > data_regs + k ;
2008-12-25 12:17:09 +03:00
* bitp = n ;
return 0 ;
}
2012-06-20 12:29:04 +04:00
static int get_config_reg ( struct sh_pfc * pfc , pinmux_enum_t enum_id ,
2011-12-13 20:00:46 +04:00
struct pinmux_cfg_reg * * crp ,
int * fieldp , int * valuep ,
2008-10-08 15:41:43 +04:00
unsigned long * * cntp )
{
struct pinmux_cfg_reg * config_reg ;
2011-12-13 20:01:05 +04:00
unsigned long r_width , f_width , curr_width , ncomb ;
int k , m , n , pos , bit_pos ;
2008-10-08 15:41:43 +04:00
k = 0 ;
while ( 1 ) {
2012-12-16 02:50:43 +04:00
config_reg = pfc - > pdata - > cfg_regs + k ;
2008-10-08 15:41:43 +04:00
r_width = config_reg - > reg_width ;
f_width = config_reg - > field_width ;
if ( ! r_width )
break ;
2011-12-13 20:01:05 +04:00
pos = 0 ;
m = 0 ;
for ( bit_pos = 0 ; bit_pos < r_width ; bit_pos + = curr_width ) {
if ( f_width )
curr_width = f_width ;
else
curr_width = config_reg - > var_field_width [ m ] ;
ncomb = 1 < < curr_width ;
for ( n = 0 ; n < ncomb ; n + + ) {
if ( config_reg - > enum_ids [ pos + n ] = = enum_id ) {
* crp = config_reg ;
* fieldp = m ;
* valuep = n ;
* cntp = & config_reg - > cnt [ m ] ;
return 0 ;
}
2008-10-08 15:41:43 +04:00
}
2011-12-13 20:01:05 +04:00
pos + = ncomb ;
m + + ;
2008-10-08 15:41:43 +04:00
}
k + + ;
}
return - 1 ;
}
2012-06-20 12:29:04 +04:00
int sh_pfc_gpio_to_enum ( struct sh_pfc * pfc , unsigned gpio , int pos ,
pinmux_enum_t * enum_idp )
2008-10-08 15:41:43 +04:00
{
2012-12-16 02:50:43 +04:00
pinmux_enum_t enum_id = pfc - > pdata - > gpios [ gpio ] . enum_id ;
pinmux_enum_t * data = pfc - > pdata - > gpio_data ;
2008-10-08 15:41:43 +04:00
int k ;
2012-12-16 02:50:43 +04:00
if ( ! enum_in_range ( enum_id , & pfc - > pdata - > data ) ) {
if ( ! enum_in_range ( enum_id , & pfc - > pdata - > mark ) ) {
2008-10-08 15:41:43 +04:00
pr_err ( " non data/mark enum_id for gpio %d \n " , gpio ) ;
return - 1 ;
}
}
if ( pos ) {
* enum_idp = data [ pos + 1 ] ;
return pos + 1 ;
}
2012-12-16 02:50:43 +04:00
for ( k = 0 ; k < pfc - > pdata - > gpio_data_size ; k + + ) {
2008-10-08 15:41:43 +04:00
if ( data [ k ] = = enum_id ) {
* enum_idp = data [ k + 1 ] ;
return k + 1 ;
}
}
pr_err ( " cannot locate data/mark enum_id for gpio %d \n " , gpio ) ;
return - 1 ;
}
2012-06-20 12:29:04 +04:00
int sh_pfc_config_gpio ( struct sh_pfc * pfc , unsigned gpio , int pinmux_type ,
int cfg_mode )
2008-10-08 15:41:43 +04:00
{
struct pinmux_cfg_reg * cr = NULL ;
pinmux_enum_t enum_id ;
struct pinmux_range * range ;
2011-12-13 20:00:46 +04:00
int in_range , pos , field , value ;
2008-10-08 15:41:43 +04:00
unsigned long * cntp ;
switch ( pinmux_type ) {
case PINMUX_TYPE_FUNCTION :
range = NULL ;
break ;
case PINMUX_TYPE_OUTPUT :
2012-12-16 02:50:43 +04:00
range = & pfc - > pdata - > output ;
2008-10-08 15:41:43 +04:00
break ;
case PINMUX_TYPE_INPUT :
2012-12-16 02:50:43 +04:00
range = & pfc - > pdata - > input ;
2008-10-08 15:41:43 +04:00
break ;
case PINMUX_TYPE_INPUT_PULLUP :
2012-12-16 02:50:43 +04:00
range = & pfc - > pdata - > input_pu ;
2008-10-08 15:41:43 +04:00
break ;
case PINMUX_TYPE_INPUT_PULLDOWN :
2012-12-16 02:50:43 +04:00
range = & pfc - > pdata - > input_pd ;
2008-10-08 15:41:43 +04:00
break ;
default :
goto out_err ;
}
pos = 0 ;
enum_id = 0 ;
2011-12-13 20:00:46 +04:00
field = 0 ;
value = 0 ;
2008-10-08 15:41:43 +04:00
while ( 1 ) {
2012-06-20 12:29:04 +04:00
pos = sh_pfc_gpio_to_enum ( pfc , gpio , pos , & enum_id ) ;
2008-10-08 15:41:43 +04:00
if ( pos < = 0 )
goto out_err ;
if ( ! enum_id )
break ;
2010-01-19 16:52:28 +03:00
/* first check if this is a function enum */
2012-12-16 02:50:43 +04:00
in_range = enum_in_range ( enum_id , & pfc - > pdata - > function ) ;
2010-01-19 16:52:28 +03:00
if ( ! in_range ) {
/* not a function enum */
if ( range ) {
/*
* other range exists , so this pin is
* a regular GPIO pin that now is being
* bound to a specific direction .
*
* for this case we only allow function enums
* and the enums that match the other range .
*/
in_range = enum_in_range ( enum_id , range ) ;
/*
* special case pass through for fixed
* input - only or output - only pins without
* function enum register association .
*/
if ( in_range & & enum_id = = range - > force )
continue ;
} else {
/*
* no other range exists , so this pin
* must then be of the function type .
*
* allow function type pins to select
* any combination of function / in / out
* in their MARK lists .
*/
in_range = 1 ;
}
2008-10-22 13:29:17 +04:00
}
2008-10-08 15:41:43 +04:00
if ( ! in_range )
continue ;
2012-06-20 12:29:04 +04:00
if ( get_config_reg ( pfc , enum_id , & cr ,
2011-12-13 20:00:46 +04:00
& field , & value , & cntp ) ! = 0 )
2008-10-08 15:41:43 +04:00
goto out_err ;
switch ( cfg_mode ) {
case GPIO_CFG_DRYRUN :
2011-12-13 20:00:55 +04:00
if ( ! * cntp | |
2012-06-20 12:29:04 +04:00
( read_config_reg ( pfc , cr , field ) ! = value ) )
2008-10-08 15:41:43 +04:00
continue ;
break ;
case GPIO_CFG_REQ :
2012-06-20 12:29:04 +04:00
write_config_reg ( pfc , cr , field , value ) ;
2008-10-08 15:41:43 +04:00
* cntp = * cntp + 1 ;
break ;
case GPIO_CFG_FREE :
* cntp = * cntp - 1 ;
break ;
}
}
return 0 ;
out_err :
return - 1 ;
}
2012-12-16 02:50:47 +04:00
static int sh_pfc_probe ( struct platform_device * pdev )
2008-10-08 15:41:43 +04:00
{
2012-12-16 02:50:47 +04:00
struct sh_pfc_platform_data * pdata = pdev - > dev . platform_data ;
struct sh_pfc * pfc ;
2008-12-25 12:17:18 +03:00
int ret ;
2008-10-08 15:41:43 +04:00
2012-06-20 19:03:41 +04:00
/*
* Ensure that the type encoding fits
*/
BUILD_BUG_ON ( PINMUX_FLAG_TYPE > ( ( 1 < < PINMUX_FLAG_DBIT_SHIFT ) - 1 ) ) ;
2012-12-16 02:50:47 +04:00
if ( pdata = = NULL )
return - ENODEV ;
2008-10-08 15:41:43 +04:00
2012-12-16 02:50:47 +04:00
pfc = devm_kzalloc ( & pdev - > dev , sizeof ( pfc ) , GFP_KERNEL ) ;
if ( pfc = = NULL )
return - ENOMEM ;
2012-12-16 02:50:43 +04:00
2012-12-16 02:50:47 +04:00
pfc - > pdata = pdata ;
pfc - > dev = & pdev - > dev ;
ret = pfc_ioremap ( pfc ) ;
if ( unlikely ( ret < 0 ) )
2011-12-09 07:14:27 +04:00
return ret ;
2012-12-16 02:50:47 +04:00
spin_lock_init ( & pfc - > lock ) ;
2008-12-25 12:17:34 +03:00
2012-07-10 07:08:14 +04:00
pinctrl_provide_dummies ( ) ;
2012-12-16 02:50:47 +04:00
setup_data_regs ( pfc ) ;
2011-12-09 07:14:27 +04:00
2012-07-10 07:08:14 +04:00
/*
* Initialize pinctrl bindings first
*/
2012-12-16 02:50:47 +04:00
ret = sh_pfc_register_pinctrl ( pfc ) ;
2012-12-16 02:50:45 +04:00
if ( unlikely ( ret ! = 0 ) )
2012-12-16 02:50:49 +04:00
return ret ;
2012-07-10 07:08:14 +04:00
2012-12-16 02:50:46 +04:00
# ifdef CONFIG_GPIO_SH_PFC
2012-07-10 07:08:14 +04:00
/*
* Then the GPIO chip
*/
2012-12-16 02:50:47 +04:00
ret = sh_pfc_register_gpiochip ( pfc ) ;
2012-12-16 02:50:46 +04:00
if ( unlikely ( ret ! = 0 ) ) {
2012-07-10 07:08:14 +04:00
/*
* If the GPIO chip fails to come up we still leave the
* PFC state as it is , given that there are already
* extant users of it that have succeeded by this point .
*/
2012-12-16 02:50:46 +04:00
pr_notice ( " failed to init GPIO chip, ignoring... \n " ) ;
2012-06-20 12:29:04 +04:00
}
2012-12-16 02:50:46 +04:00
# endif
2010-10-03 22:54:56 +04:00
2012-12-16 02:50:47 +04:00
platform_set_drvdata ( pdev , pfc ) ;
pr_info ( " %s support registered \n " , pdata - > name ) ;
2012-07-10 07:08:14 +04:00
2012-06-20 12:29:04 +04:00
return 0 ;
2010-10-03 22:54:56 +04:00
}
2012-12-16 02:50:46 +04:00
2012-12-16 02:50:47 +04:00
static int sh_pfc_remove ( struct platform_device * pdev )
{
struct sh_pfc * pfc = platform_get_drvdata ( pdev ) ;
# ifdef CONFIG_GPIO_SH_PFC
sh_pfc_unregister_gpiochip ( pfc ) ;
# endif
sh_pfc_unregister_pinctrl ( pfc ) ;
platform_set_drvdata ( pdev , NULL ) ;
return 0 ;
}
static const struct platform_device_id sh_pfc_id_table [ ] = {
{ " sh-pfc " , 0 } ,
{ } ,
} ;
MODULE_DEVICE_TABLE ( platform , sh_pfc_id_table ) ;
static struct platform_driver sh_pfc_driver = {
. probe = sh_pfc_probe ,
. remove = sh_pfc_remove ,
. id_table = sh_pfc_id_table ,
. driver = {
. name = DRV_NAME ,
. owner = THIS_MODULE ,
} ,
} ;
static struct platform_device sh_pfc_device = {
. name = DRV_NAME ,
. id = - 1 ,
} ;
int __init register_sh_pfc ( struct sh_pfc_platform_data * pdata )
{
int rc ;
sh_pfc_device . dev . platform_data = pdata ;
rc = platform_driver_register ( & sh_pfc_driver ) ;
if ( likely ( ! rc ) ) {
rc = platform_device_register ( & sh_pfc_device ) ;
if ( unlikely ( rc ) )
platform_driver_unregister ( & sh_pfc_driver ) ;
}
return rc ;
}
static void __exit sh_pfc_exit ( void )
{
platform_driver_unregister ( & sh_pfc_driver ) ;
}
module_exit ( sh_pfc_exit ) ;
2012-12-16 02:50:46 +04:00
MODULE_AUTHOR ( " Magnus Damm, Paul Mundt, Laurent Pinchart " ) ;
MODULE_DESCRIPTION ( " Pin Control and GPIO driver for SuperH pin function controller " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;