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, reg: desc->reg, val: &raw); |
52 | if (ret) |
53 | return ret; |
54 | |
55 | aspeed_sig_desc_print_val(desc, enable: enabled, rv: raw); |
56 | want = enabled ? desc->enable : desc->disable; |
57 | |
58 | return ((raw & desc->mask) >> __ffs(desc->mask)) == want; |
59 | } |
60 | |
61 | /** |
62 | * aspeed_sig_expr_eval - Query the enabled or disabled state for a |
63 | * mux function's signal on a pin |
64 | * |
65 | * @ctx: The driver context for the pinctrl IP |
66 | * @expr: An expression controlling the signal for a mux function on a pin |
67 | * @enabled: True to query the enabled state, false to query disabled state |
68 | * |
69 | * Return: 1 if the expression composed by @enabled evaluates true, 0 if not, |
70 | * and less than zero if an unrecoverable failure occurred. |
71 | * |
72 | * A mux function is enabled or disabled if the function's signal expression |
73 | * for each pin in the function's pin group evaluates true for the desired |
74 | * state. An signal expression evaluates true if all of its associated signal |
75 | * descriptors evaluate true for the desired state. |
76 | * |
77 | * If an expression's state is described by more than one bit, either through |
78 | * multi-bit bitfields in a single signal descriptor or through multiple signal |
79 | * descriptors of a single bit then it is possible for the expression to be in |
80 | * neither the enabled nor disabled state. Thus we must explicitly test for |
81 | * either condition as required. |
82 | */ |
83 | int aspeed_sig_expr_eval(struct aspeed_pinmux_data *ctx, |
84 | const struct aspeed_sig_expr *expr, bool enabled) |
85 | { |
86 | int ret; |
87 | int i; |
88 | |
89 | if (ctx->ops->eval) |
90 | return ctx->ops->eval(ctx, expr, enabled); |
91 | |
92 | for (i = 0; i < expr->ndescs; i++) { |
93 | const struct aspeed_sig_desc *desc = &expr->descs[i]; |
94 | |
95 | ret = aspeed_sig_desc_eval(desc, enabled, map: ctx->maps[desc->ip]); |
96 | if (ret <= 0) |
97 | return ret; |
98 | } |
99 | |
100 | return 1; |
101 | } |
102 | |