1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0-or-later */
2*4882a593Smuzhiyun /* Copyright (C) 2019 IBM Corp. */
3*4882a593Smuzhiyun
4*4882a593Smuzhiyun #ifndef ASPEED_PINMUX_H
5*4882a593Smuzhiyun #define ASPEED_PINMUX_H
6*4882a593Smuzhiyun
7*4882a593Smuzhiyun #include <linux/regmap.h>
8*4882a593Smuzhiyun #include <stdbool.h>
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun /*
11*4882a593Smuzhiyun * The ASPEED SoCs provide typically more than 200 pins for GPIO and other
12*4882a593Smuzhiyun * functions. The SoC function enabled on a pin is determined on a priority
13*4882a593Smuzhiyun * basis where a given pin can provide a number of different signal types.
14*4882a593Smuzhiyun *
15*4882a593Smuzhiyun * The signal active on a pin is described by both a priority level and
16*4882a593Smuzhiyun * compound logical expressions involving multiple operators, registers and
17*4882a593Smuzhiyun * bits. Some difficulty arises as the pin's function bit masks for each
18*4882a593Smuzhiyun * priority level are frequently not the same (i.e. cannot just flip a bit to
19*4882a593Smuzhiyun * change from a high to low priority signal), or even in the same register.
20*4882a593Smuzhiyun * Further, not all signals can be unmuxed, as some expressions depend on
21*4882a593Smuzhiyun * values in the hardware strapping register (which may be treated as
22*4882a593Smuzhiyun * read-only).
23*4882a593Smuzhiyun *
24*4882a593Smuzhiyun * SoC Multi-function Pin Expression Examples
25*4882a593Smuzhiyun * ------------------------------------------
26*4882a593Smuzhiyun *
27*4882a593Smuzhiyun * Here are some sample mux configurations from the AST2400 and AST2500
28*4882a593Smuzhiyun * datasheets to illustrate the corner cases, roughly in order of least to most
29*4882a593Smuzhiyun * corner. The signal priorities are in decending order from P0 (highest).
30*4882a593Smuzhiyun *
31*4882a593Smuzhiyun * D6 is a pin with a single function (beside GPIO); a high priority signal
32*4882a593Smuzhiyun * that participates in one function:
33*4882a593Smuzhiyun *
34*4882a593Smuzhiyun * Ball | Default | P0 Signal | P0 Expression | P1 Signal | P1 Expression | Other
35*4882a593Smuzhiyun * -----+---------+-----------+-----------------------------+-----------+---------------+----------
36*4882a593Smuzhiyun * D6 GPIOA0 MAC1LINK SCU80[0]=1 GPIOA0
37*4882a593Smuzhiyun * -----+---------+-----------+-----------------------------+-----------+---------------+----------
38*4882a593Smuzhiyun *
39*4882a593Smuzhiyun * C5 is a multi-signal pin (high and low priority signals). Here we touch
40*4882a593Smuzhiyun * different registers for the different functions that enable each signal:
41*4882a593Smuzhiyun *
42*4882a593Smuzhiyun * -----+---------+-----------+-----------------------------+-----------+---------------+----------
43*4882a593Smuzhiyun * C5 GPIOA4 SCL9 SCU90[22]=1 TIMER5 SCU80[4]=1 GPIOA4
44*4882a593Smuzhiyun * -----+---------+-----------+-----------------------------+-----------+---------------+----------
45*4882a593Smuzhiyun *
46*4882a593Smuzhiyun * E19 is a single-signal pin with two functions that influence the active
47*4882a593Smuzhiyun * signal. In this case both bits have the same meaning - enable a dedicated
48*4882a593Smuzhiyun * LPC reset pin. However it's not always the case that the bits in the
49*4882a593Smuzhiyun * OR-relationship have the same meaning.
50*4882a593Smuzhiyun *
51*4882a593Smuzhiyun * -----+---------+-----------+-----------------------------+-----------+---------------+----------
52*4882a593Smuzhiyun * E19 GPIOB4 LPCRST# SCU80[12]=1 | Strap[14]=1 GPIOB4
53*4882a593Smuzhiyun * -----+---------+-----------+-----------------------------+-----------+---------------+----------
54*4882a593Smuzhiyun *
55*4882a593Smuzhiyun * For example, pin B19 has a low-priority signal that's enabled by two
56*4882a593Smuzhiyun * distinct SoC functions: A specific SIOPBI bit in register SCUA4, and an ACPI
57*4882a593Smuzhiyun * bit in the STRAP register. The ACPI bit configures signals on pins in
58*4882a593Smuzhiyun * addition to B19. Both of the low priority functions as well as the high
59*4882a593Smuzhiyun * priority function must be disabled for GPIOF1 to be used.
60*4882a593Smuzhiyun *
61*4882a593Smuzhiyun * Ball | Default | P0 Signal | P0 Expression | P1 Signal | P1 Expression | Other
62*4882a593Smuzhiyun * -----+---------+-----------+-----------------------------------------+-----------+----------------------------------------+----------
63*4882a593Smuzhiyun * B19 GPIOF1 NDCD4 SCU80[25]=1 SIOPBI# SCUA4[12]=1 | Strap[19]=0 GPIOF1
64*4882a593Smuzhiyun * -----+---------+-----------+-----------------------------------------+-----------+----------------------------------------+----------
65*4882a593Smuzhiyun *
66*4882a593Smuzhiyun * For pin E18, the SoC ANDs the expected state of three bits to determine the
67*4882a593Smuzhiyun * pin's active signal:
68*4882a593Smuzhiyun *
69*4882a593Smuzhiyun * * SCU3C[3]: Enable external SOC reset function
70*4882a593Smuzhiyun * * SCU80[15]: Enable SPICS1# or EXTRST# function pin
71*4882a593Smuzhiyun * * SCU90[31]: Select SPI interface CS# output
72*4882a593Smuzhiyun *
73*4882a593Smuzhiyun * -----+---------+-----------+-----------------------------------------+-----------+----------------------------------------+----------
74*4882a593Smuzhiyun * E18 GPIOB7 EXTRST# SCU3C[3]=1 & SCU80[15]=1 & SCU90[31]=0 SPICS1# SCU3C[3]=1 & SCU80[15]=1 & SCU90[31]=1 GPIOB7
75*4882a593Smuzhiyun * -----+---------+-----------+-----------------------------------------+-----------+----------------------------------------+----------
76*4882a593Smuzhiyun *
77*4882a593Smuzhiyun * (Bits SCU3C[3] and SCU80[15] appear to only be used in the expressions for
78*4882a593Smuzhiyun * selecting the signals on pin E18)
79*4882a593Smuzhiyun *
80*4882a593Smuzhiyun * Pin T5 is a multi-signal pin with a more complex configuration:
81*4882a593Smuzhiyun *
82*4882a593Smuzhiyun * Ball | Default | P0 Signal | P0 Expression | P1 Signal | P1 Expression | Other
83*4882a593Smuzhiyun * -----+---------+-----------+------------------------------+-----------+---------------+----------
84*4882a593Smuzhiyun * T5 GPIOL1 VPIDE SCU90[5:4]!=0 & SCU84[17]=1 NDCD1 SCU84[17]=1 GPIOL1
85*4882a593Smuzhiyun * -----+---------+-----------+------------------------------+-----------+---------------+----------
86*4882a593Smuzhiyun *
87*4882a593Smuzhiyun * The high priority signal configuration is best thought of in terms of its
88*4882a593Smuzhiyun * exploded form, with reference to the SCU90[5:4] bits:
89*4882a593Smuzhiyun *
90*4882a593Smuzhiyun * * SCU90[5:4]=00: disable
91*4882a593Smuzhiyun * * SCU90[5:4]=01: 18 bits (R6/G6/B6) video mode.
92*4882a593Smuzhiyun * * SCU90[5:4]=10: 24 bits (R8/G8/B8) video mode.
93*4882a593Smuzhiyun * * SCU90[5:4]=11: 30 bits (R10/G10/B10) video mode.
94*4882a593Smuzhiyun *
95*4882a593Smuzhiyun * Re-writing:
96*4882a593Smuzhiyun *
97*4882a593Smuzhiyun * -----+---------+-----------+------------------------------+-----------+---------------+----------
98*4882a593Smuzhiyun * T5 GPIOL1 VPIDE (SCU90[5:4]=1 & SCU84[17]=1) NDCD1 SCU84[17]=1 GPIOL1
99*4882a593Smuzhiyun * | (SCU90[5:4]=2 & SCU84[17]=1)
100*4882a593Smuzhiyun * | (SCU90[5:4]=3 & SCU84[17]=1)
101*4882a593Smuzhiyun * -----+---------+-----------+------------------------------+-----------+---------------+----------
102*4882a593Smuzhiyun *
103*4882a593Smuzhiyun * For reference the SCU84[17] bit configure the "UART1 NDCD1 or Video VPIDE
104*4882a593Smuzhiyun * function pin", where the signal itself is determined by whether SCU94[5:4]
105*4882a593Smuzhiyun * is disabled or in one of the 18, 24 or 30bit video modes.
106*4882a593Smuzhiyun *
107*4882a593Smuzhiyun * Other video-input-related pins require an explicit state in SCU90[5:4], e.g.
108*4882a593Smuzhiyun * W1 and U5:
109*4882a593Smuzhiyun *
110*4882a593Smuzhiyun * -----+---------+-----------+------------------------------+-----------+---------------+----------
111*4882a593Smuzhiyun * W1 GPIOL6 VPIB0 SCU90[5:4]=3 & SCU84[22]=1 TXD1 SCU84[22]=1 GPIOL6
112*4882a593Smuzhiyun * U5 GPIOL7 VPIB1 SCU90[5:4]=3 & SCU84[23]=1 RXD1 SCU84[23]=1 GPIOL7
113*4882a593Smuzhiyun * -----+---------+-----------+------------------------------+-----------+---------------+----------
114*4882a593Smuzhiyun *
115*4882a593Smuzhiyun * The examples of T5 and W1 are particularly fertile, as they also demonstrate
116*4882a593Smuzhiyun * that despite operating as part of the video input bus each signal needs to
117*4882a593Smuzhiyun * be enabled individually via it's own SCU84 (in the cases of T5 and W1)
118*4882a593Smuzhiyun * register bit. This is a little crazy if the bus doesn't have optional
119*4882a593Smuzhiyun * signals, but is used to decent effect with some of the UARTs where not all
120*4882a593Smuzhiyun * signals are required. However, this isn't done consistently - UART1 is
121*4882a593Smuzhiyun * enabled on a per-pin basis, and by contrast, all signals for UART6 are
122*4882a593Smuzhiyun * enabled by a single bit.
123*4882a593Smuzhiyun *
124*4882a593Smuzhiyun * Further, the high and low priority signals listed in the table above share
125*4882a593Smuzhiyun * a configuration bit. The VPI signals should operate in concert in a single
126*4882a593Smuzhiyun * function, but the UART signals should retain the ability to be configured
127*4882a593Smuzhiyun * independently. This pushes the implementation down the path of tagging a
128*4882a593Smuzhiyun * signal's expressions with the function they participate in, rather than
129*4882a593Smuzhiyun * defining masks affecting multiple signals per function. The latter approach
130*4882a593Smuzhiyun * fails in this instance where applying the configuration for the UART pin of
131*4882a593Smuzhiyun * interest will stomp on the state of other UART signals when disabling the
132*4882a593Smuzhiyun * VPI functions on the current pin.
133*4882a593Smuzhiyun *
134*4882a593Smuzhiyun * Ball | Default | P0 Signal | P0 Expression | P1 Signal | P1 Expression | Other
135*4882a593Smuzhiyun * -----+------------+-----------+---------------------------+-----------+---------------+------------
136*4882a593Smuzhiyun * A12 RGMII1TXCK GPIOT0 SCUA0[0]=1 RMII1TXEN Strap[6]=0 RGMII1TXCK
137*4882a593Smuzhiyun * B12 RGMII1TXCTL GPIOT1 SCUA0[1]=1 – Strap[6]=0 RGMII1TXCTL
138*4882a593Smuzhiyun * -----+------------+-----------+---------------------------+-----------+---------------+------------
139*4882a593Smuzhiyun *
140*4882a593Smuzhiyun * A12 demonstrates that the "Other" signal isn't always GPIO - in this case
141*4882a593Smuzhiyun * GPIOT0 is a high-priority signal and RGMII1TXCK is Other. Thus, GPIO
142*4882a593Smuzhiyun * should be treated like any other signal type with full function expression
143*4882a593Smuzhiyun * requirements, and not assumed to be the default case. Separately, GPIOT0 and
144*4882a593Smuzhiyun * GPIOT1's signal descriptor bits are distinct, therefore we must iterate all
145*4882a593Smuzhiyun * pins in the function's group to disable the higher-priority signals such
146*4882a593Smuzhiyun * that the signal for the function of interest is correctly enabled.
147*4882a593Smuzhiyun *
148*4882a593Smuzhiyun * Finally, three priority levels aren't always enough; the AST2500 brings with
149*4882a593Smuzhiyun * it 18 pins of five priority levels, however the 18 pins only use three of
150*4882a593Smuzhiyun * the five priority levels.
151*4882a593Smuzhiyun *
152*4882a593Smuzhiyun * Ultimately the requirement to control pins in the examples above drive the
153*4882a593Smuzhiyun * design:
154*4882a593Smuzhiyun *
155*4882a593Smuzhiyun * * Pins provide signals according to functions activated in the mux
156*4882a593Smuzhiyun * configuration
157*4882a593Smuzhiyun *
158*4882a593Smuzhiyun * * Pins provide up to five signal types in a priority order
159*4882a593Smuzhiyun *
160*4882a593Smuzhiyun * * For priorities levels defined on a pin, each priority provides one signal
161*4882a593Smuzhiyun *
162*4882a593Smuzhiyun * * Enabling lower priority signals requires higher priority signals be
163*4882a593Smuzhiyun * disabled
164*4882a593Smuzhiyun *
165*4882a593Smuzhiyun * * A function represents a set of signals; functions are distinct if they
166*4882a593Smuzhiyun * do not share a subset of signals (and may be distinct if they are a
167*4882a593Smuzhiyun * strict subset).
168*4882a593Smuzhiyun *
169*4882a593Smuzhiyun * * Signals participate in one or more functions or groups
170*4882a593Smuzhiyun *
171*4882a593Smuzhiyun * * A function is described by an expression of one or more signal
172*4882a593Smuzhiyun * descriptors, which compare bit values in a register
173*4882a593Smuzhiyun *
174*4882a593Smuzhiyun * * A signal expression is the smallest set of signal descriptors whose
175*4882a593Smuzhiyun * comparisons must evaluate 'true' for a signal to be enabled on a pin.
176*4882a593Smuzhiyun *
177*4882a593Smuzhiyun * * A signal participating in a function is active on a pin if evaluating all
178*4882a593Smuzhiyun * signal descriptors in the pin's signal expression for the function yields
179*4882a593Smuzhiyun * a 'true' result
180*4882a593Smuzhiyun *
181*4882a593Smuzhiyun * * A signal at a given priority on a given pin is active if any of the
182*4882a593Smuzhiyun * functions in which the signal participates are active, and no higher
183*4882a593Smuzhiyun * priority signal on the pin is active
184*4882a593Smuzhiyun *
185*4882a593Smuzhiyun * * GPIO is configured per-pin
186*4882a593Smuzhiyun *
187*4882a593Smuzhiyun * And so:
188*4882a593Smuzhiyun *
189*4882a593Smuzhiyun * * To disable a signal, any function(s) activating the signal must be
190*4882a593Smuzhiyun * disabled
191*4882a593Smuzhiyun *
192*4882a593Smuzhiyun * * Each pin must know the signal expressions of functions in which it
193*4882a593Smuzhiyun * participates, for the purpose of enabling the Other function. This is done
194*4882a593Smuzhiyun * by deactivating all functions that activate higher priority signals on the
195*4882a593Smuzhiyun * pin.
196*4882a593Smuzhiyun *
197*4882a593Smuzhiyun * As a concrete example:
198*4882a593Smuzhiyun *
199*4882a593Smuzhiyun * * T5 provides three signals types: VPIDE, NDCD1 and GPIO
200*4882a593Smuzhiyun *
201*4882a593Smuzhiyun * * The VPIDE signal participates in 3 functions: VPI18, VPI24 and VPI30
202*4882a593Smuzhiyun *
203*4882a593Smuzhiyun * * The NDCD1 signal participates in just its own NDCD1 function
204*4882a593Smuzhiyun *
205*4882a593Smuzhiyun * * VPIDE is high priority, NDCD1 is low priority, and GPIOL1 is the least
206*4882a593Smuzhiyun * prioritised
207*4882a593Smuzhiyun *
208*4882a593Smuzhiyun * * The prerequisit for activating the NDCD1 signal is that the VPI18, VPI24
209*4882a593Smuzhiyun * and VPI30 functions all be disabled
210*4882a593Smuzhiyun *
211*4882a593Smuzhiyun * * Similarly, all of VPI18, VPI24, VPI30 and NDCD1 functions must be disabled
212*4882a593Smuzhiyun * to provide GPIOL6
213*4882a593Smuzhiyun *
214*4882a593Smuzhiyun * Considerations
215*4882a593Smuzhiyun * --------------
216*4882a593Smuzhiyun *
217*4882a593Smuzhiyun * If pinctrl allows us to allocate a pin we can configure a function without
218*4882a593Smuzhiyun * concern for the function of already allocated pins, if pin groups are
219*4882a593Smuzhiyun * created with respect to the SoC functions in which they participate. This is
220*4882a593Smuzhiyun * intuitive, but it did not feel obvious from the bit/pin relationships.
221*4882a593Smuzhiyun *
222*4882a593Smuzhiyun * Conversely, failing to allocate all pins in a group indicates some bits (as
223*4882a593Smuzhiyun * well as pins) required for the group's configuration will already be in use,
224*4882a593Smuzhiyun * likely in a way that's inconsistent with the requirements of the failed
225*4882a593Smuzhiyun * group.
226*4882a593Smuzhiyun *
227*4882a593Smuzhiyun * Implementation
228*4882a593Smuzhiyun * --------------
229*4882a593Smuzhiyun *
230*4882a593Smuzhiyun * Beyond the documentation below the various structures and helper macros that
231*4882a593Smuzhiyun * allow the implementation to hang together are defined. The macros are fairly
232*4882a593Smuzhiyun * dense, so below we walk through some raw examples of the configuration
233*4882a593Smuzhiyun * tables in an effort to clarify the concepts.
234*4882a593Smuzhiyun *
235*4882a593Smuzhiyun * The complexity of configuring the mux combined with the scale of the pins
236*4882a593Smuzhiyun * and functions was a concern, so the table design along with the macro jungle
237*4882a593Smuzhiyun * is an attempt to address it. The rough principles of the approach are:
238*4882a593Smuzhiyun *
239*4882a593Smuzhiyun * 1. Use a data-driven solution rather than embedding state into code
240*4882a593Smuzhiyun * 2. Minimise editing to the specifics of the given mux configuration
241*4882a593Smuzhiyun * 3. Detect as many errors as possible at compile time
242*4882a593Smuzhiyun *
243*4882a593Smuzhiyun * Addressing point 3 leads to naming of symbols in terms of the four
244*4882a593Smuzhiyun * properties associated with a given mux configuration: The pin, the signal,
245*4882a593Smuzhiyun * the group and the function. In this way copy/paste errors cause duplicate
246*4882a593Smuzhiyun * symbols to be defined, which prevents successful compilation. Failing to
247*4882a593Smuzhiyun * properly parent the tables leads to unused symbol warnings, and use of
248*4882a593Smuzhiyun * designated initialisers and additional warnings ensures that there are
249*4882a593Smuzhiyun * no override errors in the pin, group and function arrays.
250*4882a593Smuzhiyun *
251*4882a593Smuzhiyun * Addressing point 2 drives the development of the macro jungle, as it
252*4882a593Smuzhiyun * centralises the definition noise at the cost of taking some time to
253*4882a593Smuzhiyun * understand.
254*4882a593Smuzhiyun *
255*4882a593Smuzhiyun * Here's a complete, concrete "pre-processed" example of the table structures
256*4882a593Smuzhiyun * used to describe the D6 ball from the examples above:
257*4882a593Smuzhiyun *
258*4882a593Smuzhiyun * ```
259*4882a593Smuzhiyun * static const struct aspeed_sig_desc sig_descs_MAC1LINK_MAC1LINK[] = {
260*4882a593Smuzhiyun * {
261*4882a593Smuzhiyun * .ip = ASPEED_IP_SCU,
262*4882a593Smuzhiyun * .reg = 0x80,
263*4882a593Smuzhiyun * .mask = BIT(0),
264*4882a593Smuzhiyun * .enable = 1,
265*4882a593Smuzhiyun * .disable = 0
266*4882a593Smuzhiyun * },
267*4882a593Smuzhiyun * };
268*4882a593Smuzhiyun *
269*4882a593Smuzhiyun * static const struct aspeed_sig_expr sig_expr_MAC1LINK_MAC1LINK = {
270*4882a593Smuzhiyun * .signal = "MAC1LINK",
271*4882a593Smuzhiyun * .function = "MAC1LINK",
272*4882a593Smuzhiyun * .ndescs = ARRAY_SIZE(sig_descs_MAC1LINK_MAC1LINK),
273*4882a593Smuzhiyun * .descs = &(sig_descs_MAC1LINK_MAC1LINK)[0],
274*4882a593Smuzhiyun * };
275*4882a593Smuzhiyun *
276*4882a593Smuzhiyun * static const struct aspeed_sig_expr *sig_exprs_MAC1LINK_MAC1LINK[] = {
277*4882a593Smuzhiyun * &sig_expr_MAC1LINK_MAC1LINK,
278*4882a593Smuzhiyun * NULL,
279*4882a593Smuzhiyun * };
280*4882a593Smuzhiyun *
281*4882a593Smuzhiyun * static const struct aspeed_sig_desc sig_descs_GPIOA0_GPIOA0[] = { };
282*4882a593Smuzhiyun *
283*4882a593Smuzhiyun * static const struct aspeed_sig_expr sig_expr_GPIOA0_GPIOA0 = {
284*4882a593Smuzhiyun * .signal = "GPIOA0",
285*4882a593Smuzhiyun * .function = "GPIOA0",
286*4882a593Smuzhiyun * .ndescs = ARRAY_SIZE(sig_descs_GPIOA0_GPIOA0),
287*4882a593Smuzhiyun * .descs = &(sig_descs_GPIOA0_GPIOA0)[0],
288*4882a593Smuzhiyun * };
289*4882a593Smuzhiyun *
290*4882a593Smuzhiyun * static const struct aspeed_sig_expr *sig_exprs_GPIOA0_GPIOA0[] = {
291*4882a593Smuzhiyun * &sig_expr_GPIOA0_GPIOA0,
292*4882a593Smuzhiyun * NULL
293*4882a593Smuzhiyun * };
294*4882a593Smuzhiyun *
295*4882a593Smuzhiyun * static const struct aspeed_sig_expr **pin_exprs_0[] = {
296*4882a593Smuzhiyun * sig_exprs_MAC1LINK_MAC1LINK,
297*4882a593Smuzhiyun * sig_exprs_GPIOA0_GPIOA0,
298*4882a593Smuzhiyun * NULL
299*4882a593Smuzhiyun * };
300*4882a593Smuzhiyun *
301*4882a593Smuzhiyun * static const struct aspeed_pin_desc pin_0 = { "0", (&pin_exprs_0[0]) };
302*4882a593Smuzhiyun * static const int group_pins_MAC1LINK[] = { 0 };
303*4882a593Smuzhiyun * static const char *func_groups_MAC1LINK[] = { "MAC1LINK" };
304*4882a593Smuzhiyun *
305*4882a593Smuzhiyun * static struct pinctrl_pin_desc aspeed_g4_pins[] = {
306*4882a593Smuzhiyun * [0] = { .number = 0, .name = "D6", .drv_data = &pin_0 },
307*4882a593Smuzhiyun * };
308*4882a593Smuzhiyun *
309*4882a593Smuzhiyun * static const struct aspeed_pin_group aspeed_g4_groups[] = {
310*4882a593Smuzhiyun * {
311*4882a593Smuzhiyun * .name = "MAC1LINK",
312*4882a593Smuzhiyun * .pins = &(group_pins_MAC1LINK)[0],
313*4882a593Smuzhiyun * .npins = ARRAY_SIZE(group_pins_MAC1LINK),
314*4882a593Smuzhiyun * },
315*4882a593Smuzhiyun * };
316*4882a593Smuzhiyun *
317*4882a593Smuzhiyun * static const struct aspeed_pin_function aspeed_g4_functions[] = {
318*4882a593Smuzhiyun * {
319*4882a593Smuzhiyun * .name = "MAC1LINK",
320*4882a593Smuzhiyun * .groups = &func_groups_MAC1LINK[0],
321*4882a593Smuzhiyun * .ngroups = ARRAY_SIZE(func_groups_MAC1LINK),
322*4882a593Smuzhiyun * },
323*4882a593Smuzhiyun * };
324*4882a593Smuzhiyun * ```
325*4882a593Smuzhiyun *
326*4882a593Smuzhiyun * At the end of the day much of the above code is compressed into the
327*4882a593Smuzhiyun * following two lines:
328*4882a593Smuzhiyun *
329*4882a593Smuzhiyun * ```
330*4882a593Smuzhiyun * #define D6 0
331*4882a593Smuzhiyun * SSSF_PIN_DECL(D6, GPIOA0, MAC1LINK, SIG_DESC_SET(SCU80, 0));
332*4882a593Smuzhiyun * ```
333*4882a593Smuzhiyun *
334*4882a593Smuzhiyun * The two examples below show just the differences from the example above.
335*4882a593Smuzhiyun *
336*4882a593Smuzhiyun * Ball E18 demonstrates a function, EXTRST, that requires multiple descriptors
337*4882a593Smuzhiyun * be set for it to be muxed:
338*4882a593Smuzhiyun *
339*4882a593Smuzhiyun * ```
340*4882a593Smuzhiyun * static const struct aspeed_sig_desc sig_descs_EXTRST_EXTRST[] = {
341*4882a593Smuzhiyun * {
342*4882a593Smuzhiyun * .ip = ASPEED_IP_SCU,
343*4882a593Smuzhiyun * .reg = 0x3C,
344*4882a593Smuzhiyun * .mask = BIT(3),
345*4882a593Smuzhiyun * .enable = 1,
346*4882a593Smuzhiyun * .disable = 0
347*4882a593Smuzhiyun * },
348*4882a593Smuzhiyun * {
349*4882a593Smuzhiyun * .ip = ASPEED_IP_SCU,
350*4882a593Smuzhiyun * .reg = 0x80,
351*4882a593Smuzhiyun * .mask = BIT(15),
352*4882a593Smuzhiyun * .enable = 1,
353*4882a593Smuzhiyun * .disable = 0
354*4882a593Smuzhiyun * },
355*4882a593Smuzhiyun * {
356*4882a593Smuzhiyun * .ip = ASPEED_IP_SCU,
357*4882a593Smuzhiyun * .reg = 0x90,
358*4882a593Smuzhiyun * .mask = BIT(31),
359*4882a593Smuzhiyun * .enable = 0,
360*4882a593Smuzhiyun * .disable = 1
361*4882a593Smuzhiyun * },
362*4882a593Smuzhiyun * };
363*4882a593Smuzhiyun *
364*4882a593Smuzhiyun * static const struct aspeed_sig_expr sig_expr_EXTRST_EXTRST = {
365*4882a593Smuzhiyun * .signal = "EXTRST",
366*4882a593Smuzhiyun * .function = "EXTRST",
367*4882a593Smuzhiyun * .ndescs = ARRAY_SIZE(sig_descs_EXTRST_EXTRST),
368*4882a593Smuzhiyun * .descs = &(sig_descs_EXTRST_EXTRST)[0],
369*4882a593Smuzhiyun * };
370*4882a593Smuzhiyun * ...
371*4882a593Smuzhiyun * ```
372*4882a593Smuzhiyun *
373*4882a593Smuzhiyun * For ball E19, we have multiple functions enabling a single signal, LPCRST#.
374*4882a593Smuzhiyun * The data structures look like:
375*4882a593Smuzhiyun *
376*4882a593Smuzhiyun * static const struct aspeed_sig_desc sig_descs_LPCRST_LPCRST[] = {
377*4882a593Smuzhiyun * {
378*4882a593Smuzhiyun * .ip = ASPEED_IP_SCU,
379*4882a593Smuzhiyun * .reg = 0x80,
380*4882a593Smuzhiyun * .mask = BIT(12),
381*4882a593Smuzhiyun * .enable = 1,
382*4882a593Smuzhiyun * .disable = 0
383*4882a593Smuzhiyun * },
384*4882a593Smuzhiyun * };
385*4882a593Smuzhiyun *
386*4882a593Smuzhiyun * static const struct aspeed_sig_expr sig_expr_LPCRST_LPCRST = {
387*4882a593Smuzhiyun * .signal = "LPCRST",
388*4882a593Smuzhiyun * .function = "LPCRST",
389*4882a593Smuzhiyun * .ndescs = ARRAY_SIZE(sig_descs_LPCRST_LPCRST),
390*4882a593Smuzhiyun * .descs = &(sig_descs_LPCRST_LPCRST)[0],
391*4882a593Smuzhiyun * };
392*4882a593Smuzhiyun *
393*4882a593Smuzhiyun * static const struct aspeed_sig_desc sig_descs_LPCRST_LPCRSTS[] = {
394*4882a593Smuzhiyun * {
395*4882a593Smuzhiyun * .ip = ASPEED_IP_SCU,
396*4882a593Smuzhiyun * .reg = 0x70,
397*4882a593Smuzhiyun * .mask = BIT(14),
398*4882a593Smuzhiyun * .enable = 1,
399*4882a593Smuzhiyun * .disable = 0
400*4882a593Smuzhiyun * },
401*4882a593Smuzhiyun * };
402*4882a593Smuzhiyun *
403*4882a593Smuzhiyun * static const struct aspeed_sig_expr sig_expr_LPCRST_LPCRSTS = {
404*4882a593Smuzhiyun * .signal = "LPCRST",
405*4882a593Smuzhiyun * .function = "LPCRSTS",
406*4882a593Smuzhiyun * .ndescs = ARRAY_SIZE(sig_descs_LPCRST_LPCRSTS),
407*4882a593Smuzhiyun * .descs = &(sig_descs_LPCRST_LPCRSTS)[0],
408*4882a593Smuzhiyun * };
409*4882a593Smuzhiyun *
410*4882a593Smuzhiyun * static const struct aspeed_sig_expr *sig_exprs_LPCRST_LPCRST[] = {
411*4882a593Smuzhiyun * &sig_expr_LPCRST_LPCRST,
412*4882a593Smuzhiyun * &sig_expr_LPCRST_LPCRSTS,
413*4882a593Smuzhiyun * NULL,
414*4882a593Smuzhiyun * };
415*4882a593Smuzhiyun * ...
416*4882a593Smuzhiyun * ```
417*4882a593Smuzhiyun *
418*4882a593Smuzhiyun * Both expressions listed in the sig_exprs_LPCRST_LPCRST array need to be set
419*4882a593Smuzhiyun * to disabled for the associated GPIO to be muxed.
420*4882a593Smuzhiyun *
421*4882a593Smuzhiyun */
422*4882a593Smuzhiyun
423*4882a593Smuzhiyun #define ASPEED_IP_SCU 0
424*4882a593Smuzhiyun #define ASPEED_IP_GFX 1
425*4882a593Smuzhiyun #define ASPEED_IP_LPC 2
426*4882a593Smuzhiyun #define ASPEED_NR_PINMUX_IPS 3
427*4882a593Smuzhiyun
428*4882a593Smuzhiyun /**
429*4882a593Smuzhiyun * A signal descriptor, which describes the register, bits and the
430*4882a593Smuzhiyun * enable/disable values that should be compared or written.
431*4882a593Smuzhiyun *
432*4882a593Smuzhiyun * @ip: The IP block identifier, used as an index into the regmap array in
433*4882a593Smuzhiyun * struct aspeed_pinctrl_data
434*4882a593Smuzhiyun * @reg: The register offset with respect to the base address of the IP block
435*4882a593Smuzhiyun * @mask: The mask to apply to the register. The lowest set bit of the mask is
436*4882a593Smuzhiyun * used to derive the shift value.
437*4882a593Smuzhiyun * @enable: The value that enables the function. Value should be in the LSBs,
438*4882a593Smuzhiyun * not at the position of the mask.
439*4882a593Smuzhiyun * @disable: The value that disables the function. Value should be in the
440*4882a593Smuzhiyun * LSBs, not at the position of the mask.
441*4882a593Smuzhiyun */
442*4882a593Smuzhiyun struct aspeed_sig_desc {
443*4882a593Smuzhiyun unsigned int ip;
444*4882a593Smuzhiyun unsigned int reg;
445*4882a593Smuzhiyun u32 mask;
446*4882a593Smuzhiyun u32 enable;
447*4882a593Smuzhiyun u32 disable;
448*4882a593Smuzhiyun };
449*4882a593Smuzhiyun
450*4882a593Smuzhiyun /**
451*4882a593Smuzhiyun * Describes a signal expression. The expression is evaluated by ANDing the
452*4882a593Smuzhiyun * evaluation of the descriptors.
453*4882a593Smuzhiyun *
454*4882a593Smuzhiyun * @signal: The signal name for the priority level on the pin. If the signal
455*4882a593Smuzhiyun * type is GPIO, then the signal name must begin with the
456*4882a593Smuzhiyun * prefix "GPI", e.g. GPIOA0, GPIT0 etc.
457*4882a593Smuzhiyun * @function: The name of the function the signal participates in for the
458*4882a593Smuzhiyun * associated expression. For pin-specific GPIO, the function
459*4882a593Smuzhiyun * name must match the signal name.
460*4882a593Smuzhiyun * @ndescs: The number of signal descriptors in the expression
461*4882a593Smuzhiyun * @descs: Pointer to an array of signal descriptors that comprise the
462*4882a593Smuzhiyun * function expression
463*4882a593Smuzhiyun */
464*4882a593Smuzhiyun struct aspeed_sig_expr {
465*4882a593Smuzhiyun const char *signal;
466*4882a593Smuzhiyun const char *function;
467*4882a593Smuzhiyun int ndescs;
468*4882a593Smuzhiyun const struct aspeed_sig_desc *descs;
469*4882a593Smuzhiyun };
470*4882a593Smuzhiyun
471*4882a593Smuzhiyun /**
472*4882a593Smuzhiyun * A struct capturing the list of expressions enabling signals at each priority
473*4882a593Smuzhiyun * for a given pin. The signal configuration for a priority level is evaluated
474*4882a593Smuzhiyun * by ORing the evaluation of the signal expressions in the respective
475*4882a593Smuzhiyun * priority's list.
476*4882a593Smuzhiyun *
477*4882a593Smuzhiyun * @name: A name for the pin
478*4882a593Smuzhiyun * @prios: A pointer to an array of expression list pointers
479*4882a593Smuzhiyun *
480*4882a593Smuzhiyun */
481*4882a593Smuzhiyun struct aspeed_pin_desc {
482*4882a593Smuzhiyun const char *name;
483*4882a593Smuzhiyun const struct aspeed_sig_expr ***prios;
484*4882a593Smuzhiyun };
485*4882a593Smuzhiyun
486*4882a593Smuzhiyun /* Macro hell */
487*4882a593Smuzhiyun
488*4882a593Smuzhiyun #define SIG_DESC_IP_BIT(ip, reg, idx, val) \
489*4882a593Smuzhiyun { ip, reg, BIT_MASK(idx), val, (((val) + 1) & 1) }
490*4882a593Smuzhiyun
491*4882a593Smuzhiyun /**
492*4882a593Smuzhiyun * Short-hand macro for describing an SCU descriptor enabled by the state of
493*4882a593Smuzhiyun * one bit. The disable value is derived.
494*4882a593Smuzhiyun *
495*4882a593Smuzhiyun * @reg: The signal's associated register, offset from base
496*4882a593Smuzhiyun * @idx: The signal's bit index in the register
497*4882a593Smuzhiyun * @val: The value (0 or 1) that enables the function
498*4882a593Smuzhiyun */
499*4882a593Smuzhiyun #define SIG_DESC_BIT(reg, idx, val) \
500*4882a593Smuzhiyun SIG_DESC_IP_BIT(ASPEED_IP_SCU, reg, idx, val)
501*4882a593Smuzhiyun
502*4882a593Smuzhiyun #define SIG_DESC_IP_SET(ip, reg, idx) SIG_DESC_IP_BIT(ip, reg, idx, 1)
503*4882a593Smuzhiyun
504*4882a593Smuzhiyun /**
505*4882a593Smuzhiyun * A further short-hand macro expanding to an SCU descriptor enabled by a set
506*4882a593Smuzhiyun * bit.
507*4882a593Smuzhiyun *
508*4882a593Smuzhiyun * @reg: The register, offset from base
509*4882a593Smuzhiyun * @idx: The bit index in the register
510*4882a593Smuzhiyun */
511*4882a593Smuzhiyun #define SIG_DESC_SET(reg, idx) SIG_DESC_IP_BIT(ASPEED_IP_SCU, reg, idx, 1)
512*4882a593Smuzhiyun #define SIG_DESC_CLEAR(reg, idx) { ASPEED_IP_SCU, reg, BIT_MASK(idx), 0, 0 }
513*4882a593Smuzhiyun
514*4882a593Smuzhiyun #define SIG_DESC_LIST_SYM(sig, group) sig_descs_ ## sig ## _ ## group
515*4882a593Smuzhiyun #define SIG_DESC_LIST_DECL(sig, group, ...) \
516*4882a593Smuzhiyun static const struct aspeed_sig_desc SIG_DESC_LIST_SYM(sig, group)[] = \
517*4882a593Smuzhiyun { __VA_ARGS__ }
518*4882a593Smuzhiyun
519*4882a593Smuzhiyun #define SIG_EXPR_SYM(sig, group) sig_expr_ ## sig ## _ ## group
520*4882a593Smuzhiyun #define SIG_EXPR_DECL_(sig, group, func) \
521*4882a593Smuzhiyun static const struct aspeed_sig_expr SIG_EXPR_SYM(sig, group) = \
522*4882a593Smuzhiyun { \
523*4882a593Smuzhiyun .signal = #sig, \
524*4882a593Smuzhiyun .function = #func, \
525*4882a593Smuzhiyun .ndescs = ARRAY_SIZE(SIG_DESC_LIST_SYM(sig, group)), \
526*4882a593Smuzhiyun .descs = &(SIG_DESC_LIST_SYM(sig, group))[0], \
527*4882a593Smuzhiyun }
528*4882a593Smuzhiyun
529*4882a593Smuzhiyun /**
530*4882a593Smuzhiyun * Declare a signal expression.
531*4882a593Smuzhiyun *
532*4882a593Smuzhiyun * @sig: A macro symbol name for the signal (is subjected to stringification
533*4882a593Smuzhiyun * and token pasting)
534*4882a593Smuzhiyun * @func: The function in which the signal is participating
535*4882a593Smuzhiyun * @...: Signal descriptors that define the signal expression
536*4882a593Smuzhiyun *
537*4882a593Smuzhiyun * For example, the following declares the ROMD8 signal for the ROM16 function:
538*4882a593Smuzhiyun *
539*4882a593Smuzhiyun * SIG_EXPR_DECL(ROMD8, ROM16, ROM16, SIG_DESC_SET(SCU90, 6));
540*4882a593Smuzhiyun *
541*4882a593Smuzhiyun * And with multiple signal descriptors:
542*4882a593Smuzhiyun *
543*4882a593Smuzhiyun * SIG_EXPR_DECL(ROMD8, ROM16S, ROM16S, SIG_DESC_SET(HW_STRAP1, 4),
544*4882a593Smuzhiyun * { HW_STRAP1, GENMASK(1, 0), 0, 0 });
545*4882a593Smuzhiyun */
546*4882a593Smuzhiyun #define SIG_EXPR_DECL(sig, group, func, ...) \
547*4882a593Smuzhiyun SIG_DESC_LIST_DECL(sig, group, __VA_ARGS__); \
548*4882a593Smuzhiyun SIG_EXPR_DECL_(sig, group, func)
549*4882a593Smuzhiyun
550*4882a593Smuzhiyun /**
551*4882a593Smuzhiyun * Declare a pointer to a signal expression
552*4882a593Smuzhiyun *
553*4882a593Smuzhiyun * @sig: The macro symbol name for the signal (subjected to token pasting)
554*4882a593Smuzhiyun * @func: The macro symbol name for the function (subjected to token pasting)
555*4882a593Smuzhiyun */
556*4882a593Smuzhiyun #define SIG_EXPR_PTR(sig, group) (&SIG_EXPR_SYM(sig, group))
557*4882a593Smuzhiyun
558*4882a593Smuzhiyun #define SIG_EXPR_LIST_SYM(sig, group) sig_exprs_ ## sig ## _ ## group
559*4882a593Smuzhiyun
560*4882a593Smuzhiyun /**
561*4882a593Smuzhiyun * Declare a signal expression list for reference in a struct aspeed_pin_prio.
562*4882a593Smuzhiyun *
563*4882a593Smuzhiyun * @sig: A macro symbol name for the signal (is subjected to token pasting)
564*4882a593Smuzhiyun * @...: Signal expression structure pointers (use SIG_EXPR_PTR())
565*4882a593Smuzhiyun *
566*4882a593Smuzhiyun * For example, the 16-bit ROM bus can be enabled by one of two possible signal
567*4882a593Smuzhiyun * expressions:
568*4882a593Smuzhiyun *
569*4882a593Smuzhiyun * SIG_EXPR_DECL(ROMD8, ROM16, ROM16, SIG_DESC_SET(SCU90, 6));
570*4882a593Smuzhiyun * SIG_EXPR_DECL(ROMD8, ROM16S, ROM16S, SIG_DESC_SET(HW_STRAP1, 4),
571*4882a593Smuzhiyun * { HW_STRAP1, GENMASK(1, 0), 0, 0 });
572*4882a593Smuzhiyun * SIG_EXPR_LIST_DECL(ROMD8, SIG_EXPR_PTR(ROMD8, ROM16),
573*4882a593Smuzhiyun * SIG_EXPR_PTR(ROMD8, ROM16S));
574*4882a593Smuzhiyun */
575*4882a593Smuzhiyun #define SIG_EXPR_LIST_DECL(sig, group, ...) \
576*4882a593Smuzhiyun static const struct aspeed_sig_expr *SIG_EXPR_LIST_SYM(sig, group)[] =\
577*4882a593Smuzhiyun { __VA_ARGS__, NULL }
578*4882a593Smuzhiyun
579*4882a593Smuzhiyun #define stringify(x) #x
580*4882a593Smuzhiyun #define istringify(x) stringify(x)
581*4882a593Smuzhiyun
582*4882a593Smuzhiyun /**
583*4882a593Smuzhiyun * Create an expression symbol alias from (signal, group) to (pin, signal).
584*4882a593Smuzhiyun *
585*4882a593Smuzhiyun * @pin: The pin number
586*4882a593Smuzhiyun * @sig: The signal name
587*4882a593Smuzhiyun * @group: The name of the group of which the pin is a member that is
588*4882a593Smuzhiyun * associated with the function's signal
589*4882a593Smuzhiyun *
590*4882a593Smuzhiyun * Using an alias in this way enables detection of copy/paste errors (defining
591*4882a593Smuzhiyun * the signal for a group multiple times) whilst enabling multiple pin groups
592*4882a593Smuzhiyun * to exist for a signal without intrusive side-effects on defining the list of
593*4882a593Smuzhiyun * signals available on a pin.
594*4882a593Smuzhiyun */
595*4882a593Smuzhiyun #define SIG_EXPR_LIST_ALIAS(pin, sig, group) \
596*4882a593Smuzhiyun static const struct aspeed_sig_expr *\
597*4882a593Smuzhiyun SIG_EXPR_LIST_SYM(pin, sig)[ARRAY_SIZE(SIG_EXPR_LIST_SYM(sig, group))] \
598*4882a593Smuzhiyun __attribute__((alias(istringify(SIG_EXPR_LIST_SYM(sig, group)))))
599*4882a593Smuzhiyun
600*4882a593Smuzhiyun /**
601*4882a593Smuzhiyun * A short-hand macro for declaring a function expression and an expression
602*4882a593Smuzhiyun * list with a single expression (SE) and a single group (SG) of pins.
603*4882a593Smuzhiyun *
604*4882a593Smuzhiyun * @pin: The pin the signal will be routed to
605*4882a593Smuzhiyun * @sig: The signal that will be routed to the pin for the function
606*4882a593Smuzhiyun * @func: A macro symbol name for the function
607*4882a593Smuzhiyun * @...: Function descriptors that define the function expression
608*4882a593Smuzhiyun *
609*4882a593Smuzhiyun * For example, signal NCTS6 participates in its own function with one group:
610*4882a593Smuzhiyun *
611*4882a593Smuzhiyun * SIG_EXPR_LIST_DECL_SINGLE(A18, NCTS6, NCTS6, SIG_DESC_SET(SCU90, 7));
612*4882a593Smuzhiyun */
613*4882a593Smuzhiyun #define SIG_EXPR_LIST_DECL_SESG(pin, sig, func, ...) \
614*4882a593Smuzhiyun SIG_DESC_LIST_DECL(sig, func, __VA_ARGS__); \
615*4882a593Smuzhiyun SIG_EXPR_DECL_(sig, func, func); \
616*4882a593Smuzhiyun SIG_EXPR_LIST_DECL(sig, func, SIG_EXPR_PTR(sig, func)); \
617*4882a593Smuzhiyun SIG_EXPR_LIST_ALIAS(pin, sig, func)
618*4882a593Smuzhiyun
619*4882a593Smuzhiyun /**
620*4882a593Smuzhiyun * Similar to the above, but for pins with a single expression (SE) and
621*4882a593Smuzhiyun * multiple groups (MG) of pins.
622*4882a593Smuzhiyun *
623*4882a593Smuzhiyun * @pin: The pin the signal will be routed to
624*4882a593Smuzhiyun * @sig: The signal that will be routed to the pin for the function
625*4882a593Smuzhiyun * @group: The name of the function's pin group in which the pin participates
626*4882a593Smuzhiyun * @func: A macro symbol name for the function
627*4882a593Smuzhiyun * @...: Function descriptors that define the function expression
628*4882a593Smuzhiyun */
629*4882a593Smuzhiyun #define SIG_EXPR_LIST_DECL_SEMG(pin, sig, group, func, ...) \
630*4882a593Smuzhiyun SIG_DESC_LIST_DECL(sig, group, __VA_ARGS__); \
631*4882a593Smuzhiyun SIG_EXPR_DECL_(sig, group, func); \
632*4882a593Smuzhiyun SIG_EXPR_LIST_DECL(sig, group, SIG_EXPR_PTR(sig, group)); \
633*4882a593Smuzhiyun SIG_EXPR_LIST_ALIAS(pin, sig, group)
634*4882a593Smuzhiyun
635*4882a593Smuzhiyun /**
636*4882a593Smuzhiyun * Similar to the above, but for pins with a dual expressions (DE) and
637*4882a593Smuzhiyun * and a single group (SG) of pins.
638*4882a593Smuzhiyun *
639*4882a593Smuzhiyun * @pin: The pin the signal will be routed to
640*4882a593Smuzhiyun * @sig: The signal that will be routed to the pin for the function
641*4882a593Smuzhiyun * @group: The name of the function's pin group in which the pin participates
642*4882a593Smuzhiyun * @func: A macro symbol name for the function
643*4882a593Smuzhiyun * @...: Function descriptors that define the function expression
644*4882a593Smuzhiyun */
645*4882a593Smuzhiyun #define SIG_EXPR_LIST_DECL_DESG(pin, sig, f0, f1) \
646*4882a593Smuzhiyun SIG_EXPR_LIST_DECL(sig, f0, \
647*4882a593Smuzhiyun SIG_EXPR_PTR(sig, f0), \
648*4882a593Smuzhiyun SIG_EXPR_PTR(sig, f1)); \
649*4882a593Smuzhiyun SIG_EXPR_LIST_ALIAS(pin, sig, f0)
650*4882a593Smuzhiyun
651*4882a593Smuzhiyun #define SIG_EXPR_LIST_PTR(sig, group) SIG_EXPR_LIST_SYM(sig, group)
652*4882a593Smuzhiyun
653*4882a593Smuzhiyun #define PIN_EXPRS_SYM(pin) pin_exprs_ ## pin
654*4882a593Smuzhiyun #define PIN_EXPRS_PTR(pin) (&PIN_EXPRS_SYM(pin)[0])
655*4882a593Smuzhiyun #define PIN_SYM(pin) pin_ ## pin
656*4882a593Smuzhiyun
657*4882a593Smuzhiyun #define PIN_DECL_(pin, ...) \
658*4882a593Smuzhiyun static const struct aspeed_sig_expr **PIN_EXPRS_SYM(pin)[] = \
659*4882a593Smuzhiyun { __VA_ARGS__, NULL }; \
660*4882a593Smuzhiyun static const struct aspeed_pin_desc PIN_SYM(pin) = \
661*4882a593Smuzhiyun { #pin, PIN_EXPRS_PTR(pin) }
662*4882a593Smuzhiyun
663*4882a593Smuzhiyun /**
664*4882a593Smuzhiyun * Declare a single signal pin
665*4882a593Smuzhiyun *
666*4882a593Smuzhiyun * @pin: The pin number
667*4882a593Smuzhiyun * @other: Macro name for "other" functionality (subjected to stringification)
668*4882a593Smuzhiyun * @sig: Macro name for the signal (subjected to stringification)
669*4882a593Smuzhiyun *
670*4882a593Smuzhiyun * For example:
671*4882a593Smuzhiyun *
672*4882a593Smuzhiyun * #define E3 80
673*4882a593Smuzhiyun * SIG_EXPR_LIST_DECL_SINGLE(SCL5, I2C5, I2C5_DESC);
674*4882a593Smuzhiyun * PIN_DECL_1(E3, GPIOK0, SCL5);
675*4882a593Smuzhiyun */
676*4882a593Smuzhiyun #define PIN_DECL_1(pin, other, sig) \
677*4882a593Smuzhiyun SIG_EXPR_LIST_DECL_SESG(pin, other, other); \
678*4882a593Smuzhiyun PIN_DECL_(pin, SIG_EXPR_LIST_PTR(pin, sig), \
679*4882a593Smuzhiyun SIG_EXPR_LIST_PTR(pin, other))
680*4882a593Smuzhiyun
681*4882a593Smuzhiyun /**
682*4882a593Smuzhiyun * Single signal, single function pin declaration
683*4882a593Smuzhiyun *
684*4882a593Smuzhiyun * @pin: The pin number
685*4882a593Smuzhiyun * @other: Macro name for "other" functionality (subjected to stringification)
686*4882a593Smuzhiyun * @sig: Macro name for the signal (subjected to stringification)
687*4882a593Smuzhiyun * @...: Signal descriptors that define the function expression
688*4882a593Smuzhiyun *
689*4882a593Smuzhiyun * For example:
690*4882a593Smuzhiyun *
691*4882a593Smuzhiyun * SSSF_PIN_DECL(A4, GPIOA2, TIMER3, SIG_DESC_SET(SCU80, 2));
692*4882a593Smuzhiyun */
693*4882a593Smuzhiyun #define SSSF_PIN_DECL(pin, other, sig, ...) \
694*4882a593Smuzhiyun SIG_EXPR_LIST_DECL_SESG(pin, sig, sig, __VA_ARGS__); \
695*4882a593Smuzhiyun SIG_EXPR_LIST_DECL_SESG(pin, other, other); \
696*4882a593Smuzhiyun PIN_DECL_(pin, SIG_EXPR_LIST_PTR(pin, sig), \
697*4882a593Smuzhiyun SIG_EXPR_LIST_PTR(pin, other)); \
698*4882a593Smuzhiyun FUNC_GROUP_DECL(sig, pin)
699*4882a593Smuzhiyun /**
700*4882a593Smuzhiyun * Declare a two-signal pin
701*4882a593Smuzhiyun *
702*4882a593Smuzhiyun * @pin: The pin number
703*4882a593Smuzhiyun * @other: Macro name for "other" functionality (subjected to stringification)
704*4882a593Smuzhiyun * @high: Macro name for the highest priority signal functions
705*4882a593Smuzhiyun * @low: Macro name for the low signal functions
706*4882a593Smuzhiyun *
707*4882a593Smuzhiyun * For example:
708*4882a593Smuzhiyun *
709*4882a593Smuzhiyun * #define A8 56
710*4882a593Smuzhiyun * SIG_EXPR_DECL(ROMD8, ROM16, SIG_DESC_SET(SCU90, 6));
711*4882a593Smuzhiyun * SIG_EXPR_DECL(ROMD8, ROM16S, SIG_DESC_SET(HW_STRAP1, 4),
712*4882a593Smuzhiyun * { HW_STRAP1, GENMASK(1, 0), 0, 0 });
713*4882a593Smuzhiyun * SIG_EXPR_LIST_DECL(ROMD8, SIG_EXPR_PTR(ROMD8, ROM16),
714*4882a593Smuzhiyun * SIG_EXPR_PTR(ROMD8, ROM16S));
715*4882a593Smuzhiyun * SIG_EXPR_LIST_DECL_SINGLE(NCTS6, NCTS6, SIG_DESC_SET(SCU90, 7));
716*4882a593Smuzhiyun * PIN_DECL_2(A8, GPIOH0, ROMD8, NCTS6);
717*4882a593Smuzhiyun */
718*4882a593Smuzhiyun #define PIN_DECL_2(pin, other, high, low) \
719*4882a593Smuzhiyun SIG_EXPR_LIST_DECL_SESG(pin, other, other); \
720*4882a593Smuzhiyun PIN_DECL_(pin, \
721*4882a593Smuzhiyun SIG_EXPR_LIST_PTR(pin, high), \
722*4882a593Smuzhiyun SIG_EXPR_LIST_PTR(pin, low), \
723*4882a593Smuzhiyun SIG_EXPR_LIST_PTR(pin, other))
724*4882a593Smuzhiyun
725*4882a593Smuzhiyun #define PIN_DECL_3(pin, other, high, medium, low) \
726*4882a593Smuzhiyun SIG_EXPR_LIST_DECL_SESG(pin, other, other); \
727*4882a593Smuzhiyun PIN_DECL_(pin, \
728*4882a593Smuzhiyun SIG_EXPR_LIST_PTR(pin, high), \
729*4882a593Smuzhiyun SIG_EXPR_LIST_PTR(pin, medium), \
730*4882a593Smuzhiyun SIG_EXPR_LIST_PTR(pin, low), \
731*4882a593Smuzhiyun SIG_EXPR_LIST_PTR(pin, other))
732*4882a593Smuzhiyun
733*4882a593Smuzhiyun #define GROUP_SYM(group) group_pins_ ## group
734*4882a593Smuzhiyun #define GROUP_DECL(group, ...) \
735*4882a593Smuzhiyun static const int GROUP_SYM(group)[] = { __VA_ARGS__ }
736*4882a593Smuzhiyun
737*4882a593Smuzhiyun #define FUNC_SYM(func) func_groups_ ## func
738*4882a593Smuzhiyun #define FUNC_DECL_(func, ...) \
739*4882a593Smuzhiyun static const char *FUNC_SYM(func)[] = { __VA_ARGS__ }
740*4882a593Smuzhiyun
741*4882a593Smuzhiyun #define FUNC_DECL_1(func, group) FUNC_DECL_(func, #group)
742*4882a593Smuzhiyun #define FUNC_DECL_2(func, one, two) FUNC_DECL_(func, #one, #two)
743*4882a593Smuzhiyun #define FUNC_DECL_3(func, one, two, three) FUNC_DECL_(func, #one, #two, #three)
744*4882a593Smuzhiyun
745*4882a593Smuzhiyun #define FUNC_GROUP_DECL(func, ...) \
746*4882a593Smuzhiyun GROUP_DECL(func, __VA_ARGS__); \
747*4882a593Smuzhiyun FUNC_DECL_(func, #func)
748*4882a593Smuzhiyun
749*4882a593Smuzhiyun
750*4882a593Smuzhiyun #define GPIO_PIN_DECL(pin, gpio) \
751*4882a593Smuzhiyun SIG_EXPR_LIST_DECL_SESG(pin, gpio, gpio); \
752*4882a593Smuzhiyun PIN_DECL_(pin, SIG_EXPR_LIST_PTR(pin, gpio))
753*4882a593Smuzhiyun
754*4882a593Smuzhiyun struct aspeed_pin_group {
755*4882a593Smuzhiyun const char *name;
756*4882a593Smuzhiyun const unsigned int *pins;
757*4882a593Smuzhiyun const unsigned int npins;
758*4882a593Smuzhiyun };
759*4882a593Smuzhiyun
760*4882a593Smuzhiyun #define ASPEED_PINCTRL_GROUP(name_) { \
761*4882a593Smuzhiyun .name = #name_, \
762*4882a593Smuzhiyun .pins = &(GROUP_SYM(name_))[0], \
763*4882a593Smuzhiyun .npins = ARRAY_SIZE(GROUP_SYM(name_)), \
764*4882a593Smuzhiyun }
765*4882a593Smuzhiyun
766*4882a593Smuzhiyun struct aspeed_pin_function {
767*4882a593Smuzhiyun const char *name;
768*4882a593Smuzhiyun const char *const *groups;
769*4882a593Smuzhiyun unsigned int ngroups;
770*4882a593Smuzhiyun };
771*4882a593Smuzhiyun
772*4882a593Smuzhiyun #define ASPEED_PINCTRL_FUNC(name_, ...) { \
773*4882a593Smuzhiyun .name = #name_, \
774*4882a593Smuzhiyun .groups = &FUNC_SYM(name_)[0], \
775*4882a593Smuzhiyun .ngroups = ARRAY_SIZE(FUNC_SYM(name_)), \
776*4882a593Smuzhiyun }
777*4882a593Smuzhiyun
778*4882a593Smuzhiyun struct aspeed_pinmux_data;
779*4882a593Smuzhiyun
780*4882a593Smuzhiyun struct aspeed_pinmux_ops {
781*4882a593Smuzhiyun int (*eval)(struct aspeed_pinmux_data *ctx,
782*4882a593Smuzhiyun const struct aspeed_sig_expr *expr, bool enabled);
783*4882a593Smuzhiyun int (*set)(struct aspeed_pinmux_data *ctx,
784*4882a593Smuzhiyun const struct aspeed_sig_expr *expr, bool enabled);
785*4882a593Smuzhiyun };
786*4882a593Smuzhiyun
787*4882a593Smuzhiyun struct aspeed_pinmux_data {
788*4882a593Smuzhiyun struct device *dev;
789*4882a593Smuzhiyun struct regmap *maps[ASPEED_NR_PINMUX_IPS];
790*4882a593Smuzhiyun
791*4882a593Smuzhiyun const struct aspeed_pinmux_ops *ops;
792*4882a593Smuzhiyun
793*4882a593Smuzhiyun const struct aspeed_pin_group *groups;
794*4882a593Smuzhiyun const unsigned int ngroups;
795*4882a593Smuzhiyun
796*4882a593Smuzhiyun const struct aspeed_pin_function *functions;
797*4882a593Smuzhiyun const unsigned int nfunctions;
798*4882a593Smuzhiyun };
799*4882a593Smuzhiyun
800*4882a593Smuzhiyun int aspeed_sig_desc_eval(const struct aspeed_sig_desc *desc, bool enabled,
801*4882a593Smuzhiyun struct regmap *map);
802*4882a593Smuzhiyun
803*4882a593Smuzhiyun int aspeed_sig_expr_eval(struct aspeed_pinmux_data *ctx,
804*4882a593Smuzhiyun const struct aspeed_sig_expr *expr, bool enabled);
805*4882a593Smuzhiyun
aspeed_sig_expr_set(struct aspeed_pinmux_data * ctx,const struct aspeed_sig_expr * expr,bool enabled)806*4882a593Smuzhiyun static inline int aspeed_sig_expr_set(struct aspeed_pinmux_data *ctx,
807*4882a593Smuzhiyun const struct aspeed_sig_expr *expr,
808*4882a593Smuzhiyun bool enabled)
809*4882a593Smuzhiyun {
810*4882a593Smuzhiyun return ctx->ops->set(ctx, expr, enabled);
811*4882a593Smuzhiyun }
812*4882a593Smuzhiyun
813*4882a593Smuzhiyun #endif /* ASPEED_PINMUX_H */
814