pinctrl: aspeed: Add multiple pin group support for functions

The AST2400 and AST2500 SoCs only exposed one pin group per function.
Lone pin groups drove some implementation simplifications in the ASPEED
pinmux infrastructure that is now invalid for the AST2600, which
supports multiple groups per function for some functions on the chip
(SMBus Alert pins and UARTs among others).

This patch reworks the macro jungle to enable support for multiple pin
groups. In the process we inflict some collateral damage on the existing
AST2400 and AST2500 drivers, but the rework is mostly a relatively
straight-forward, automated transform of adding the pin name as an
argument to some macro calls and implementing wrappers to paper over
groups in the cases where there aren't multiple.

As previously documented, the macro infrastructure exposes mux
configuration as symbols in the source file which are used to detect
accidental duplication. Previously these symbols were named in terms of
the signal for a given expression. As the AST2600 supports multiple pin
groups for a function, the signal name on its own is no-longer unique,
and we must switch to the (signal, group) tuple. However, this means
that we can no-longer derive the signal expression symbol name from the
signal name alone, which among other cases, impacts the operation of the
PIN_DECL_x() macros.

To fix that and avoid requiring we awkwardly provide the associated
group name for every signal for every PIN_DECL_x() invocation, instead
opportunistically alias the name of the signal expression symbol from
the unique (signal, group) tuple to the also unique (pin, signal) tuple,
then reference the alias symbol in the tables generated by PIN_DECL_x().
This way we do not require extra group parameters for PIN_DECL_x() as
the pin name was already provided as an argument, and instead simply
require that the pin name be provided to the expression declaration
macros in order to generate the alias symbol.

