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