1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* Copyright (C) 2019 IBM Corp. */
3 
4 /* Pieces to enable drivers to implement the .set callback */
5 
6 #include "pinmux-aspeed.h"
7 
8 static const char *const aspeed_pinmux_ips[] = {
9 	[ASPEED_IP_SCU] = "SCU",
10 	[ASPEED_IP_GFX] = "GFX",
11 	[ASPEED_IP_LPC] = "LPC",
12 };
13 
14 static inline void aspeed_sig_desc_print_val(
15 		const struct aspeed_sig_desc *desc, bool enable, u32 rv)
16 {
17 	pr_debug("Want %s%X[0x%08X]=0x%X, got 0x%X from 0x%08X\n",
18 			aspeed_pinmux_ips[desc->ip], desc->reg,
19 			desc->mask, enable ? desc->enable : desc->disable,
20 			(rv & desc->mask) >> __ffs(desc->mask), rv);
21 }
22 
23 /**
24  * Query the enabled or disabled state of a signal descriptor
25  *
26  * @desc: The signal descriptor of interest
27  * @enabled: True to query the enabled state, false to query disabled state
28  * @map: The IP block's regmap instance
29  *
30  * Return: 1 if the descriptor's bitfield is configured to the state
31  * selected by @enabled, 0 if not, and less than zero if an unrecoverable
32  * failure occurred
33  *
34  * Evaluation of descriptor state is non-trivial in that it is not a binary
35  * outcome: The bitfields can be greater than one bit in size and thus can take
36  * a value that is neither the enabled nor disabled state recorded in the
37  * descriptor (typically this means a different function to the one of interest
38  * is enabled). Thus we must explicitly test for either condition as required.
39  */
40 int aspeed_sig_desc_eval(const struct aspeed_sig_desc *desc,
41 			 bool enabled, struct regmap *map)
42 {
43 	int ret;
44 	unsigned int raw;
45 	u32 want;
46 
47 	if (!map)
48 		return -ENODEV;
49 
50 	ret = regmap_read(map, desc->reg, &raw);
51 	if (ret)
52 		return ret;
53 
54 	aspeed_sig_desc_print_val(desc, enabled, raw);
55 	want = enabled ? desc->enable : desc->disable;
56 
57 	return ((raw & desc->mask) >> __ffs(desc->mask)) == want;
58 }
59 
60 /**
61  * Query the enabled or disabled state for a mux function's signal on a pin
62  *
63  * @ctx: The driver context for the pinctrl IP
64  * @expr: An expression controlling the signal for a mux function on a pin
65  * @enabled: True to query the enabled state, false to query disabled state
66  *
67  * Return: 1 if the expression composed by @enabled evaluates true, 0 if not,
68  * and less than zero if an unrecoverable failure occurred.
69  *
70  * A mux function is enabled or disabled if the function's signal expression
71  * for each pin in the function's pin group evaluates true for the desired
72  * state. An signal expression evaluates true if all of its associated signal
73  * descriptors evaluate true for the desired state.
74  *
75  * If an expression's state is described by more than one bit, either through
76  * multi-bit bitfields in a single signal descriptor or through multiple signal
77  * descriptors of a single bit then it is possible for the expression to be in
78  * neither the enabled nor disabled state. Thus we must explicitly test for
79  * either condition as required.
80  */
81 int aspeed_sig_expr_eval(struct aspeed_pinmux_data *ctx,
82 			 const struct aspeed_sig_expr *expr, bool enabled)
83 {
84 	int ret;
85 	int i;
86 
87 	if (ctx->ops->eval)
88 		return ctx->ops->eval(ctx, expr, enabled);
89 
90 	for (i = 0; i < expr->ndescs; i++) {
91 		const struct aspeed_sig_desc *desc = &expr->descs[i];
92 
93 		ret = aspeed_sig_desc_eval(desc, enabled, ctx->maps[desc->ip]);
94 		if (ret <= 0)
95 			return ret;
96 	}
97 
98 	return 1;
99 }
100