From nobody Thu May 16 23:22:54 2024 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id D0D30C77B72 for ; Mon, 17 Apr 2023 19:51:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230336AbjDQTvP (ORCPT ); Mon, 17 Apr 2023 15:51:15 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58610 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230312AbjDQTvM (ORCPT ); Mon, 17 Apr 2023 15:51:12 -0400 Received: from mail-yb1-xb2d.google.com (mail-yb1-xb2d.google.com [IPv6:2607:f8b0:4864:20::b2d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0F04346A8 for ; Mon, 17 Apr 2023 12:51:06 -0700 (PDT) Received: by mail-yb1-xb2d.google.com with SMTP id o11so8296315ybk.11 for ; Mon, 17 Apr 2023 12:51:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1681761065; x=1684353065; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=GlSrap1bzXBmwnplUgP8mtHdzj46PthZOVye53HSV2c=; b=AGKunyIPlr3hYKgg6D1FDqrpfk4MC2Ud7ir6bvEJGrMOtrDvDI9+YCDquhVglyU8kv yVEs/X6/r8ELCvb5+TqRrfrtBEqhZGVp5mDXarpDLn4cO1wJzU4bHe/N3DYTfC3T+yiJ o/VT331GSKj7DU2PAM838NXPexmtK7D73DqLHQvW4E4haHveaZ34eyVH07ukRHP1T7wL +s5ABL+6DjqEMR4HDXHJHCUB7JWYOivPdQIpfZz74IE/Vy5dn41c4j28hpJY7HqHizs4 PokymNnAe7d+XtqkmlGreGMhMLr2FyEKwu/cO57x2ON2e3Dk5gWEiSv/ssKsMuhmQHAz zDHw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1681761065; x=1684353065; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=GlSrap1bzXBmwnplUgP8mtHdzj46PthZOVye53HSV2c=; b=ZDR1ggVNS7xblSwtjy+YfwVQKsqqnpmv0IJg3ODm9Knxf8yZodIjk3J8e9OI25ZcVa CWBjZhxpRTLneDJzLqK53y83r/DYZNiBhatp04TPQGdDxGUq/1TFG3uByswV/pzV7rIP e5Wryl/7xddsBd3dBaFE4WENvgTgwEkdlS7/z+cQMe5kT9C3fwj6QZyF8xX4Dq/Ke4T+ qqs+ZvkFHPlfdFUO37beicJj30TLzmIn4gyafMY6D1x7aTpDutkY7x+Jdj4fl2kIS0Dw VUeapXuFDjs3sKjz7CEvuGZYePxWnKcusfYbVeynAZv4m6wRROWvXk+lysLjMNuRnC2K 9Jew== X-Gm-Message-State: AAQBX9dQgkCzzvMfkaJwRsO6OlX6rH1tZbokIAfxTKTTf3vRS//xTpVG YAllLTg8O2lJOuCqIsuD8NBhfw== X-Google-Smtp-Source: AKy350bBAQVoIc4Xg9dbSJy8cO2o3CkeRJYQGBttWGg262oWNzW4mOgdOeNjq+iiXzyyZx+wYXChqQ== X-Received: by 2002:a25:680c:0:b0:b7e:518e:bdad with SMTP id d12-20020a25680c000000b00b7e518ebdadmr15167420ybc.6.1681761065145; Mon, 17 Apr 2023 12:51:05 -0700 (PDT) Received: from fedora.attlocal.net (69-109-179-158.lightspeed.dybhfl.sbcglobal.net. [69.109.179.158]) by smtp.gmail.com with ESMTPSA id u125-20020a817983000000b005463f6ae720sm3293158ywc.68.2023.04.17.12.51.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 17 Apr 2023 12:51:04 -0700 (PDT) From: William Breathitt Gray To: linux-iio@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Andy Shevchenko , Johannes Berg , Jonathan Cameron , Andrew Morton , Al Viro , Nathan Chancellor , Nick Desaulniers , William Breathitt Gray Subject: [PATCH v4 1/4] counter: 104-quad-8: Utilize bitfield access macros Date: Mon, 17 Apr 2023 15:50:47 -0400 Message-Id: <7cea5ad049c75d8d1c6f25e288aa743a8d2a25d8.1681753140.git.william.gray@linaro.org> X-Mailer: git-send-email 2.39.2 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" The 104-QUAD-8 features several registers with various bitfields. Utilize bitfield access macros such as u8_get_bits() and u8_encode_bits() to make the code easier to read and the intent clearer. Suggested-by: Jonathan Cameron Signed-off-by: William Breathitt Gray --- Changes in v4: none Changes in v3: none Changes in v2: - Replace FIELD_PREP() and FIELD_GET() with u8_encode_bits() and u8_get_bits() drivers/counter/104-quad-8.c | 274 ++++++++++++++++++++++------------- 1 file changed, 172 insertions(+), 102 deletions(-) diff --git a/drivers/counter/104-quad-8.c b/drivers/counter/104-quad-8.c index d9cb937665cf..f07e4a9b946d 100644 --- a/drivers/counter/104-quad-8.c +++ b/drivers/counter/104-quad-8.c @@ -5,7 +5,8 @@ * * This driver supports the ACCES 104-QUAD-8 and ACCES 104-QUAD-4. */ -#include +#include +#include #include #include #include @@ -98,36 +99,108 @@ struct quad8 { }; =20 /* Error flag */ -#define QUAD8_FLAG_E BIT(4) +#define FLAG_E BIT(4) /* Up/Down flag */ -#define QUAD8_FLAG_UD BIT(5) +#define FLAG_UD BIT(5) + +#define REGISTER_SELECTION GENMASK(6, 5) + /* Reset and Load Signal Decoders */ -#define QUAD8_CTR_RLD 0x00 +#define SELECT_RLD u8_encode_bits(0x0, REGISTER_SELECTION) /* Counter Mode Register */ -#define QUAD8_CTR_CMR 0x20 +#define SELECT_CMR u8_encode_bits(0x1, REGISTER_SELECTION) /* Input / Output Control Register */ -#define QUAD8_CTR_IOR 0x40 +#define SELECT_IOR u8_encode_bits(0x2, REGISTER_SELECTION) /* Index Control Register */ -#define QUAD8_CTR_IDR 0x60 +#define SELECT_IDR u8_encode_bits(0x3, REGISTER_SELECTION) + +/* + * Reset and Load Signal Decoders + */ +#define RESETS GENMASK(2, 1) +#define LOADS GENMASK(4, 3) /* Reset Byte Pointer (three byte data pointer) */ -#define QUAD8_RLD_RESET_BP 0x01 -/* Reset Counter */ -#define QUAD8_RLD_RESET_CNTR 0x02 -/* Reset Borrow Toggle, Carry Toggle, Compare Toggle, and Sign flags */ -#define QUAD8_RLD_RESET_FLAGS 0x04 +#define RESET_BP BIT(0) +/* Reset Borrow Toggle, Carry toggle, Compare toggle, Sign, and Index flag= s */ +#define RESET_BT_CT_CPT_S_IDX u8_encode_bits(0x2, RESETS) /* Reset Error flag */ -#define QUAD8_RLD_RESET_E 0x06 +#define RESET_E u8_encode_bits(0x3, RESETS) /* Preset Register to Counter */ -#define QUAD8_RLD_PRESET_CNTR 0x08 +#define TRANSFER_PR_TO_CNTR u8_encode_bits(0x1, LOADS) /* Transfer Counter to Output Latch */ -#define QUAD8_RLD_CNTR_OUT 0x10 +#define TRANSFER_CNTR_TO_OL u8_encode_bits(0x2, LOADS) /* Transfer Preset Register LSB to FCK Prescaler */ -#define QUAD8_RLD_PRESET_PSC 0x18 -#define QUAD8_CHAN_OP_RESET_COUNTERS 0x01 -#define QUAD8_CHAN_OP_ENABLE_INTERRUPT_FUNC 0x04 -#define QUAD8_CMR_QUADRATURE_X1 0x08 -#define QUAD8_CMR_QUADRATURE_X2 0x10 -#define QUAD8_CMR_QUADRATURE_X4 0x18 +#define TRANSFER_PR0_TO_PSC u8_encode_bits(0x3, LOADS) + +/* + * Counter Mode Registers + */ +#define COUNT_ENCODING BIT(0) +#define COUNT_MODE GENMASK(2, 1) +#define QUADRATURE_MODE GENMASK(4, 3) +/* Binary count */ +#define BINARY u8_encode_bits(0x0, COUNT_ENCODING) +/* Normal count */ +#define NORMAL_COUNT 0x0 +/* Range Limit */ +#define RANGE_LIMIT 0x1 +/* Non-recycle count */ +#define NON_RECYCLE_COUNT 0x2 +/* Modulo-N */ +#define MODULO_N 0x3 +/* Non-quadrature */ +#define NON_QUADRATURE 0x0 +/* Quadrature X1 */ +#define QUADRATURE_X1 0x1 +/* Quadrature X2 */ +#define QUADRATURE_X2 0x2 +/* Quadrature X4 */ +#define QUADRATURE_X4 0x3 + +/* + * Input/Output Control Register + */ +#define AB_GATE BIT(0) +#define LOAD_PIN BIT(1) +#define FLG_PINS GENMASK(4, 3) +/* Disable inputs A and B */ +#define DISABLE_AB u8_encode_bits(0x0, AB_GATE) +/* Load Counter input */ +#define LOAD_CNTR 0x0 +/* FLG1 =3D CARRY(active low); FLG2 =3D BORROW(active low) */ +#define FLG1_CARRY_FLG2_BORROW 0x0 +/* FLG1 =3D COMPARE(active low); FLG2 =3D BORROW(active low) */ +#define FLG1_COMPARE_FLG2_BORROW 0x1 +/* FLG1 =3D Carry(active low)/Borrow(active low); FLG2 =3D U/D(active low)= flag */ +#define FLG1_CARRYBORROW_FLG2_UD 0x2 +/* FLG1 =3D INDX (low pulse at INDEX pin active level); FLG2 =3D E flag */ +#define FLG1_INDX_FLG2_E 0x3 + +/* + * INDEX CONTROL REGISTERS + */ +#define INDEX_MODE BIT(0) +#define INDEX_POLARITY BIT(1) +/* Disable Index mode */ +#define DISABLE_INDEX_MODE 0x0 +/* Negative Index Polarity */ +#define NEGATIVE_INDEX_POLARITY 0x0 + +/* + * Channel Operation Register + */ +#define COUNTERS_OPERATION BIT(0) +#define INTERRUPT_FUNCTION BIT(2) +/* Enable all Counters */ +#define ENABLE_COUNTERS u8_encode_bits(0x0, COUNTERS_OPERATION) +/* Reset all Counters */ +#define RESET_COUNTERS u8_encode_bits(0x1, COUNTERS_OPERATION) +/* Disable the interrupt function */ +#define DISABLE_INTERRUPT_FUNCTION u8_encode_bits(0x0, INTERRUPT_FUNCTION) +/* Enable the interrupt function */ +#define ENABLE_INTERRUPT_FUNCTION u8_encode_bits(0x1, INTERRUPT_FUNCTION) +/* Any write to the Channel Operation register clears any pending interrup= ts */ +#define CLEAR_PENDING_INTERRUPTS (ENABLE_COUNTERS | ENABLE_INTERRUPT_FUNCT= ION) =20 /* Each Counter is 24 bits wide */ #define LS7267_CNTR_MAX GENMASK(23, 0) @@ -162,9 +235,7 @@ static int quad8_count_read(struct counter_device *coun= ter, =20 spin_lock_irqsave(&priv->lock, irqflags); =20 - /* Reset Byte Pointer; transfer Counter to Output Latch */ - iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_CNTR_OUT, - &chan->control); + iowrite8(SELECT_RLD | RESET_BP | TRANSFER_CNTR_TO_OL, &chan->control); =20 for (i =3D 0; i < 3; i++) *val |=3D (unsigned long)ioread8(&chan->data) << (8 * i); @@ -187,28 +258,23 @@ static int quad8_count_write(struct counter_device *c= ounter, =20 spin_lock_irqsave(&priv->lock, irqflags); =20 - /* Reset Byte Pointer */ - iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control); + iowrite8(SELECT_RLD | RESET_BP, &chan->control); =20 /* Counter can only be set via Preset Register */ for (i =3D 0; i < 3; i++) iowrite8(val >> (8 * i), &chan->data); =20 - /* Transfer Preset Register to Counter */ - iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_PRESET_CNTR, &chan->control); + iowrite8(SELECT_RLD | TRANSFER_PR_TO_CNTR, &chan->control); =20 - /* Reset Byte Pointer */ - iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control); + iowrite8(SELECT_RLD | RESET_BP, &chan->control); =20 /* Set Preset Register back to original value */ val =3D priv->preset[count->id]; for (i =3D 0; i < 3; i++) iowrite8(val >> (8 * i), &chan->data); =20 - /* Reset Borrow, Carry, Compare, and Sign flags */ - iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_FLAGS, &chan->control); - /* Reset Error flag */ - iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_E, &chan->control); + iowrite8(SELECT_RLD | RESET_BT_CT_CPT_S_IDX, &chan->control); + iowrite8(SELECT_RLD | RESET_E, &chan->control); =20 spin_unlock_irqrestore(&priv->lock, irqflags); =20 @@ -279,8 +345,8 @@ static int quad8_function_write(struct counter_device *= counter, =20 spin_lock_irqsave(&priv->lock, irqflags); =20 - mode_cfg =3D priv->count_mode[id] << 1; - idr_cfg =3D priv->index_polarity[id] << 1; + mode_cfg =3D u8_encode_bits(priv->count_mode[id], COUNT_MODE); + idr_cfg =3D u8_encode_bits(priv->index_polarity[id], INDEX_POLARITY); =20 if (function =3D=3D COUNTER_FUNCTION_PULSE_DIRECTION) { *quadrature_mode =3D 0; @@ -288,11 +354,14 @@ static int quad8_function_write(struct counter_device= *counter, /* Quadrature scaling only available in quadrature mode */ *scale =3D 0; =20 + mode_cfg |=3D u8_encode_bits(NON_QUADRATURE, QUADRATURE_MODE); + /* Synchronous function not supported in non-quadrature mode */ if (*synchronous_mode) { *synchronous_mode =3D 0; /* Disable synchronous function mode */ - iowrite8(QUAD8_CTR_IDR | idr_cfg, control); + idr_cfg |=3D u8_encode_bits(*synchronous_mode, INDEX_MODE); + iowrite8(SELECT_IDR | idr_cfg, control); } } else { *quadrature_mode =3D 1; @@ -300,15 +369,15 @@ static int quad8_function_write(struct counter_device= *counter, switch (function) { case COUNTER_FUNCTION_QUADRATURE_X1_A: *scale =3D 0; - mode_cfg |=3D QUAD8_CMR_QUADRATURE_X1; + mode_cfg |=3D u8_encode_bits(QUADRATURE_X1, QUADRATURE_MODE); break; case COUNTER_FUNCTION_QUADRATURE_X2_A: *scale =3D 1; - mode_cfg |=3D QUAD8_CMR_QUADRATURE_X2; + mode_cfg |=3D u8_encode_bits(QUADRATURE_X2, QUADRATURE_MODE); break; case COUNTER_FUNCTION_QUADRATURE_X4: *scale =3D 2; - mode_cfg |=3D QUAD8_CMR_QUADRATURE_X4; + mode_cfg |=3D u8_encode_bits(QUADRATURE_X4, QUADRATURE_MODE); break; default: /* should never reach this path */ @@ -318,7 +387,7 @@ static int quad8_function_write(struct counter_device *= counter, } =20 /* Load mode configuration to Counter Mode Register */ - iowrite8(QUAD8_CTR_CMR | mode_cfg, control); + iowrite8(SELECT_CMR | mode_cfg, control); =20 spin_unlock_irqrestore(&priv->lock, irqflags); =20 @@ -332,9 +401,11 @@ static int quad8_direction_read(struct counter_device = *counter, const struct quad8 *const priv =3D counter_priv(counter); unsigned int ud_flag; u8 __iomem *const flag_addr =3D &priv->reg->channel[count->id].control; + u8 flag; =20 + flag =3D ioread8(flag_addr); /* U/D flag: nonzero =3D up, zero =3D down */ - ud_flag =3D ioread8(flag_addr) & QUAD8_FLAG_UD; + ud_flag =3D u8_get_bits(flag, FLAG_UD); =20 *direction =3D (ud_flag) ? COUNTER_COUNT_DIRECTION_FORWARD : COUNTER_COUNT_DIRECTION_BACKWARD; @@ -423,10 +494,10 @@ static int quad8_action_read(struct counter_device *c= ounter, } =20 enum { - QUAD8_EVENT_CARRY =3D 0, - QUAD8_EVENT_COMPARE =3D 1, - QUAD8_EVENT_CARRY_BORROW =3D 2, - QUAD8_EVENT_INDEX =3D 3, + QUAD8_EVENT_CARRY =3D FLG1_CARRY_FLG2_BORROW, + QUAD8_EVENT_COMPARE =3D FLG1_COMPARE_FLG2_BORROW, + QUAD8_EVENT_CARRY_BORROW =3D FLG1_CARRYBORROW_FLG2_UD, + QUAD8_EVENT_INDEX =3D FLG1_INDX_FLG2_E, }; =20 static int quad8_events_configure(struct counter_device *counter) @@ -471,10 +542,10 @@ static int quad8_events_configure(struct counter_devi= ce *counter) priv->irq_trigger[event_node->channel] =3D next_irq_trigger; =20 /* Load configuration to I/O Control Register */ - ior_cfg =3D priv->ab_enable[event_node->channel] | - priv->preset_enable[event_node->channel] << 1 | - priv->irq_trigger[event_node->channel] << 3; - iowrite8(QUAD8_CTR_IOR | ior_cfg, + ior_cfg =3D u8_encode_bits(priv->ab_enable[event_node->channel], AB_GATE= ) | + u8_encode_bits(priv->preset_enable[event_node->channel], LOAD_PIN) | + u8_encode_bits(priv->irq_trigger[event_node->channel], FLG_PINS); + iowrite8(SELECT_IOR | ior_cfg, &priv->reg->channel[event_node->channel].control); } =20 @@ -544,16 +615,16 @@ static int quad8_index_polarity_set(struct counter_de= vice *counter, const size_t channel_id =3D signal->id - 16; u8 __iomem *const control =3D &priv->reg->channel[channel_id].control; unsigned long irqflags; - unsigned int idr_cfg =3D index_polarity << 1; + unsigned int idr_cfg =3D u8_encode_bits(index_polarity, INDEX_POLARITY); =20 spin_lock_irqsave(&priv->lock, irqflags); =20 - idr_cfg |=3D priv->synchronous_mode[channel_id]; + idr_cfg |=3D u8_encode_bits(priv->synchronous_mode[channel_id], INDEX_MOD= E); =20 priv->index_polarity[channel_id] =3D index_polarity; =20 /* Load Index Control configuration to Index Control Register */ - iowrite8(QUAD8_CTR_IDR | idr_cfg, control); + iowrite8(SELECT_IDR | idr_cfg, control); =20 spin_unlock_irqrestore(&priv->lock, irqflags); =20 @@ -611,11 +682,11 @@ static int quad8_synchronous_mode_set(struct counter_= device *counter, const size_t channel_id =3D signal->id - 16; u8 __iomem *const control =3D &priv->reg->channel[channel_id].control; unsigned long irqflags; - unsigned int idr_cfg =3D synchronous_mode; + unsigned int idr_cfg =3D u8_encode_bits(synchronous_mode, INDEX_MODE); =20 spin_lock_irqsave(&priv->lock, irqflags); =20 - idr_cfg |=3D priv->index_polarity[channel_id] << 1; + idr_cfg |=3D u8_encode_bits(priv->index_polarity[channel_id], INDEX_POLAR= ITY); =20 /* Index function must be non-synchronous in non-quadrature mode */ if (synchronous_mode && !priv->quadrature_mode[channel_id]) { @@ -626,7 +697,7 @@ static int quad8_synchronous_mode_set(struct counter_de= vice *counter, priv->synchronous_mode[channel_id] =3D synchronous_mode; =20 /* Load Index Control configuration to Index Control Register */ - iowrite8(QUAD8_CTR_IDR | idr_cfg, control); + iowrite8(SELECT_IDR | idr_cfg, control); =20 spin_unlock_irqrestore(&priv->lock, irqflags); =20 @@ -648,18 +719,17 @@ static int quad8_count_mode_read(struct counter_devic= e *counter, { const struct quad8 *const priv =3D counter_priv(counter); =20 - /* Map 104-QUAD-8 count mode to Generic Counter count mode */ switch (priv->count_mode[count->id]) { - case 0: + case NORMAL_COUNT: *cnt_mode =3D COUNTER_COUNT_MODE_NORMAL; break; - case 1: + case RANGE_LIMIT: *cnt_mode =3D COUNTER_COUNT_MODE_RANGE_LIMIT; break; - case 2: + case NON_RECYCLE_COUNT: *cnt_mode =3D COUNTER_COUNT_MODE_NON_RECYCLE; break; - case 3: + case MODULO_N: *cnt_mode =3D COUNTER_COUNT_MODE_MODULO_N; break; } @@ -677,19 +747,18 @@ static int quad8_count_mode_write(struct counter_devi= ce *counter, u8 __iomem *const control =3D &priv->reg->channel[count->id].control; unsigned long irqflags; =20 - /* Map Generic Counter count mode to 104-QUAD-8 count mode */ switch (cnt_mode) { case COUNTER_COUNT_MODE_NORMAL: - count_mode =3D 0; + count_mode =3D NORMAL_COUNT; break; case COUNTER_COUNT_MODE_RANGE_LIMIT: - count_mode =3D 1; + count_mode =3D RANGE_LIMIT; break; case COUNTER_COUNT_MODE_NON_RECYCLE: - count_mode =3D 2; + count_mode =3D NON_RECYCLE_COUNT; break; case COUNTER_COUNT_MODE_MODULO_N: - count_mode =3D 3; + count_mode =3D MODULO_N; break; default: /* should never reach this path */ @@ -701,14 +770,16 @@ static int quad8_count_mode_write(struct counter_devi= ce *counter, priv->count_mode[count->id] =3D count_mode; =20 /* Set count mode configuration value */ - mode_cfg =3D count_mode << 1; + mode_cfg =3D u8_encode_bits(count_mode, COUNT_MODE); =20 /* Add quadrature mode configuration */ if (priv->quadrature_mode[count->id]) - mode_cfg |=3D (priv->quadrature_scale[count->id] + 1) << 3; + mode_cfg |=3D u8_encode_bits(priv->quadrature_scale[count->id] + 1, QUAD= RATURE_MODE); + else + mode_cfg |=3D u8_encode_bits(NON_QUADRATURE, QUADRATURE_MODE); =20 /* Load mode configuration to Counter Mode Register */ - iowrite8(QUAD8_CTR_CMR | mode_cfg, control); + iowrite8(SELECT_CMR | mode_cfg, control); =20 spin_unlock_irqrestore(&priv->lock, irqflags); =20 @@ -737,11 +808,12 @@ static int quad8_count_enable_write(struct counter_de= vice *counter, =20 priv->ab_enable[count->id] =3D enable; =20 - ior_cfg =3D enable | priv->preset_enable[count->id] << 1 | - priv->irq_trigger[count->id] << 3; + ior_cfg =3D u8_encode_bits(enable, AB_GATE) | + u8_encode_bits(priv->preset_enable[count->id], LOAD_PIN) | + u8_encode_bits(priv->irq_trigger[count->id], FLG_PINS); =20 /* Load I/O control configuration */ - iowrite8(QUAD8_CTR_IOR | ior_cfg, control); + iowrite8(SELECT_IOR | ior_cfg, control); =20 spin_unlock_irqrestore(&priv->lock, irqflags); =20 @@ -758,8 +830,10 @@ static int quad8_error_noise_get(struct counter_device= *counter, { const struct quad8 *const priv =3D counter_priv(counter); u8 __iomem *const flag_addr =3D &priv->reg->channel[count->id].control; + u8 flag; =20 - *noise_error =3D !!(ioread8(flag_addr) & QUAD8_FLAG_E); + flag =3D ioread8(flag_addr); + *noise_error =3D u8_get_bits(flag, FLAG_E); =20 return 0; } @@ -782,8 +856,7 @@ static void quad8_preset_register_set(struct quad8 *con= st priv, const int id, =20 priv->preset[id] =3D preset; =20 - /* Reset Byte Pointer */ - iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control); + iowrite8(SELECT_RLD | RESET_BP, &chan->control); =20 /* Set Preset Register */ for (i =3D 0; i < 3; i++) @@ -818,8 +891,8 @@ static int quad8_count_ceiling_read(struct counter_devi= ce *counter, =20 /* Range Limit and Modulo-N count modes use preset value as ceiling */ switch (priv->count_mode[count->id]) { - case 1: - case 3: + case RANGE_LIMIT: + case MODULO_N: *ceiling =3D priv->preset[count->id]; break; default: @@ -845,8 +918,8 @@ static int quad8_count_ceiling_write(struct counter_dev= ice *counter, =20 /* Range Limit and Modulo-N count modes use preset value as ceiling */ switch (priv->count_mode[count->id]) { - case 1: - case 3: + case RANGE_LIMIT: + case MODULO_N: quad8_preset_register_set(priv, count->id, ceiling); spin_unlock_irqrestore(&priv->lock, irqflags); return 0; @@ -884,11 +957,12 @@ static int quad8_count_preset_enable_write(struct cou= nter_device *counter, =20 priv->preset_enable[count->id] =3D preset_enable; =20 - ior_cfg =3D priv->ab_enable[count->id] | preset_enable << 1 | - priv->irq_trigger[count->id] << 3; + ior_cfg =3D u8_encode_bits(priv->ab_enable[count->id], AB_GATE) | + u8_encode_bits(preset_enable, LOAD_PIN) | + u8_encode_bits(priv->irq_trigger[count->id], FLG_PINS); =20 /* Load I/O control configuration to Input / Output Control Register */ - iowrite8(QUAD8_CTR_IOR | ior_cfg, control); + iowrite8(SELECT_IOR | ior_cfg, control); =20 spin_unlock_irqrestore(&priv->lock, irqflags); =20 @@ -987,13 +1061,11 @@ static int quad8_signal_fck_prescaler_write(struct c= ounter_device *counter, =20 priv->fck_prescaler[channel_id] =3D prescaler; =20 - /* Reset Byte Pointer */ - iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control); + iowrite8(SELECT_RLD | RESET_BP, &chan->control); =20 /* Set filter clock factor */ iowrite8(prescaler, &chan->data); - iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_PRESET_PSC, - &chan->control); + iowrite8(SELECT_RLD | RESET_BP | TRANSFER_PR0_TO_PSC, &chan->control); =20 spin_unlock_irqrestore(&priv->lock, irqflags); =20 @@ -1183,7 +1255,7 @@ static irqreturn_t quad8_irq_handler(int irq, void *p= rivate) } =20 /* Clear pending interrupts on device */ - iowrite8(QUAD8_CHAN_OP_ENABLE_INTERRUPT_FUNC, &priv->reg->channel_oper); + iowrite8(CLEAR_PENDING_INTERRUPTS, &priv->reg->channel_oper); =20 return IRQ_HANDLED; } @@ -1192,27 +1264,25 @@ static void quad8_init_counter(struct channel_reg _= _iomem *const chan) { unsigned long i; =20 - /* Reset Byte Pointer */ - iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control); + iowrite8(SELECT_RLD | RESET_BP, &chan->control); /* Reset filter clock factor */ iowrite8(0, &chan->data); - iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_PRESET_PSC, - &chan->control); - /* Reset Byte Pointer */ - iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control); + iowrite8(SELECT_RLD | RESET_BP | TRANSFER_PR0_TO_PSC, &chan->control); + iowrite8(SELECT_RLD | RESET_BP, &chan->control); /* Reset Preset Register */ for (i =3D 0; i < 3; i++) iowrite8(0x00, &chan->data); - /* Reset Borrow, Carry, Compare, and Sign flags */ - iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_FLAGS, &chan->control); - /* Reset Error flag */ - iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_E, &chan->control); + iowrite8(SELECT_RLD | RESET_BT_CT_CPT_S_IDX, &chan->control); + iowrite8(SELECT_RLD | RESET_E, &chan->control); /* Binary encoding; Normal count; non-quadrature mode */ - iowrite8(QUAD8_CTR_CMR, &chan->control); + iowrite8(SELECT_CMR | BINARY | u8_encode_bits(NORMAL_COUNT, COUNT_MODE) | + u8_encode_bits(NON_QUADRATURE, QUADRATURE_MODE), &chan->control); /* Disable A and B inputs; preset on index; FLG1 as Carry */ - iowrite8(QUAD8_CTR_IOR, &chan->control); + iowrite8(SELECT_IOR | DISABLE_AB | u8_encode_bits(LOAD_CNTR, LOAD_PIN) | + u8_encode_bits(FLG1_CARRY_FLG2_BORROW, FLG_PINS), &chan->control); /* Disable index function; negative index polarity */ - iowrite8(QUAD8_CTR_IDR, &chan->control); + iowrite8(SELECT_IDR | u8_encode_bits(DISABLE_INDEX_MODE, INDEX_MODE) | + u8_encode_bits(NEGATIVE_INDEX_POLARITY, INDEX_POLARITY), &chan->control= ); } =20 static int quad8_probe(struct device *dev, unsigned int id) @@ -1251,14 +1321,14 @@ static int quad8_probe(struct device *dev, unsigned= int id) /* Reset Index/Interrupt Register */ iowrite8(0x00, &priv->reg->index_interrupt); /* Reset all counters and disable interrupt function */ - iowrite8(QUAD8_CHAN_OP_RESET_COUNTERS, &priv->reg->channel_oper); + iowrite8(RESET_COUNTERS | DISABLE_INTERRUPT_FUNCTION, &priv->reg->channel= _oper); /* Set initial configuration for all counters */ for (i =3D 0; i < QUAD8_NUM_COUNTERS; i++) quad8_init_counter(priv->reg->channel + i); /* Disable Differential Encoder Cable Status for all channels */ iowrite8(0xFF, &priv->reg->cable_status); /* Enable all counters and enable interrupt function */ - iowrite8(QUAD8_CHAN_OP_ENABLE_INTERRUPT_FUNC, &priv->reg->channel_oper); + iowrite8(ENABLE_COUNTERS | ENABLE_INTERRUPT_FUNCTION, &priv->reg->channel= _oper); =20 err =3D devm_request_irq(&counter->dev, irq[id], quad8_irq_handler, IRQF_SHARED, counter->name, counter); --=20 2.39.2 From nobody Thu May 16 23:22:54 2024 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C680BC77B72 for ; Mon, 17 Apr 2023 19:51:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230428AbjDQTvR (ORCPT ); Mon, 17 Apr 2023 15:51:17 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58634 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230281AbjDQTvM (ORCPT ); Mon, 17 Apr 2023 15:51:12 -0400 Received: from mail-yw1-x112f.google.com (mail-yw1-x112f.google.com [IPv6:2607:f8b0:4864:20::112f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3BB6F46BC for ; Mon, 17 Apr 2023 12:51:07 -0700 (PDT) Received: by mail-yw1-x112f.google.com with SMTP id 00721157ae682-552fb3c2bb7so21868237b3.10 for ; Mon, 17 Apr 2023 12:51:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1681761066; x=1684353066; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=SLq1l3OH2+A6ANeXA+/7+wCVl6cBh6uGfESz9CJegvU=; b=ExOFN7svFt9oRiDuCm2EFNcyANcf9Cf1jBAcuJxDh2/1IwJSRJwcDHHEKjpcppraEk IbvxwT1vr46SW813yKBNSF4sgyJLtV1AumIQx/aKnrGvGQUAIyiR+bDf100xgoHwONo1 VDiAwwkI+zYeYW7+vq4VdprXCTWJygiPxWfgSa5oTEHH9PxNtgGlRif9YxhiovW/6+qU fS3x6w/0pU4EMWb8TWbAQDxum042CuM/k0iNfYsHKSJCITPYXwpGmM2cKIJ48VXrZ2Eo 4wMYNy09Mak0YBaFEw/NwlWI3S+SHVeU1XA/YD7oQS+mOEWYwwfio6ZEaAGXu+wdjxJx UHDg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1681761066; x=1684353066; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=SLq1l3OH2+A6ANeXA+/7+wCVl6cBh6uGfESz9CJegvU=; b=esJu6rG1rYNgBgaYp4I1ymI5NCm54Xa5Z2sWvGShExr5ZefX8qY8Gfa9d3mUmsVyYP 8HKp/oY2Zt/x1e4jhar9q/AzrEW+hsbNbam534s/t66wEaSpyo+Us3D+jtRTLvkt881b QuXZ7DrnWc5lnJOofm5FHUk2ho11q6POR0/BpHBH9skO+zyORBYp85Mf7eRecWKX+Oc9 Kw3vL3KlcvDVok3jwNOqMV53ptHXcX6mEAgVHNxR5uDjcYHZWCGXDb8eYPjLiBvSux5A D75UBq7MSBJ4HCmt0hWnTs97Xli3ZEGMBD+u3+Jfdd1eYO5voG1Nj7+2a1VAIbDL7UJ6 4CRw== X-Gm-Message-State: AAQBX9dn2AlwtFeeGTSsaquZrN7bx76CujSd3bibssySB4h54UQffgud a3nSbcZZUf34Kxzsh7rhiMlcdw== X-Google-Smtp-Source: AKy350YurKtAOpIuRF5N1ocDtcKdmgLzuw/ABBKHOrUG45ItY3tRyUxGiN5e7/fSYBJmM3QK5nuUlg== X-Received: by 2002:a81:9e11:0:b0:551:11e7:30cc with SMTP id m17-20020a819e11000000b0055111e730ccmr10315824ywj.22.1681761066081; Mon, 17 Apr 2023 12:51:06 -0700 (PDT) Received: from fedora.attlocal.net (69-109-179-158.lightspeed.dybhfl.sbcglobal.net. [69.109.179.158]) by smtp.gmail.com with ESMTPSA id u125-20020a817983000000b005463f6ae720sm3293158ywc.68.2023.04.17.12.51.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 17 Apr 2023 12:51:05 -0700 (PDT) From: William Breathitt Gray To: linux-iio@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Andy Shevchenko , Johannes Berg , Jonathan Cameron , Andrew Morton , Al Viro , Nathan Chancellor , Nick Desaulniers , William Breathitt Gray Subject: [PATCH v4 2/4] counter: 104-quad-8: Refactor to buffer states for CMR, IOR, and IDR Date: Mon, 17 Apr 2023 15:50:48 -0400 Message-Id: <48071415aed43ecdd8595174191b0d906205a9e3.1681753140.git.william.gray@linaro.org> X-Mailer: git-send-email 2.39.2 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" The 104-quad-8 driver buffers the device configuration states separately, however each device has only three control registers: CMR, IOR, and IDR. Refactoring to buffer the states of these control registers rather than each configuration separately results in succinct code that more closely matches what is happening on the device. Signed-off-by: William Breathitt Gray --- Changes in v4: none Changes in v3: - Add __always_inline attribute for quad8_control_register_update() Changes in v2: - Replace FIELD_PREP() and FIELD_GET() with u8_encode_bits() and u8_get_bits() - Replace FIELD_MODIFY() with u8p_replace_bits() - Wrap up control register update in quad8_control_register_update() drivers/counter/104-quad-8.c | 288 +++++++++++++---------------------- 1 file changed, 105 insertions(+), 183 deletions(-) diff --git a/drivers/counter/104-quad-8.c b/drivers/counter/104-quad-8.c index f07e4a9b946d..0188c9c4e4cb 100644 --- a/drivers/counter/104-quad-8.c +++ b/drivers/counter/104-quad-8.c @@ -68,32 +68,21 @@ struct quad8_reg { /** * struct quad8 - device private data structure * @lock: lock to prevent clobbering device states during R/W ops - * @counter: instance of the counter_device + * @cmr: array of Counter Mode Register states + * @ior: array of Input / Output Control Register states + * @idr: array of Index Control Register states * @fck_prescaler: array of filter clock prescaler configurations * @preset: array of preset values - * @count_mode: array of count mode configurations - * @quadrature_mode: array of quadrature mode configurations - * @quadrature_scale: array of quadrature mode scale configurations - * @ab_enable: array of A and B inputs enable configurations - * @preset_enable: array of set_to_preset_on_index attribute configurations - * @irq_trigger: array of current IRQ trigger function configurations - * @synchronous_mode: array of index function synchronous mode configurati= ons - * @index_polarity: array of index function polarity configurations * @cable_fault_enable: differential encoder cable status enable configura= tions * @reg: I/O address offset for the device registers */ struct quad8 { spinlock_t lock; + u8 cmr[QUAD8_NUM_COUNTERS]; + u8 ior[QUAD8_NUM_COUNTERS]; + u8 idr[QUAD8_NUM_COUNTERS]; unsigned int fck_prescaler[QUAD8_NUM_COUNTERS]; unsigned int preset[QUAD8_NUM_COUNTERS]; - unsigned int count_mode[QUAD8_NUM_COUNTERS]; - unsigned int quadrature_mode[QUAD8_NUM_COUNTERS]; - unsigned int quadrature_scale[QUAD8_NUM_COUNTERS]; - unsigned int ab_enable[QUAD8_NUM_COUNTERS]; - unsigned int preset_enable[QUAD8_NUM_COUNTERS]; - unsigned int irq_trigger[QUAD8_NUM_COUNTERS]; - unsigned int synchronous_mode[QUAD8_NUM_COUNTERS]; - unsigned int index_polarity[QUAD8_NUM_COUNTERS]; unsigned int cable_fault_enable; struct quad8_reg __iomem *reg; }; @@ -102,6 +91,8 @@ struct quad8 { #define FLAG_E BIT(4) /* Up/Down flag */ #define FLAG_UD BIT(5) +/* Counting up */ +#define UP 0x1 =20 #define REGISTER_SELECTION GENMASK(6, 5) =20 @@ -183,8 +174,12 @@ struct quad8 { #define INDEX_POLARITY BIT(1) /* Disable Index mode */ #define DISABLE_INDEX_MODE 0x0 +/* Enable Index mode */ +#define ENABLE_INDEX_MODE 0x1 /* Negative Index Polarity */ #define NEGATIVE_INDEX_POLARITY 0x0 +/* Positive Index Polarity */ +#define POSITIVE_INDEX_POLARITY 0x1 =20 /* * Channel Operation Register @@ -205,6 +200,14 @@ struct quad8 { /* Each Counter is 24 bits wide */ #define LS7267_CNTR_MAX GENMASK(23, 0) =20 +static __always_inline void quad8_control_register_update(struct quad8 *co= nst priv, u8 *const buf, + const size_t channel, const u8 val, + const u8 field) +{ + u8p_replace_bits(&buf[channel], val, field); + iowrite8(buf[channel], &priv->reg->channel[channel].control); +} + static int quad8_signal_read(struct counter_device *counter, struct counter_signal *signal, enum counter_signal_level *level) @@ -291,19 +294,17 @@ static const enum counter_function quad8_count_functi= ons_list[] =3D { static int quad8_function_get(const struct quad8 *const priv, const size_t= id, enum counter_function *const function) { - if (!priv->quadrature_mode[id]) { + switch (u8_get_bits(priv->cmr[id], QUADRATURE_MODE)) { + case NON_QUADRATURE: *function =3D COUNTER_FUNCTION_PULSE_DIRECTION; return 0; - } - - switch (priv->quadrature_scale[id]) { - case 0: + case QUADRATURE_X1: *function =3D COUNTER_FUNCTION_QUADRATURE_X1_A; return 0; - case 1: + case QUADRATURE_X2: *function =3D COUNTER_FUNCTION_QUADRATURE_X2_A; return 0; - case 2: + case QUADRATURE_X4: *function =3D COUNTER_FUNCTION_QUADRATURE_X4; return 0; default: @@ -335,59 +336,36 @@ static int quad8_function_write(struct counter_device= *counter, { struct quad8 *const priv =3D counter_priv(counter); const int id =3D count->id; - unsigned int *const quadrature_mode =3D priv->quadrature_mode + id; - unsigned int *const scale =3D priv->quadrature_scale + id; - unsigned int *const synchronous_mode =3D priv->synchronous_mode + id; - u8 __iomem *const control =3D &priv->reg->channel[id].control; unsigned long irqflags; unsigned int mode_cfg; - unsigned int idr_cfg; - - spin_lock_irqsave(&priv->lock, irqflags); - - mode_cfg =3D u8_encode_bits(priv->count_mode[id], COUNT_MODE); - idr_cfg =3D u8_encode_bits(priv->index_polarity[id], INDEX_POLARITY); + bool synchronous_mode; =20 - if (function =3D=3D COUNTER_FUNCTION_PULSE_DIRECTION) { - *quadrature_mode =3D 0; - - /* Quadrature scaling only available in quadrature mode */ - *scale =3D 0; - - mode_cfg |=3D u8_encode_bits(NON_QUADRATURE, QUADRATURE_MODE); + switch (function) { + case COUNTER_FUNCTION_PULSE_DIRECTION: + mode_cfg =3D NON_QUADRATURE; + break; + case COUNTER_FUNCTION_QUADRATURE_X1_A: + mode_cfg =3D QUADRATURE_X1; + break; + case COUNTER_FUNCTION_QUADRATURE_X2_A: + mode_cfg =3D QUADRATURE_X2; + break; + case COUNTER_FUNCTION_QUADRATURE_X4: + mode_cfg =3D QUADRATURE_X4; + break; + default: + /* should never reach this path */ + return -EINVAL; + } =20 - /* Synchronous function not supported in non-quadrature mode */ - if (*synchronous_mode) { - *synchronous_mode =3D 0; - /* Disable synchronous function mode */ - idr_cfg |=3D u8_encode_bits(*synchronous_mode, INDEX_MODE); - iowrite8(SELECT_IDR | idr_cfg, control); - } - } else { - *quadrature_mode =3D 1; + spin_lock_irqsave(&priv->lock, irqflags); =20 - switch (function) { - case COUNTER_FUNCTION_QUADRATURE_X1_A: - *scale =3D 0; - mode_cfg |=3D u8_encode_bits(QUADRATURE_X1, QUADRATURE_MODE); - break; - case COUNTER_FUNCTION_QUADRATURE_X2_A: - *scale =3D 1; - mode_cfg |=3D u8_encode_bits(QUADRATURE_X2, QUADRATURE_MODE); - break; - case COUNTER_FUNCTION_QUADRATURE_X4: - *scale =3D 2; - mode_cfg |=3D u8_encode_bits(QUADRATURE_X4, QUADRATURE_MODE); - break; - default: - /* should never reach this path */ - spin_unlock_irqrestore(&priv->lock, irqflags); - return -EINVAL; - } - } + /* Synchronous function not supported in non-quadrature mode */ + synchronous_mode =3D u8_get_bits(priv->idr[id], INDEX_MODE) =3D=3D ENABLE= _INDEX_MODE; + if (synchronous_mode && mode_cfg =3D=3D NON_QUADRATURE) + quad8_control_register_update(priv, priv->idr, id, DISABLE_INDEX_MODE, I= NDEX_MODE); =20 - /* Load mode configuration to Counter Mode Register */ - iowrite8(SELECT_CMR | mode_cfg, control); + quad8_control_register_update(priv, priv->cmr, id, mode_cfg, QUADRATURE_M= ODE); =20 spin_unlock_irqrestore(&priv->lock, irqflags); =20 @@ -399,15 +377,11 @@ static int quad8_direction_read(struct counter_device= *counter, enum counter_count_direction *direction) { const struct quad8 *const priv =3D counter_priv(counter); - unsigned int ud_flag; u8 __iomem *const flag_addr =3D &priv->reg->channel[count->id].control; u8 flag; =20 flag =3D ioread8(flag_addr); - /* U/D flag: nonzero =3D up, zero =3D down */ - ud_flag =3D u8_get_bits(flag, FLAG_UD); - - *direction =3D (ud_flag) ? COUNTER_COUNT_DIRECTION_FORWARD : + *direction =3D (u8_get_bits(flag, FLAG_UD) =3D=3D UP) ? COUNTER_COUNT_DIR= ECTION_FORWARD : COUNTER_COUNT_DIRECTION_BACKWARD; =20 return 0; @@ -437,13 +411,13 @@ static int quad8_action_read(struct counter_device *c= ounter, const size_t signal_a_id =3D count->synapses[0].signal->id; enum counter_count_direction direction; =20 + /* Default action mode */ + *action =3D COUNTER_SYNAPSE_ACTION_NONE; + /* Handle Index signals */ if (synapse->signal->id >=3D 16) { - if (!priv->preset_enable[count->id]) + if (u8_get_bits(priv->ior[count->id], LOAD_PIN) =3D=3D LOAD_CNTR) *action =3D COUNTER_SYNAPSE_ACTION_RISING_EDGE; - else - *action =3D COUNTER_SYNAPSE_ACTION_NONE; - return 0; } =20 @@ -463,9 +437,6 @@ static int quad8_action_read(struct counter_device *cou= nter, =20 spin_unlock_irqrestore(&priv->lock, irqflags); =20 - /* Default action mode */ - *action =3D COUNTER_SYNAPSE_ACTION_NONE; - /* Determine action mode based on current count function mode */ switch (function) { case COUNTER_FUNCTION_PULSE_DIRECTION: @@ -493,37 +464,29 @@ static int quad8_action_read(struct counter_device *c= ounter, } } =20 -enum { - QUAD8_EVENT_CARRY =3D FLG1_CARRY_FLG2_BORROW, - QUAD8_EVENT_COMPARE =3D FLG1_COMPARE_FLG2_BORROW, - QUAD8_EVENT_CARRY_BORROW =3D FLG1_CARRYBORROW_FLG2_UD, - QUAD8_EVENT_INDEX =3D FLG1_INDX_FLG2_E, -}; - static int quad8_events_configure(struct counter_device *counter) { struct quad8 *const priv =3D counter_priv(counter); unsigned long irq_enabled =3D 0; unsigned long irqflags; struct counter_event_node *event_node; - unsigned int next_irq_trigger; - unsigned long ior_cfg; + u8 flg_pins; =20 spin_lock_irqsave(&priv->lock, irqflags); =20 list_for_each_entry(event_node, &counter->events_list, l) { switch (event_node->event) { case COUNTER_EVENT_OVERFLOW: - next_irq_trigger =3D QUAD8_EVENT_CARRY; + flg_pins =3D FLG1_CARRY_FLG2_BORROW; break; case COUNTER_EVENT_THRESHOLD: - next_irq_trigger =3D QUAD8_EVENT_COMPARE; + flg_pins =3D FLG1_COMPARE_FLG2_BORROW; break; case COUNTER_EVENT_OVERFLOW_UNDERFLOW: - next_irq_trigger =3D QUAD8_EVENT_CARRY_BORROW; + flg_pins =3D FLG1_CARRYBORROW_FLG2_UD; break; case COUNTER_EVENT_INDEX: - next_irq_trigger =3D QUAD8_EVENT_INDEX; + flg_pins =3D FLG1_INDX_FLG2_E; break; default: /* should never reach this path */ @@ -535,18 +498,12 @@ static int quad8_events_configure(struct counter_devi= ce *counter) irq_enabled |=3D BIT(event_node->channel); =20 /* Skip configuration if it is the same as previously set */ - if (priv->irq_trigger[event_node->channel] =3D=3D next_irq_trigger) + if (flg_pins =3D=3D u8_get_bits(priv->ior[event_node->channel], FLG_PINS= )) continue; =20 /* Save new IRQ function configuration */ - priv->irq_trigger[event_node->channel] =3D next_irq_trigger; - - /* Load configuration to I/O Control Register */ - ior_cfg =3D u8_encode_bits(priv->ab_enable[event_node->channel], AB_GATE= ) | - u8_encode_bits(priv->preset_enable[event_node->channel], LOAD_PIN) | - u8_encode_bits(priv->irq_trigger[event_node->channel], FLG_PINS); - iowrite8(SELECT_IOR | ior_cfg, - &priv->reg->channel[event_node->channel].control); + quad8_control_register_update(priv, priv->ior, event_node->channel, flg_= pins, + FLG_PINS); } =20 iowrite8(irq_enabled, &priv->reg->index_interrupt); @@ -602,7 +559,7 @@ static int quad8_index_polarity_get(struct counter_devi= ce *counter, const struct quad8 *const priv =3D counter_priv(counter); const size_t channel_id =3D signal->id - 16; =20 - *index_polarity =3D priv->index_polarity[channel_id]; + *index_polarity =3D u8_get_bits(priv->idr[channel_id], INDEX_POLARITY); =20 return 0; } @@ -613,18 +570,11 @@ static int quad8_index_polarity_set(struct counter_de= vice *counter, { struct quad8 *const priv =3D counter_priv(counter); const size_t channel_id =3D signal->id - 16; - u8 __iomem *const control =3D &priv->reg->channel[channel_id].control; unsigned long irqflags; - unsigned int idr_cfg =3D u8_encode_bits(index_polarity, INDEX_POLARITY); =20 spin_lock_irqsave(&priv->lock, irqflags); =20 - idr_cfg |=3D u8_encode_bits(priv->synchronous_mode[channel_id], INDEX_MOD= E); - - priv->index_polarity[channel_id] =3D index_polarity; - - /* Load Index Control configuration to Index Control Register */ - iowrite8(SELECT_IDR | idr_cfg, control); + quad8_control_register_update(priv, priv->idr, channel_id, index_polarity= , INDEX_POLARITY); =20 spin_unlock_irqrestore(&priv->lock, irqflags); =20 @@ -642,7 +592,7 @@ static int quad8_polarity_read(struct counter_device *c= ounter, if (err) return err; =20 - *polarity =3D (index_polarity) ? COUNTER_SIGNAL_POLARITY_POSITIVE : + *polarity =3D (index_polarity =3D=3D POSITIVE_INDEX_POLARITY) ? COUNTER_S= IGNAL_POLARITY_POSITIVE : COUNTER_SIGNAL_POLARITY_NEGATIVE; =20 return 0; @@ -652,7 +602,8 @@ static int quad8_polarity_write(struct counter_device *= counter, struct counter_signal *signal, enum counter_signal_polarity polarity) { - const u32 pol =3D (polarity =3D=3D COUNTER_SIGNAL_POLARITY_POSITIVE) ? 1 = : 0; + const u32 pol =3D (polarity =3D=3D COUNTER_SIGNAL_POLARITY_POSITIVE) ? PO= SITIVE_INDEX_POLARITY : + NEGATIVE_INDEX_POLARITY; =20 return quad8_index_polarity_set(counter, signal, pol); } @@ -669,7 +620,7 @@ static int quad8_synchronous_mode_get(struct counter_de= vice *counter, const struct quad8 *const priv =3D counter_priv(counter); const size_t channel_id =3D signal->id - 16; =20 - *synchronous_mode =3D priv->synchronous_mode[channel_id]; + *synchronous_mode =3D u8_get_bits(priv->idr[channel_id], INDEX_MODE); =20 return 0; } @@ -680,24 +631,19 @@ static int quad8_synchronous_mode_set(struct counter_= device *counter, { struct quad8 *const priv =3D counter_priv(counter); const size_t channel_id =3D signal->id - 16; - u8 __iomem *const control =3D &priv->reg->channel[channel_id].control; + u8 quadrature_mode; unsigned long irqflags; - unsigned int idr_cfg =3D u8_encode_bits(synchronous_mode, INDEX_MODE); =20 spin_lock_irqsave(&priv->lock, irqflags); =20 - idr_cfg |=3D u8_encode_bits(priv->index_polarity[channel_id], INDEX_POLAR= ITY); - /* Index function must be non-synchronous in non-quadrature mode */ - if (synchronous_mode && !priv->quadrature_mode[channel_id]) { + quadrature_mode =3D u8_get_bits(priv->idr[channel_id], QUADRATURE_MODE); + if (synchronous_mode && quadrature_mode =3D=3D NON_QUADRATURE) { spin_unlock_irqrestore(&priv->lock, irqflags); return -EINVAL; } =20 - priv->synchronous_mode[channel_id] =3D synchronous_mode; - - /* Load Index Control configuration to Index Control Register */ - iowrite8(SELECT_IDR | idr_cfg, control); + quad8_control_register_update(priv, priv->idr, channel_id, synchronous_mo= de, INDEX_MODE); =20 spin_unlock_irqrestore(&priv->lock, irqflags); =20 @@ -719,7 +665,7 @@ static int quad8_count_mode_read(struct counter_device = *counter, { const struct quad8 *const priv =3D counter_priv(counter); =20 - switch (priv->count_mode[count->id]) { + switch (u8_get_bits(priv->cmr[count->id], COUNT_MODE)) { case NORMAL_COUNT: *cnt_mode =3D COUNTER_COUNT_MODE_NORMAL; break; @@ -743,8 +689,6 @@ static int quad8_count_mode_write(struct counter_device= *counter, { struct quad8 *const priv =3D counter_priv(counter); unsigned int count_mode; - unsigned int mode_cfg; - u8 __iomem *const control =3D &priv->reg->channel[count->id].control; unsigned long irqflags; =20 switch (cnt_mode) { @@ -767,19 +711,7 @@ static int quad8_count_mode_write(struct counter_devic= e *counter, =20 spin_lock_irqsave(&priv->lock, irqflags); =20 - priv->count_mode[count->id] =3D count_mode; - - /* Set count mode configuration value */ - mode_cfg =3D u8_encode_bits(count_mode, COUNT_MODE); - - /* Add quadrature mode configuration */ - if (priv->quadrature_mode[count->id]) - mode_cfg |=3D u8_encode_bits(priv->quadrature_scale[count->id] + 1, QUAD= RATURE_MODE); - else - mode_cfg |=3D u8_encode_bits(NON_QUADRATURE, QUADRATURE_MODE); - - /* Load mode configuration to Counter Mode Register */ - iowrite8(SELECT_CMR | mode_cfg, control); + quad8_control_register_update(priv, priv->cmr, count->id, count_mode, COU= NT_MODE); =20 spin_unlock_irqrestore(&priv->lock, irqflags); =20 @@ -791,7 +723,7 @@ static int quad8_count_enable_read(struct counter_devic= e *counter, { const struct quad8 *const priv =3D counter_priv(counter); =20 - *enable =3D priv->ab_enable[count->id]; + *enable =3D u8_get_bits(priv->ior[count->id], AB_GATE); =20 return 0; } @@ -800,20 +732,11 @@ static int quad8_count_enable_write(struct counter_de= vice *counter, struct counter_count *count, u8 enable) { struct quad8 *const priv =3D counter_priv(counter); - u8 __iomem *const control =3D &priv->reg->channel[count->id].control; unsigned long irqflags; - unsigned int ior_cfg; =20 spin_lock_irqsave(&priv->lock, irqflags); =20 - priv->ab_enable[count->id] =3D enable; - - ior_cfg =3D u8_encode_bits(enable, AB_GATE) | - u8_encode_bits(priv->preset_enable[count->id], LOAD_PIN) | - u8_encode_bits(priv->irq_trigger[count->id], FLG_PINS); - - /* Load I/O control configuration */ - iowrite8(SELECT_IOR | ior_cfg, control); + quad8_control_register_update(priv, priv->ior, count->id, enable, AB_GATE= ); =20 spin_unlock_irqrestore(&priv->lock, irqflags); =20 @@ -890,7 +813,7 @@ static int quad8_count_ceiling_read(struct counter_devi= ce *counter, spin_lock_irqsave(&priv->lock, irqflags); =20 /* Range Limit and Modulo-N count modes use preset value as ceiling */ - switch (priv->count_mode[count->id]) { + switch (u8_get_bits(priv->cmr[count->id], COUNT_MODE)) { case RANGE_LIMIT: case MODULO_N: *ceiling =3D priv->preset[count->id]; @@ -917,7 +840,7 @@ static int quad8_count_ceiling_write(struct counter_dev= ice *counter, spin_lock_irqsave(&priv->lock, irqflags); =20 /* Range Limit and Modulo-N count modes use preset value as ceiling */ - switch (priv->count_mode[count->id]) { + switch (u8_get_bits(priv->cmr[count->id], COUNT_MODE)) { case RANGE_LIMIT: case MODULO_N: quad8_preset_register_set(priv, count->id, ceiling); @@ -936,7 +859,8 @@ static int quad8_count_preset_enable_read(struct counte= r_device *counter, { const struct quad8 *const priv =3D counter_priv(counter); =20 - *preset_enable =3D !priv->preset_enable[count->id]; + /* Preset enable is active low in Input/Output Control register */ + *preset_enable =3D !u8_get_bits(priv->ior[count->id], LOAD_PIN); =20 return 0; } @@ -946,23 +870,12 @@ static int quad8_count_preset_enable_write(struct cou= nter_device *counter, u8 preset_enable) { struct quad8 *const priv =3D counter_priv(counter); - u8 __iomem *const control =3D &priv->reg->channel[count->id].control; unsigned long irqflags; - unsigned int ior_cfg; - - /* Preset enable is active low in Input/Output Control register */ - preset_enable =3D !preset_enable; =20 spin_lock_irqsave(&priv->lock, irqflags); =20 - priv->preset_enable[count->id] =3D preset_enable; - - ior_cfg =3D u8_encode_bits(priv->ab_enable[count->id], AB_GATE) | - u8_encode_bits(preset_enable, LOAD_PIN) | - u8_encode_bits(priv->irq_trigger[count->id], FLG_PINS); - - /* Load I/O control configuration to Input / Output Control Register */ - iowrite8(SELECT_IOR | ior_cfg, control); + /* Preset enable is active low in Input/Output Control register */ + quad8_control_register_update(priv, priv->ior, count->id, !preset_enable,= LOAD_PIN); =20 spin_unlock_irqrestore(&priv->lock, irqflags); =20 @@ -1224,6 +1137,7 @@ static irqreturn_t quad8_irq_handler(int irq, void *p= rivate) struct quad8 *const priv =3D counter_priv(counter); unsigned long irq_status; unsigned long channel; + unsigned int flg_pins; u8 event; =20 irq_status =3D ioread8(&priv->reg->interrupt_status); @@ -1231,23 +1145,24 @@ static irqreturn_t quad8_irq_handler(int irq, void = *private) return IRQ_NONE; =20 for_each_set_bit(channel, &irq_status, QUAD8_NUM_COUNTERS) { - switch (priv->irq_trigger[channel]) { - case QUAD8_EVENT_CARRY: + flg_pins =3D u8_get_bits(priv->ior[channel], FLG_PINS); + switch (flg_pins) { + case FLG1_CARRY_FLG2_BORROW: event =3D COUNTER_EVENT_OVERFLOW; break; - case QUAD8_EVENT_COMPARE: + case FLG1_COMPARE_FLG2_BORROW: event =3D COUNTER_EVENT_THRESHOLD; break; - case QUAD8_EVENT_CARRY_BORROW: + case FLG1_CARRYBORROW_FLG2_UD: event =3D COUNTER_EVENT_OVERFLOW_UNDERFLOW; break; - case QUAD8_EVENT_INDEX: + case FLG1_INDX_FLG2_E: event =3D COUNTER_EVENT_INDEX; break; default: /* should never reach this path */ WARN_ONCE(true, "invalid interrupt trigger function %u configured for c= hannel %lu\n", - priv->irq_trigger[channel], channel); + flg_pins, channel); continue; } =20 @@ -1260,8 +1175,9 @@ static irqreturn_t quad8_irq_handler(int irq, void *p= rivate) return IRQ_HANDLED; } =20 -static void quad8_init_counter(struct channel_reg __iomem *const chan) +static void quad8_init_counter(struct quad8 *const priv, const size_t chan= nel) { + struct channel_reg __iomem *const chan =3D priv->reg->channel + channel; unsigned long i; =20 iowrite8(SELECT_RLD | RESET_BP, &chan->control); @@ -1274,15 +1190,21 @@ static void quad8_init_counter(struct channel_reg _= _iomem *const chan) iowrite8(0x00, &chan->data); iowrite8(SELECT_RLD | RESET_BT_CT_CPT_S_IDX, &chan->control); iowrite8(SELECT_RLD | RESET_E, &chan->control); + /* Binary encoding; Normal count; non-quadrature mode */ - iowrite8(SELECT_CMR | BINARY | u8_encode_bits(NORMAL_COUNT, COUNT_MODE) | - u8_encode_bits(NON_QUADRATURE, QUADRATURE_MODE), &chan->control); + priv->cmr[channel] =3D SELECT_CMR | BINARY | u8_encode_bits(NORMAL_COUNT,= COUNT_MODE) | + u8_encode_bits(NON_QUADRATURE, QUADRATURE_MODE); + iowrite8(priv->cmr[channel], &chan->control); + /* Disable A and B inputs; preset on index; FLG1 as Carry */ - iowrite8(SELECT_IOR | DISABLE_AB | u8_encode_bits(LOAD_CNTR, LOAD_PIN) | - u8_encode_bits(FLG1_CARRY_FLG2_BORROW, FLG_PINS), &chan->control); + priv->ior[channel] =3D SELECT_IOR | DISABLE_AB | u8_encode_bits(LOAD_CNTR= , LOAD_PIN) | + u8_encode_bits(FLG1_CARRY_FLG2_BORROW, FLG_PINS); + iowrite8(priv->ior[channel], &chan->control); + /* Disable index function; negative index polarity */ - iowrite8(SELECT_IDR | u8_encode_bits(DISABLE_INDEX_MODE, INDEX_MODE) | - u8_encode_bits(NEGATIVE_INDEX_POLARITY, INDEX_POLARITY), &chan->control= ); + priv->idr[channel] =3D SELECT_IDR | u8_encode_bits(DISABLE_INDEX_MODE, IN= DEX_MODE) | + u8_encode_bits(NEGATIVE_INDEX_POLARITY, INDEX_POLARITY); + iowrite8(priv->idr[channel], &chan->control); } =20 static int quad8_probe(struct device *dev, unsigned int id) @@ -1324,7 +1246,7 @@ static int quad8_probe(struct device *dev, unsigned i= nt id) iowrite8(RESET_COUNTERS | DISABLE_INTERRUPT_FUNCTION, &priv->reg->channel= _oper); /* Set initial configuration for all counters */ for (i =3D 0; i < QUAD8_NUM_COUNTERS; i++) - quad8_init_counter(priv->reg->channel + i); + quad8_init_counter(priv, i); /* Disable Differential Encoder Cable Status for all channels */ iowrite8(0xFF, &priv->reg->cable_status); /* Enable all counters and enable interrupt function */ --=20 2.39.2 From nobody Thu May 16 23:22:54 2024 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id B80C9C77B76 for ; Mon, 17 Apr 2023 19:51:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230384AbjDQTvX (ORCPT ); Mon, 17 Apr 2023 15:51:23 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58640 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230350AbjDQTvN (ORCPT ); Mon, 17 Apr 2023 15:51:13 -0400 Received: from mail-yw1-x112d.google.com (mail-yw1-x112d.google.com [IPv6:2607:f8b0:4864:20::112d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2CA3C4232 for ; Mon, 17 Apr 2023 12:51:08 -0700 (PDT) Received: by mail-yw1-x112d.google.com with SMTP id 00721157ae682-54fa9da5e5bso230015527b3.1 for ; Mon, 17 Apr 2023 12:51:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1681761067; x=1684353067; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=FyO0V+aAYGjTDJDpsci/EuW4KjxAcnDomhsrheQk3CM=; b=cZL7T73rLY7IabF7z+jkSTqbEQam25ymaIf2EuiL6ejE2qv20q77MvV6voXHr2+Wms perv0gqhhyNwyCqaLhLCtKL6pqdQlfbfA8rhe/JGahISpghh/ETYGwd8UMgn1Wj2GT9G 9o06bqpa+J1fh8UK5QvhgKrbcbGbR/jX+snWotFPdxfe5/DaHoeSS1wLGFnH94eAQNeK zS7X1a+p6tMupxgMRmPknAGPNACzjUT8o1jqML0EMLLBNFM0fZvDBj6zP5h401qICA4M L2noLYGghHy33hm7F4m1IRUTkBf+KxxMQkWaauM40djkIpUzvyZrz4urNvKOOtrTxaUA s0RQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1681761067; x=1684353067; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=FyO0V+aAYGjTDJDpsci/EuW4KjxAcnDomhsrheQk3CM=; b=hy1oAOGJl3txaIaxysK/pHw8GOXcOlr+aalvn2CLWybqluB3aPCAI5DQY7zu/ZmKoZ wct7DkTsa1vQwLQb466patbijF4GVij3XNxIZOZH8pH+34glxKXLUEvGc6riP20y22If ZswbShqxhLAuWweemGCOJjLhero/5JSHEHc6G92vmFshV62XlbAT6y/XUROWjKg1AnQS ZECX83ga3X+a0ELAWbwJIHxV4bT4KTYn6THDi75QoXhhIPQnKPxXcF3pQbyTMFyVJNyK BtoFsH4poXEYhAiQ+/wAuuk9smXIG+2MhmhsyT/yx2K809JY4QRLoHXMzLXhsi2WHSvE mFBQ== X-Gm-Message-State: AAQBX9ceAUSwnZhyEsRkYOjntll57+Cti05WTtGSiHA/Sy45fdSLmROV yBep+hGu1SoYQ+ypeVWO3ecegg== X-Google-Smtp-Source: AKy350Zatm5TsJnMUEvxN1Ba/9wxBYmE0op5LwyEehTLKCE5V2hLIZABmH7KqxuOxu9A+tVE/bDpOw== X-Received: by 2002:a81:4a86:0:b0:552:cad8:dc2a with SMTP id x128-20020a814a86000000b00552cad8dc2amr5439310ywa.52.1681761067351; Mon, 17 Apr 2023 12:51:07 -0700 (PDT) Received: from fedora.attlocal.net (69-109-179-158.lightspeed.dybhfl.sbcglobal.net. [69.109.179.158]) by smtp.gmail.com with ESMTPSA id u125-20020a817983000000b005463f6ae720sm3293158ywc.68.2023.04.17.12.51.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 17 Apr 2023 12:51:06 -0700 (PDT) From: William Breathitt Gray To: linux-iio@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Andy Shevchenko , Johannes Berg , Jonathan Cameron , Andrew Morton , Al Viro , Nathan Chancellor , Nick Desaulniers , William Breathitt Gray Subject: [PATCH v4 3/4] counter: 104-quad-8: Utilize helper functions to handle PR, FLAG and PSC Date: Mon, 17 Apr 2023 15:50:49 -0400 Message-Id: X-Mailer: git-send-email 2.39.2 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" The Preset Register (PR), Flag Register (FLAG), and Filter Clock Prescaler (PSC) have common usage patterns. Wrap up such usage into dedicated functions to improve code clarity. Signed-off-by: William Breathitt Gray --- Changes in v4: - Fix endianness errors by utilizing get_unaligned_le24() and put_unaligned_le24() Changes in v3: none Changes in v2: - Utilize ioread8_rep() and iowrite8_rep() to read and write counter data drivers/counter/104-quad-8.c | 97 +++++++++++++++++------------------- 1 file changed, 45 insertions(+), 52 deletions(-) diff --git a/drivers/counter/104-quad-8.c b/drivers/counter/104-quad-8.c index 0188c9c4e4cb..d6ede651cc5e 100644 --- a/drivers/counter/104-quad-8.c +++ b/drivers/counter/104-quad-8.c @@ -21,6 +21,8 @@ #include #include =20 +#include + #define QUAD8_EXTENT 32 =20 static unsigned int base[max_num_isa_dev(QUAD8_EXTENT)]; @@ -232,52 +234,60 @@ static int quad8_count_read(struct counter_device *co= unter, struct quad8 *const priv =3D counter_priv(counter); struct channel_reg __iomem *const chan =3D priv->reg->channel + count->id; unsigned long irqflags; - int i; - - *val =3D 0; + u8 value[3]; =20 spin_lock_irqsave(&priv->lock, irqflags); =20 iowrite8(SELECT_RLD | RESET_BP | TRANSFER_CNTR_TO_OL, &chan->control); - - for (i =3D 0; i < 3; i++) - *val |=3D (unsigned long)ioread8(&chan->data) << (8 * i); + ioread8_rep(&chan->data, value, sizeof(value)); =20 spin_unlock_irqrestore(&priv->lock, irqflags); =20 + *val =3D get_unaligned_le24(value); + return 0; } =20 +static void quad8_preset_register_set(struct quad8 *const priv, const size= _t id, + const unsigned long preset) +{ + struct channel_reg __iomem *const chan =3D priv->reg->channel + id; + u8 value[3]; + + put_unaligned_le24(preset, value); + + iowrite8(SELECT_RLD | RESET_BP, &chan->control); + iowrite8_rep(&chan->data, value, sizeof(value)); +} + +static void quad8_flag_register_reset(struct quad8 *const priv, const size= _t id) +{ + struct channel_reg __iomem *const chan =3D priv->reg->channel + id; + + iowrite8(SELECT_RLD | RESET_BT_CT_CPT_S_IDX, &chan->control); + iowrite8(SELECT_RLD | RESET_E, &chan->control); +} + static int quad8_count_write(struct counter_device *counter, struct counter_count *count, u64 val) { struct quad8 *const priv =3D counter_priv(counter); struct channel_reg __iomem *const chan =3D priv->reg->channel + count->id; unsigned long irqflags; - int i; =20 if (val > LS7267_CNTR_MAX) return -ERANGE; =20 spin_lock_irqsave(&priv->lock, irqflags); =20 - iowrite8(SELECT_RLD | RESET_BP, &chan->control); - /* Counter can only be set via Preset Register */ - for (i =3D 0; i < 3; i++) - iowrite8(val >> (8 * i), &chan->data); - + quad8_preset_register_set(priv, count->id, val); iowrite8(SELECT_RLD | TRANSFER_PR_TO_CNTR, &chan->control); =20 - iowrite8(SELECT_RLD | RESET_BP, &chan->control); + quad8_flag_register_reset(priv, count->id); =20 /* Set Preset Register back to original value */ - val =3D priv->preset[count->id]; - for (i =3D 0; i < 3; i++) - iowrite8(val >> (8 * i), &chan->data); - - iowrite8(SELECT_RLD | RESET_BT_CT_CPT_S_IDX, &chan->control); - iowrite8(SELECT_RLD | RESET_E, &chan->control); + quad8_preset_register_set(priv, count->id, priv->preset[count->id]); =20 spin_unlock_irqrestore(&priv->lock, irqflags); =20 @@ -771,21 +781,6 @@ static int quad8_count_preset_read(struct counter_devi= ce *counter, return 0; } =20 -static void quad8_preset_register_set(struct quad8 *const priv, const int = id, - const unsigned int preset) -{ - struct channel_reg __iomem *const chan =3D priv->reg->channel + id; - int i; - - priv->preset[id] =3D preset; - - iowrite8(SELECT_RLD | RESET_BP, &chan->control); - - /* Set Preset Register */ - for (i =3D 0; i < 3; i++) - iowrite8(preset >> (8 * i), &chan->data); -} - static int quad8_count_preset_write(struct counter_device *counter, struct counter_count *count, u64 preset) { @@ -797,6 +792,7 @@ static int quad8_count_preset_write(struct counter_devi= ce *counter, =20 spin_lock_irqsave(&priv->lock, irqflags); =20 + priv->preset[count->id] =3D preset; quad8_preset_register_set(priv, count->id, preset); =20 spin_unlock_irqrestore(&priv->lock, irqflags); @@ -843,6 +839,7 @@ static int quad8_count_ceiling_write(struct counter_dev= ice *counter, switch (u8_get_bits(priv->cmr[count->id], COUNT_MODE)) { case RANGE_LIMIT: case MODULO_N: + priv->preset[count->id] =3D ceiling; quad8_preset_register_set(priv, count->id, ceiling); spin_unlock_irqrestore(&priv->lock, irqflags); return 0; @@ -961,24 +958,28 @@ static int quad8_signal_fck_prescaler_read(struct cou= nter_device *counter, return 0; } =20 +static void quad8_filter_clock_prescaler_set(struct quad8 *const priv, con= st size_t id, + const u8 prescaler) +{ + struct channel_reg __iomem *const chan =3D priv->reg->channel + id; + + iowrite8(SELECT_RLD | RESET_BP, &chan->control); + iowrite8(prescaler, &chan->data); + iowrite8(SELECT_RLD | TRANSFER_PR0_TO_PSC, &chan->control); +} + static int quad8_signal_fck_prescaler_write(struct counter_device *counter, struct counter_signal *signal, u8 prescaler) { struct quad8 *const priv =3D counter_priv(counter); const size_t channel_id =3D signal->id / 2; - struct channel_reg __iomem *const chan =3D priv->reg->channel + channel_i= d; unsigned long irqflags; =20 spin_lock_irqsave(&priv->lock, irqflags); =20 priv->fck_prescaler[channel_id] =3D prescaler; - - iowrite8(SELECT_RLD | RESET_BP, &chan->control); - - /* Set filter clock factor */ - iowrite8(prescaler, &chan->data); - iowrite8(SELECT_RLD | RESET_BP | TRANSFER_PR0_TO_PSC, &chan->control); + quad8_filter_clock_prescaler_set(priv, channel_id, prescaler); =20 spin_unlock_irqrestore(&priv->lock, irqflags); =20 @@ -1178,18 +1179,10 @@ static irqreturn_t quad8_irq_handler(int irq, void = *private) static void quad8_init_counter(struct quad8 *const priv, const size_t chan= nel) { struct channel_reg __iomem *const chan =3D priv->reg->channel + channel; - unsigned long i; =20 - iowrite8(SELECT_RLD | RESET_BP, &chan->control); - /* Reset filter clock factor */ - iowrite8(0, &chan->data); - iowrite8(SELECT_RLD | RESET_BP | TRANSFER_PR0_TO_PSC, &chan->control); - iowrite8(SELECT_RLD | RESET_BP, &chan->control); - /* Reset Preset Register */ - for (i =3D 0; i < 3; i++) - iowrite8(0x00, &chan->data); - iowrite8(SELECT_RLD | RESET_BT_CT_CPT_S_IDX, &chan->control); - iowrite8(SELECT_RLD | RESET_E, &chan->control); + quad8_filter_clock_prescaler_set(priv, channel, 0); + quad8_preset_register_set(priv, channel, 0); + quad8_flag_register_reset(priv, channel); =20 /* Binary encoding; Normal count; non-quadrature mode */ priv->cmr[channel] =3D SELECT_CMR | BINARY | u8_encode_bits(NORMAL_COUNT,= COUNT_MODE) | --=20 2.39.2 From nobody Thu May 16 23:22:54 2024 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6132BC77B78 for ; Mon, 17 Apr 2023 19:51:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229579AbjDQTvc (ORCPT ); Mon, 17 Apr 2023 15:51:32 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59258 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230350AbjDQTv2 (ORCPT ); Mon, 17 Apr 2023 15:51:28 -0400 Received: from mail-yw1-x1129.google.com (mail-yw1-x1129.google.com [IPv6:2607:f8b0:4864:20::1129]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 609EA44B0 for ; Mon, 17 Apr 2023 12:51:09 -0700 (PDT) Received: by mail-yw1-x1129.google.com with SMTP id 00721157ae682-54fbb713301so188154837b3.11 for ; Mon, 17 Apr 2023 12:51:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1681761068; x=1684353068; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=rEvLVA96vWTMuP3gha+tW69fpKPtcA8BHU4XRw3gyvE=; b=gY/HmAZI+eCQafIsmsArKdDzHEwAlRv/V9b47LZrdT4HPZ/iuK+S8qdrwON3RdvpM+ wwv0FioHSWaZKKKtIkX9GjikeyxLAPhTpfDDQOWb26L/037ptN2FzuVhvidBiiDl+HPj 1wdpg1c5vMycM1ccstrNq8WJYQUpx/wnlrJMn7wsVb5XEDr5rBD4+rThO0Qq+92UGCyv foMtw/wO1bcaHfiDzc2gHP9F3P5oXBsOHagBw9iIfyLrwKKlJC7n+QotEltpik6PncUA ftgVIoBOAMhqRNPfg9NOrnIsbL2wo0Nqr7BX9FkW7T/MzK3dZ4ExVtVzR3dxqo+gQzOl cC2g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1681761068; x=1684353068; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=rEvLVA96vWTMuP3gha+tW69fpKPtcA8BHU4XRw3gyvE=; b=bPCPtVzVrZOFRSV9kD8JSLnLKpvsTTa0iRRa5O4HNP5Mk4Cjnv6gqldYITmJ9zVnpM kxjgfQmDW0Heh+c08ngOupXGuwj99s3fPRVrBcBAvt4yKO8FyVjtafw1UAc12kYSy+4R jL/De5xkit44FUEk+kNCQ1PqFyrwHcj2E3cOkNYzt7YnaIpI49LG3bs4QS0BJfKS5znS vWuyExZ6VYIB5d/zz3P1dzBnsTG9IbcC2CRy9wguiufrLcSCyiJnEhNKEiGi8M/Z3R/d s7CauTrhXPljQ83rOL8tdm39XUhdQbiwcs3PGoVbAGbCFesqBeBc6WrqI8TkhNIy4LnH mZxg== X-Gm-Message-State: AAQBX9fVL89nK5xTn24WY/kcHkKWhh2q6hT/q9wNmFvP19w2pTedTIfl XHcBlKeVGAo7uXZWSY5Yc3TIlA== X-Google-Smtp-Source: AKy350YU2veZX1zAVpWs12pPX+VIecaIET46gb3dRlcSqjc83Ze+iQgnULU5k/4vtwkn8wRsUjyOUg== X-Received: by 2002:a81:7202:0:b0:549:27a8:90b with SMTP id n2-20020a817202000000b0054927a8090bmr15483361ywc.40.1681761068357; Mon, 17 Apr 2023 12:51:08 -0700 (PDT) Received: from fedora.attlocal.net (69-109-179-158.lightspeed.dybhfl.sbcglobal.net. [69.109.179.158]) by smtp.gmail.com with ESMTPSA id u125-20020a817983000000b005463f6ae720sm3293158ywc.68.2023.04.17.12.51.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 17 Apr 2023 12:51:07 -0700 (PDT) From: William Breathitt Gray To: linux-iio@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Andy Shevchenko , Johannes Berg , Jonathan Cameron , Andrew Morton , Al Viro , Nathan Chancellor , Nick Desaulniers , William Breathitt Gray Subject: [PATCH v4 4/4] counter: 104-quad-8: Migrate to the regmap API Date: Mon, 17 Apr 2023 15:50:50 -0400 Message-Id: <1f1f7920d2be94aedb6fdf49f429fe6137c8cb24.1681753140.git.william.gray@linaro.org> X-Mailer: git-send-email 2.39.2 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" The regmap API supports IO port accessors so we can take advantage of regmap abstractions rather than handling access to the device registers directly in the driver. With regmap we get boundary checks, read-write permissions, operation synchronization locks, and more for free. Most important of all, rather than rolling our own we utilize implementations that are known to work and gain from any future improvements and fixes that come. Suggested-by: Andy Shevchenko Signed-off-by: William Breathitt Gray Reviewed-by tag for you for the changes in this patch? --- Changes in v4: - Mention benefits of using regmap in the commit description - Use "int ret" for regmap_* return values throughout for consistency - Reorganize declaration lists to prioritize longer lines first drivers/counter/104-quad-8.c | 365 ++++++++++++++++++++++------------- drivers/counter/Kconfig | 1 + 2 files changed, 229 insertions(+), 137 deletions(-) diff --git a/drivers/counter/104-quad-8.c b/drivers/counter/104-quad-8.c index d6ede651cc5e..ed1f57511955 100644 --- a/drivers/counter/104-quad-8.c +++ b/drivers/counter/104-quad-8.c @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include #include @@ -18,8 +18,9 @@ #include #include #include -#include +#include #include +#include =20 #include =20 @@ -37,35 +38,13 @@ MODULE_PARM_DESC(irq, "ACCES 104-QUAD-8 interrupt line = numbers"); =20 #define QUAD8_NUM_COUNTERS 8 =20 -/** - * struct channel_reg - channel register structure - * @data: Count data - * @control: Channel flags and control - */ -struct channel_reg { - u8 data; - u8 control; -}; - -/** - * struct quad8_reg - device register structure - * @channel: quadrature counter data and control - * @interrupt_status: channel interrupt status - * @channel_oper: enable/reset counters and interrupt functions - * @index_interrupt: enable channel interrupts - * @reserved: reserved for Factory Use - * @index_input_levels: index signal logical input level - * @cable_status: differential encoder cable status - */ -struct quad8_reg { - struct channel_reg channel[QUAD8_NUM_COUNTERS]; - u8 interrupt_status; - u8 channel_oper; - u8 index_interrupt; - u8 reserved[3]; - u8 index_input_levels; - u8 cable_status; -}; +#define QUAD8_DATA(_channel) ((_channel) * 2) +#define QUAD8_CONTROL(_channel) (QUAD8_DATA(_channel) + 1) +#define QUAD8_INTERRUPT_STATUS 0x10 +#define QUAD8_CHANNEL_OPERATION 0x11 +#define QUAD8_INDEX_INTERRUPT 0x12 +#define QUAD8_INDEX_INPUT_LEVELS 0x16 +#define QUAD8_CABLE_STATUS 0x17 =20 /** * struct quad8 - device private data structure @@ -76,7 +55,7 @@ struct quad8_reg { * @fck_prescaler: array of filter clock prescaler configurations * @preset: array of preset values * @cable_fault_enable: differential encoder cable status enable configura= tions - * @reg: I/O address offset for the device registers + * @map: regmap for the device */ struct quad8 { spinlock_t lock; @@ -86,7 +65,30 @@ struct quad8 { unsigned int fck_prescaler[QUAD8_NUM_COUNTERS]; unsigned int preset[QUAD8_NUM_COUNTERS]; unsigned int cable_fault_enable; - struct quad8_reg __iomem *reg; + struct regmap *map; +}; + +static const struct regmap_range quad8_wr_ranges[] =3D { + regmap_reg_range(0x0, 0xF), regmap_reg_range(0x11, 0x12), regmap_reg_rang= e(0x17, 0x17), +}; +static const struct regmap_range quad8_rd_ranges[] =3D { + regmap_reg_range(0x0, 0x12), regmap_reg_range(0x16, 0x18), +}; +static const struct regmap_access_table quad8_wr_table =3D { + .yes_ranges =3D quad8_wr_ranges, + .n_yes_ranges =3D ARRAY_SIZE(quad8_wr_ranges), +}; +static const struct regmap_access_table quad8_rd_table =3D { + .yes_ranges =3D quad8_rd_ranges, + .n_yes_ranges =3D ARRAY_SIZE(quad8_rd_ranges), +}; +static const struct regmap_config quad8_regmap_config =3D { + .reg_bits =3D 8, + .reg_stride =3D 1, + .val_bits =3D 8, + .io_port =3D true, + .wr_table =3D &quad8_wr_table, + .rd_table =3D &quad8_rd_table, }; =20 /* Error flag */ @@ -202,12 +204,12 @@ struct quad8 { /* Each Counter is 24 bits wide */ #define LS7267_CNTR_MAX GENMASK(23, 0) =20 -static __always_inline void quad8_control_register_update(struct quad8 *co= nst priv, u8 *const buf, - const size_t channel, const u8 val, - const u8 field) +static __always_inline int quad8_control_register_update(struct regmap *co= nst map, u8 *const buf, + const size_t channel, const u8 val, + const u8 field) { u8p_replace_bits(&buf[channel], val, field); - iowrite8(buf[channel], &priv->reg->channel[channel].control); + return regmap_write(map, QUAD8_CONTROL(channel), buf[channel]); } =20 static int quad8_signal_read(struct counter_device *counter, @@ -215,15 +217,17 @@ static int quad8_signal_read(struct counter_device *c= ounter, enum counter_signal_level *level) { const struct quad8 *const priv =3D counter_priv(counter); - unsigned int state; + int ret; =20 /* Only Index signal levels can be read */ if (signal->id < 16) return -EINVAL; =20 - state =3D ioread8(&priv->reg->index_input_levels) & BIT(signal->id - 16); + ret =3D regmap_test_bits(priv->map, QUAD8_INDEX_INPUT_LEVELS, BIT(signal-= >id - 16)); + if (ret < 0) + return ret; =20 - *level =3D (state) ? COUNTER_SIGNAL_LEVEL_HIGH : COUNTER_SIGNAL_LEVEL_LOW; + *level =3D (ret) ? COUNTER_SIGNAL_LEVEL_HIGH : COUNTER_SIGNAL_LEVEL_LOW; =20 return 0; } @@ -232,48 +236,56 @@ static int quad8_count_read(struct counter_device *co= unter, struct counter_count *count, u64 *val) { struct quad8 *const priv =3D counter_priv(counter); - struct channel_reg __iomem *const chan =3D priv->reg->channel + count->id; unsigned long irqflags; u8 value[3]; + int ret; =20 spin_lock_irqsave(&priv->lock, irqflags); =20 - iowrite8(SELECT_RLD | RESET_BP | TRANSFER_CNTR_TO_OL, &chan->control); - ioread8_rep(&chan->data, value, sizeof(value)); + ret =3D regmap_write(priv->map, QUAD8_CONTROL(count->id), + SELECT_RLD | RESET_BP | TRANSFER_CNTR_TO_OL); + if (ret) + goto exit_unlock; + ret =3D regmap_noinc_read(priv->map, QUAD8_DATA(count->id), value, sizeof= (value)); =20 +exit_unlock: spin_unlock_irqrestore(&priv->lock, irqflags); =20 *val =3D get_unaligned_le24(value); =20 - return 0; + return ret; } =20 -static void quad8_preset_register_set(struct quad8 *const priv, const size= _t id, - const unsigned long preset) +static int quad8_preset_register_set(struct quad8 *const priv, const size_= t id, + const unsigned long preset) { - struct channel_reg __iomem *const chan =3D priv->reg->channel + id; u8 value[3]; + int ret; =20 put_unaligned_le24(preset, value); =20 - iowrite8(SELECT_RLD | RESET_BP, &chan->control); - iowrite8_rep(&chan->data, value, sizeof(value)); + ret =3D regmap_write(priv->map, QUAD8_CONTROL(id), SELECT_RLD | RESET_BP); + if (ret) + return ret; + return regmap_noinc_write(priv->map, QUAD8_DATA(id), value, sizeof(value)= ); } =20 -static void quad8_flag_register_reset(struct quad8 *const priv, const size= _t id) +static int quad8_flag_register_reset(struct quad8 *const priv, const size_= t id) { - struct channel_reg __iomem *const chan =3D priv->reg->channel + id; + int ret; =20 - iowrite8(SELECT_RLD | RESET_BT_CT_CPT_S_IDX, &chan->control); - iowrite8(SELECT_RLD | RESET_E, &chan->control); + ret =3D regmap_write(priv->map, QUAD8_CONTROL(id), SELECT_RLD | RESET_BT_= CT_CPT_S_IDX); + if (ret) + return ret; + return regmap_write(priv->map, QUAD8_CONTROL(id), SELECT_RLD | RESET_E); } =20 static int quad8_count_write(struct counter_device *counter, struct counter_count *count, u64 val) { struct quad8 *const priv =3D counter_priv(counter); - struct channel_reg __iomem *const chan =3D priv->reg->channel + count->id; unsigned long irqflags; + int ret; =20 if (val > LS7267_CNTR_MAX) return -ERANGE; @@ -281,17 +293,24 @@ static int quad8_count_write(struct counter_device *c= ounter, spin_lock_irqsave(&priv->lock, irqflags); =20 /* Counter can only be set via Preset Register */ - quad8_preset_register_set(priv, count->id, val); - iowrite8(SELECT_RLD | TRANSFER_PR_TO_CNTR, &chan->control); + ret =3D quad8_preset_register_set(priv, count->id, val); + if (ret) + goto exit_unlock; + ret =3D regmap_write(priv->map, QUAD8_CONTROL(count->id), SELECT_RLD | TR= ANSFER_PR_TO_CNTR); + if (ret) + goto exit_unlock; =20 - quad8_flag_register_reset(priv, count->id); + ret =3D quad8_flag_register_reset(priv, count->id); + if (ret) + goto exit_unlock; =20 /* Set Preset Register back to original value */ - quad8_preset_register_set(priv, count->id, priv->preset[count->id]); + ret =3D quad8_preset_register_set(priv, count->id, priv->preset[count->id= ]); =20 +exit_unlock: spin_unlock_irqrestore(&priv->lock, irqflags); =20 - return 0; + return ret; } =20 static const enum counter_function quad8_count_functions_list[] =3D { @@ -349,6 +368,7 @@ static int quad8_function_write(struct counter_device *= counter, unsigned long irqflags; unsigned int mode_cfg; bool synchronous_mode; + int ret; =20 switch (function) { case COUNTER_FUNCTION_PULSE_DIRECTION: @@ -372,14 +392,19 @@ static int quad8_function_write(struct counter_device= *counter, =20 /* Synchronous function not supported in non-quadrature mode */ synchronous_mode =3D u8_get_bits(priv->idr[id], INDEX_MODE) =3D=3D ENABLE= _INDEX_MODE; - if (synchronous_mode && mode_cfg =3D=3D NON_QUADRATURE) - quad8_control_register_update(priv, priv->idr, id, DISABLE_INDEX_MODE, I= NDEX_MODE); + if (synchronous_mode && mode_cfg =3D=3D NON_QUADRATURE) { + ret =3D quad8_control_register_update(priv->map, priv->idr, id, DISABLE_= INDEX_MODE, + INDEX_MODE); + if (ret) + goto exit_unlock; + } =20 - quad8_control_register_update(priv, priv->cmr, id, mode_cfg, QUADRATURE_M= ODE); + ret =3D quad8_control_register_update(priv->map, priv->cmr, id, mode_cfg,= QUADRATURE_MODE); =20 +exit_unlock: spin_unlock_irqrestore(&priv->lock, irqflags); =20 - return 0; + return ret; } =20 static int quad8_direction_read(struct counter_device *counter, @@ -387,10 +412,12 @@ static int quad8_direction_read(struct counter_device= *counter, enum counter_count_direction *direction) { const struct quad8 *const priv =3D counter_priv(counter); - u8 __iomem *const flag_addr =3D &priv->reg->channel[count->id].control; - u8 flag; + unsigned int flag; + int ret; =20 - flag =3D ioread8(flag_addr); + ret =3D regmap_read(priv->map, QUAD8_CONTROL(count->id), &flag); + if (ret) + return ret; *direction =3D (u8_get_bits(flag, FLAG_UD) =3D=3D UP) ? COUNTER_COUNT_DIR= ECTION_FORWARD : COUNTER_COUNT_DIRECTION_BACKWARD; =20 @@ -481,6 +508,7 @@ static int quad8_events_configure(struct counter_device= *counter) unsigned long irqflags; struct counter_event_node *event_node; u8 flg_pins; + int ret; =20 spin_lock_irqsave(&priv->lock, irqflags); =20 @@ -500,8 +528,8 @@ static int quad8_events_configure(struct counter_device= *counter) break; default: /* should never reach this path */ - spin_unlock_irqrestore(&priv->lock, irqflags); - return -EINVAL; + ret =3D -EINVAL; + goto exit_unlock; } =20 /* Enable IRQ line */ @@ -512,15 +540,18 @@ static int quad8_events_configure(struct counter_devi= ce *counter) continue; =20 /* Save new IRQ function configuration */ - quad8_control_register_update(priv, priv->ior, event_node->channel, flg_= pins, - FLG_PINS); + ret =3D quad8_control_register_update(priv->map, priv->ior, event_node->= channel, + flg_pins, FLG_PINS); + if (ret) + goto exit_unlock; } =20 - iowrite8(irq_enabled, &priv->reg->index_interrupt); + ret =3D regmap_write(priv->map, QUAD8_INDEX_INTERRUPT, irq_enabled); =20 +exit_unlock: spin_unlock_irqrestore(&priv->lock, irqflags); =20 - return 0; + return ret; } =20 static int quad8_watch_validate(struct counter_device *counter, @@ -581,14 +612,16 @@ static int quad8_index_polarity_set(struct counter_de= vice *counter, struct quad8 *const priv =3D counter_priv(counter); const size_t channel_id =3D signal->id - 16; unsigned long irqflags; + int ret; =20 spin_lock_irqsave(&priv->lock, irqflags); =20 - quad8_control_register_update(priv, priv->idr, channel_id, index_polarity= , INDEX_POLARITY); + ret =3D quad8_control_register_update(priv->map, priv->idr, channel_id, i= ndex_polarity, + INDEX_POLARITY); =20 spin_unlock_irqrestore(&priv->lock, irqflags); =20 - return 0; + return ret; } =20 static int quad8_polarity_read(struct counter_device *counter, @@ -643,21 +676,24 @@ static int quad8_synchronous_mode_set(struct counter_= device *counter, const size_t channel_id =3D signal->id - 16; u8 quadrature_mode; unsigned long irqflags; + int ret; =20 spin_lock_irqsave(&priv->lock, irqflags); =20 /* Index function must be non-synchronous in non-quadrature mode */ quadrature_mode =3D u8_get_bits(priv->idr[channel_id], QUADRATURE_MODE); if (synchronous_mode && quadrature_mode =3D=3D NON_QUADRATURE) { - spin_unlock_irqrestore(&priv->lock, irqflags); - return -EINVAL; + ret =3D -EINVAL; + goto exit_unlock; } =20 - quad8_control_register_update(priv, priv->idr, channel_id, synchronous_mo= de, INDEX_MODE); + ret =3D quad8_control_register_update(priv->map, priv->idr, channel_id, s= ynchronous_mode, + INDEX_MODE); =20 +exit_unlock: spin_unlock_irqrestore(&priv->lock, irqflags); =20 - return 0; + return ret; } =20 static int quad8_count_floor_read(struct counter_device *counter, @@ -700,6 +736,7 @@ static int quad8_count_mode_write(struct counter_device= *counter, struct quad8 *const priv =3D counter_priv(counter); unsigned int count_mode; unsigned long irqflags; + int ret; =20 switch (cnt_mode) { case COUNTER_COUNT_MODE_NORMAL: @@ -721,11 +758,12 @@ static int quad8_count_mode_write(struct counter_devi= ce *counter, =20 spin_lock_irqsave(&priv->lock, irqflags); =20 - quad8_control_register_update(priv, priv->cmr, count->id, count_mode, COU= NT_MODE); + ret =3D quad8_control_register_update(priv->map, priv->cmr, count->id, co= unt_mode, + COUNT_MODE); =20 spin_unlock_irqrestore(&priv->lock, irqflags); =20 - return 0; + return ret; } =20 static int quad8_count_enable_read(struct counter_device *counter, @@ -743,14 +781,15 @@ static int quad8_count_enable_write(struct counter_de= vice *counter, { struct quad8 *const priv =3D counter_priv(counter); unsigned long irqflags; + int ret; =20 spin_lock_irqsave(&priv->lock, irqflags); =20 - quad8_control_register_update(priv, priv->ior, count->id, enable, AB_GATE= ); + ret =3D quad8_control_register_update(priv->map, priv->ior, count->id, en= able, AB_GATE); =20 spin_unlock_irqrestore(&priv->lock, irqflags); =20 - return 0; + return ret; } =20 static const char *const quad8_noise_error_states[] =3D { @@ -762,10 +801,12 @@ static int quad8_error_noise_get(struct counter_devic= e *counter, struct counter_count *count, u32 *noise_error) { const struct quad8 *const priv =3D counter_priv(counter); - u8 __iomem *const flag_addr =3D &priv->reg->channel[count->id].control; - u8 flag; + unsigned int flag; + int ret; =20 - flag =3D ioread8(flag_addr); + ret =3D regmap_read(priv->map, QUAD8_CONTROL(count->id), &flag); + if (ret) + return ret; *noise_error =3D u8_get_bits(flag, FLAG_E); =20 return 0; @@ -786,6 +827,7 @@ static int quad8_count_preset_write(struct counter_devi= ce *counter, { struct quad8 *const priv =3D counter_priv(counter); unsigned long irqflags; + int ret; =20 if (preset > LS7267_CNTR_MAX) return -ERANGE; @@ -793,11 +835,11 @@ static int quad8_count_preset_write(struct counter_de= vice *counter, spin_lock_irqsave(&priv->lock, irqflags); =20 priv->preset[count->id] =3D preset; - quad8_preset_register_set(priv, count->id, preset); + ret =3D quad8_preset_register_set(priv, count->id, preset); =20 spin_unlock_irqrestore(&priv->lock, irqflags); =20 - return 0; + return ret; } =20 static int quad8_count_ceiling_read(struct counter_device *counter, @@ -829,6 +871,7 @@ static int quad8_count_ceiling_write(struct counter_dev= ice *counter, { struct quad8 *const priv =3D counter_priv(counter); unsigned long irqflags; + int ret; =20 if (ceiling > LS7267_CNTR_MAX) return -ERANGE; @@ -840,14 +883,16 @@ static int quad8_count_ceiling_write(struct counter_d= evice *counter, case RANGE_LIMIT: case MODULO_N: priv->preset[count->id] =3D ceiling; - quad8_preset_register_set(priv, count->id, ceiling); - spin_unlock_irqrestore(&priv->lock, irqflags); - return 0; + ret =3D quad8_preset_register_set(priv, count->id, ceiling); + break; + default: + ret =3D -EINVAL; + break; } =20 spin_unlock_irqrestore(&priv->lock, irqflags); =20 - return -EINVAL; + return ret; } =20 static int quad8_count_preset_enable_read(struct counter_device *counter, @@ -868,15 +913,17 @@ static int quad8_count_preset_enable_write(struct cou= nter_device *counter, { struct quad8 *const priv =3D counter_priv(counter); unsigned long irqflags; + int ret; =20 spin_lock_irqsave(&priv->lock, irqflags); =20 /* Preset enable is active low in Input/Output Control register */ - quad8_control_register_update(priv, priv->ior, count->id, !preset_enable,= LOAD_PIN); + ret =3D quad8_control_register_update(priv->map, priv->ior, count->id, !p= reset_enable, + LOAD_PIN); =20 spin_unlock_irqrestore(&priv->lock, irqflags); =20 - return 0; + return ret; } =20 static int quad8_signal_cable_fault_read(struct counter_device *counter, @@ -887,7 +934,7 @@ static int quad8_signal_cable_fault_read(struct counter= _device *counter, const size_t channel_id =3D signal->id / 2; unsigned long irqflags; bool disabled; - unsigned int status; + int ret; =20 spin_lock_irqsave(&priv->lock, irqflags); =20 @@ -898,13 +945,16 @@ static int quad8_signal_cable_fault_read(struct count= er_device *counter, return -EINVAL; } =20 - /* Logic 0 =3D cable fault */ - status =3D ioread8(&priv->reg->cable_status); + ret =3D regmap_test_bits(priv->map, QUAD8_CABLE_STATUS, BIT(channel_id)); + if (ret < 0) { + spin_unlock_irqrestore(&priv->lock, irqflags); + return ret; + } =20 spin_unlock_irqrestore(&priv->lock, irqflags); =20 - /* Mask respective channel and invert logic */ - *cable_fault =3D !(status & BIT(channel_id)); + /* Logic 0 =3D cable fault */ + *cable_fault =3D !ret; =20 return 0; } @@ -929,6 +979,7 @@ static int quad8_signal_cable_fault_enable_write(struct= counter_device *counter, const size_t channel_id =3D signal->id / 2; unsigned long irqflags; unsigned int cable_fault_enable; + int ret; =20 spin_lock_irqsave(&priv->lock, irqflags); =20 @@ -940,11 +991,11 @@ static int quad8_signal_cable_fault_enable_write(stru= ct counter_device *counter, /* Enable is active low in Differential Encoder Cable Status register */ cable_fault_enable =3D ~priv->cable_fault_enable; =20 - iowrite8(cable_fault_enable, &priv->reg->cable_status); + ret =3D regmap_write(priv->map, QUAD8_CABLE_STATUS, cable_fault_enable); =20 spin_unlock_irqrestore(&priv->lock, irqflags); =20 - return 0; + return ret; } =20 static int quad8_signal_fck_prescaler_read(struct counter_device *counter, @@ -958,14 +1009,18 @@ static int quad8_signal_fck_prescaler_read(struct co= unter_device *counter, return 0; } =20 -static void quad8_filter_clock_prescaler_set(struct quad8 *const priv, con= st size_t id, - const u8 prescaler) +static int quad8_filter_clock_prescaler_set(struct quad8 *const priv, cons= t size_t id, + const u8 prescaler) { - struct channel_reg __iomem *const chan =3D priv->reg->channel + id; - - iowrite8(SELECT_RLD | RESET_BP, &chan->control); - iowrite8(prescaler, &chan->data); - iowrite8(SELECT_RLD | TRANSFER_PR0_TO_PSC, &chan->control); + int ret; + + ret =3D regmap_write(priv->map, QUAD8_CONTROL(id), SELECT_RLD | RESET_BP); + if (ret) + return ret; + ret =3D regmap_write(priv->map, QUAD8_DATA(id), prescaler); + if (ret) + return ret; + return regmap_write(priv->map, QUAD8_CONTROL(id), SELECT_RLD | TRANSFER_P= R0_TO_PSC); } =20 static int quad8_signal_fck_prescaler_write(struct counter_device *counter, @@ -975,15 +1030,16 @@ static int quad8_signal_fck_prescaler_write(struct c= ounter_device *counter, struct quad8 *const priv =3D counter_priv(counter); const size_t channel_id =3D signal->id / 2; unsigned long irqflags; + int ret; =20 spin_lock_irqsave(&priv->lock, irqflags); =20 priv->fck_prescaler[channel_id] =3D prescaler; - quad8_filter_clock_prescaler_set(priv, channel_id, prescaler); + ret =3D quad8_filter_clock_prescaler_set(priv, channel_id, prescaler); =20 spin_unlock_irqrestore(&priv->lock, irqflags); =20 - return 0; + return ret; } =20 static struct counter_comp quad8_signal_ext[] =3D { @@ -1136,15 +1192,20 @@ static irqreturn_t quad8_irq_handler(int irq, void = *private) { struct counter_device *counter =3D private; struct quad8 *const priv =3D counter_priv(counter); + unsigned int status; unsigned long irq_status; unsigned long channel; unsigned int flg_pins; u8 event; + int ret; =20 - irq_status =3D ioread8(&priv->reg->interrupt_status); - if (!irq_status) + ret =3D regmap_read(priv->map, QUAD8_INTERRUPT_STATUS, &status); + if (ret) + return ret; + if (!status) return IRQ_NONE; =20 + irq_status =3D status; for_each_set_bit(channel, &irq_status, QUAD8_NUM_COUNTERS) { flg_pins =3D u8_get_bits(priv->ior[channel], FLG_PINS); switch (flg_pins) { @@ -1170,42 +1231,54 @@ static irqreturn_t quad8_irq_handler(int irq, void = *private) counter_push_event(counter, event, channel); } =20 - /* Clear pending interrupts on device */ - iowrite8(CLEAR_PENDING_INTERRUPTS, &priv->reg->channel_oper); + ret =3D regmap_write(priv->map, QUAD8_CHANNEL_OPERATION, CLEAR_PENDING_IN= TERRUPTS); + if (ret) + return ret; =20 return IRQ_HANDLED; } =20 -static void quad8_init_counter(struct quad8 *const priv, const size_t chan= nel) +static int quad8_init_counter(struct quad8 *const priv, const size_t chann= el) { - struct channel_reg __iomem *const chan =3D priv->reg->channel + channel; - - quad8_filter_clock_prescaler_set(priv, channel, 0); - quad8_preset_register_set(priv, channel, 0); - quad8_flag_register_reset(priv, channel); + int ret; + + ret =3D quad8_filter_clock_prescaler_set(priv, channel, 0); + if (ret) + return ret; + ret =3D quad8_preset_register_set(priv, channel, 0); + if (ret) + return ret; + ret =3D quad8_flag_register_reset(priv, channel); + if (ret) + return ret; =20 /* Binary encoding; Normal count; non-quadrature mode */ priv->cmr[channel] =3D SELECT_CMR | BINARY | u8_encode_bits(NORMAL_COUNT,= COUNT_MODE) | u8_encode_bits(NON_QUADRATURE, QUADRATURE_MODE); - iowrite8(priv->cmr[channel], &chan->control); + ret =3D regmap_write(priv->map, QUAD8_CONTROL(channel), priv->cmr[channel= ]); + if (ret) + return ret; =20 /* Disable A and B inputs; preset on index; FLG1 as Carry */ priv->ior[channel] =3D SELECT_IOR | DISABLE_AB | u8_encode_bits(LOAD_CNTR= , LOAD_PIN) | u8_encode_bits(FLG1_CARRY_FLG2_BORROW, FLG_PINS); - iowrite8(priv->ior[channel], &chan->control); + ret =3D regmap_write(priv->map, QUAD8_CONTROL(channel), priv->ior[channel= ]); + if (ret) + return ret; =20 /* Disable index function; negative index polarity */ priv->idr[channel] =3D SELECT_IDR | u8_encode_bits(DISABLE_INDEX_MODE, IN= DEX_MODE) | u8_encode_bits(NEGATIVE_INDEX_POLARITY, INDEX_POLARITY); - iowrite8(priv->idr[channel], &chan->control); + return regmap_write(priv->map, QUAD8_CONTROL(channel), priv->idr[channel]= ); } =20 static int quad8_probe(struct device *dev, unsigned int id) { struct counter_device *counter; struct quad8 *priv; + void __iomem *regs; unsigned long i; - int err; + int ret; =20 if (!devm_request_region(dev, base[id], QUAD8_EXTENT, dev_name(dev))) { dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n", @@ -1218,10 +1291,15 @@ static int quad8_probe(struct device *dev, unsigned= int id) return -ENOMEM; priv =3D counter_priv(counter); =20 - priv->reg =3D devm_ioport_map(dev, base[id], QUAD8_EXTENT); - if (!priv->reg) + regs =3D devm_ioport_map(dev, base[id], QUAD8_EXTENT); + if (!regs) return -ENOMEM; =20 + priv->map =3D devm_regmap_init_mmio(dev, regs, &quad8_regmap_config); + if (IS_ERR(priv->map)) + return dev_err_probe(dev, PTR_ERR(priv->map), + "Unable to initialize register map\n"); + /* Initialize Counter device and driver data */ counter->name =3D dev_name(dev); counter->parent =3D dev; @@ -1234,25 +1312,38 @@ static int quad8_probe(struct device *dev, unsigned= int id) spin_lock_init(&priv->lock); =20 /* Reset Index/Interrupt Register */ - iowrite8(0x00, &priv->reg->index_interrupt); + ret =3D regmap_write(priv->map, QUAD8_INDEX_INTERRUPT, 0x00); + if (ret) + return ret; /* Reset all counters and disable interrupt function */ - iowrite8(RESET_COUNTERS | DISABLE_INTERRUPT_FUNCTION, &priv->reg->channel= _oper); + ret =3D regmap_write(priv->map, QUAD8_CHANNEL_OPERATION, + RESET_COUNTERS | DISABLE_INTERRUPT_FUNCTION); + if (ret) + return ret; /* Set initial configuration for all counters */ - for (i =3D 0; i < QUAD8_NUM_COUNTERS; i++) - quad8_init_counter(priv, i); + for (i =3D 0; i < QUAD8_NUM_COUNTERS; i++) { + ret =3D quad8_init_counter(priv, i); + if (ret) + return ret; + } /* Disable Differential Encoder Cable Status for all channels */ - iowrite8(0xFF, &priv->reg->cable_status); + ret =3D regmap_write(priv->map, QUAD8_CABLE_STATUS, GENMASK(7, 0)); + if (ret) + return ret; /* Enable all counters and enable interrupt function */ - iowrite8(ENABLE_COUNTERS | ENABLE_INTERRUPT_FUNCTION, &priv->reg->channel= _oper); + ret =3D regmap_write(priv->map, QUAD8_CHANNEL_OPERATION, + ENABLE_COUNTERS | ENABLE_INTERRUPT_FUNCTION); + if (ret) + return ret; =20 - err =3D devm_request_irq(&counter->dev, irq[id], quad8_irq_handler, + ret =3D devm_request_irq(&counter->dev, irq[id], quad8_irq_handler, IRQF_SHARED, counter->name, counter); - if (err) - return err; + if (ret) + return ret; =20 - err =3D devm_counter_add(dev, counter); - if (err < 0) - return dev_err_probe(dev, err, "Failed to add counter\n"); + ret =3D devm_counter_add(dev, counter); + if (ret < 0) + return dev_err_probe(dev, ret, "Failed to add counter\n"); =20 return 0; } diff --git a/drivers/counter/Kconfig b/drivers/counter/Kconfig index b5ba8fb02cf7..52e80c0b6168 100644 --- a/drivers/counter/Kconfig +++ b/drivers/counter/Kconfig @@ -16,6 +16,7 @@ config 104_QUAD_8 tristate "ACCES 104-QUAD-8 driver" depends on (PC104 && X86) || COMPILE_TEST select ISA_BUS_API + select REGMAP_MMIO help Say yes here to build support for the ACCES 104-QUAD-8 quadrature encoder counter/interface device family (104-QUAD-8, 104-QUAD-4). --=20 2.39.2