2008-10-08 15:41:43 +04:00
/*
2016-02-29 23:48:40 +03:00
* Pin Control and GPIO driver for SuperH Pin Function Controller .
*
* Authors : Magnus Damm , Paul Mundt , Laurent Pinchart
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"
2010-10-03 22:54:56 +04:00
2012-12-16 02:50:52 +04:00
# include <linux/bitops.h>
2008-10-08 15:41:43 +04:00
# include <linux/err.h>
2012-12-16 02:50:52 +04:00
# include <linux/errno.h>
2008-10-08 15:41:43 +04:00
# include <linux/io.h>
2011-12-09 07:14:27 +04:00
# include <linux/ioport.h>
2012-12-16 02:50:52 +04:00
# include <linux/kernel.h>
2016-02-29 23:48:40 +03:00
# include <linux/init.h>
2013-06-17 22:50:02 +04:00
# include <linux/of.h>
# include <linux/of_device.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>
2012-12-16 02:50:52 +04:00
# include <linux/slab.h>
2011-12-09 07:14:27 +04:00
2012-12-16 02:50:44 +04:00
# include "core.h"
2013-12-11 07:26:26 +04:00
static int sh_pfc_map_resources ( struct sh_pfc * pfc ,
struct platform_device * pdev )
2011-12-09 07:14:27 +04:00
{
2015-06-25 12:39:53 +03:00
unsigned int num_windows , num_irqs ;
2013-12-11 07:26:26 +04:00
struct sh_pfc_window * windows ;
unsigned int * irqs = NULL ;
2011-12-09 07:14:27 +04:00
struct resource * res ;
2013-12-11 07:26:26 +04:00
unsigned int i ;
2015-06-25 12:39:53 +03:00
int irq ;
2013-12-11 07:26:26 +04:00
/* Count the MEM and IRQ resources. */
2015-06-25 12:39:53 +03:00
for ( num_windows = 0 ; ; num_windows + + ) {
res = platform_get_resource ( pdev , IORESOURCE_MEM , num_windows ) ;
if ( ! res )
2013-12-11 07:26:26 +04:00
break ;
2015-06-25 12:39:53 +03:00
}
for ( num_irqs = 0 ; ; num_irqs + + ) {
irq = platform_get_irq ( pdev , num_irqs ) ;
if ( irq = = - EPROBE_DEFER )
return irq ;
if ( irq < 0 )
2013-12-11 07:26:26 +04:00
break ;
}
2011-12-09 07:14:27 +04:00
2013-12-11 07:26:26 +04:00
if ( num_windows = = 0 )
2013-02-17 02:39:07 +04:00
return - EINVAL ;
2011-12-09 07:14:27 +04:00
2013-12-11 07:26:26 +04:00
/* Allocate memory windows and IRQs arrays. */
windows = devm_kzalloc ( pfc - > dev , num_windows * sizeof ( * windows ) ,
GFP_KERNEL ) ;
if ( windows = = NULL )
2012-12-16 02:50:48 +04:00
return - ENOMEM ;
2011-12-09 07:14:27 +04:00
2013-12-11 07:26:26 +04:00
pfc - > num_windows = num_windows ;
pfc - > windows = windows ;
2012-12-16 02:50:55 +04:00
2013-12-11 07:26:26 +04:00
if ( num_irqs ) {
irqs = devm_kzalloc ( pfc - > dev , num_irqs * sizeof ( * irqs ) ,
GFP_KERNEL ) ;
if ( irqs = = NULL )
2012-12-16 02:50:48 +04:00
return - ENOMEM ;
2013-12-11 07:26:26 +04:00
pfc - > num_irqs = num_irqs ;
pfc - > irqs = irqs ;
}
/* Fill them. */
2015-06-25 12:39:53 +03:00
for ( i = 0 ; i < num_windows ; i + + ) {
res = platform_get_resource ( pdev , IORESOURCE_MEM , i ) ;
windows - > phys = res - > start ;
windows - > size = resource_size ( res ) ;
windows - > virt = devm_ioremap_resource ( pfc - > dev , res ) ;
if ( IS_ERR ( windows - > virt ) )
return - ENOMEM ;
windows + + ;
2011-12-09 07:14:27 +04:00
}
2015-06-25 12:39:53 +03:00
for ( i = 0 ; i < num_irqs ; i + + )
* irqs + + = platform_get_irq ( pdev , i ) ;
2011-12-09 07:14:27 +04:00
return 0 ;
}
2015-03-12 13:09:16 +03:00
static void __iomem * sh_pfc_phys_to_virt ( struct sh_pfc * pfc , u32 reg )
2011-12-09 07:14:27 +04:00
{
2012-12-16 02:50:53 +04:00
struct sh_pfc_window * window ;
2015-03-12 13:09:16 +03:00
phys_addr_t address = reg ;
2013-02-17 02:39:07 +04:00
unsigned int i ;
2011-12-09 07:14:27 +04:00
/* scan through physical windows and convert address */
2013-02-17 02:39:07 +04:00
for ( i = 0 ; i < pfc - > num_windows ; i + + ) {
2013-12-11 07:26:25 +04:00
window = pfc - > windows + i ;
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 ) ;
}
2013-02-17 02:39:07 +04:00
BUG ( ) ;
2013-03-26 04:44:52 +04:00
return NULL ;
2011-12-09 07:14:27 +04:00
}
2008-10-08 15:41:43 +04:00
2013-03-08 20:43:54 +04:00
int sh_pfc_get_pin_index ( struct sh_pfc * pfc , unsigned int pin )
2013-02-15 01:35:09 +04:00
{
2013-02-15 04:33:38 +04:00
unsigned int offset ;
unsigned int i ;
2013-07-15 20:38:30 +04:00
for ( i = 0 , offset = 0 ; i < pfc - > nr_ranges ; + + i ) {
const struct sh_pfc_pin_range * range = & pfc - > ranges [ i ] ;
2013-02-15 04:33:38 +04:00
if ( pin < = range - > end )
2013-07-15 20:38:30 +04:00
return pin > = range - > start
? offset + pin - range - > start : - 1 ;
2013-02-15 04:33:38 +04:00
2013-07-15 20:38:30 +04:00
offset + = range - > end - range - > start + 1 ;
2013-02-15 04:33:38 +04:00
}
2013-03-10 19:38:23 +04:00
return - EINVAL ;
2013-02-15 01:35:09 +04:00
}
2013-07-15 15:03:20 +04:00
static int sh_pfc_enum_in_range ( u16 enum_id , const struct pinmux_range * r )
2008-10-08 15:41:43 +04:00
{
if ( enum_id < r - > begin )
return 0 ;
if ( enum_id > r - > end )
return 0 ;
return 1 ;
}
2015-03-12 13:09:14 +03:00
u32 sh_pfc_read_raw_reg ( void __iomem * mapped_reg , unsigned int reg_width )
2008-12-25 12:17:26 +03:00
{
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 ;
}
2015-03-12 13:09:14 +03:00
void sh_pfc_write_raw_reg ( void __iomem * mapped_reg , unsigned int reg_width ,
2015-02-27 20:38:04 +03:00
u32 data )
2008-12-25 12:17:26 +03:00
{
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-12-16 02:50:53 +04:00
static void sh_pfc_config_reg_helper ( struct sh_pfc * pfc ,
2013-02-16 21:47:05 +04:00
const struct pinmux_cfg_reg * crp ,
2015-03-12 13:09:14 +03:00
unsigned int in_pos ,
2015-02-27 20:38:04 +03:00
void __iomem * * mapped_regp , u32 * maskp ,
2015-03-12 13:09:14 +03:00
unsigned int * posp )
2008-10-08 15:41:43 +04:00
{
2013-12-11 07:26:21 +04:00
unsigned int k ;
2011-12-13 20:01:05 +04:00
2012-12-16 02:50:53 +04:00
* mapped_regp = sh_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-12-16 02:50:53 +04:00
static void sh_pfc_write_config_reg ( struct sh_pfc * pfc ,
2013-02-16 21:47:05 +04:00
const struct pinmux_cfg_reg * crp ,
2015-03-12 13:09:14 +03:00
unsigned int field , u32 value )
2008-12-25 12:17:18 +03:00
{
2011-12-13 20:00:55 +04:00
void __iomem * mapped_reg ;
2015-03-12 13:09:14 +03:00
unsigned int pos ;
2015-02-27 20:38:04 +03:00
u32 mask , data ;
2008-12-25 12:17:18 +03:00
2012-12-16 02:50:53 +04:00
sh_pfc_config_reg_helper ( pfc , crp , field , & mapped_reg , & mask , & pos ) ;
2008-10-08 15:41:43 +04:00
2015-03-12 13:09:16 +03:00
dev_dbg ( pfc - > dev , " write_reg addr = %x, value = 0x%x, field = %u, "
2015-03-12 13:09:13 +03:00
" r_width = %u, f_width = %u \n " ,
2013-03-10 21:00:02 +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
2012-12-16 02:50:53 +04:00
data = sh_pfc_read_raw_reg ( mapped_reg , crp - > reg_width ) ;
2011-12-13 20:01:14 +04:00
data & = mask ;
data | = value ;
2012-12-16 02:51:20 +04:00
if ( pfc - > info - > unlock_reg )
2012-12-16 02:50:53 +04:00
sh_pfc_write_raw_reg (
2012-12-16 02:51:20 +04:00
sh_pfc_phys_to_virt ( pfc , pfc - > info - > unlock_reg ) , 32 ,
2012-12-16 02:50:53 +04:00
~ data ) ;
2011-12-13 20:01:14 +04:00
2012-12-16 02:50:53 +04:00
sh_pfc_write_raw_reg ( mapped_reg , crp - > reg_width , data ) ;
2008-10-08 15:41:43 +04:00
}
2013-07-15 15:03:20 +04:00
static int sh_pfc_get_config_reg ( struct sh_pfc * pfc , u16 enum_id ,
2015-03-12 13:09:14 +03:00
const struct pinmux_cfg_reg * * crp ,
unsigned int * fieldp , u32 * valuep )
2008-10-08 15:41:43 +04:00
{
2015-03-12 13:09:14 +03:00
unsigned int k = 0 ;
2008-10-08 15:41:43 +04:00
while ( 1 ) {
2015-03-12 13:09:14 +03:00
const struct pinmux_cfg_reg * config_reg =
pfc - > info - > cfg_regs + k ;
unsigned int r_width = config_reg - > reg_width ;
unsigned int f_width = config_reg - > field_width ;
unsigned int curr_width ;
unsigned int bit_pos ;
unsigned int pos = 0 ;
unsigned int m = 0 ;
2008-10-08 15:41:43 +04:00
if ( ! r_width )
break ;
2011-12-13 20:01:05 +04:00
for ( bit_pos = 0 ; bit_pos < r_width ; bit_pos + = curr_width ) {
2015-03-12 13:09:14 +03:00
u32 ncomb ;
u32 n ;
2011-12-13 20:01:05 +04:00
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 ;
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 + + ;
}
2013-03-10 19:38:23 +04:00
return - EINVAL ;
2008-10-08 15:41:43 +04:00
}
2013-07-15 15:03:20 +04:00
static int sh_pfc_mark_to_enum ( struct sh_pfc * pfc , u16 mark , int pos ,
u16 * enum_idp )
2008-10-08 15:41:43 +04:00
{
2015-09-21 17:27:23 +03:00
const u16 * data = pfc - > info - > pinmux_data ;
2013-12-11 07:26:21 +04:00
unsigned int k ;
2008-10-08 15:41:43 +04:00
if ( pos ) {
* enum_idp = data [ pos + 1 ] ;
return pos + 1 ;
}
2015-09-21 17:27:23 +03:00
for ( k = 0 ; k < pfc - > info - > pinmux_data_size ; k + + ) {
2013-02-14 20:36:56 +04:00
if ( data [ k ] = = mark ) {
2008-10-08 15:41:43 +04:00
* enum_idp = data [ k + 1 ] ;
return k + 1 ;
}
}
2013-03-10 21:00:02 +04:00
dev_err ( pfc - > dev , " cannot locate data/mark enum_id for mark %d \n " ,
mark ) ;
2013-03-10 19:38:23 +04:00
return - EINVAL ;
2008-10-08 15:41:43 +04:00
}
2013-03-10 18:29:14 +04:00
int sh_pfc_config_mux ( struct sh_pfc * pfc , unsigned mark , int pinmux_type )
2008-10-08 15:41:43 +04:00
{
2013-02-16 21:47:05 +04:00
const struct pinmux_range * range ;
2015-03-12 13:09:14 +03:00
int pos = 0 ;
2008-10-08 15:41:43 +04:00
switch ( pinmux_type ) {
2013-03-10 20:30:25 +04:00
case PINMUX_TYPE_GPIO :
2008-10-08 15:41:43 +04:00
case PINMUX_TYPE_FUNCTION :
range = NULL ;
break ;
case PINMUX_TYPE_OUTPUT :
2012-12-16 02:51:20 +04:00
range = & pfc - > info - > output ;
2008-10-08 15:41:43 +04:00
break ;
case PINMUX_TYPE_INPUT :
2012-12-16 02:51:20 +04:00
range = & pfc - > info - > input ;
2008-10-08 15:41:43 +04:00
break ;
default :
2013-03-10 19:38:23 +04:00
return - EINVAL ;
2008-10-08 15:41:43 +04:00
}
2013-03-10 20:30:25 +04:00
/* Iterate over all the configuration fields we need to update. */
2008-10-08 15:41:43 +04:00
while ( 1 ) {
2015-03-12 13:09:14 +03:00
const struct pinmux_cfg_reg * cr ;
unsigned int field ;
u16 enum_id ;
u32 value ;
int in_range ;
int ret ;
2013-02-14 20:36:56 +04:00
pos = sh_pfc_mark_to_enum ( pfc , mark , pos , & enum_id ) ;
2013-03-10 19:38:23 +04:00
if ( pos < 0 )
return pos ;
2008-10-08 15:41:43 +04:00
if ( ! enum_id )
break ;
2013-03-10 20:30:25 +04:00
/* Check if the configuration field selects a function. If it
* doesn ' t , skip the field if it ' s not applicable to the
* requested pinmux type .
*/
2012-12-16 02:51:20 +04:00
in_range = sh_pfc_enum_in_range ( enum_id , & pfc - > info - > function ) ;
2010-01-19 16:52:28 +03:00
if ( ! in_range ) {
2013-03-10 20:30:25 +04:00
if ( pinmux_type = = PINMUX_TYPE_FUNCTION ) {
/* Functions are allowed to modify all
* fields .
*/
in_range = 1 ;
} else if ( pinmux_type ! = PINMUX_TYPE_GPIO ) {
/* Input/output types can only modify fields
* that correspond to their respective ranges .
2010-01-19 16:52:28 +03:00
*/
2012-12-16 02:50:53 +04:00
in_range = sh_pfc_enum_in_range ( enum_id , range ) ;
2010-01-19 16:52:28 +03:00
/*
* 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 ;
}
2013-03-10 20:30:25 +04:00
/* GPIOs are only allowed to modify function fields. */
2008-10-22 13:29:17 +04:00
}
2008-10-08 15:41:43 +04:00
if ( ! in_range )
continue ;
2013-03-10 19:38:23 +04:00
ret = sh_pfc_get_config_reg ( pfc , enum_id , & cr , & field , & value ) ;
if ( ret < 0 )
return ret ;
2008-10-08 15:41:43 +04:00
2013-03-10 18:29:14 +04:00
sh_pfc_write_config_reg ( pfc , cr , field , value ) ;
2008-10-08 15:41:43 +04:00
}
return 0 ;
}
2013-07-15 20:38:30 +04:00
static int sh_pfc_init_ranges ( struct sh_pfc * pfc )
{
struct sh_pfc_pin_range * range ;
unsigned int nr_ranges ;
unsigned int i ;
if ( pfc - > info - > pins [ 0 ] . pin = = ( u16 ) - 1 ) {
/* Pin number -1 denotes that the SoC doesn't report pin numbers
* in its pin arrays yet . Consider the pin numbers range as
* continuous and allocate a single range .
*/
pfc - > nr_ranges = 1 ;
pfc - > ranges = devm_kzalloc ( pfc - > dev , sizeof ( * pfc - > ranges ) ,
GFP_KERNEL ) ;
if ( pfc - > ranges = = NULL )
return - ENOMEM ;
pfc - > ranges - > start = 0 ;
pfc - > ranges - > end = pfc - > info - > nr_pins - 1 ;
pfc - > nr_gpio_pins = pfc - > info - > nr_pins ;
return 0 ;
}
2013-07-15 23:10:54 +04:00
/* Count, allocate and fill the ranges. The PFC SoC data pins array must
* be sorted by pin numbers , and pins without a GPIO port must come
* last .
*/
2013-07-15 20:38:30 +04:00
for ( i = 1 , nr_ranges = 1 ; i < pfc - > info - > nr_pins ; + + i ) {
if ( pfc - > info - > pins [ i - 1 ] . pin ! = pfc - > info - > pins [ i ] . pin - 1 )
nr_ranges + + ;
}
pfc - > nr_ranges = nr_ranges ;
pfc - > ranges = devm_kzalloc ( pfc - > dev , sizeof ( * pfc - > ranges ) * nr_ranges ,
GFP_KERNEL ) ;
if ( pfc - > ranges = = NULL )
return - ENOMEM ;
range = pfc - > ranges ;
range - > start = pfc - > info - > pins [ 0 ] . pin ;
for ( i = 1 ; i < pfc - > info - > nr_pins ; + + i ) {
2013-07-15 23:10:54 +04:00
if ( pfc - > info - > pins [ i - 1 ] . pin = = pfc - > info - > pins [ i ] . pin - 1 )
continue ;
range - > end = pfc - > info - > pins [ i - 1 ] . pin ;
if ( ! ( pfc - > info - > pins [ i - 1 ] . configs & SH_PFC_PIN_CFG_NO_GPIO ) )
pfc - > nr_gpio_pins = range - > end + 1 ;
range + + ;
range - > start = pfc - > info - > pins [ i ] . pin ;
2013-07-15 20:38:30 +04:00
}
range - > end = pfc - > info - > pins [ i - 1 ] . pin ;
2013-07-15 23:10:54 +04:00
if ( ! ( pfc - > info - > pins [ i - 1 ] . configs & SH_PFC_PIN_CFG_NO_GPIO ) )
pfc - > nr_gpio_pins = range - > end + 1 ;
2013-07-15 20:38:30 +04:00
return 0 ;
}
2013-06-17 22:50:02 +04:00
# ifdef CONFIG_OF
static const struct of_device_id sh_pfc_of_table [ ] = {
2015-01-25 16:49:52 +03:00
# ifdef CONFIG_PINCTRL_PFC_EMEV2
{
. compatible = " renesas,pfc-emev2 " ,
. data = & emev2_pinmux_info ,
} ,
# endif
2013-06-17 22:50:02 +04:00
# ifdef CONFIG_PINCTRL_PFC_R8A73A4
{
. compatible = " renesas,pfc-r8a73a4 " ,
. data = & r8a73a4_pinmux_info ,
} ,
# endif
# ifdef CONFIG_PINCTRL_PFC_R8A7740
{
. compatible = " renesas,pfc-r8a7740 " ,
. data = & r8a7740_pinmux_info ,
} ,
# endif
# ifdef CONFIG_PINCTRL_PFC_R8A7778
{
. compatible = " renesas,pfc-r8a7778 " ,
. data = & r8a7778_pinmux_info ,
} ,
# endif
# ifdef CONFIG_PINCTRL_PFC_R8A7779
{
. compatible = " renesas,pfc-r8a7779 " ,
. data = & r8a7779_pinmux_info ,
} ,
# endif
# ifdef CONFIG_PINCTRL_PFC_R8A7790
{
. compatible = " renesas,pfc-r8a7790 " ,
. data = & r8a7790_pinmux_info ,
} ,
# endif
2013-10-17 01:46:05 +04:00
# ifdef CONFIG_PINCTRL_PFC_R8A7791
{
. compatible = " renesas,pfc-r8a7791 " ,
. data = & r8a7791_pinmux_info ,
} ,
# endif
2015-05-12 12:13:19 +03:00
# ifdef CONFIG_PINCTRL_PFC_R8A7793
{
. compatible = " renesas,pfc-r8a7793 " ,
. data = & r8a7793_pinmux_info ,
} ,
# endif
pinctrl: sh-pfc: add R8A7794 PFC support
Add PFC support for the R8A7794 SoC including pin groups for some
on-chip devices such as ETH, I2C, INTC, MSIOF, QSPI, [H]SCIF...
Sergei: squashed together several patches, fixed the MLB_CLK typo,
added IRQ4.. IRQ9 pin groups, fixed IRQn comments, added ETH B pin
group names, removed stray new line and fixed typos in the comments
in the pinmux_config_regs[] initializer, removed the platform device
ID, took into account limited number of signals in the GPIO1/5/6
controllers, added reasonable and removed unreasonable
copyrights, modified the bindings document, renamed, added changelog.
Changes in version 5:
- resolved rejects, refreshed the patch;
- added Laurent Pinchart's ACK.
Changes in version 4:
- reused the PORT_GP_26() macro to #define PORT_GP_28().
Changes in version 3:
- removed the platform device ID;
- added PORT_GP_26() and PORT_GP_28() macros, used them for GPIO1/5/6 in the
CPU_ALL_PORT() macro.
Changes in version 2:
- rebased the patch.
Signed-off-by: Hisashi Nakamura <hisashi.nakamura.ak@renesas.com>
Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
2015-06-06 01:34:48 +03:00
# ifdef CONFIG_PINCTRL_PFC_R8A7794
{
. compatible = " renesas,pfc-r8a7794 " ,
. data = & r8a7794_pinmux_info ,
} ,
# endif
2015-09-03 05:51:49 +03:00
# ifdef CONFIG_PINCTRL_PFC_R8A7795
{
. compatible = " renesas,pfc-r8a7795 " ,
. data = & r8a7795_pinmux_info ,
} ,
# endif
2013-06-17 22:50:02 +04:00
# ifdef CONFIG_PINCTRL_PFC_SH73A0
{
. compatible = " renesas,pfc-sh73a0 " ,
. data = & sh73a0_pinmux_info ,
} ,
# endif
{ } ,
} ;
# endif
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
{
2013-06-17 22:50:02 +04:00
const struct platform_device_id * platid = platform_get_device_id ( pdev ) ;
# ifdef CONFIG_OF
struct device_node * np = pdev - > dev . of_node ;
# endif
2013-02-16 21:47:05 +04:00
const struct sh_pfc_soc_info * info ;
2012-12-16 02:50:47 +04:00
struct sh_pfc * pfc ;
2008-12-25 12:17:18 +03:00
int ret ;
2008-10-08 15:41:43 +04:00
2013-06-17 22:50:02 +04:00
# ifdef CONFIG_OF
if ( np )
2016-03-01 19:38:46 +03:00
info = of_device_get_match_data ( & pdev - > dev ) ;
2013-06-17 22:50:02 +04:00
else
# endif
info = platid ? ( const void * ) platid - > driver_data : NULL ;
2012-12-16 02:51:20 +04:00
if ( info = = NULL )
2012-12-16 02:50:47 +04:00
return - ENODEV ;
2008-10-08 15:41:43 +04:00
2013-02-14 16:23:47 +04:00
pfc = devm_kzalloc ( & pdev - > dev , sizeof ( * pfc ) , GFP_KERNEL ) ;
2012-12-16 02:50:47 +04:00
if ( pfc = = NULL )
return - ENOMEM ;
2012-12-16 02:50:43 +04:00
2012-12-16 02:51:20 +04:00
pfc - > info = info ;
2012-12-16 02:50:47 +04:00
pfc - > dev = & pdev - > dev ;
2013-12-11 07:26:26 +04:00
ret = sh_pfc_map_resources ( pfc , pdev ) ;
2012-12-16 02:50:47 +04:00
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
2013-04-21 22:21:57 +04:00
if ( info - > ops & & info - > ops - > init ) {
ret = info - > ops - > init ( pfc ) ;
if ( ret < 0 )
return ret ;
}
2012-07-10 07:08:14 +04:00
pinctrl_provide_dummies ( ) ;
2011-12-09 07:14:27 +04:00
2013-07-15 20:38:30 +04:00
ret = sh_pfc_init_ranges ( pfc ) ;
if ( ret < 0 )
return ret ;
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 ) )
2014-09-11 01:55:55 +04:00
return ret ;
2012-07-10 07:08:14 +04:00
2016-02-17 11:15:49 +03:00
# ifdef CONFIG_PINCTRL_SH_PFC_GPIO
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 .
*/
2013-03-10 21:00:02 +04:00
dev_notice ( pfc - > dev , " 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 ) ;
2013-03-10 21:00:02 +04:00
dev_info ( pfc - > dev , " %s support registered \n " , info - > 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 ) ;
2016-02-17 11:15:49 +03:00
# ifdef CONFIG_PINCTRL_SH_PFC_GPIO
2012-12-16 02:50:47 +04:00
sh_pfc_unregister_gpiochip ( pfc ) ;
# endif
sh_pfc_unregister_pinctrl ( pfc ) ;
return 0 ;
}
static const struct platform_device_id sh_pfc_id_table [ ] = {
2012-12-16 02:51:29 +04:00
# ifdef CONFIG_PINCTRL_PFC_SH7203
{ " pfc-sh7203 " , ( kernel_ulong_t ) & sh7203_pinmux_info } ,
# endif
2012-12-16 02:51:30 +04:00
# ifdef CONFIG_PINCTRL_PFC_SH7264
{ " pfc-sh7264 " , ( kernel_ulong_t ) & sh7264_pinmux_info } ,
# endif
2012-12-16 02:51:31 +04:00
# ifdef CONFIG_PINCTRL_PFC_SH7269
{ " pfc-sh7269 " , ( kernel_ulong_t ) & sh7269_pinmux_info } ,
# endif
2012-12-16 02:51:32 +04:00
# ifdef CONFIG_PINCTRL_PFC_SH7720
{ " pfc-sh7720 " , ( kernel_ulong_t ) & sh7720_pinmux_info } ,
2012-12-16 02:51:33 +04:00
# endif
# ifdef CONFIG_PINCTRL_PFC_SH7722
{ " pfc-sh7722 " , ( kernel_ulong_t ) & sh7722_pinmux_info } ,
2012-12-16 02:51:34 +04:00
# endif
# ifdef CONFIG_PINCTRL_PFC_SH7723
{ " pfc-sh7723 " , ( kernel_ulong_t ) & sh7723_pinmux_info } ,
2012-12-16 02:51:35 +04:00
# endif
# ifdef CONFIG_PINCTRL_PFC_SH7724
{ " pfc-sh7724 " , ( kernel_ulong_t ) & sh7724_pinmux_info } ,
2012-12-16 02:51:36 +04:00
# endif
# ifdef CONFIG_PINCTRL_PFC_SH7734
{ " pfc-sh7734 " , ( kernel_ulong_t ) & sh7734_pinmux_info } ,
2012-12-16 02:51:37 +04:00
# endif
# ifdef CONFIG_PINCTRL_PFC_SH7757
{ " pfc-sh7757 " , ( kernel_ulong_t ) & sh7757_pinmux_info } ,
2012-12-16 02:51:38 +04:00
# endif
# ifdef CONFIG_PINCTRL_PFC_SH7785
{ " pfc-sh7785 " , ( kernel_ulong_t ) & sh7785_pinmux_info } ,
2012-12-16 02:51:39 +04:00
# endif
# ifdef CONFIG_PINCTRL_PFC_SH7786
{ " pfc-sh7786 " , ( kernel_ulong_t ) & sh7786_pinmux_info } ,
2012-12-16 02:51:40 +04:00
# endif
# ifdef CONFIG_PINCTRL_PFC_SHX3
{ " pfc-shx3 " , ( kernel_ulong_t ) & shx3_pinmux_info } ,
2012-12-16 02:51:21 +04:00
# endif
2012-12-16 02:50:47 +04:00
{ " sh-pfc " , 0 } ,
{ } ,
} ;
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 ,
2013-06-17 22:50:02 +04:00
. of_match_table = of_match_ptr ( sh_pfc_of_table ) ,
2012-12-16 02:50:47 +04:00
} ,
} ;
2012-12-16 02:50:54 +04:00
static int __init sh_pfc_init ( void )
{
return platform_driver_register ( & sh_pfc_driver ) ;
2012-12-16 02:50:47 +04:00
}
2012-12-16 02:50:54 +04:00
postcore_initcall ( sh_pfc_init ) ;