18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* Copyright (C) 2019 IBM Corp. */ 38c2ecf20Sopenharmony_ci 48c2ecf20Sopenharmony_ci/* Pieces to enable drivers to implement the .set callback */ 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#include "pinmux-aspeed.h" 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_cistatic const char *const aspeed_pinmux_ips[] = { 98c2ecf20Sopenharmony_ci [ASPEED_IP_SCU] = "SCU", 108c2ecf20Sopenharmony_ci [ASPEED_IP_GFX] = "GFX", 118c2ecf20Sopenharmony_ci [ASPEED_IP_LPC] = "LPC", 128c2ecf20Sopenharmony_ci}; 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_cistatic inline void aspeed_sig_desc_print_val( 158c2ecf20Sopenharmony_ci const struct aspeed_sig_desc *desc, bool enable, u32 rv) 168c2ecf20Sopenharmony_ci{ 178c2ecf20Sopenharmony_ci pr_debug("Want %s%X[0x%08X]=0x%X, got 0x%X from 0x%08X\n", 188c2ecf20Sopenharmony_ci aspeed_pinmux_ips[desc->ip], desc->reg, 198c2ecf20Sopenharmony_ci desc->mask, enable ? desc->enable : desc->disable, 208c2ecf20Sopenharmony_ci (rv & desc->mask) >> __ffs(desc->mask), rv); 218c2ecf20Sopenharmony_ci} 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci/** 248c2ecf20Sopenharmony_ci * Query the enabled or disabled state of a signal descriptor 258c2ecf20Sopenharmony_ci * 268c2ecf20Sopenharmony_ci * @desc: The signal descriptor of interest 278c2ecf20Sopenharmony_ci * @enabled: True to query the enabled state, false to query disabled state 288c2ecf20Sopenharmony_ci * @map: The IP block's regmap instance 298c2ecf20Sopenharmony_ci * 308c2ecf20Sopenharmony_ci * Return: 1 if the descriptor's bitfield is configured to the state 318c2ecf20Sopenharmony_ci * selected by @enabled, 0 if not, and less than zero if an unrecoverable 328c2ecf20Sopenharmony_ci * failure occurred 338c2ecf20Sopenharmony_ci * 348c2ecf20Sopenharmony_ci * Evaluation of descriptor state is non-trivial in that it is not a binary 358c2ecf20Sopenharmony_ci * outcome: The bitfields can be greater than one bit in size and thus can take 368c2ecf20Sopenharmony_ci * a value that is neither the enabled nor disabled state recorded in the 378c2ecf20Sopenharmony_ci * descriptor (typically this means a different function to the one of interest 388c2ecf20Sopenharmony_ci * is enabled). Thus we must explicitly test for either condition as required. 398c2ecf20Sopenharmony_ci */ 408c2ecf20Sopenharmony_ciint aspeed_sig_desc_eval(const struct aspeed_sig_desc *desc, 418c2ecf20Sopenharmony_ci bool enabled, struct regmap *map) 428c2ecf20Sopenharmony_ci{ 438c2ecf20Sopenharmony_ci int ret; 448c2ecf20Sopenharmony_ci unsigned int raw; 458c2ecf20Sopenharmony_ci u32 want; 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci if (!map) 488c2ecf20Sopenharmony_ci return -ENODEV; 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci ret = regmap_read(map, desc->reg, &raw); 518c2ecf20Sopenharmony_ci if (ret) 528c2ecf20Sopenharmony_ci return ret; 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci aspeed_sig_desc_print_val(desc, enabled, raw); 558c2ecf20Sopenharmony_ci want = enabled ? desc->enable : desc->disable; 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci return ((raw & desc->mask) >> __ffs(desc->mask)) == want; 588c2ecf20Sopenharmony_ci} 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci/** 618c2ecf20Sopenharmony_ci * Query the enabled or disabled state for a mux function's signal on a pin 628c2ecf20Sopenharmony_ci * 638c2ecf20Sopenharmony_ci * @ctx: The driver context for the pinctrl IP 648c2ecf20Sopenharmony_ci * @expr: An expression controlling the signal for a mux function on a pin 658c2ecf20Sopenharmony_ci * @enabled: True to query the enabled state, false to query disabled state 668c2ecf20Sopenharmony_ci * 678c2ecf20Sopenharmony_ci * Return: 1 if the expression composed by @enabled evaluates true, 0 if not, 688c2ecf20Sopenharmony_ci * and less than zero if an unrecoverable failure occurred. 698c2ecf20Sopenharmony_ci * 708c2ecf20Sopenharmony_ci * A mux function is enabled or disabled if the function's signal expression 718c2ecf20Sopenharmony_ci * for each pin in the function's pin group evaluates true for the desired 728c2ecf20Sopenharmony_ci * state. An signal expression evaluates true if all of its associated signal 738c2ecf20Sopenharmony_ci * descriptors evaluate true for the desired state. 748c2ecf20Sopenharmony_ci * 758c2ecf20Sopenharmony_ci * If an expression's state is described by more than one bit, either through 768c2ecf20Sopenharmony_ci * multi-bit bitfields in a single signal descriptor or through multiple signal 778c2ecf20Sopenharmony_ci * descriptors of a single bit then it is possible for the expression to be in 788c2ecf20Sopenharmony_ci * neither the enabled nor disabled state. Thus we must explicitly test for 798c2ecf20Sopenharmony_ci * either condition as required. 808c2ecf20Sopenharmony_ci */ 818c2ecf20Sopenharmony_ciint aspeed_sig_expr_eval(struct aspeed_pinmux_data *ctx, 828c2ecf20Sopenharmony_ci const struct aspeed_sig_expr *expr, bool enabled) 838c2ecf20Sopenharmony_ci{ 848c2ecf20Sopenharmony_ci int ret; 858c2ecf20Sopenharmony_ci int i; 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci if (ctx->ops->eval) 888c2ecf20Sopenharmony_ci return ctx->ops->eval(ctx, expr, enabled); 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci for (i = 0; i < expr->ndescs; i++) { 918c2ecf20Sopenharmony_ci const struct aspeed_sig_desc *desc = &expr->descs[i]; 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci ret = aspeed_sig_desc_eval(desc, enabled, ctx->maps[desc->ip]); 948c2ecf20Sopenharmony_ci if (ret <= 0) 958c2ecf20Sopenharmony_ci return ret; 968c2ecf20Sopenharmony_ci } 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci return 1; 998c2ecf20Sopenharmony_ci} 100