2019-06-01 11:09:00 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2017-10-12 15:40:26 +03:00
/*
* First generation of pinmux driver for Amlogic Meson SoCs
*
* Copyright ( C ) 2014 Beniamino Galvani < b . galvani @ gmail . com >
* Copyright ( C ) 2017 Jerome Brunet < jbrunet @ baylibre . com >
*/
/* For this first generation of pinctrl driver every pinmux group can be
* enabled by a specific bit in the first register range . When all groups for
* a given pin are disabled the pin acts as a GPIO .
*/
# include <linux/device.h>
# include <linux/regmap.h>
# include <linux/pinctrl/pinctrl.h>
# include <linux/pinctrl/pinmux.h>
# include "pinctrl-meson.h"
# include "pinctrl-meson8-pmx.h"
/**
* meson8_pmx_disable_other_groups ( ) - disable other groups using a given pin
*
* @ pc : meson pin controller device
* @ pin : number of the pin
* @ sel_group : index of the selected group , or - 1 if none
*
* The function disables all pinmux groups using a pin except the
* selected one . If @ sel_group is - 1 all groups are disabled , leaving
* the pin in GPIO mode .
*/
static void meson8_pmx_disable_other_groups ( struct meson_pinctrl * pc ,
unsigned int pin , int sel_group )
{
struct meson_pmx_group * group ;
struct meson8_pmx_data * pmx_data ;
int i , j ;
for ( i = 0 ; i < pc - > data - > num_groups ; i + + ) {
group = & pc - > data - > groups [ i ] ;
pmx_data = ( struct meson8_pmx_data * ) group - > data ;
if ( pmx_data - > is_gpio | | i = = sel_group )
continue ;
for ( j = 0 ; j < group - > num_pins ; j + + ) {
if ( group - > pins [ j ] = = pin ) {
/* We have found a group using the pin */
regmap_update_bits ( pc - > reg_mux ,
pmx_data - > reg * 4 ,
BIT ( pmx_data - > bit ) , 0 ) ;
}
}
}
}
static int meson8_pmx_set_mux ( struct pinctrl_dev * pcdev , unsigned func_num ,
unsigned group_num )
{
struct meson_pinctrl * pc = pinctrl_dev_get_drvdata ( pcdev ) ;
struct meson_pmx_func * func = & pc - > data - > funcs [ func_num ] ;
struct meson_pmx_group * group = & pc - > data - > groups [ group_num ] ;
struct meson8_pmx_data * pmx_data =
( struct meson8_pmx_data * ) group - > data ;
int i , ret = 0 ;
dev_dbg ( pc - > dev , " enable function %s, group %s \n " , func - > name ,
group - > name ) ;
/*
* Disable groups using the same pin .
* The selected group is not disabled to avoid glitches .
*/
for ( i = 0 ; i < group - > num_pins ; i + + )
meson8_pmx_disable_other_groups ( pc , group - > pins [ i ] , group_num ) ;
/* Function 0 (GPIO) doesn't need any additional setting */
if ( func_num )
ret = regmap_update_bits ( pc - > reg_mux , pmx_data - > reg * 4 ,
BIT ( pmx_data - > bit ) ,
BIT ( pmx_data - > bit ) ) ;
return ret ;
}
static int meson8_pmx_request_gpio ( struct pinctrl_dev * pcdev ,
struct pinctrl_gpio_range * range ,
unsigned offset )
{
struct meson_pinctrl * pc = pinctrl_dev_get_drvdata ( pcdev ) ;
meson8_pmx_disable_other_groups ( pc , offset , - 1 ) ;
return 0 ;
}
const struct pinmux_ops meson8_pmx_ops = {
. set_mux = meson8_pmx_set_mux ,
. get_functions_count = meson_pmx_get_funcs_count ,
. get_function_name = meson_pmx_get_func_name ,
. get_function_groups = meson_pmx_get_groups ,
. gpio_request_enable = meson8_pmx_request_gpio ,
} ;
2020-10-26 21:30:25 +03:00
EXPORT_SYMBOL_GPL ( meson8_pmx_ops ) ;
MODULE_LICENSE ( " GPL v2 " ) ;