The patch implements the alias strategy and fixes up all the expression
definition macro calls in the AST2400 and AST2500 drivers to account for
pin groups. Given the implementation strategy has the property that
compilation either fails or loudly warns for bad pin descriptions, this
patch is theoretically tested by successfully compiling both affected
drivers. For a more practical test I've inspected the diff of the
content of the pinctrl debugfs entries before and after the patch under
qemu; all pins, functions and groups match.

Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
Link: https://lore.kernel.org/r/20190729055604.13239-5-andrew@aj.id.au
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
This commit is contained in:
Andrew Jeffery 2019-07-29 15:26:02 +09:30 committed by Linus Walleij
parent 27d1f73670
commit e7a96b0b7d
3 changed files with 1789 additions and 1489 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -162,10 +162,11 @@
* * Enabling lower priority signals requires higher priority signals be
* disabled
*
* * A function represents a set of signals; functions are distinct if their
* sets of signals are not equal
* * A function represents a set of signals; functions are distinct if they
* do not share a subset of signals (and may be distinct if they are a
* strict subset).
*
* * Signals participate in one or more functions
* * Signals participate in one or more functions or groups
*
* * A function is described by an expression of one or more signal
* descriptors, which compare bit values in a register
@ -508,19 +509,19 @@ struct aspeed_pin_desc {
*/
#define SIG_DESC_SET(reg, idx) SIG_DESC_IP_BIT(ASPEED_IP_SCU, reg, idx, 1)
#define SIG_DESC_LIST_SYM(sig, func) sig_descs_ ## sig ## _ ## func
#define SIG_DESC_LIST_DECL(sig, func, ...) \
static const struct aspeed_sig_desc SIG_DESC_LIST_SYM(sig, func)[] = \
#define SIG_DESC_LIST_SYM(sig, group) sig_descs_ ## sig ## _ ## group
#define SIG_DESC_LIST_DECL(sig, group, ...) \
static const struct aspeed_sig_desc SIG_DESC_LIST_SYM(sig, group)[] = \
{ __VA_ARGS__ }
#define SIG_EXPR_SYM(sig, func) sig_expr_ ## sig ## _ ## func
#define SIG_EXPR_DECL_(sig, func) \
static const struct aspeed_sig_expr SIG_EXPR_SYM(sig, func) = \
#define SIG_EXPR_SYM(sig, group) sig_expr_ ## sig ## _ ## group
#define SIG_EXPR_DECL_(sig, group, func) \
static const struct aspeed_sig_expr SIG_EXPR_SYM(sig, group) = \
{ \
.signal = #sig, \
.function = #func, \
.ndescs = ARRAY_SIZE(SIG_DESC_LIST_SYM(sig, func)), \
.descs = &(SIG_DESC_LIST_SYM(sig, func))[0], \
.ndescs = ARRAY_SIZE(SIG_DESC_LIST_SYM(sig, group)), \
.descs = &(SIG_DESC_LIST_SYM(sig, group))[0], \
}
/**
@ -533,16 +534,16 @@ struct aspeed_pin_desc {
*
* For example, the following declares the ROMD8 signal for the ROM16 function:
*
* SIG_EXPR_DECL(ROMD8, ROM16, SIG_DESC_SET(SCU90, 6));
* SIG_EXPR_DECL(ROMD8, ROM16, ROM16, SIG_DESC_SET(SCU90, 6));
*
* And with multiple signal descriptors:
*
* SIG_EXPR_DECL(ROMD8, ROM16S, SIG_DESC_SET(HW_STRAP1, 4),
* SIG_EXPR_DECL(ROMD8, ROM16S, ROM16S, SIG_DESC_SET(HW_STRAP1, 4),
* { HW_STRAP1, GENMASK(1, 0), 0, 0 });
*/
#define SIG_EXPR_DECL(sig, func, ...) \
SIG_DESC_LIST_DECL(sig, func, __VA_ARGS__); \
SIG_EXPR_DECL_(sig, func)
#define SIG_EXPR_DECL(sig, group, func, ...) \
SIG_DESC_LIST_DECL(sig, group, __VA_ARGS__); \
SIG_EXPR_DECL_(sig, group, func)
/**
* Declare a pointer to a signal expression
@ -550,9 +551,9 @@ struct aspeed_pin_desc {
* @sig: The macro symbol name for the signal (subjected to token pasting)
* @func: The macro symbol name for the function (subjected to token pasting)
*/
#define SIG_EXPR_PTR(sig, func) (&SIG_EXPR_SYM(sig, func))
#define SIG_EXPR_PTR(sig, group) (&SIG_EXPR_SYM(sig, group))
#define SIG_EXPR_LIST_SYM(sig) sig_exprs_ ## sig
#define SIG_EXPR_LIST_SYM(sig, group) sig_exprs_ ## sig ## _ ## group
/**
* Declare a signal expression list for reference in a struct aspeed_pin_prio.
@ -563,36 +564,89 @@ struct aspeed_pin_desc {
* For example, the 16-bit ROM bus can be enabled by one of two possible signal
* expressions:
*
* SIG_EXPR_DECL(ROMD8, ROM16, SIG_DESC_SET(SCU90, 6));
* SIG_EXPR_DECL(ROMD8, ROM16S, SIG_DESC_SET(HW_STRAP1, 4),
* SIG_EXPR_DECL(ROMD8, ROM16, ROM16, SIG_DESC_SET(SCU90, 6));
* SIG_EXPR_DECL(ROMD8, ROM16S, ROM16S, SIG_DESC_SET(HW_STRAP1, 4),
* { HW_STRAP1, GENMASK(1, 0), 0, 0 });
* SIG_EXPR_LIST_DECL(ROMD8, SIG_EXPR_PTR(ROMD8, ROM16),
* SIG_EXPR_PTR(ROMD8, ROM16S));
*/
#define SIG_EXPR_LIST_DECL(sig, ...) \
static const struct aspeed_sig_expr *SIG_EXPR_LIST_SYM(sig)[] = \
#define SIG_EXPR_LIST_DECL(sig, group, ...) \
static const struct aspeed_sig_expr *SIG_EXPR_LIST_SYM(sig, group)[] =\
{ __VA_ARGS__, NULL }
#define stringify(x) #x
#define istringify(x) stringify(x)
/**
* Create an expression symbol alias from (signal, group) to (pin, signal).
*
* @pin: The pin number
* @sig: The signal name
* @group: The name of the group of which the pin is a member that is
* associated with the function's signal
*
* Using an alias in this way enables detection of copy/paste errors (defining
* the signal for a group multiple times) whilst enabling multiple pin groups
* to exist for a signal without intrusive side-effects on defining the list of
* signals available on a pin.
*/
#define SIG_EXPR_LIST_ALIAS(pin, sig, group) \
static const struct aspeed_sig_expr *\
SIG_EXPR_LIST_SYM(pin, sig)[ARRAY_SIZE(SIG_EXPR_LIST_SYM(sig, group))] \
__attribute__((alias(istringify(SIG_EXPR_LIST_SYM(sig, group)))))
/**
* A short-hand macro for declaring a function expression and an expression
* list with a single function.
* list with a single expression (SE) and a single group (SG) of pins.
*
* @func: A macro symbol name for the function (is subjected to token pasting)
* @pin: The pin the signal will be routed to
* @sig: The signal that will be routed to the pin for the function
* @func: A macro symbol name for the function
* @...: Function descriptors that define the function expression
*
* For example, signal NCTS6 participates in its own function with one group:
*
* SIG_EXPR_LIST_DECL_SINGLE(NCTS6, NCTS6, SIG_DESC_SET(SCU90, 7));
* SIG_EXPR_LIST_DECL_SINGLE(A18, NCTS6, NCTS6, SIG_DESC_SET(SCU90, 7));
*/
#define SIG_EXPR_LIST_DECL_SINGLE(sig, func, ...) \
#define SIG_EXPR_LIST_DECL_SESG(pin, sig, func, ...) \
SIG_DESC_LIST_DECL(sig, func, __VA_ARGS__); \
SIG_EXPR_DECL_(sig, func); \
SIG_EXPR_LIST_DECL(sig, SIG_EXPR_PTR(sig, func))
SIG_EXPR_DECL_(sig, func, func); \
SIG_EXPR_LIST_DECL(sig, func, SIG_EXPR_PTR(sig, func)); \
SIG_EXPR_LIST_ALIAS(pin, sig, func)
#define SIG_EXPR_LIST_DECL_DUAL(sig, f0, f1) \
SIG_EXPR_LIST_DECL(sig, SIG_EXPR_PTR(sig, f0), SIG_EXPR_PTR(sig, f1))
/**
* Similar to the above, but for pins with a single expression (SE) and
* multiple groups (MG) of pins.
*
* @pin: The pin the signal will be routed to
* @sig: The signal that will be routed to the pin for the function
* @group: The name of the function's pin group in which the pin participates
* @func: A macro symbol name for the function
* @...: Function descriptors that define the function expression
*/
#define SIG_EXPR_LIST_DECL_SEMG(pin, sig, group, func, ...) \
SIG_DESC_LIST_DECL(sig, group, __VA_ARGS__); \
SIG_EXPR_DECL_(sig, group, func); \
SIG_EXPR_LIST_DECL(sig, group, SIG_EXPR_PTR(sig, group)); \
SIG_EXPR_LIST_ALIAS(pin, sig, group)
#define SIG_EXPR_LIST_PTR(sig) (&SIG_EXPR_LIST_SYM(sig)[0])
/**
* Similar to the above, but for pins with a dual expressions (DE) and
* and a single group (SG) of pins.
*
* @pin: The pin the signal will be routed to
* @sig: The signal that will be routed to the pin for the function
* @group: The name of the function's pin group in which the pin participates
* @func: A macro symbol name for the function
* @...: Function descriptors that define the function expression
*/
#define SIG_EXPR_LIST_DECL_DESG(pin, sig, f0, f1) \
SIG_EXPR_LIST_DECL(sig, f0, \
SIG_EXPR_PTR(sig, f0), \
SIG_EXPR_PTR(sig, f1)); \
SIG_EXPR_LIST_ALIAS(pin, sig, f0)
#define SIG_EXPR_LIST_PTR(sig, group) SIG_EXPR_LIST_SYM(sig, group)
#define PIN_EXPRS_SYM(pin) pin_exprs_ ## pin
#define PIN_EXPRS_PTR(pin) (&PIN_EXPRS_SYM(pin)[0])
@ -618,8 +672,9 @@ struct aspeed_pin_desc {
* PIN_DECL_1(E3, GPIOK0, SCL5);
*/
#define PIN_DECL_1(pin, other, sig) \
SIG_EXPR_LIST_DECL_SINGLE(other, other); \
PIN_DECL_(pin, SIG_EXPR_LIST_PTR(sig), SIG_EXPR_LIST_PTR(other))
SIG_EXPR_LIST_DECL_SESG(pin, other, other); \
PIN_DECL_(pin, SIG_EXPR_LIST_PTR(pin, sig), \
SIG_EXPR_LIST_PTR(pin, other))
/**
* Single signal, single function pin declaration
@ -634,9 +689,10 @@ struct aspeed_pin_desc {
* SSSF_PIN_DECL(A4, GPIOA2, TIMER3, SIG_DESC_SET(SCU80, 2));
*/
#define SSSF_PIN_DECL(pin, other, sig, ...) \
SIG_EXPR_LIST_DECL_SINGLE(sig, sig, __VA_ARGS__); \
SIG_EXPR_LIST_DECL_SINGLE(other, other); \
PIN_DECL_(pin, SIG_EXPR_LIST_PTR(sig), SIG_EXPR_LIST_PTR(other)); \
SIG_EXPR_LIST_DECL_SESG(pin, sig, sig, __VA_ARGS__); \
SIG_EXPR_LIST_DECL_SESG(pin, other, other); \
PIN_DECL_(pin, SIG_EXPR_LIST_PTR(pin, sig), \
SIG_EXPR_LIST_PTR(pin, other)); \
FUNC_GROUP_DECL(sig, pin)
/**
* Declare a two-signal pin
@ -658,30 +714,38 @@ struct aspeed_pin_desc {
* PIN_DECL_2(A8, GPIOH0, ROMD8, NCTS6);
*/
#define PIN_DECL_2(pin, other, high, low) \
SIG_EXPR_LIST_DECL_SINGLE(other, other); \
SIG_EXPR_LIST_DECL_SESG(pin, other, other); \
PIN_DECL_(pin, \
SIG_EXPR_LIST_PTR(high), \
SIG_EXPR_LIST_PTR(low), \
SIG_EXPR_LIST_PTR(other))
SIG_EXPR_LIST_PTR(pin, high), \
SIG_EXPR_LIST_PTR(pin, low), \
SIG_EXPR_LIST_PTR(pin, other))
#define PIN_DECL_3(pin, other, high, medium, low) \
SIG_EXPR_LIST_DECL_SINGLE(other, other); \
SIG_EXPR_LIST_DECL_SESG(pin, other, other); \
PIN_DECL_(pin, \
SIG_EXPR_LIST_PTR(high), \
SIG_EXPR_LIST_PTR(medium), \
SIG_EXPR_LIST_PTR(low), \
SIG_EXPR_LIST_PTR(other))
SIG_EXPR_LIST_PTR(pin, high), \
SIG_EXPR_LIST_PTR(pin, medium), \
SIG_EXPR_LIST_PTR(pin, low), \
SIG_EXPR_LIST_PTR(pin, other))
#define GROUP_SYM(group) group_pins_ ## group
#define GROUP_DECL(group, ...) \
static const int GROUP_SYM(group)[] = { __VA_ARGS__ }
#define FUNC_SYM(func) func_groups_ ## func
#define FUNC_DECL_(func, ...) \
static const char *FUNC_SYM(func)[] = { __VA_ARGS__ }
#define FUNC_DECL_2(func, one, two) FUNC_DECL_(func, #one, #two)
#define PIN_GROUP_SYM(func) pins_ ## func
#define FUNC_GROUP_SYM(func) groups_ ## func
#define FUNC_GROUP_DECL(func, ...) \
static const int PIN_GROUP_SYM(func)[] = { __VA_ARGS__ }; \
static const char *FUNC_GROUP_SYM(func)[] = { #func }
GROUP_DECL(func, __VA_ARGS__); \
FUNC_DECL_(func, #func)
#define GPIO_PIN_DECL(pin, gpio) \
SIG_EXPR_LIST_DECL_SINGLE(gpio, gpio); \
PIN_DECL_(pin, SIG_EXPR_LIST_PTR(gpio))
SIG_EXPR_LIST_DECL_SESG(pin, gpio, gpio); \
PIN_DECL_(pin, SIG_EXPR_LIST_PTR(pin, gpio))
struct aspeed_pin_group {
const char *name;
@ -691,8 +755,8 @@ struct aspeed_pin_group {
#define ASPEED_PINCTRL_GROUP(name_) { \
.name = #name_, \
.pins = &(PIN_GROUP_SYM(name_))[0], \
.npins = ARRAY_SIZE(PIN_GROUP_SYM(name_)), \
.pins = &(GROUP_SYM(name_))[0], \
.npins = ARRAY_SIZE(GROUP_SYM(name_)), \
}
struct aspeed_pin_function {
@ -703,8 +767,8 @@ struct aspeed_pin_function {
#define ASPEED_PINCTRL_FUNC(name_, ...) { \
.name = #name_, \
.groups = &FUNC_GROUP_SYM(name_)[0], \
.ngroups = ARRAY_SIZE(FUNC_GROUP_SYM(name_)), \
.groups = &FUNC_SYM(name_)[0], \
.ngroups = ARRAY_SIZE(FUNC_SYM(name_)), \
}
struct aspeed_pinmux_data;