2018-01-06 03:09:26 +03:00
// SPDX-License-Identifier: (GPL-2.0 OR MIT)
/*
* Microsemi SoCs pinctrl driver
*
* Author : < alexandre . belloni @ free - electrons . com >
* License : Dual MIT / GPL
* Copyright ( c ) 2017 Microsemi Corporation
*/
# include <linux/gpio/driver.h>
# include <linux/interrupt.h>
# include <linux/io.h>
# include <linux/of_device.h>
# include <linux/of_platform.h>
# include <linux/pinctrl/pinctrl.h>
# include <linux/pinctrl/pinmux.h>
# include <linux/pinctrl/pinconf.h>
# include <linux/pinctrl/pinconf-generic.h>
# include <linux/platform_device.h>
# include <linux/regmap.h>
# include <linux/slab.h>
# include "core.h"
# include "pinconf.h"
# include "pinmux.h"
# define OCELOT_GPIO_OUT_SET 0x0
# define OCELOT_GPIO_OUT_CLR 0x4
# define OCELOT_GPIO_OUT 0x8
# define OCELOT_GPIO_IN 0xc
# define OCELOT_GPIO_OE 0x10
# define OCELOT_GPIO_INTR 0x14
# define OCELOT_GPIO_INTR_ENA 0x18
# define OCELOT_GPIO_INTR_IDENT 0x1c
# define OCELOT_GPIO_ALT0 0x20
# define OCELOT_GPIO_ALT1 0x24
# define OCELOT_GPIO_SD_MAP 0x28
# define OCELOT_PINS 22
# define OCELOT_FUNC_PER_PIN 4
enum {
FUNC_NONE ,
FUNC_GPIO ,
FUNC_IRQ0_IN ,
FUNC_IRQ0_OUT ,
FUNC_IRQ1_IN ,
FUNC_IRQ1_OUT ,
FUNC_MIIM1 ,
FUNC_PCI_WAKE ,
FUNC_PTP0 ,
FUNC_PTP1 ,
FUNC_PTP2 ,
FUNC_PTP3 ,
FUNC_PWM ,
FUNC_RECO_CLK0 ,
FUNC_RECO_CLK1 ,
FUNC_SFP0 ,
FUNC_SFP1 ,
FUNC_SFP2 ,
FUNC_SFP3 ,
FUNC_SFP4 ,
FUNC_SFP5 ,
FUNC_SG0 ,
FUNC_SI ,
FUNC_TACHO ,
FUNC_TWI ,
FUNC_TWI_SCL_M ,
FUNC_UART ,
FUNC_UART2 ,
FUNC_MAX
} ;
static const char * const ocelot_function_names [ ] = {
[ FUNC_NONE ] = " none " ,
[ FUNC_GPIO ] = " gpio " ,
[ FUNC_IRQ0_IN ] = " irq0_in " ,
[ FUNC_IRQ0_OUT ] = " irq0_out " ,
[ FUNC_IRQ1_IN ] = " irq1_in " ,
[ FUNC_IRQ1_OUT ] = " irq1_out " ,
[ FUNC_MIIM1 ] = " miim1 " ,
[ FUNC_PCI_WAKE ] = " pci_wake " ,
[ FUNC_PTP0 ] = " ptp0 " ,
[ FUNC_PTP1 ] = " ptp1 " ,
[ FUNC_PTP2 ] = " ptp2 " ,
[ FUNC_PTP3 ] = " ptp3 " ,
[ FUNC_PWM ] = " pwm " ,
[ FUNC_RECO_CLK0 ] = " reco_clk0 " ,
[ FUNC_RECO_CLK1 ] = " reco_clk1 " ,
[ FUNC_SFP0 ] = " sfp0 " ,
[ FUNC_SFP1 ] = " sfp1 " ,
[ FUNC_SFP2 ] = " sfp2 " ,
[ FUNC_SFP3 ] = " sfp3 " ,
[ FUNC_SFP4 ] = " sfp4 " ,
[ FUNC_SFP5 ] = " sfp5 " ,
[ FUNC_SG0 ] = " sg0 " ,
[ FUNC_SI ] = " si " ,
[ FUNC_TACHO ] = " tacho " ,
[ FUNC_TWI ] = " twi " ,
[ FUNC_TWI_SCL_M ] = " twi_scl_m " ,
[ FUNC_UART ] = " uart " ,
[ FUNC_UART2 ] = " uart2 " ,
} ;
struct ocelot_pmx_func {
const char * * groups ;
unsigned int ngroups ;
} ;
struct ocelot_pin_caps {
unsigned int pin ;
unsigned char functions [ OCELOT_FUNC_PER_PIN ] ;
} ;
struct ocelot_pinctrl {
struct device * dev ;
struct pinctrl_dev * pctl ;
struct gpio_chip gpio_chip ;
struct regmap * map ;
struct ocelot_pmx_func func [ FUNC_MAX ] ;
} ;
# define OCELOT_P(p, f0, f1, f2) \
static struct ocelot_pin_caps ocelot_pin_ # # p = { \
. pin = p , \
. functions = { \
FUNC_GPIO , FUNC_ # # f0 , FUNC_ # # f1 , FUNC_ # # f2 , \
} , \
}
OCELOT_P ( 0 , SG0 , NONE , NONE ) ;
OCELOT_P ( 1 , SG0 , NONE , NONE ) ;
OCELOT_P ( 2 , SG0 , NONE , NONE ) ;
OCELOT_P ( 3 , SG0 , NONE , NONE ) ;
OCELOT_P ( 4 , IRQ0_IN , IRQ0_OUT , TWI ) ;
OCELOT_P ( 5 , IRQ1_IN , IRQ1_OUT , PCI_WAKE ) ;
OCELOT_P ( 6 , UART , TWI_SCL_M , NONE ) ;
OCELOT_P ( 7 , UART , TWI_SCL_M , NONE ) ;
OCELOT_P ( 8 , SI , TWI_SCL_M , IRQ0_OUT ) ;
OCELOT_P ( 9 , SI , TWI_SCL_M , IRQ1_OUT ) ;
OCELOT_P ( 10 , PTP2 , TWI_SCL_M , SFP0 ) ;
OCELOT_P ( 11 , PTP3 , TWI_SCL_M , SFP1 ) ;
OCELOT_P ( 12 , UART2 , TWI_SCL_M , SFP2 ) ;
OCELOT_P ( 13 , UART2 , TWI_SCL_M , SFP3 ) ;
OCELOT_P ( 14 , MIIM1 , TWI_SCL_M , SFP4 ) ;
OCELOT_P ( 15 , MIIM1 , TWI_SCL_M , SFP5 ) ;
OCELOT_P ( 16 , TWI , NONE , SI ) ;
OCELOT_P ( 17 , TWI , TWI_SCL_M , SI ) ;
OCELOT_P ( 18 , PTP0 , TWI_SCL_M , NONE ) ;
OCELOT_P ( 19 , PTP1 , TWI_SCL_M , NONE ) ;
OCELOT_P ( 20 , RECO_CLK0 , TACHO , NONE ) ;
OCELOT_P ( 21 , RECO_CLK1 , PWM , NONE ) ;
# define OCELOT_PIN(n) { \
. number = n , \
. name = " GPIO_ " # n , \
. drv_data = & ocelot_pin_ # # n \
}
static const struct pinctrl_pin_desc ocelot_pins [ ] = {
OCELOT_PIN ( 0 ) ,
OCELOT_PIN ( 1 ) ,
OCELOT_PIN ( 2 ) ,
OCELOT_PIN ( 3 ) ,
OCELOT_PIN ( 4 ) ,
OCELOT_PIN ( 5 ) ,
OCELOT_PIN ( 6 ) ,
OCELOT_PIN ( 7 ) ,
OCELOT_PIN ( 8 ) ,
OCELOT_PIN ( 9 ) ,
OCELOT_PIN ( 10 ) ,
OCELOT_PIN ( 11 ) ,
OCELOT_PIN ( 12 ) ,
OCELOT_PIN ( 13 ) ,
OCELOT_PIN ( 14 ) ,
OCELOT_PIN ( 15 ) ,
OCELOT_PIN ( 16 ) ,
OCELOT_PIN ( 17 ) ,
OCELOT_PIN ( 18 ) ,
OCELOT_PIN ( 19 ) ,
OCELOT_PIN ( 20 ) ,
OCELOT_PIN ( 21 ) ,
} ;
static int ocelot_get_functions_count ( struct pinctrl_dev * pctldev )
{
return ARRAY_SIZE ( ocelot_function_names ) ;
}
static const char * ocelot_get_function_name ( struct pinctrl_dev * pctldev ,
unsigned int function )
{
return ocelot_function_names [ function ] ;
}
static int ocelot_get_function_groups ( struct pinctrl_dev * pctldev ,
unsigned int function ,
const char * const * * groups ,
unsigned * const num_groups )
{
struct ocelot_pinctrl * info = pinctrl_dev_get_drvdata ( pctldev ) ;
* groups = info - > func [ function ] . groups ;
* num_groups = info - > func [ function ] . ngroups ;
return 0 ;
}
static int ocelot_pin_function_idx ( unsigned int pin , unsigned int function )
{
struct ocelot_pin_caps * p = ocelot_pins [ pin ] . drv_data ;
int i ;
for ( i = 0 ; i < OCELOT_FUNC_PER_PIN ; i + + ) {
if ( function = = p - > functions [ i ] )
return i ;
}
return - 1 ;
}
static int ocelot_pinmux_set_mux ( struct pinctrl_dev * pctldev ,
unsigned int selector , unsigned int group )
{
struct ocelot_pinctrl * info = pinctrl_dev_get_drvdata ( pctldev ) ;
struct ocelot_pin_caps * pin = ocelot_pins [ group ] . drv_data ;
int f ;
f = ocelot_pin_function_idx ( group , selector ) ;
if ( f < 0 )
return - EINVAL ;
/*
* f is encoded on two bits .
* bit 0 of f goes in BIT ( pin ) of ALT0 , bit 1 of f goes in BIT ( pin ) of
* ALT1
* This is racy because both registers can ' t be updated at the same time
* but it doesn ' t matter much for now .
*/
regmap_update_bits ( info - > map , OCELOT_GPIO_ALT0 , BIT ( pin - > pin ) ,
f < < pin - > pin ) ;
regmap_update_bits ( info - > map , OCELOT_GPIO_ALT1 , BIT ( pin - > pin ) ,
f < < ( pin - > pin - 1 ) ) ;
return 0 ;
}
static int ocelot_gpio_set_direction ( struct pinctrl_dev * pctldev ,
struct pinctrl_gpio_range * range ,
unsigned int pin , bool input )
{
struct ocelot_pinctrl * info = pinctrl_dev_get_drvdata ( pctldev ) ;
regmap_update_bits ( info - > map , OCELOT_GPIO_OE , BIT ( pin ) ,
2018-03-22 15:35:00 +03:00
input ? 0 : BIT ( pin ) ) ;
2018-01-06 03:09:26 +03:00
return 0 ;
}
static int ocelot_gpio_request_enable ( struct pinctrl_dev * pctldev ,
struct pinctrl_gpio_range * range ,
unsigned int offset )
{
struct ocelot_pinctrl * info = pinctrl_dev_get_drvdata ( pctldev ) ;
regmap_update_bits ( info - > map , OCELOT_GPIO_ALT0 , BIT ( offset ) , 0 ) ;
regmap_update_bits ( info - > map , OCELOT_GPIO_ALT1 , BIT ( offset ) , 0 ) ;
return 0 ;
}
static const struct pinmux_ops ocelot_pmx_ops = {
. get_functions_count = ocelot_get_functions_count ,
. get_function_name = ocelot_get_function_name ,
. get_function_groups = ocelot_get_function_groups ,
. set_mux = ocelot_pinmux_set_mux ,
. gpio_set_direction = ocelot_gpio_set_direction ,
. gpio_request_enable = ocelot_gpio_request_enable ,
} ;
static int ocelot_pctl_get_groups_count ( struct pinctrl_dev * pctldev )
{
return ARRAY_SIZE ( ocelot_pins ) ;
}
static const char * ocelot_pctl_get_group_name ( struct pinctrl_dev * pctldev ,
unsigned int group )
{
return ocelot_pins [ group ] . name ;
}
static int ocelot_pctl_get_group_pins ( struct pinctrl_dev * pctldev ,
unsigned int group ,
const unsigned int * * pins ,
unsigned int * num_pins )
{
* pins = & ocelot_pins [ group ] . number ;
* num_pins = 1 ;
return 0 ;
}
static const struct pinctrl_ops ocelot_pctl_ops = {
. get_groups_count = ocelot_pctl_get_groups_count ,
. get_group_name = ocelot_pctl_get_group_name ,
. get_group_pins = ocelot_pctl_get_group_pins ,
. dt_node_to_map = pinconf_generic_dt_node_to_map_pin ,
. dt_free_map = pinconf_generic_dt_free_map ,
} ;
static struct pinctrl_desc ocelot_desc = {
. name = " ocelot-pinctrl " ,
. pins = ocelot_pins ,
. npins = ARRAY_SIZE ( ocelot_pins ) ,
. pctlops = & ocelot_pctl_ops ,
. pmxops = & ocelot_pmx_ops ,
. owner = THIS_MODULE ,
} ;
static int ocelot_create_group_func_map ( struct device * dev ,
struct ocelot_pinctrl * info )
{
u16 pins [ ARRAY_SIZE ( ocelot_pins ) ] ;
int f , npins , i ;
for ( f = 0 ; f < FUNC_MAX ; f + + ) {
for ( npins = 0 , i = 0 ; i < ARRAY_SIZE ( ocelot_pins ) ; i + + ) {
if ( ocelot_pin_function_idx ( i , f ) > = 0 )
pins [ npins + + ] = i ;
}
info - > func [ f ] . ngroups = npins ;
treewide: devm_kzalloc() -> devm_kcalloc()
The devm_kzalloc() function has a 2-factor argument form, devm_kcalloc().
This patch replaces cases of:
devm_kzalloc(handle, a * b, gfp)
with:
devm_kcalloc(handle, a * b, gfp)
as well as handling cases of:
devm_kzalloc(handle, a * b * c, gfp)
with:
devm_kzalloc(handle, array3_size(a, b, c), gfp)
as it's slightly less ugly than:
devm_kcalloc(handle, array_size(a, b), c, gfp)
This does, however, attempt to ignore constant size factors like:
devm_kzalloc(handle, 4 * 1024, gfp)
though any constants defined via macros get caught up in the conversion.
Any factors with a sizeof() of "unsigned char", "char", and "u8" were
dropped, since they're redundant.
Some manual whitespace fixes were needed in this patch, as Coccinelle
really liked to write "=devm_kcalloc..." instead of "= devm_kcalloc...".
The Coccinelle script used for this was:
// Fix redundant parens around sizeof().
@@
expression HANDLE;
type TYPE;
expression THING, E;
@@
(
devm_kzalloc(HANDLE,
- (sizeof(TYPE)) * E
+ sizeof(TYPE) * E
, ...)
|
devm_kzalloc(HANDLE,
- (sizeof(THING)) * E
+ sizeof(THING) * E
, ...)
)
// Drop single-byte sizes and redundant parens.
@@
expression HANDLE;
expression COUNT;
typedef u8;
typedef __u8;
@@
(
devm_kzalloc(HANDLE,
- sizeof(u8) * (COUNT)
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(__u8) * (COUNT)
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(char) * (COUNT)
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(unsigned char) * (COUNT)
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(u8) * COUNT
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(__u8) * COUNT
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(char) * COUNT
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(unsigned char) * COUNT
+ COUNT
, ...)
)
// 2-factor product with sizeof(type/expression) and identifier or constant.
@@
expression HANDLE;
type TYPE;
expression THING;
identifier COUNT_ID;
constant COUNT_CONST;
@@
(
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * (COUNT_ID)
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * COUNT_ID
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * (COUNT_CONST)
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * COUNT_CONST
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * (COUNT_ID)
+ COUNT_ID, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * COUNT_ID
+ COUNT_ID, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * (COUNT_CONST)
+ COUNT_CONST, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * COUNT_CONST
+ COUNT_CONST, sizeof(THING)
, ...)
)
// 2-factor product, only identifiers.
@@
expression HANDLE;
identifier SIZE, COUNT;
@@
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- SIZE * COUNT
+ COUNT, SIZE
, ...)
// 3-factor product with 1 sizeof(type) or sizeof(expression), with
// redundant parens removed.
@@
expression HANDLE;
expression THING;
identifier STRIDE, COUNT;
type TYPE;
@@
(
devm_kzalloc(HANDLE,
- sizeof(TYPE) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
)
// 3-factor product with 2 sizeof(variable), with redundant parens removed.
@@
expression HANDLE;
expression THING1, THING2;
identifier COUNT;
type TYPE1, TYPE2;
@@
(
devm_kzalloc(HANDLE,
- sizeof(TYPE1) * sizeof(TYPE2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
)
// 3-factor product, only identifiers, with redundant parens removed.
@@
expression HANDLE;
identifier STRIDE, SIZE, COUNT;
@@
(
devm_kzalloc(HANDLE,
- (COUNT) * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- COUNT * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- COUNT * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- (COUNT) * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- COUNT * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- (COUNT) * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- (COUNT) * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- COUNT * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
)
// Any remaining multi-factor products, first at least 3-factor products,
// when they're not all constants...
@@
expression HANDLE;
expression E1, E2, E3;
constant C1, C2, C3;
@@
(
devm_kzalloc(HANDLE, C1 * C2 * C3, ...)
|
devm_kzalloc(HANDLE,
- (E1) * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
|
devm_kzalloc(HANDLE,
- (E1) * (E2) * E3
+ array3_size(E1, E2, E3)
, ...)
|
devm_kzalloc(HANDLE,
- (E1) * (E2) * (E3)
+ array3_size(E1, E2, E3)
, ...)
|
devm_kzalloc(HANDLE,
- E1 * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
)
// And then all remaining 2 factors products when they're not all constants,
// keeping sizeof() as the second factor argument.
@@
expression HANDLE;
expression THING, E1, E2;
type TYPE;
constant C1, C2, C3;
@@
(
devm_kzalloc(HANDLE, sizeof(THING) * C2, ...)
|
devm_kzalloc(HANDLE, sizeof(TYPE) * C2, ...)
|
devm_kzalloc(HANDLE, C1 * C2 * C3, ...)
|
devm_kzalloc(HANDLE, C1 * C2, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * (E2)
+ E2, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * E2
+ E2, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * (E2)
+ E2, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * E2
+ E2, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- (E1) * E2
+ E1, E2
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- (E1) * (E2)
+ E1, E2
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- E1 * E2
+ E1, E2
, ...)
)
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-06-13 00:07:58 +03:00
info - > func [ f ] . groups = devm_kcalloc ( dev ,
npins ,
2018-01-06 03:09:26 +03:00
sizeof ( char * ) ,
GFP_KERNEL ) ;
if ( ! info - > func [ f ] . groups )
return - ENOMEM ;
for ( i = 0 ; i < npins ; i + + )
info - > func [ f ] . groups [ i ] = ocelot_pins [ pins [ i ] ] . name ;
}
return 0 ;
}
static int ocelot_pinctrl_register ( struct platform_device * pdev ,
struct ocelot_pinctrl * info )
{
int ret ;
ret = ocelot_create_group_func_map ( & pdev - > dev , info ) ;
if ( ret ) {
dev_err ( & pdev - > dev , " Unable to create group func map. \n " ) ;
return ret ;
}
info - > pctl = devm_pinctrl_register ( & pdev - > dev , & ocelot_desc , info ) ;
if ( IS_ERR ( info - > pctl ) ) {
dev_err ( & pdev - > dev , " Failed to register pinctrl \n " ) ;
return PTR_ERR ( info - > pctl ) ;
}
return 0 ;
}
static int ocelot_gpio_get ( struct gpio_chip * chip , unsigned int offset )
{
struct ocelot_pinctrl * info = gpiochip_get_data ( chip ) ;
unsigned int val ;
regmap_read ( info - > map , OCELOT_GPIO_IN , & val ) ;
return ! ! ( val & BIT ( offset ) ) ;
}
static void ocelot_gpio_set ( struct gpio_chip * chip , unsigned int offset ,
int value )
{
struct ocelot_pinctrl * info = gpiochip_get_data ( chip ) ;
if ( value )
regmap_write ( info - > map , OCELOT_GPIO_OUT_SET , BIT ( offset ) ) ;
else
regmap_write ( info - > map , OCELOT_GPIO_OUT_CLR , BIT ( offset ) ) ;
}
static int ocelot_gpio_get_direction ( struct gpio_chip * chip ,
unsigned int offset )
{
struct ocelot_pinctrl * info = gpiochip_get_data ( chip ) ;
unsigned int val ;
regmap_read ( info - > map , OCELOT_GPIO_OE , & val ) ;
return ! ( val & BIT ( offset ) ) ;
}
static int ocelot_gpio_direction_input ( struct gpio_chip * chip ,
unsigned int offset )
{
return pinctrl_gpio_direction_input ( chip - > base + offset ) ;
}
static int ocelot_gpio_direction_output ( struct gpio_chip * chip ,
unsigned int offset , int value )
{
struct ocelot_pinctrl * info = gpiochip_get_data ( chip ) ;
unsigned int pin = BIT ( offset ) ;
if ( value )
regmap_write ( info - > map , OCELOT_GPIO_OUT_SET , pin ) ;
else
regmap_write ( info - > map , OCELOT_GPIO_OUT_CLR , pin ) ;
return pinctrl_gpio_direction_output ( chip - > base + offset ) ;
}
static const struct gpio_chip ocelot_gpiolib_chip = {
. request = gpiochip_generic_request ,
. free = gpiochip_generic_free ,
. set = ocelot_gpio_set ,
. get = ocelot_gpio_get ,
. get_direction = ocelot_gpio_get_direction ,
. direction_input = ocelot_gpio_direction_input ,
. direction_output = ocelot_gpio_direction_output ,
. owner = THIS_MODULE ,
} ;
static int ocelot_gpiochip_register ( struct platform_device * pdev ,
struct ocelot_pinctrl * info )
{
struct gpio_chip * gc ;
int ret ;
info - > gpio_chip = ocelot_gpiolib_chip ;
gc = & info - > gpio_chip ;
gc - > ngpio = OCELOT_PINS ;
gc - > parent = & pdev - > dev ;
gc - > base = 0 ;
gc - > of_node = info - > dev - > of_node ;
gc - > label = " ocelot-gpio " ;
ret = devm_gpiochip_add_data ( & pdev - > dev , gc , info ) ;
if ( ret )
return ret ;
/* TODO: this can be used as an irqchip but no board is using that */
return 0 ;
}
static const struct regmap_config ocelot_pinctrl_regmap_config = {
. reg_bits = 32 ,
. val_bits = 32 ,
. reg_stride = 4 ,
. max_register = 0x64 ,
} ;
static const struct of_device_id ocelot_pinctrl_of_match [ ] = {
{ . compatible = " mscc,ocelot-pinctrl " } ,
{ } ,
} ;
2018-02-08 17:24:37 +03:00
static int ocelot_pinctrl_probe ( struct platform_device * pdev )
2018-01-06 03:09:26 +03:00
{
struct device * dev = & pdev - > dev ;
struct ocelot_pinctrl * info ;
void __iomem * base ;
int ret ;
info = devm_kzalloc ( dev , sizeof ( * info ) , GFP_KERNEL ) ;
if ( ! info )
return - ENOMEM ;
base = devm_ioremap_resource ( dev ,
platform_get_resource ( pdev , IORESOURCE_MEM , 0 ) ) ;
if ( IS_ERR ( base ) ) {
dev_err ( dev , " Failed to ioremap registers \n " ) ;
return PTR_ERR ( base ) ;
}
info - > map = devm_regmap_init_mmio ( dev , base ,
& ocelot_pinctrl_regmap_config ) ;
if ( IS_ERR ( info - > map ) ) {
dev_err ( dev , " Failed to create regmap \n " ) ;
return PTR_ERR ( info - > map ) ;
}
dev_set_drvdata ( dev , info - > map ) ;
info - > dev = dev ;
ret = ocelot_pinctrl_register ( pdev , info ) ;
if ( ret )
return ret ;
ret = ocelot_gpiochip_register ( pdev , info ) ;
if ( ret )
return ret ;
return 0 ;
}
static struct platform_driver ocelot_pinctrl_driver = {
. driver = {
. name = " pinctrl-ocelot " ,
. of_match_table = of_match_ptr ( ocelot_pinctrl_of_match ) ,
. suppress_bind_attrs = true ,
} ,
. probe = ocelot_pinctrl_probe ,
} ;
builtin_platform_driver ( ocelot_pinctrl_driver ) ;