162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* Copyright (C) 2019 IBM Corp. */ 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci/* Pieces to enable drivers to implement the .set callback */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#include "pinmux-aspeed.h" 762306a36Sopenharmony_ci 862306a36Sopenharmony_cistatic const char *const aspeed_pinmux_ips[] = { 962306a36Sopenharmony_ci [ASPEED_IP_SCU] = "SCU", 1062306a36Sopenharmony_ci [ASPEED_IP_GFX] = "GFX", 1162306a36Sopenharmony_ci [ASPEED_IP_LPC] = "LPC", 1262306a36Sopenharmony_ci}; 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_cistatic inline void aspeed_sig_desc_print_val( 1562306a36Sopenharmony_ci const struct aspeed_sig_desc *desc, bool enable, u32 rv) 1662306a36Sopenharmony_ci{ 1762306a36Sopenharmony_ci pr_debug("Want %s%X[0x%08X]=0x%X, got 0x%X from 0x%08X\n", 1862306a36Sopenharmony_ci aspeed_pinmux_ips[desc->ip], desc->reg, 1962306a36Sopenharmony_ci desc->mask, enable ? desc->enable : desc->disable, 2062306a36Sopenharmony_ci (rv & desc->mask) >> __ffs(desc->mask), rv); 2162306a36Sopenharmony_ci} 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci/** 2462306a36Sopenharmony_ci * aspeed_sig_desc_eval() - Query the enabled or disabled state of a signal 2562306a36Sopenharmony_ci * descriptor. 2662306a36Sopenharmony_ci * 2762306a36Sopenharmony_ci * @desc: The signal descriptor of interest 2862306a36Sopenharmony_ci * @enabled: True to query the enabled state, false to query disabled state 2962306a36Sopenharmony_ci * @map: The IP block's regmap instance 3062306a36Sopenharmony_ci * 3162306a36Sopenharmony_ci * Return: 1 if the descriptor's bitfield is configured to the state 3262306a36Sopenharmony_ci * selected by @enabled, 0 if not, and less than zero if an unrecoverable 3362306a36Sopenharmony_ci * failure occurred 3462306a36Sopenharmony_ci * 3562306a36Sopenharmony_ci * Evaluation of descriptor state is non-trivial in that it is not a binary 3662306a36Sopenharmony_ci * outcome: The bitfields can be greater than one bit in size and thus can take 3762306a36Sopenharmony_ci * a value that is neither the enabled nor disabled state recorded in the 3862306a36Sopenharmony_ci * descriptor (typically this means a different function to the one of interest 3962306a36Sopenharmony_ci * is enabled). Thus we must explicitly test for either condition as required. 4062306a36Sopenharmony_ci */ 4162306a36Sopenharmony_ciint aspeed_sig_desc_eval(const struct aspeed_sig_desc *desc, 4262306a36Sopenharmony_ci bool enabled, struct regmap *map) 4362306a36Sopenharmony_ci{ 4462306a36Sopenharmony_ci int ret; 4562306a36Sopenharmony_ci unsigned int raw; 4662306a36Sopenharmony_ci u32 want; 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci if (!map) 4962306a36Sopenharmony_ci return -ENODEV; 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci ret = regmap_read(map, desc->reg, &raw); 5262306a36Sopenharmony_ci if (ret) 5362306a36Sopenharmony_ci return ret; 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci aspeed_sig_desc_print_val(desc, enabled, raw); 5662306a36Sopenharmony_ci want = enabled ? desc->enable : desc->disable; 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci return ((raw & desc->mask) >> __ffs(desc->mask)) == want; 5962306a36Sopenharmony_ci} 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci/** 6262306a36Sopenharmony_ci * aspeed_sig_expr_eval - Query the enabled or disabled state for a 6362306a36Sopenharmony_ci * mux function's signal on a pin 6462306a36Sopenharmony_ci * 6562306a36Sopenharmony_ci * @ctx: The driver context for the pinctrl IP 6662306a36Sopenharmony_ci * @expr: An expression controlling the signal for a mux function on a pin 6762306a36Sopenharmony_ci * @enabled: True to query the enabled state, false to query disabled state 6862306a36Sopenharmony_ci * 6962306a36Sopenharmony_ci * Return: 1 if the expression composed by @enabled evaluates true, 0 if not, 7062306a36Sopenharmony_ci * and less than zero if an unrecoverable failure occurred. 7162306a36Sopenharmony_ci * 7262306a36Sopenharmony_ci * A mux function is enabled or disabled if the function's signal expression 7362306a36Sopenharmony_ci * for each pin in the function's pin group evaluates true for the desired 7462306a36Sopenharmony_ci * state. An signal expression evaluates true if all of its associated signal 7562306a36Sopenharmony_ci * descriptors evaluate true for the desired state. 7662306a36Sopenharmony_ci * 7762306a36Sopenharmony_ci * If an expression's state is described by more than one bit, either through 7862306a36Sopenharmony_ci * multi-bit bitfields in a single signal descriptor or through multiple signal 7962306a36Sopenharmony_ci * descriptors of a single bit then it is possible for the expression to be in 8062306a36Sopenharmony_ci * neither the enabled nor disabled state. Thus we must explicitly test for 8162306a36Sopenharmony_ci * either condition as required. 8262306a36Sopenharmony_ci */ 8362306a36Sopenharmony_ciint aspeed_sig_expr_eval(struct aspeed_pinmux_data *ctx, 8462306a36Sopenharmony_ci const struct aspeed_sig_expr *expr, bool enabled) 8562306a36Sopenharmony_ci{ 8662306a36Sopenharmony_ci int ret; 8762306a36Sopenharmony_ci int i; 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci if (ctx->ops->eval) 9062306a36Sopenharmony_ci return ctx->ops->eval(ctx, expr, enabled); 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci for (i = 0; i < expr->ndescs; i++) { 9362306a36Sopenharmony_ci const struct aspeed_sig_desc *desc = &expr->descs[i]; 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci ret = aspeed_sig_desc_eval(desc, enabled, ctx->maps[desc->ip]); 9662306a36Sopenharmony_ci if (ret <= 0) 9762306a36Sopenharmony_ci return ret; 9862306a36Sopenharmony_ci } 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci return 1; 10162306a36Sopenharmony_ci} 102