2018-09-07 05:13:29 +03:00
// SPDX-License-Identifier: GPL-2.0
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
*/
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>
2022-04-13 20:23:24 +03:00
# include <linux/init.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>
2022-04-13 20:23:24 +03:00
# include <linux/math.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>
pinctrl: sh-pfc: Save/restore registers for PSCI system suspend
During PSCI system suspend, R-Car Gen3 SoCs are powered down, and their
pinctrl register state is lost. Note that as the boot loader skips most
initialization after system resume, pinctrl register state differs from
the state encountered during normal system boot, too.
To fix this, save all GPIO and peripheral function select, module
select, drive strength control, bias, and other I/O control registers
during system suspend, and restore them during system resume.
Note that to avoid overhead on platforms not needing it, the
suspend/resume code has a build time dependency on sleep and PSCI
support, and a runtime dependency on PSCI.
Inspired by a patch in the BSP by Hien Dang.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
2017-09-29 15:17:18 +03:00
# include <linux/psci.h>
2012-12-16 02:50:52 +04:00
# include <linux/slab.h>
pinctrl: sh-pfc: Split R-Car H3 support in two independent drivers
Despite using the same compatible values ("r8a7795"-based) because of
historical reasons, R-Car H3 ES1.x (R8A77950) and R-Car H3 ES2.0+
(R8A77951) are really different SoCs, with different part numbers, and
with different Pin Function Controller blocks.
Reflect this in the pinctrl configuration, by replacing the existing
CONFIG_PINCTRL_PFC_R8A7795 symbol by two new config symbols:
CONFIG_PINCTRL_PFC_R8A77950 and CONFIG_PINCTRL_PFC_R8A77951. The latter
are selected automatically, depending on the soon-to-be-introduced
corresponding SoC-specific config options, and on the current common
config option, to relax dependencies.
Rename the individual pin control driver source files from
pfc-r8a7795-es1.c to pfc-r8a77950.c, and from pfc-r8a7795.c to
pfc-r8a77951.c, and make them truly independent.
As both SoCs share the same compatible value, special care must be taken
to match them to the correct pin control driver, if support for it is
included in the running kernel.
This will allow making support for early R-Car H3 revisions optional,
the largest share of which is taken by the pin control driver.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Reviewed-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Tested-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Link: https://lore.kernel.org/r/20191230083156.19191-1-geert+renesas@glider.be
2019-12-30 11:31:56 +03:00
# include <linux/sys_soc.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
{
2013-12-11 07:26:26 +04:00
struct sh_pfc_window * windows ;
unsigned int * irqs = NULL ;
2019-10-16 17:26:01 +03:00
unsigned int num_windows ;
2011-12-09 07:14:27 +04:00
struct resource * res ;
2013-12-11 07:26:26 +04:00
unsigned int i ;
2019-10-16 17:26:01 +03:00
int num_irqs ;
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
}
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
2019-10-16 17:26:01 +03:00
num_irqs = platform_irq_count ( pdev ) ;
if ( num_irqs < 0 )
return num_irqs ;
2013-12-11 07:26:26 +04:00
/* Allocate memory windows and IRQs arrays. */
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
windows = devm_kcalloc ( pfc - > dev , num_windows , sizeof ( * windows ) ,
2013-12-11 07:26:26 +04:00
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 ) {
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
irqs = devm_kcalloc ( pfc - > dev , num_irqs , sizeof ( * irqs ) ,
2013-12-11 07:26:26 +04:00
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 + + ) {
2022-04-29 11:26:36 +03:00
windows - > virt = devm_platform_get_and_ioremap_resource ( pdev , i , & res ) ;
2015-06-25 12:39:53 +03:00
if ( IS_ERR ( windows - > virt ) )
return - ENOMEM ;
2022-04-29 11:26:36 +03:00
windows - > phys = res - > start ;
windows - > size = resource_size ( res ) ;
2015-06-25 12:39:53 +03:00
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 ( ) ;
}
2017-09-29 12:03:11 +03:00
u32 sh_pfc_read ( struct sh_pfc * pfc , u32 reg )
2016-03-23 17:06:00 +03:00
{
2017-09-29 12:03:11 +03:00
return sh_pfc_read_raw_reg ( sh_pfc_phys_to_virt ( pfc , reg ) , 32 ) ;
2016-03-23 17:06:00 +03:00
}
2021-01-12 19:59:07 +03:00
static void sh_pfc_unlock_reg ( struct sh_pfc * pfc , u32 reg , u32 data )
2016-03-23 17:06:00 +03:00
{
2021-01-12 19:59:07 +03:00
u32 unlock ;
if ( ! pfc - > info - > unlock_reg )
return ;
2016-03-23 17:06:00 +03:00
2021-01-12 19:59:07 +03:00
if ( pfc - > info - > unlock_reg > = 0x80000000UL )
unlock = pfc - > info - > unlock_reg ;
else
/* unlock_reg is a mask */
unlock = reg & ~ pfc - > info - > unlock_reg ;
sh_pfc_write_raw_reg ( sh_pfc_phys_to_virt ( pfc , unlock ) , 32 , ~ data ) ;
}
void sh_pfc_write ( struct sh_pfc * pfc , u32 reg , u32 data )
{
sh_pfc_unlock_reg ( pfc , reg , data ) ;
2017-09-29 12:03:11 +03:00
sh_pfc_write_raw_reg ( sh_pfc_phys_to_virt ( pfc , reg ) , 32 , data ) ;
2016-03-23 17:06:00 +03:00
}
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 + + )
2022-04-13 20:23:24 +03:00
* posp - = abs ( crp - > var_field_width [ k ] ) ;
2011-12-13 20:01:05 +04:00
}
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 " ,
2018-12-13 17:20:13 +03:00
crp - > reg , value , field , crp - > reg_width , hweight32 ( mask ) ) ;
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 ;
2021-01-12 19:59:07 +03:00
sh_pfc_unlock_reg ( pfc , crp - > reg , data ) ;
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
2022-04-13 20:23:24 +03:00
for ( bit_pos = 0 ; bit_pos < r_width ; bit_pos + = curr_width , m + + ) {
2015-03-12 13:09:14 +03:00
u32 ncomb ;
u32 n ;
2022-04-13 20:23:24 +03:00
if ( f_width ) {
2011-12-13 20:01:05 +04:00
curr_width = f_width ;
2022-04-13 20:23:24 +03:00
} else {
curr_width = abs ( config_reg - > var_field_width [ m ] ) ;
if ( config_reg - > var_field_width [ m ] < 0 )
continue ;
}
2011-12-13 20:01:05 +04:00
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 ;
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 ;
pinctrl: renesas: Protect GPIO leftovers by CONFIG_PINCTRL_SH_FUNC_GPIO
On SuperH and ARM SH/R-Mobile SoCs, the pin control driver handles
GPIOs, too. To reduce code size when compiling a kernel supporting only
modern SoCs, most, but not all, of the GPIO functionality is protected
by checks for CONFIG_PINCTRL_SH_FUNC_GPIO.
Factor out the remaining parts when not needed:
1. sh_pfc_soc_info.{in,out}put describe GPIO pins that have input
resp. output capabilities (SuperH and SH/R-Mobile).
2. sh_pfc_soc_info.gpio_irq{,_size} describe the mapping from GPIO
pins to interrupt numbers (SH/R-Mobile).
3. sh_pfc_gpio_set_direction() configures GPIO direction, called from
the GPIO driver through pinctrl_gpio_direction_{in,out}put()
(SH/R-Mobile). Unfortunately this function cannot just be moved to
drivers/pinctrl/renesas/gpio.c, as it relies on knowledge of
sh_pfc_pinctrl, which is internal to
drivers/pinctrl/renesas/pinctrl.c.
While code size reduction is minimal, this does help in documenting
depencies.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://lore.kernel.org/r/20201028151637.1734130-9-geert+renesas@glider.be
2020-10-28 18:16:37 +03:00
# ifdef CONFIG_PINCTRL_SH_PFC_GPIO
2008-10-08 15:41:43 +04:00
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 ;
pinctrl: renesas: Protect GPIO leftovers by CONFIG_PINCTRL_SH_FUNC_GPIO
On SuperH and ARM SH/R-Mobile SoCs, the pin control driver handles
GPIOs, too. To reduce code size when compiling a kernel supporting only
modern SoCs, most, but not all, of the GPIO functionality is protected
by checks for CONFIG_PINCTRL_SH_FUNC_GPIO.
Factor out the remaining parts when not needed:
1. sh_pfc_soc_info.{in,out}put describe GPIO pins that have input
resp. output capabilities (SuperH and SH/R-Mobile).
2. sh_pfc_soc_info.gpio_irq{,_size} describe the mapping from GPIO
pins to interrupt numbers (SH/R-Mobile).
3. sh_pfc_gpio_set_direction() configures GPIO direction, called from
the GPIO driver through pinctrl_gpio_direction_{in,out}put()
(SH/R-Mobile). Unfortunately this function cannot just be moved to
drivers/pinctrl/renesas/gpio.c, as it relies on knowledge of
sh_pfc_pinctrl, which is internal to
drivers/pinctrl/renesas/pinctrl.c.
While code size reduction is minimal, this does help in documenting
depencies.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://lore.kernel.org/r/20201028151637.1734130-9-geert+renesas@glider.be
2020-10-28 18:16:37 +03:00
# endif /* CONFIG_PINCTRL_SH_PFC_GPIO */
2008-10-08 15:41:43 +04:00
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 ;
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
pfc - > ranges = devm_kcalloc ( pfc - > dev , nr_ranges , sizeof ( * pfc - > ranges ) ,
2013-07-15 20:38:30 +04:00
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
2020-05-04 00:46:46 +03:00
# ifdef CONFIG_PINCTRL_PFC_R8A7742
{
. compatible = " renesas,pfc-r8a7742 " ,
. data = & r8a7742_pinmux_info ,
} ,
# endif
2017-04-20 21:46:08 +03:00
# ifdef CONFIG_PINCTRL_PFC_R8A7743
{
. compatible = " renesas,pfc-r8a7743 " ,
. data = & r8a7743_pinmux_info ,
} ,
# endif
2018-09-11 13:30:05 +03:00
# ifdef CONFIG_PINCTRL_PFC_R8A7744
{
. compatible = " renesas,pfc-r8a7744 " ,
. data = & r8a7744_pinmux_info ,
} ,
# endif
2017-04-28 21:52:35 +03:00
# ifdef CONFIG_PINCTRL_PFC_R8A7745
{
. compatible = " renesas,pfc-r8a7745 " ,
. data = & r8a7745_pinmux_info ,
} ,
# endif
2018-04-24 14:03:08 +03:00
# ifdef CONFIG_PINCTRL_PFC_R8A77470
{
. compatible = " renesas,pfc-r8a77470 " ,
. data = & r8a77470_pinmux_info ,
} ,
# endif
2018-08-13 16:52:32 +03:00
# ifdef CONFIG_PINCTRL_PFC_R8A774A1
{
. compatible = " renesas,pfc-r8a774a1 " ,
. data = & r8a774a1_pinmux_info ,
} ,
# endif
2019-09-19 11:17:16 +03:00
# ifdef CONFIG_PINCTRL_PFC_R8A774B1
{
. compatible = " renesas,pfc-r8a774b1 " ,
. data = & r8a774b1_pinmux_info ,
} ,
# endif
2018-09-12 16:31:02 +03:00
# ifdef CONFIG_PINCTRL_PFC_R8A774C0
{
. compatible = " renesas,pfc-r8a774c0 " ,
. data = & r8a774c0_pinmux_info ,
} ,
# endif
2020-07-07 19:18:12 +03:00
# ifdef CONFIG_PINCTRL_PFC_R8A774E1
{
. compatible = " renesas,pfc-r8a774e1 " ,
. data = & r8a774e1_pinmux_info ,
} ,
# endif
2013-06-17 22:50:02 +04:00
# 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
2016-06-30 00:21:08 +03:00
# ifdef CONFIG_PINCTRL_PFC_R8A7792
{
. compatible = " renesas,pfc-r8a7792 " ,
. data = & r8a7792_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
2021-07-19 18:17:00 +03:00
/*
* Both r8a7795 entries must be present to make sanity checks work , but only
* the first entry is actually used .
* R - Car H3 ES1 . x is matched using soc_device_match ( ) instead .
*/
# ifdef CONFIG_PINCTRL_PFC_R8A77951
2015-09-03 05:51:49 +03:00
{
. compatible = " renesas,pfc-r8a7795 " ,
2021-07-19 18:17:00 +03:00
. data = & r8a77951_pinmux_info ,
2015-09-03 05:51:49 +03:00
} ,
pinctrl: sh-pfc: Split R-Car H3 support in two independent drivers
Despite using the same compatible values ("r8a7795"-based) because of
historical reasons, R-Car H3 ES1.x (R8A77950) and R-Car H3 ES2.0+
(R8A77951) are really different SoCs, with different part numbers, and
with different Pin Function Controller blocks.
Reflect this in the pinctrl configuration, by replacing the existing
CONFIG_PINCTRL_PFC_R8A7795 symbol by two new config symbols:
CONFIG_PINCTRL_PFC_R8A77950 and CONFIG_PINCTRL_PFC_R8A77951. The latter
are selected automatically, depending on the soon-to-be-introduced
corresponding SoC-specific config options, and on the current common
config option, to relax dependencies.
Rename the individual pin control driver source files from
pfc-r8a7795-es1.c to pfc-r8a77950.c, and from pfc-r8a7795.c to
pfc-r8a77951.c, and make them truly independent.
As both SoCs share the same compatible value, special care must be taken
to match them to the correct pin control driver, if support for it is
included in the running kernel.
This will allow making support for early R-Car H3 revisions optional,
the largest share of which is taken by the pin control driver.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Reviewed-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Tested-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Link: https://lore.kernel.org/r/20191230083156.19191-1-geert+renesas@glider.be
2019-12-30 11:31:56 +03:00
# endif
2021-07-19 18:17:00 +03:00
# ifdef CONFIG_PINCTRL_PFC_R8A77950
2018-12-13 17:48:45 +03:00
{
pinctrl: sh-pfc: Split R-Car H3 support in two independent drivers
Despite using the same compatible values ("r8a7795"-based) because of
historical reasons, R-Car H3 ES1.x (R8A77950) and R-Car H3 ES2.0+
(R8A77951) are really different SoCs, with different part numbers, and
with different Pin Function Controller blocks.
Reflect this in the pinctrl configuration, by replacing the existing
CONFIG_PINCTRL_PFC_R8A7795 symbol by two new config symbols:
CONFIG_PINCTRL_PFC_R8A77950 and CONFIG_PINCTRL_PFC_R8A77951. The latter
are selected automatically, depending on the soon-to-be-introduced
corresponding SoC-specific config options, and on the current common
config option, to relax dependencies.
Rename the individual pin control driver source files from
pfc-r8a7795-es1.c to pfc-r8a77950.c, and from pfc-r8a7795.c to
pfc-r8a77951.c, and make them truly independent.
As both SoCs share the same compatible value, special care must be taken
to match them to the correct pin control driver, if support for it is
included in the running kernel.
This will allow making support for early R-Car H3 revisions optional,
the largest share of which is taken by the pin control driver.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Reviewed-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Tested-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Link: https://lore.kernel.org/r/20191230083156.19191-1-geert+renesas@glider.be
2019-12-30 11:31:56 +03:00
. compatible = " renesas,pfc-r8a7795 " ,
2021-07-19 18:17:00 +03:00
. data = & r8a77950_pinmux_info ,
2018-12-13 17:48:45 +03:00
} ,
2015-09-03 05:51:49 +03:00
# endif
2019-10-23 15:29:54 +03:00
# ifdef CONFIG_PINCTRL_PFC_R8A77960
2016-08-18 16:12:32 +03:00
{
. compatible = " renesas,pfc-r8a7796 " ,
2019-10-23 15:29:54 +03:00
. data = & r8a77960_pinmux_info ,
2016-08-18 16:12:32 +03:00
} ,
# endif
2019-10-23 15:29:55 +03:00
# ifdef CONFIG_PINCTRL_PFC_R8A77961
{
. compatible = " renesas,pfc-r8a77961 " ,
. data = & r8a77961_pinmux_info ,
} ,
# endif
2018-02-20 18:12:07 +03:00
# ifdef CONFIG_PINCTRL_PFC_R8A77965
{
. compatible = " renesas,pfc-r8a77965 " ,
. data = & r8a77965_pinmux_info ,
} ,
# endif
2017-11-10 20:59:01 +03:00
# ifdef CONFIG_PINCTRL_PFC_R8A77970
{
. compatible = " renesas,pfc-r8a77970 " ,
. data = & r8a77970_pinmux_info ,
} ,
# endif
2018-03-08 22:14:32 +03:00
# ifdef CONFIG_PINCTRL_PFC_R8A77980
{
. compatible = " renesas,pfc-r8a77980 " ,
. data = & r8a77980_pinmux_info ,
} ,
# endif
2018-05-11 06:22:23 +03:00
# ifdef CONFIG_PINCTRL_PFC_R8A77990
{
. compatible = " renesas,pfc-r8a77990 " ,
. data = & r8a77990_pinmux_info ,
} ,
# endif
2017-08-09 15:19:41 +03:00
# ifdef CONFIG_PINCTRL_PFC_R8A77995
{
. compatible = " renesas,pfc-r8a77995 " ,
. data = & r8a77995_pinmux_info ,
} ,
# endif
2021-01-12 19:59:10 +03:00
# ifdef CONFIG_PINCTRL_PFC_R8A779A0
{
. compatible = " renesas,pfc-r8a779a0 " ,
. data = & r8a779a0_pinmux_info ,
} ,
# endif
2022-02-21 18:43:38 +03:00
# ifdef CONFIG_PINCTRL_PFC_R8A779F0
{
. compatible = " renesas,pfc-r8a779f0 " ,
. data = & r8a779f0_pinmux_info ,
} ,
# endif
2022-07-01 04:36:13 +03:00
# ifdef CONFIG_PINCTRL_PFC_R8A779G0
{
. compatible = " renesas,pfc-r8a779g0 " ,
. data = & r8a779g0_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
pinctrl: sh-pfc: Save/restore registers for PSCI system suspend
During PSCI system suspend, R-Car Gen3 SoCs are powered down, and their
pinctrl register state is lost. Note that as the boot loader skips most
initialization after system resume, pinctrl register state differs from
the state encountered during normal system boot, too.
To fix this, save all GPIO and peripheral function select, module
select, drive strength control, bias, and other I/O control registers
during system suspend, and restore them during system resume.
Note that to avoid overhead on platforms not needing it, the
suspend/resume code has a build time dependency on sleep and PSCI
support, and a runtime dependency on PSCI.
Inspired by a patch in the BSP by Hien Dang.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
2017-09-29 15:17:18 +03:00
# if defined(CONFIG_PM_SLEEP) && defined(CONFIG_ARM_PSCI_FW)
static void sh_pfc_nop_reg ( struct sh_pfc * pfc , u32 reg , unsigned int idx )
{
}
static void sh_pfc_save_reg ( struct sh_pfc * pfc , u32 reg , unsigned int idx )
{
pfc - > saved_regs [ idx ] = sh_pfc_read ( pfc , reg ) ;
}
static void sh_pfc_restore_reg ( struct sh_pfc * pfc , u32 reg , unsigned int idx )
{
sh_pfc_write ( pfc , reg , pfc - > saved_regs [ idx ] ) ;
}
static unsigned int sh_pfc_walk_regs ( struct sh_pfc * pfc ,
void ( * do_reg ) ( struct sh_pfc * pfc , u32 reg , unsigned int idx ) )
{
unsigned int i , n = 0 ;
if ( pfc - > info - > cfg_regs )
for ( i = 0 ; pfc - > info - > cfg_regs [ i ] . reg ; i + + )
do_reg ( pfc , pfc - > info - > cfg_regs [ i ] . reg , n + + ) ;
if ( pfc - > info - > drive_regs )
for ( i = 0 ; pfc - > info - > drive_regs [ i ] . reg ; i + + )
do_reg ( pfc , pfc - > info - > drive_regs [ i ] . reg , n + + ) ;
if ( pfc - > info - > bias_regs )
pinctrl: renesas: Fix save/restore on SoCs with pull-down only pins
If some bits in a pin Pull-Up control register (PUPR) control pin
pull-down instead of pin pull-up, there are two pinmux_bias_reg entries:
a first one with the puen field filled in, listing pins with pull-up
functionality, and a second one with the pud field filled in, listing
pins with pull-down functionality. On encountering the second entry,
where puen is NULL, the for-loop terminates early, causing the remaining
bias registers not to be saved/restored during PSCI system suspend.
Fortunately this does not trigger on any supported system yet, as PSCI
is only used on R-Car Gen3 and RZ/G2 systems, which all have separate
pin Pull-Enable (PUEN) and pin Pull-Up/Down control (PUD) registers.
Avoid this ever becoming a problem by treating pinmux_bias_reg.puen and
pinmux_bias_reg.pud the same. Note that a register controlling both
pull-up and pull-down pins would be saved and restored twice, which is
harmless.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://lore.kernel.org/r/59d2fbddff685b6a7a82ff17d2b37633e30e8860.1633615652.git.geert+renesas@glider.be
2021-10-07 17:38:46 +03:00
for ( i = 0 ; pfc - > info - > bias_regs [ i ] . puen | |
pfc - > info - > bias_regs [ i ] . pud ; i + + ) {
if ( pfc - > info - > bias_regs [ i ] . puen )
do_reg ( pfc , pfc - > info - > bias_regs [ i ] . puen , n + + ) ;
pinctrl: sh-pfc: Save/restore registers for PSCI system suspend
During PSCI system suspend, R-Car Gen3 SoCs are powered down, and their
pinctrl register state is lost. Note that as the boot loader skips most
initialization after system resume, pinctrl register state differs from
the state encountered during normal system boot, too.
To fix this, save all GPIO and peripheral function select, module
select, drive strength control, bias, and other I/O control registers
during system suspend, and restore them during system resume.
Note that to avoid overhead on platforms not needing it, the
suspend/resume code has a build time dependency on sleep and PSCI
support, and a runtime dependency on PSCI.
Inspired by a patch in the BSP by Hien Dang.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
2017-09-29 15:17:18 +03:00
if ( pfc - > info - > bias_regs [ i ] . pud )
do_reg ( pfc , pfc - > info - > bias_regs [ i ] . pud , n + + ) ;
}
if ( pfc - > info - > ioctrl_regs )
for ( i = 0 ; pfc - > info - > ioctrl_regs [ i ] . reg ; i + + )
do_reg ( pfc , pfc - > info - > ioctrl_regs [ i ] . reg , n + + ) ;
return n ;
}
static int sh_pfc_suspend_init ( struct sh_pfc * pfc )
{
unsigned int n ;
/* This is the best we can do to check for the presence of PSCI */
if ( ! psci_ops . cpu_suspend )
return 0 ;
n = sh_pfc_walk_regs ( pfc , sh_pfc_nop_reg ) ;
if ( ! n )
return 0 ;
pfc - > saved_regs = devm_kmalloc_array ( pfc - > dev , n ,
sizeof ( * pfc - > saved_regs ) ,
GFP_KERNEL ) ;
if ( ! pfc - > saved_regs )
return - ENOMEM ;
dev_dbg ( pfc - > dev , " Allocated space to save %u regs \n " , n ) ;
return 0 ;
}
static int sh_pfc_suspend_noirq ( struct device * dev )
{
struct sh_pfc * pfc = dev_get_drvdata ( dev ) ;
if ( pfc - > saved_regs )
sh_pfc_walk_regs ( pfc , sh_pfc_save_reg ) ;
return 0 ;
}
static int sh_pfc_resume_noirq ( struct device * dev )
{
struct sh_pfc * pfc = dev_get_drvdata ( dev ) ;
if ( pfc - > saved_regs )
sh_pfc_walk_regs ( pfc , sh_pfc_restore_reg ) ;
return 0 ;
}
static const struct dev_pm_ops sh_pfc_pm = {
SET_NOIRQ_SYSTEM_SLEEP_PM_OPS ( sh_pfc_suspend_noirq , sh_pfc_resume_noirq )
} ;
# define DEV_PM_OPS &sh_pfc_pm
# else
static int sh_pfc_suspend_init ( struct sh_pfc * pfc ) { return 0 ; }
# define DEV_PM_OPS NULL
# endif /* CONFIG_PM_SLEEP && CONFIG_ARM_PSCI_FW */
2018-12-13 17:48:45 +03:00
# ifdef DEBUG
2020-01-10 16:19:18 +03:00
# define SH_PFC_MAX_REGS 300
2022-02-21 19:21:58 +03:00
# define SH_PFC_MAX_ENUMS 5000
2020-01-10 16:19:18 +03:00
2021-09-06 16:40:40 +03:00
static unsigned int sh_pfc_errors __initdata ;
static unsigned int sh_pfc_warnings __initdata ;
2021-12-23 17:56:22 +03:00
static bool sh_pfc_bias_done __initdata ;
2021-12-23 17:56:23 +03:00
static bool sh_pfc_drive_done __initdata ;
2021-12-23 17:56:24 +03:00
static bool sh_pfc_power_done __initdata ;
2021-10-07 17:38:48 +03:00
static struct {
u32 reg ;
u32 bits ;
} * sh_pfc_regs __initdata ;
2021-09-06 16:40:40 +03:00
static u32 sh_pfc_num_regs __initdata ;
static u16 * sh_pfc_enums __initdata ;
static u32 sh_pfc_num_enums __initdata ;
2020-01-10 16:19:15 +03:00
2020-01-10 16:19:16 +03:00
# define sh_pfc_err(fmt, ...) \
do { \
pr_err ( " %s: " fmt , drvname , # # __VA_ARGS__ ) ; \
sh_pfc_errors + + ; \
} while ( 0 )
2021-12-23 17:56:22 +03:00
# define sh_pfc_err_once(type, fmt, ...) \
do { \
if ( ! sh_pfc_ # # type # # _done ) { \
sh_pfc_ # # type # # _done = true ; \
sh_pfc_err ( fmt , # # __VA_ARGS__ ) ; \
} \
} while ( 0 )
2020-01-10 16:19:16 +03:00
# define sh_pfc_warn(fmt, ...) \
do { \
pr_warn ( " %s: " fmt , drvname , # # __VA_ARGS__ ) ; \
sh_pfc_warnings + + ; \
} while ( 0 )
2019-04-25 11:54:11 +03:00
static bool __init is0s ( const u16 * enum_ids , unsigned int n )
2018-12-13 17:48:45 +03:00
{
unsigned int i ;
for ( i = 0 ; i < n ; i + + )
if ( enum_ids [ i ] )
return false ;
return true ;
}
2020-01-10 16:19:17 +03:00
static bool __init same_name ( const char * a , const char * b )
{
2021-12-23 17:56:20 +03:00
return a & & b & & ! strcmp ( a , b ) ;
2020-01-10 16:19:17 +03:00
}
2021-10-07 17:38:48 +03:00
static void __init sh_pfc_check_reg ( const char * drvname , u32 reg , u32 bits )
2020-01-10 16:19:18 +03:00
{
unsigned int i ;
2021-10-07 17:38:48 +03:00
for ( i = 0 ; i < sh_pfc_num_regs ; i + + ) {
if ( reg ! = sh_pfc_regs [ i ] . reg )
continue ;
if ( bits & sh_pfc_regs [ i ] . bits )
sh_pfc_err ( " reg 0x%x: bits 0x%x conflict \n " , reg ,
bits & sh_pfc_regs [ i ] . bits ) ;
sh_pfc_regs [ i ] . bits | = bits ;
return ;
}
2020-01-10 16:19:18 +03:00
if ( sh_pfc_num_regs = = SH_PFC_MAX_REGS ) {
pr_warn_once ( " %s: Please increase SH_PFC_MAX_REGS \n " , drvname ) ;
return ;
}
2021-10-07 17:38:48 +03:00
sh_pfc_regs [ sh_pfc_num_regs ] . reg = reg ;
sh_pfc_regs [ sh_pfc_num_regs ] . bits = bits ;
sh_pfc_num_regs + + ;
2020-01-10 16:19:18 +03:00
}
2020-01-10 16:19:19 +03:00
static int __init sh_pfc_check_enum ( const char * drvname , u16 enum_id )
{
unsigned int i ;
for ( i = 0 ; i < sh_pfc_num_enums ; i + + ) {
if ( enum_id = = sh_pfc_enums [ i ] )
return - EINVAL ;
}
if ( sh_pfc_num_enums = = SH_PFC_MAX_ENUMS ) {
pr_warn_once ( " %s: Please increase SH_PFC_MAX_ENUMS \n " , drvname ) ;
return 0 ;
}
sh_pfc_enums [ sh_pfc_num_enums + + ] = enum_id ;
return 0 ;
}
static void __init sh_pfc_check_reg_enums ( const char * drvname , u32 reg ,
const u16 * enums , unsigned int n )
{
unsigned int i ;
for ( i = 0 ; i < n ; i + + ) {
if ( enums [ i ] & & sh_pfc_check_enum ( drvname , enums [ i ] ) )
sh_pfc_err ( " reg 0x%x enum_id %u conflict \n " , reg ,
enums [ i ] ) ;
}
}
2021-12-23 17:56:22 +03:00
static const struct sh_pfc_pin __init * sh_pfc_find_pin (
const struct sh_pfc_soc_info * info , u32 reg , unsigned int pin )
2020-01-10 16:19:23 +03:00
{
const char * drvname = info - > name ;
unsigned int i ;
if ( pin = = SH_PFC_PIN_NONE )
2021-12-23 17:56:22 +03:00
return NULL ;
2020-01-10 16:19:23 +03:00
for ( i = 0 ; i < info - > nr_pins ; i + + ) {
if ( pin = = info - > pins [ i ] . pin )
2021-12-23 17:56:22 +03:00
return & info - > pins [ i ] ;
2020-01-10 16:19:23 +03:00
}
sh_pfc_err ( " reg 0x%x: pin %u not found \n " , reg , pin ) ;
2021-12-23 17:56:22 +03:00
return NULL ;
2020-01-10 16:19:23 +03:00
}
2019-04-25 11:54:11 +03:00
static void __init sh_pfc_check_cfg_reg ( const char * drvname ,
const struct pinmux_cfg_reg * cfg_reg )
2018-12-13 17:48:45 +03:00
{
2022-04-13 20:24:12 +03:00
unsigned int i , n , rw , r ;
2022-04-13 20:23:24 +03:00
int fw ;
2018-12-13 17:48:45 +03:00
2021-10-07 17:38:48 +03:00
sh_pfc_check_reg ( drvname , cfg_reg - > reg ,
GENMASK ( cfg_reg - > reg_width - 1 , 0 ) ) ;
2020-01-10 16:19:18 +03:00
2018-12-13 17:48:45 +03:00
if ( cfg_reg - > field_width ) {
2022-02-21 19:21:58 +03:00
fw = cfg_reg - > field_width ;
n = ( cfg_reg - > reg_width / fw ) < < fw ;
2022-04-13 20:24:12 +03:00
for ( i = 0 , r = 0 ; i < n ; i + = 1 < < fw ) {
if ( is0s ( & cfg_reg - > enum_ids [ i ] , 1 < < fw ) )
r + + ;
}
if ( ( r < < fw ) * sizeof ( u16 ) > cfg_reg - > reg_width / fw )
sh_pfc_warn ( " reg 0x%x can be described with variable-width reserved fields \n " ,
cfg_reg - > reg ) ;
2020-01-10 16:19:19 +03:00
/* Skip field checks (done at build time) */
goto check_enum_ids ;
2018-12-13 17:48:45 +03:00
}
for ( i = 0 , n = 0 , rw = 0 ; ( fw = cfg_reg - > var_field_width [ i ] ) ; i + + ) {
2022-04-13 20:23:24 +03:00
if ( fw < 0 ) {
rw + = - fw ;
} else {
if ( is0s ( & cfg_reg - > enum_ids [ n ] , 1 < < fw ) )
sh_pfc_warn ( " reg 0x%x: field [%u:%u] can be described as reserved \n " ,
cfg_reg - > reg , rw , rw + fw - 1 ) ;
n + = 1 < < fw ;
rw + = fw ;
}
2018-12-13 17:48:45 +03:00
}
2020-01-10 16:19:16 +03:00
if ( rw ! = cfg_reg - > reg_width )
sh_pfc_err ( " reg 0x%x: var_field_width declares %u instead of %u bits \n " ,
cfg_reg - > reg , rw , cfg_reg - > reg_width ) ;
2018-12-13 17:48:45 +03:00
2020-01-10 16:19:16 +03:00
if ( n ! = cfg_reg - > nr_enum_ids )
sh_pfc_err ( " reg 0x%x: enum_ids[] has %u instead of %u values \n " ,
cfg_reg - > reg , cfg_reg - > nr_enum_ids , n ) ;
2020-01-10 16:19:19 +03:00
check_enum_ids :
sh_pfc_check_reg_enums ( drvname , cfg_reg - > reg , cfg_reg - > enum_ids , n ) ;
2018-12-13 17:48:45 +03:00
}
2020-01-10 16:19:23 +03:00
static void __init sh_pfc_check_drive_reg ( const struct sh_pfc_soc_info * info ,
const struct pinmux_drive_reg * drive )
{
2021-12-23 17:56:23 +03:00
const char * drvname = info - > name ;
const struct sh_pfc_pin * pin ;
2020-01-10 16:19:23 +03:00
unsigned int i ;
for ( i = 0 ; i < ARRAY_SIZE ( drive - > fields ) ; i + + ) {
const struct pinmux_drive_reg_field * field = & drive - > fields [ i ] ;
if ( ! field - > pin & & ! field - > offset & & ! field - > size )
continue ;
2021-10-07 17:38:48 +03:00
sh_pfc_check_reg ( info - > name , drive - > reg ,
GENMASK ( field - > offset + field - > size - 1 ,
field - > offset ) ) ;
2020-01-10 16:19:23 +03:00
2021-12-23 17:56:23 +03:00
pin = sh_pfc_find_pin ( info , drive - > reg , field - > pin ) ;
if ( pin & & ! ( pin - > configs & SH_PFC_PIN_CFG_DRIVE_STRENGTH ) )
sh_pfc_err ( " drive_reg 0x%x: field %u: pin %s lacks SH_PFC_PIN_CFG_DRIVE_STRENGTH flag \n " ,
drive - > reg , i , pin - > name ) ;
2020-01-10 16:19:23 +03:00
}
}
2020-01-10 16:19:24 +03:00
static void __init sh_pfc_check_bias_reg ( const struct sh_pfc_soc_info * info ,
const struct pinmux_bias_reg * bias )
{
2021-12-23 17:56:22 +03:00
const char * drvname = info - > name ;
const struct sh_pfc_pin * pin ;
2020-01-10 16:19:24 +03:00
unsigned int i ;
2021-10-07 17:38:48 +03:00
u32 bits ;
for ( i = 0 , bits = 0 ; i < ARRAY_SIZE ( bias - > pins ) ; i + + )
if ( bias - > pins [ i ] ! = SH_PFC_PIN_NONE )
bits | = BIT ( i ) ;
2020-01-10 16:19:24 +03:00
2021-10-07 17:38:49 +03:00
if ( bias - > puen )
sh_pfc_check_reg ( info - > name , bias - > puen , bits ) ;
2020-01-10 16:19:24 +03:00
if ( bias - > pud )
2021-10-07 17:38:48 +03:00
sh_pfc_check_reg ( info - > name , bias - > pud , bits ) ;
2021-12-23 17:56:22 +03:00
for ( i = 0 ; i < ARRAY_SIZE ( bias - > pins ) ; i + + ) {
pin = sh_pfc_find_pin ( info , bias - > puen , bias - > pins [ i ] ) ;
if ( ! pin )
continue ;
if ( bias - > puen & & bias - > pud ) {
/*
* Pull - enable and pull - up / down control registers
* As some SoCs have pins that support only pull - up
* or pull - down , we just check for one of them
*/
if ( ! ( pin - > configs & SH_PFC_PIN_CFG_PULL_UP_DOWN ) )
sh_pfc_err ( " bias_reg 0x%x:%u: pin %s lacks one or more SH_PFC_PIN_CFG_PULL_* flags \n " ,
bias - > puen , i , pin - > name ) ;
} else if ( bias - > puen ) {
/* Pull-up control register only */
if ( ! ( pin - > configs & SH_PFC_PIN_CFG_PULL_UP ) )
sh_pfc_err ( " bias_reg 0x%x:%u: pin %s lacks SH_PFC_PIN_CFG_PULL_UP flag \n " ,
bias - > puen , i , pin - > name ) ;
} else if ( bias - > pud ) {
/* Pull-down control register only */
if ( ! ( pin - > configs & SH_PFC_PIN_CFG_PULL_DOWN ) )
sh_pfc_err ( " bias_reg 0x%x:%u: pin %s lacks SH_PFC_PIN_CFG_PULL_DOWN flag \n " ,
bias - > pud , i , pin - > name ) ;
}
}
2020-01-10 16:19:24 +03:00
}
2021-12-23 17:56:21 +03:00
static void __init sh_pfc_compare_groups ( const char * drvname ,
const struct sh_pfc_pin_group * a ,
const struct sh_pfc_pin_group * b )
{
unsigned int i ;
size_t len ;
if ( same_name ( a - > name , b - > name ) )
sh_pfc_err ( " group %s: name conflict \n " , a - > name ) ;
if ( a - > nr_pins > b - > nr_pins )
swap ( a , b ) ;
len = a - > nr_pins * sizeof ( a - > pins [ 0 ] ) ;
for ( i = 0 ; i < = b - > nr_pins - a - > nr_pins ; i + + ) {
if ( a - > pins = = b - > pins + i | | a - > mux = = b - > mux + i | |
memcmp ( a - > pins , b - > pins + i , len ) | |
memcmp ( a - > mux , b - > mux + i , len ) )
continue ;
if ( a - > nr_pins = = b - > nr_pins )
sh_pfc_warn ( " group %s can be an alias for %s \n " ,
a - > name , b - > name ) ;
else
sh_pfc_warn ( " group %s is a subset of %s \n " , a - > name ,
b - > name ) ;
}
}
2019-04-25 11:54:11 +03:00
static void __init sh_pfc_check_info ( const struct sh_pfc_soc_info * info )
2018-12-13 17:48:45 +03:00
{
2021-12-23 17:56:23 +03:00
const struct pinmux_drive_reg * drive_regs = info - > drive_regs ;
2022-04-19 11:08:32 +03:00
# define drive_nfields ARRAY_SIZE(drive_regs->fields)
# define drive_ofs(i) drive_regs[(i) / drive_nfields]
# define drive_reg(i) drive_ofs(i).reg
# define drive_bit(i) ((i) % drive_nfields)
# define drive_field(i) drive_ofs(i).fields[drive_bit(i)]
2021-10-07 17:38:49 +03:00
const struct pinmux_bias_reg * bias_regs = info - > bias_regs ;
2022-04-19 11:08:32 +03:00
# define bias_npins ARRAY_SIZE(bias_regs->pins)
# define bias_ofs(i) bias_regs[(i) / bias_npins]
# define bias_puen(i) bias_ofs(i).puen
# define bias_pud(i) bias_ofs(i).pud
# define bias_bit(i) ((i) % bias_npins)
# define bias_pin(i) bias_ofs(i).pins[bias_bit(i)]
2018-12-13 17:48:45 +03:00
const char * drvname = info - > name ;
unsigned int * refcnts ;
unsigned int i , j , k ;
2021-10-07 17:38:50 +03:00
pr_info ( " sh_pfc: Checking %s \n " , drvname ) ;
2020-01-10 16:19:18 +03:00
sh_pfc_num_regs = 0 ;
2020-01-10 16:19:19 +03:00
sh_pfc_num_enums = 0 ;
2021-12-23 17:56:22 +03:00
sh_pfc_bias_done = false ;
2021-12-23 17:56:23 +03:00
sh_pfc_drive_done = false ;
2021-12-23 17:56:24 +03:00
sh_pfc_power_done = false ;
2018-12-13 17:48:45 +03:00
2019-03-27 13:41:36 +03:00
/* Check pins */
for ( i = 0 ; i < info - > nr_pins ; i + + ) {
2020-01-10 16:19:20 +03:00
const struct sh_pfc_pin * pin = & info - > pins [ i ] ;
2021-12-23 17:56:22 +03:00
unsigned int x ;
2020-01-10 16:19:20 +03:00
if ( ! pin - > name ) {
sh_pfc_err ( " empty pin %u \n " , i ) ;
continue ;
}
2019-03-27 13:41:36 +03:00
for ( j = 0 ; j < i ; j + + ) {
2020-01-10 16:19:20 +03:00
const struct sh_pfc_pin * pin2 = & info - > pins [ j ] ;
if ( same_name ( pin - > name , pin2 - > name ) )
sh_pfc_err ( " pin %s: name conflict \n " ,
pin - > name ) ;
2019-03-27 13:41:36 +03:00
2020-01-10 16:19:20 +03:00
if ( pin - > pin ! = ( u16 ) - 1 & & pin - > pin = = pin2 - > pin )
2020-01-10 16:19:16 +03:00
sh_pfc_err ( " pin %s/%s: pin %u conflict \n " ,
2020-01-10 16:19:20 +03:00
pin - > name , pin2 - > name , pin - > pin ) ;
2019-03-27 13:41:36 +03:00
2020-01-10 16:19:20 +03:00
if ( pin - > enum_id & & pin - > enum_id = = pin2 - > enum_id )
2020-01-10 16:19:16 +03:00
sh_pfc_err ( " pin %s/%s: enum_id %u conflict \n " ,
2020-01-10 16:19:20 +03:00
pin - > name , pin2 - > name ,
pin - > enum_id ) ;
2019-03-27 13:41:36 +03:00
}
2021-12-23 17:56:22 +03:00
if ( pin - > configs & SH_PFC_PIN_CFG_PULL_UP_DOWN ) {
if ( ! info - > ops | | ! info - > ops - > get_bias | |
! info - > ops - > set_bias )
sh_pfc_err_once ( bias , " SH_PFC_PIN_CFG_PULL_* flag set but .[gs]et_bias() not implemented \n " ) ;
if ( ! bias_regs & &
( ! info - > ops | | ! info - > ops - > pin_to_portcr ) )
sh_pfc_err_once ( bias , " SH_PFC_PIN_CFG_PULL_UP flag set but no bias_regs defined and .pin_to_portcr() not implemented \n " ) ;
}
if ( ( pin - > configs & SH_PFC_PIN_CFG_PULL_UP_DOWN ) & & bias_regs ) {
const struct pinmux_bias_reg * bias_reg =
rcar_pin_to_bias_reg ( info , pin - > pin , & x ) ;
if ( ! bias_reg | |
( ( pin - > configs & SH_PFC_PIN_CFG_PULL_UP ) & &
! bias_reg - > puen ) )
sh_pfc_err ( " pin %s: SH_PFC_PIN_CFG_PULL_UP flag set but pin not in bias_regs \n " ,
pin - > name ) ;
if ( ! bias_reg | |
( ( pin - > configs & SH_PFC_PIN_CFG_PULL_DOWN ) & &
! bias_reg - > pud ) )
sh_pfc_err ( " pin %s: SH_PFC_PIN_CFG_PULL_DOWN flag set but pin not in bias_regs \n " ,
pin - > name ) ;
}
2021-12-23 17:56:23 +03:00
if ( pin - > configs & SH_PFC_PIN_CFG_DRIVE_STRENGTH ) {
if ( ! drive_regs ) {
sh_pfc_err_once ( drive , " SH_PFC_PIN_CFG_DRIVE_STRENGTH flag set but drive_regs missing \n " ) ;
} else {
2022-04-19 11:08:32 +03:00
for ( j = 0 ; drive_reg ( j ) ; j + + ) {
if ( ! drive_field ( j ) . pin & &
! drive_field ( j ) . offset & &
! drive_field ( j ) . size )
2021-12-23 17:56:23 +03:00
continue ;
2022-04-19 11:08:32 +03:00
if ( drive_field ( j ) . pin = = pin - > pin )
2021-12-23 17:56:23 +03:00
break ;
}
2022-04-19 11:08:32 +03:00
if ( ! drive_reg ( j ) )
2021-12-23 17:56:23 +03:00
sh_pfc_err ( " pin %s: SH_PFC_PIN_CFG_DRIVE_STRENGTH flag set but not in drive_regs \n " ,
pin - > name ) ;
}
}
2021-12-23 17:56:24 +03:00
if ( pin - > configs & SH_PFC_PIN_CFG_IO_VOLTAGE ) {
if ( ! info - > ops | | ! info - > ops - > pin_to_pocctrl )
sh_pfc_err_once ( power , " SH_PFC_PIN_CFG_IO_VOLTAGE flag set but .pin_to_pocctrl() not implemented \n " ) ;
else if ( info - > ops - > pin_to_pocctrl ( pin - > pin , & x ) < 0 )
sh_pfc_err ( " pin %s: SH_PFC_PIN_CFG_IO_VOLTAGE set but invalid pin_to_pocctrl() \n " ,
pin - > name ) ;
} else if ( info - > ops & & info - > ops - > pin_to_pocctrl & &
info - > ops - > pin_to_pocctrl ( pin - > pin , & x ) > = 0 ) {
sh_pfc_warn ( " pin %s: SH_PFC_PIN_CFG_IO_VOLTAGE not set but valid pin_to_pocctrl() \n " ,
pin - > name ) ;
}
2019-03-27 13:41:36 +03:00
}
2018-12-13 17:48:45 +03:00
/* Check groups and functions */
refcnts = kcalloc ( info - > nr_groups , sizeof ( * refcnts ) , GFP_KERNEL ) ;
if ( ! refcnts )
return ;
for ( i = 0 ; i < info - > nr_functions ; i + + ) {
2020-01-10 16:19:21 +03:00
const struct sh_pfc_function * func = & info - > functions [ i ] ;
2019-04-25 11:33:55 +03:00
if ( ! func - > name ) {
2020-01-10 16:19:16 +03:00
sh_pfc_err ( " empty function %u \n " , i ) ;
2019-04-25 11:33:55 +03:00
continue ;
}
2020-01-10 16:19:21 +03:00
for ( j = 0 ; j < i ; j + + ) {
if ( same_name ( func - > name , info - > functions [ j ] . name ) )
sh_pfc_err ( " function %s: name conflict \n " ,
func - > name ) ;
}
2018-12-13 17:48:45 +03:00
for ( j = 0 ; j < func - > nr_groups ; j + + ) {
for ( k = 0 ; k < info - > nr_groups ; k + + ) {
2020-01-10 16:19:17 +03:00
if ( same_name ( func - > groups [ j ] ,
info - > groups [ k ] . name ) ) {
2018-12-13 17:48:45 +03:00
refcnts [ k ] + + ;
break ;
}
}
2020-01-10 16:19:16 +03:00
if ( k = = info - > nr_groups )
sh_pfc_err ( " function %s: group %s not found \n " ,
func - > name , func - > groups [ j ] ) ;
2018-12-13 17:48:45 +03:00
}
}
for ( i = 0 ; i < info - > nr_groups ; i + + ) {
2020-01-10 16:19:22 +03:00
const struct sh_pfc_pin_group * group = & info - > groups [ i ] ;
if ( ! group - > name ) {
2020-01-10 16:19:16 +03:00
sh_pfc_err ( " empty group %u \n " , i ) ;
2019-04-25 11:33:55 +03:00
continue ;
}
2021-12-23 17:56:21 +03:00
for ( j = 0 ; j < i ; j + + )
sh_pfc_compare_groups ( drvname , group , & info - > groups [ j ] ) ;
2020-01-10 16:19:16 +03:00
if ( ! refcnts [ i ] )
2020-01-10 16:19:22 +03:00
sh_pfc_err ( " orphan group %s \n " , group - > name ) ;
2020-01-10 16:19:16 +03:00
else if ( refcnts [ i ] > 1 )
sh_pfc_warn ( " group %s referenced by %u functions \n " ,
2020-01-10 16:19:22 +03:00
group - > name , refcnts [ i ] ) ;
2018-12-13 17:48:45 +03:00
}
kfree ( refcnts ) ;
/* Check config register descriptions */
for ( i = 0 ; info - > cfg_regs & & info - > cfg_regs [ i ] . reg ; i + + )
sh_pfc_check_cfg_reg ( drvname , & info - > cfg_regs [ i ] ) ;
2020-01-10 16:19:23 +03:00
/* Check drive strength registers */
2021-12-23 17:56:26 +03:00
for ( i = 0 ; drive_regs & & drive_regs [ i ] . reg ; i + + )
sh_pfc_check_drive_reg ( info , & drive_regs [ i ] ) ;
2022-04-19 11:08:32 +03:00
for ( i = 0 ; drive_regs & & drive_reg ( i ) ; i + + ) {
if ( ! drive_field ( i ) . pin & & ! drive_field ( i ) . offset & &
! drive_field ( i ) . size )
2021-12-23 17:56:26 +03:00
continue ;
for ( j = 0 ; j < i ; j + + ) {
2022-04-19 11:08:32 +03:00
if ( drive_field ( i ) . pin = = drive_field ( j ) . pin & &
drive_field ( j ) . offset & & drive_field ( j ) . size ) {
sh_pfc_err ( " drive_reg 0x%x:%zu/0x%x:%zu: pin conflict \n " ,
drive_reg ( i ) , drive_bit ( i ) ,
drive_reg ( j ) , drive_bit ( j ) ) ;
2021-12-23 17:56:26 +03:00
}
}
}
2020-01-10 16:19:24 +03:00
/* Check bias registers */
2021-10-07 17:38:49 +03:00
for ( i = 0 ; bias_regs & & ( bias_regs [ i ] . puen | | bias_regs [ i ] . pud ) ; i + + )
sh_pfc_check_bias_reg ( info , & bias_regs [ i ] ) ;
2020-01-10 16:19:25 +03:00
2022-04-19 11:08:32 +03:00
for ( i = 0 ; bias_regs & & ( bias_puen ( i ) | | bias_pud ( i ) ) ; i + + ) {
if ( bias_pin ( i ) = = SH_PFC_PIN_NONE )
2021-12-23 17:56:25 +03:00
continue ;
for ( j = 0 ; j < i ; j + + ) {
2022-04-19 11:08:32 +03:00
if ( bias_pin ( i ) ! = bias_pin ( j ) )
2021-12-23 17:56:25 +03:00
continue ;
2022-04-19 11:08:32 +03:00
if ( bias_puen ( i ) & & bias_puen ( j ) )
sh_pfc_err ( " bias_reg 0x%x:%zu/0x%x:%zu: pin conflict \n " ,
bias_puen ( i ) , bias_bit ( i ) ,
bias_puen ( j ) , bias_bit ( j ) ) ;
if ( bias_pud ( i ) & & bias_pud ( j ) )
sh_pfc_err ( " bias_reg 0x%x:%zu/0x%x:%zu: pin conflict \n " ,
bias_pud ( i ) , bias_bit ( i ) ,
bias_pud ( j ) , bias_bit ( j ) ) ;
2021-12-23 17:56:25 +03:00
}
}
2020-01-10 16:19:25 +03:00
/* Check ioctrl registers */
for ( i = 0 ; info - > ioctrl_regs & & info - > ioctrl_regs [ i ] . reg ; i + + )
2021-10-07 17:38:48 +03:00
sh_pfc_check_reg ( drvname , info - > ioctrl_regs [ i ] . reg , U32_MAX ) ;
2020-01-10 16:19:26 +03:00
/* Check data registers */
for ( i = 0 ; info - > data_regs & & info - > data_regs [ i ] . reg ; i + + ) {
2021-10-07 17:38:48 +03:00
sh_pfc_check_reg ( drvname , info - > data_regs [ i ] . reg ,
GENMASK ( info - > data_regs [ i ] . reg_width - 1 , 0 ) ) ;
2020-01-10 16:19:26 +03:00
sh_pfc_check_reg_enums ( drvname , info - > data_regs [ i ] . reg ,
info - > data_regs [ i ] . enum_ids ,
info - > data_regs [ i ] . reg_width ) ;
}
2020-01-10 16:19:27 +03:00
# ifdef CONFIG_PINCTRL_SH_FUNC_GPIO
/* Check function GPIOs */
for ( i = 0 ; i < info - > nr_func_gpios ; i + + ) {
const struct pinmux_func * func = & info - > func_gpios [ i ] ;
if ( ! func - > name ) {
sh_pfc_err ( " empty function gpio %u \n " , i ) ;
continue ;
}
for ( j = 0 ; j < i ; j + + ) {
if ( same_name ( func - > name , info - > func_gpios [ j ] . name ) )
sh_pfc_err ( " func_gpio %s: name conflict \n " ,
func - > name ) ;
}
if ( sh_pfc_check_enum ( drvname , func - > enum_id ) )
sh_pfc_err ( " %s enum_id %u conflict \n " , func - > name ,
func - > enum_id ) ;
}
# endif
2018-12-13 17:48:45 +03:00
}
2019-04-25 11:54:11 +03:00
static void __init sh_pfc_check_driver ( const struct platform_driver * pdrv )
2018-12-13 17:48:45 +03:00
{
unsigned int i ;
2021-01-11 19:50:13 +03:00
if ( ! IS_ENABLED ( CONFIG_SUPERH ) & &
! of_find_matching_node ( NULL , pdrv - > driver . of_match_table ) )
return ;
2020-01-10 16:19:18 +03:00
sh_pfc_regs = kcalloc ( SH_PFC_MAX_REGS , sizeof ( * sh_pfc_regs ) ,
GFP_KERNEL ) ;
if ( ! sh_pfc_regs )
return ;
2020-01-10 16:19:19 +03:00
sh_pfc_enums = kcalloc ( SH_PFC_MAX_ENUMS , sizeof ( * sh_pfc_enums ) ,
GFP_KERNEL ) ;
if ( ! sh_pfc_enums )
goto free_regs ;
2021-10-07 17:38:50 +03:00
pr_warn ( " sh_pfc: Checking builtin pinmux tables \n " ) ;
2018-12-13 17:48:45 +03:00
for ( i = 0 ; pdrv - > id_table [ i ] . name [ 0 ] ; i + + )
sh_pfc_check_info ( ( void * ) pdrv - > id_table [ i ] . driver_data ) ;
# ifdef CONFIG_OF
for ( i = 0 ; pdrv - > driver . of_match_table [ i ] . compatible [ 0 ] ; i + + )
sh_pfc_check_info ( pdrv - > driver . of_match_table [ i ] . data ) ;
# endif
2021-10-07 17:38:50 +03:00
pr_warn ( " sh_pfc: Detected %u errors and %u warnings \n " , sh_pfc_errors ,
2018-12-13 17:48:45 +03:00
sh_pfc_warnings ) ;
2020-01-10 16:19:18 +03:00
2020-01-10 16:19:19 +03:00
kfree ( sh_pfc_enums ) ;
free_regs :
2020-01-10 16:19:18 +03:00
kfree ( sh_pfc_regs ) ;
2018-12-13 17:48:45 +03:00
}
# else /* !DEBUG */
static inline void sh_pfc_check_driver ( struct platform_driver * pdrv ) { }
# endif /* !DEBUG */
pinctrl: sh-pfc: Split R-Car H3 support in two independent drivers
Despite using the same compatible values ("r8a7795"-based) because of
historical reasons, R-Car H3 ES1.x (R8A77950) and R-Car H3 ES2.0+
(R8A77951) are really different SoCs, with different part numbers, and
with different Pin Function Controller blocks.
Reflect this in the pinctrl configuration, by replacing the existing
CONFIG_PINCTRL_PFC_R8A7795 symbol by two new config symbols:
CONFIG_PINCTRL_PFC_R8A77950 and CONFIG_PINCTRL_PFC_R8A77951. The latter
are selected automatically, depending on the soon-to-be-introduced
corresponding SoC-specific config options, and on the current common
config option, to relax dependencies.
Rename the individual pin control driver source files from
pfc-r8a7795-es1.c to pfc-r8a77950.c, and from pfc-r8a7795.c to
pfc-r8a77951.c, and make them truly independent.
As both SoCs share the same compatible value, special care must be taken
to match them to the correct pin control driver, if support for it is
included in the running kernel.
This will allow making support for early R-Car H3 revisions optional,
the largest share of which is taken by the pin control driver.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Reviewed-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Tested-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Link: https://lore.kernel.org/r/20191230083156.19191-1-geert+renesas@glider.be
2019-12-30 11:31:56 +03:00
# ifdef CONFIG_OF
static const void * sh_pfc_quirk_match ( void )
{
2021-07-19 18:17:00 +03:00
# ifdef CONFIG_PINCTRL_PFC_R8A77950
pinctrl: sh-pfc: Split R-Car H3 support in two independent drivers
Despite using the same compatible values ("r8a7795"-based) because of
historical reasons, R-Car H3 ES1.x (R8A77950) and R-Car H3 ES2.0+
(R8A77951) are really different SoCs, with different part numbers, and
with different Pin Function Controller blocks.
Reflect this in the pinctrl configuration, by replacing the existing
CONFIG_PINCTRL_PFC_R8A7795 symbol by two new config symbols:
CONFIG_PINCTRL_PFC_R8A77950 and CONFIG_PINCTRL_PFC_R8A77951. The latter
are selected automatically, depending on the soon-to-be-introduced
corresponding SoC-specific config options, and on the current common
config option, to relax dependencies.
Rename the individual pin control driver source files from
pfc-r8a7795-es1.c to pfc-r8a77950.c, and from pfc-r8a7795.c to
pfc-r8a77951.c, and make them truly independent.
As both SoCs share the same compatible value, special care must be taken
to match them to the correct pin control driver, if support for it is
included in the running kernel.
This will allow making support for early R-Car H3 revisions optional,
the largest share of which is taken by the pin control driver.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Reviewed-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Tested-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Link: https://lore.kernel.org/r/20191230083156.19191-1-geert+renesas@glider.be
2019-12-30 11:31:56 +03:00
const struct soc_device_attribute * match ;
static const struct soc_device_attribute quirks [ ] = {
{
. soc_id = " r8a7795 " , . revision = " ES1.* " ,
. data = & r8a77950_pinmux_info ,
} ,
{ /* sentinel */ }
} ;
match = soc_device_match ( quirks ) ;
if ( match )
2021-07-19 18:17:00 +03:00
return match - > data ;
# endif /* CONFIG_PINCTRL_PFC_R8A77950 */
pinctrl: sh-pfc: Split R-Car H3 support in two independent drivers
Despite using the same compatible values ("r8a7795"-based) because of
historical reasons, R-Car H3 ES1.x (R8A77950) and R-Car H3 ES2.0+
(R8A77951) are really different SoCs, with different part numbers, and
with different Pin Function Controller blocks.
Reflect this in the pinctrl configuration, by replacing the existing
CONFIG_PINCTRL_PFC_R8A7795 symbol by two new config symbols:
CONFIG_PINCTRL_PFC_R8A77950 and CONFIG_PINCTRL_PFC_R8A77951. The latter
are selected automatically, depending on the soon-to-be-introduced
corresponding SoC-specific config options, and on the current common
config option, to relax dependencies.
Rename the individual pin control driver source files from
pfc-r8a7795-es1.c to pfc-r8a77950.c, and from pfc-r8a7795.c to
pfc-r8a77951.c, and make them truly independent.
As both SoCs share the same compatible value, special care must be taken
to match them to the correct pin control driver, if support for it is
included in the running kernel.
This will allow making support for early R-Car H3 revisions optional,
the largest share of which is taken by the pin control driver.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Reviewed-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Tested-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Link: https://lore.kernel.org/r/20191230083156.19191-1-geert+renesas@glider.be
2019-12-30 11:31:56 +03:00
return NULL ;
}
# endif /* CONFIG_OF */
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-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
pinctrl: sh-pfc: Split R-Car H3 support in two independent drivers
Despite using the same compatible values ("r8a7795"-based) because of
historical reasons, R-Car H3 ES1.x (R8A77950) and R-Car H3 ES2.0+
(R8A77951) are really different SoCs, with different part numbers, and
with different Pin Function Controller blocks.
Reflect this in the pinctrl configuration, by replacing the existing
CONFIG_PINCTRL_PFC_R8A7795 symbol by two new config symbols:
CONFIG_PINCTRL_PFC_R8A77950 and CONFIG_PINCTRL_PFC_R8A77951. The latter
are selected automatically, depending on the soon-to-be-introduced
corresponding SoC-specific config options, and on the current common
config option, to relax dependencies.
Rename the individual pin control driver source files from
pfc-r8a7795-es1.c to pfc-r8a77950.c, and from pfc-r8a7795.c to
pfc-r8a77951.c, and make them truly independent.
As both SoCs share the same compatible value, special care must be taken
to match them to the correct pin control driver, if support for it is
included in the running kernel.
This will allow making support for early R-Car H3 revisions optional,
the largest share of which is taken by the pin control driver.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Reviewed-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Tested-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Link: https://lore.kernel.org/r/20191230083156.19191-1-geert+renesas@glider.be
2019-12-30 11:31:56 +03:00
if ( pdev - > dev . of_node ) {
info = sh_pfc_quirk_match ( ) ;
if ( ! info )
info = of_device_get_match_data ( & pdev - > dev ) ;
} else
2013-06-17 22:50:02 +04:00
# endif
2017-09-29 11:08:56 +03:00
info = ( const void * ) platform_get_device_id ( pdev ) - > driver_data ;
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 ;
2017-03-09 21:20:48 +03:00
/* .init() may have overridden pfc->info */
info = pfc - > info ;
2013-04-21 22:21:57 +04:00
}
pinctrl: sh-pfc: Save/restore registers for PSCI system suspend
During PSCI system suspend, R-Car Gen3 SoCs are powered down, and their
pinctrl register state is lost. Note that as the boot loader skips most
initialization after system resume, pinctrl register state differs from
the state encountered during normal system boot, too.
To fix this, save all GPIO and peripheral function select, module
select, drive strength control, bias, and other I/O control registers
during system suspend, and restore them during system resume.
Note that to avoid overhead on platforms not needing it, the
suspend/resume code has a build time dependency on sleep and PSCI
support, and a runtime dependency on PSCI.
Inspired by a patch in the BSP by Hien Dang.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
2017-09-29 15:17:18 +03:00
ret = sh_pfc_suspend_init ( pfc ) ;
if ( ret )
return ret ;
2016-03-07 21:40:57 +03:00
/* Enable dummy states for those platforms without pinctrl support */
if ( ! of_have_populated_dt ( ) )
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 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
{ } ,
} ;
static struct platform_driver sh_pfc_driver = {
. probe = sh_pfc_probe ,
. 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 ) ,
pinctrl: sh-pfc: Save/restore registers for PSCI system suspend
During PSCI system suspend, R-Car Gen3 SoCs are powered down, and their
pinctrl register state is lost. Note that as the boot loader skips most
initialization after system resume, pinctrl register state differs from
the state encountered during normal system boot, too.
To fix this, save all GPIO and peripheral function select, module
select, drive strength control, bias, and other I/O control registers
during system suspend, and restore them during system resume.
Note that to avoid overhead on platforms not needing it, the
suspend/resume code has a build time dependency on sleep and PSCI
support, and a runtime dependency on PSCI.
Inspired by a patch in the BSP by Hien Dang.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
2017-09-29 15:17:18 +03:00
. pm = DEV_PM_OPS ,
2012-12-16 02:50:47 +04:00
} ,
} ;
2012-12-16 02:50:54 +04:00
static int __init sh_pfc_init ( void )
{
2018-12-13 17:48:45 +03:00
sh_pfc_check_driver ( & sh_pfc_driver ) ;
2012-12-16 02:50:54 +04:00
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 ) ;