Merge remote-tracking branch 'torvalds/master' into perf/core
[linux-2.6-microblaze.git] / drivers / pinctrl / aspeed / pinmux-aspeed.c
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  * aspeed_sig_desc_eval() - Query the enabled or disabled state of a signal
25  * descriptor.
26  *
27  * @desc: The signal descriptor of interest
28  * @enabled: True to query the enabled state, false to query disabled state
29  * @map: The IP block's regmap instance
30  *
31  * Return: 1 if the descriptor's bitfield is configured to the state
32  * selected by @enabled, 0 if not, and less than zero if an unrecoverable
33  * failure occurred
34  *
35  * Evaluation of descriptor state is non-trivial in that it is not a binary
36  * outcome: The bitfields can be greater than one bit in size and thus can take
37  * a value that is neither the enabled nor disabled state recorded in the
38  * descriptor (typically this means a different function to the one of interest
39  * is enabled). Thus we must explicitly test for either condition as required.
40  */
41 int aspeed_sig_desc_eval(const struct aspeed_sig_desc *desc,
42                          bool enabled, struct regmap *map)
43 {
44         int ret;
45         unsigned int raw;
46         u32 want;
47
48         if (!map)
49                 return -ENODEV;
50
51         ret = regmap_read(map, desc->reg, &raw);
52         if (ret)
53                 return ret;
54
55         aspeed_sig_desc_print_val(desc, enabled, raw);
56         want = enabled ? desc->enable : desc->disable;
57
58         return ((raw & desc->mask) >> __ffs(desc->mask)) == want;
59 }
60
61 /**
62  * Query the enabled or disabled state for a mux function's signal on a pin
63  *
64  * @ctx: The driver context for the pinctrl IP
65  * @expr: An expression controlling the signal for a mux function on a pin
66  * @enabled: True to query the enabled state, false to query disabled state
67  *
68  * Return: 1 if the expression composed by @enabled evaluates true, 0 if not,
69  * and less than zero if an unrecoverable failure occurred.
70  *
71  * A mux function is enabled or disabled if the function's signal expression
72  * for each pin in the function's pin group evaluates true for the desired
73  * state. An signal expression evaluates true if all of its associated signal
74  * descriptors evaluate true for the desired state.
75  *
76  * If an expression's state is described by more than one bit, either through
77  * multi-bit bitfields in a single signal descriptor or through multiple signal
78  * descriptors of a single bit then it is possible for the expression to be in
79  * neither the enabled nor disabled state. Thus we must explicitly test for
80  * either condition as required.
81  */
82 int aspeed_sig_expr_eval(struct aspeed_pinmux_data *ctx,
83                          const struct aspeed_sig_expr *expr, bool enabled)
84 {
85         int ret;
86         int i;
87
88         if (ctx->ops->eval)
89                 return ctx->ops->eval(ctx, expr, enabled);
90
91         for (i = 0; i < expr->ndescs; i++) {
92                 const struct aspeed_sig_desc *desc = &expr->descs[i];
93
94                 ret = aspeed_sig_desc_eval(desc, enabled, ctx->maps[desc->ip]);
95                 if (ret <= 0)
96                         return ret;
97         }
98
99         return 1;
100 }