From patchwork Wed May 10 16:22:40 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Martin_Za=C5=A5ovi=C4=8D?= X-Patchwork-Id: 92206 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp3756997vqo; Wed, 10 May 2023 09:31:02 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ6H4e0FKKxiUVLMUUpN+t71kq5MRu3N03V0ZUQAJMe8hwOhTk1RHdulO6QApBLqZVA2DvC3 X-Received: by 2002:a05:6a21:998c:b0:ff:e4f8:dc3 with SMTP id ve12-20020a056a21998c00b000ffe4f80dc3mr19067847pzb.39.1683736262235; Wed, 10 May 2023 09:31:02 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1683736262; cv=none; d=google.com; s=arc-20160816; b=fL9KrEfZetu3qrRGjHp2TDnYjjC3qyHK5b4cZbTdkvPsL9YBvvt7l1fnWT3pm04Iwy KrCfzE7OAlcPyaqZe+JAMrx+AVsyjym3mUljI/O5fOjHvx8kr4P6j7bfkewi9mdjGG2M 6dd2z6RUWsv0l7SQyOnDUTOatTkdbTgKkPuGsuuzdn9BhVpSrsmy8qUjI08cUrl728Aa WlLGp2C4rAQ1Y+R3a8stTEoraMS3ur8cgQeMbpHso74Au3YeaUJ+F6638VUdKQTpiONw wQJD4Fr+7syg7RKWzeNMnFuaz/Sh1qCo5AdRqixbcLLl+xD3hBJBd2KftQVOFpI1cCe/ /LsQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=GMXjZD5TG12KlJC0oMszsNGKJaWk0DNrIhumCmxtZDQ=; b=LilPZTnVFHFJizRHIi+qoNlmBBiLkqHn+Nx3vVW/nWi5mFNT311GQSXg/u3wCchXo3 uhjvlLQQavfo29rzEG0u4UaThHghx7dn5rzusvIXwz472HyXU60iwzbzCZqkw95dxR0q uw7Cdiu9etLgOKj6gPMxouU23Kh5Arml5yxIU+T5VIHXph9fdrTW5NKmMD3r6I9mYz21 nAp2Aaphlc1ScZDoZDFgvQaGF7HDWMPKYGMklv6R53pZmObKMV+qF7NBbX5xnHvUA4FE dJrqjA58+EseU8cSWGyGnCC7D+tRckLj11uD5vn7tDtoqNrb9IUhQJgVg7fymmb3lBQu sDRQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20221208 header.b=EeiLouIo; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id i4-20020a63e444000000b004df18fa49aesi4055724pgk.796.2023.05.10.09.30.47; Wed, 10 May 2023 09:31:02 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20221208 header.b=EeiLouIo; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235203AbjEJQYK (ORCPT + 99 others); Wed, 10 May 2023 12:24:10 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48334 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229546AbjEJQXc (ORCPT ); Wed, 10 May 2023 12:23:32 -0400 Received: from mail-ej1-x629.google.com (mail-ej1-x629.google.com [IPv6:2a00:1450:4864:20::629]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 198817D97; Wed, 10 May 2023 09:22:56 -0700 (PDT) Received: by mail-ej1-x629.google.com with SMTP id a640c23a62f3a-969f90d71d4so347235566b.3; Wed, 10 May 2023 09:22:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1683735774; x=1686327774; 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=GMXjZD5TG12KlJC0oMszsNGKJaWk0DNrIhumCmxtZDQ=; b=EeiLouIo8Cw00Sa3M2/bq+acP9EsBNGgNlXg3uJ3iODy1v6EnM0Ve3NcOvg0nm1J77 3v51DGXizh127Li3O3T6UmJUMRLFthAyw51Xu76O6cPH2fAL/TjvyokPMOnMMdud81Az VC1dI79sMhRb0c3b3htMcojLWb36HseGozRaa37rLTeYfAqqB1g37s8NxXgEIIFnIAma 5OWVStih6zNUsYZk15XZLggo3pOoagipJsNkNHEKPlWvLB+BltE9z3hN8p3rCGIE1osT vb01nF6S0bU8THPlnNayKkOGd2UcuR302G+BdVDb2WXl/68c/xNjvA9aNLI7KskZiHm0 o3tQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1683735774; x=1686327774; 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=GMXjZD5TG12KlJC0oMszsNGKJaWk0DNrIhumCmxtZDQ=; b=VBzN/WbkoGZhsza95lNxLe+O4itgr94qNCzt2nE/y7c/CDM2eoHiGtUkKjEYTcEIuu hzDFohKib/DXNONi/vG7ALlv+0ddTF5sJcYzMqVIINdKIIMJHEdwyo6Exi8lkih418CD +NdzyTVUu6zHKtm0xp1JaXEJC1MFA0QSCRaXNPiTR9in7AvoHV5VEKQJXv9Z1Cpe5icb Tzz2MH/bgvHFdx5LVnqzL0CI3z+I4TMcHO5Mkuq9m+L7xpgZShZusCwhwvH1OJlYrKLp NH3IjzHDIs4L1JkiPudHMlgt5jVXoaluS6+m9wFPTkFeut9OzXbmYD3+CB+b7n538HgK bAXg== X-Gm-Message-State: AC+VfDzutVD9Q+0QYrcabfajbJiEnDmcZgkfygpWgQAolae8qSNExIwd qy3A0INoofh7yN/xZt8/TsxscLPiDc+jyVZ7 X-Received: by 2002:a17:907:1614:b0:956:f4f8:23b6 with SMTP id hb20-20020a170907161400b00956f4f823b6mr19575722ejc.43.1683735774026; Wed, 10 May 2023 09:22:54 -0700 (PDT) Received: from fedora.dev.tbscz ([85.93.123.158]) by smtp.gmail.com with ESMTPSA id m28-20020a17090677dc00b00947ed087a2csm2890149ejn.154.2023.05.10.09.22.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 10 May 2023 09:22:53 -0700 (PDT) From: =?utf-8?q?Martin_Za=C5=A5ovi=C4=8D?= To: linux-kernel@vger.kernel.org Cc: robh+dt@kernel.org, krzysztof.kozlowski+dt@linaro.org, conor+dt@kernel.org, gregkh@linuxfoundation.org, beanhuo@micron.com, nipun.gupta@amd.com, linus.walleij@linaro.org, mwen@igalia.com, bvanassche@acm.org, arnd@arndb.de, ogabbay@kernel.org, linux@zary.sk, jacek.lawrynowicz@linux.intel.com, geert+renesas@glider.be, benjamin.tissoires@redhat.com, masahiroy@kernel.org, yangyicong@hisilicon.com, devicetree@vger.kernel.org, =?utf-8?q?Martin_Za?= =?utf-8?q?=C5=A5ovi=C4=8D?= , Rob Herring Subject: [PATCHv4 1/4] dt-bindings: wiegand: add Wiegand controller common properties Date: Wed, 10 May 2023 18:22:40 +0200 Message-Id: <20230510162243.95820-2-m.zatovic1@gmail.com> X-Mailer: git-send-email 2.40.0 In-Reply-To: <20230510162243.95820-1-m.zatovic1@gmail.com> References: <20230510162243.95820-1-m.zatovic1@gmail.com> MIME-Version: 1.0 X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS, T_SCC_BODY_TEXT_LINE,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1765525435073093992?= X-GMAIL-MSGID: =?utf-8?q?1765525435073093992?= Wiegand bus is defined by a Wiegand controller node. This node can contain one or more device nodes for devices attached to the controller(it is advised to only connect one device as Wiegand is a point-to-point bus). Wiegand controller needs to specify several attributes such as the pulse length in order to function properly. These attributes are documented here. Acked-by: Linus Walleij Reviewed-by: Rob Herring Signed-off-by: Martin Zaťovič --- .../bindings/wiegand/wiegand-controller.yaml | 39 +++++++++++++++++++ MAINTAINERS | 5 +++ 2 files changed, 44 insertions(+) create mode 100644 Documentation/devicetree/bindings/wiegand/wiegand-controller.yaml diff --git a/Documentation/devicetree/bindings/wiegand/wiegand-controller.yaml b/Documentation/devicetree/bindings/wiegand/wiegand-controller.yaml new file mode 100644 index 000000000000..8f36287e4fed --- /dev/null +++ b/Documentation/devicetree/bindings/wiegand/wiegand-controller.yaml @@ -0,0 +1,39 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/wiegand/wiegand-controller.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Wiegand Generic Controller Common Properties + +maintainers: + - Martin Zaťovič + +description: + Wiegand busses can be described with a node for the Wiegand controller device + and a set of child nodes for each SPI slave on the bus. + +properties: + $nodename: + pattern: "^wiegand(@.*|-[0-9a-f])?$" + + pulse-len-us: + description: + Length of the low pulse in microseconds. + + interval-len-us: + description: + Length of a whole bit (both the pulse and the high phase) in microseconds. + + frame-gap-us: + description: + Length of the last bit of a frame (both the pulse and the high phase) in + microseconds. + +required: + - compatible + - pulse-len-us + - interval-len-us + - frame-gap-us + +additionalProperties: true diff --git a/MAINTAINERS b/MAINTAINERS index 7e0b87d5aa2e..55602888f084 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -22697,6 +22697,11 @@ L: linux-input@vger.kernel.org S: Maintained F: drivers/hid/hid-wiimote* +WIEGAND BUS DRIVER +M: Martin Zaťovič +S: Maintained +F: Documentation/devicetree/bindings/wiegand/wiegand-controller.yaml + WILOCITY WIL6210 WIRELESS DRIVER L: linux-wireless@vger.kernel.org S: Orphan From patchwork Wed May 10 16:22:41 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Martin_Za=C5=A5ovi=C4=8D?= X-Patchwork-Id: 92204 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp3753397vqo; Wed, 10 May 2023 09:25:46 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ4JYOwKtc2hoVzVQ/Lrsrfya0sAZXXsCX526r4Zvp/6pZ3DFtiXna+kvFu9wrRpUJgPxNQH X-Received: by 2002:a17:90a:ff09:b0:247:c85:21f5 with SMTP id ce9-20020a17090aff0900b002470c8521f5mr25438206pjb.19.1683735946029; Wed, 10 May 2023 09:25:46 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1683735946; cv=none; d=google.com; s=arc-20160816; b=vIj/FUEsntcWgXmMDcsRGtMy/mPbDnE/p9WOmfZcPjHIQ86l7/I74IXYETLLosbqev paeVAFGehwpChep+39qM82ZFdufx1EmMybU66sI/+Vm9dUglykJfwQWg+CkNdqcc9mI5 Tp08fv/29gToZFQ8ra34cOCKbZrsJJzO/HJCflLCIyJU+PDJMpelWKUzC0r5tGyTe8Ir 9FOJi8pMiZZejP+0kmjkG81rVfr/Cxl6c3zpbdnbzmk0r5e1mXENXBUFoMwsLf0lhTIb WK7AMj9yhw61Gu3E2mgXeed1hg8U9vu0EBOnaKtQeao14LCvmDSweX+A/hkDVYFsNdgG Lv+g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=WHI30Q2RD/vYYr55KU45GDr+Oc48RdK1ZLccMHmNqZc=; b=ApdlnC0+EtOJttkHQOG3wWwq4eFvuGfUjVMvsSwqMJcZVk2Pdh3Gef2mskJSST7M2t 1xmljMjjnnIF7avVab/fv79eHYeQ4JjS2Px7tJhRVXqOf1Pv/sRP9VkRG0LgLbkO8fuM TZxg7h5i7/bUC0tjxOlUA9FGXLYU4ETRmr2s7t8Q0ugtQBkKwsxzgw0q5hQMlkhvVtS0 Mq+snbdP2IWzmZveNfvJ39o/qFUTXoZZbyL3M8IjJRctmC3XdB991stHJYCrFeH/FyzF GkSJOsY3SQe2VIlbiYgTKeLzO7yxFVyZx0r1rnlOy0tMVFbE7xqLyuaiblJaoECTIi9Q QxTQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20221208 header.b="j3n/1o9R"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id d9-20020a631d09000000b0052c96dcaa83si4439704pgd.327.2023.05.10.09.25.32; Wed, 10 May 2023 09:25:45 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20221208 header.b="j3n/1o9R"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232443AbjEJQYF (ORCPT + 99 others); Wed, 10 May 2023 12:24:05 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48376 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231175AbjEJQXc (ORCPT ); Wed, 10 May 2023 12:23:32 -0400 Received: from mail-ed1-x52d.google.com (mail-ed1-x52d.google.com [IPv6:2a00:1450:4864:20::52d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4805C7ED4; Wed, 10 May 2023 09:22:58 -0700 (PDT) Received: by mail-ed1-x52d.google.com with SMTP id 4fb4d7f45d1cf-50b37f3e664so13224175a12.1; Wed, 10 May 2023 09:22:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1683735777; x=1686327777; 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=WHI30Q2RD/vYYr55KU45GDr+Oc48RdK1ZLccMHmNqZc=; b=j3n/1o9Rzo35zGP8RtRTWMb39KJQSoN4Iw4YiFgxSmSVdwnEL2kdSB/Rr6YVTZ1y6b m6SKUTESxLSUxlIYwbAaGxTxqob2CVLpT1h3U9/sKOOfcVkxFc/NiVawv/B0wPp+nY52 7ir/3/H3DECgdP9Xk1MG6EqJcLskgE6e6rzV3WT1pD0vofgqwB9729ce/GPm/g1AXcQ2 MY0/v+OFdUEMaHaSBKUtjews64+HUUbq3dt9rUH/r6wXf9OsJM85rM+k72UnhLExWIl9 BklRVYp6xqe4wfuDpybSFiLZiCm3V5rzcq3HvXdaSHsM3RgcCTfFHYueDi1c4vEeY/mj EE9g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1683735777; x=1686327777; 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=WHI30Q2RD/vYYr55KU45GDr+Oc48RdK1ZLccMHmNqZc=; b=j4uWoDgGOsCX2JzMLsgOM6j7mhRXJWKm1xpWuU+Xlt5Hkew8RVK+pu3EIvTQ261MKW 5wO5Z6SiclgAHrD2fuXDVM7VcHVKnNA3izXrdzSBgqJov1DbCpr9JIQ2wssFqEITbzBM jR6IsvS2HB5iMgTt2u0MFKEv/JKCwAGIKnyrCR2NTAVtIXZ52d7TubIOCWN+ASE2S4B6 /Xpg1Y/cSKaS+g3+nwbC/LpBPbsOlGJYDi+WZPgETGHxF6ZmLoPVkug2g2xLExrKFwtm ipNxDsALb7nECD98Jw9gIRQqEu22sCC0+8I+XF2cDznsn3wOQmgEeK5BvDCuQTSbErmO xAnw== X-Gm-Message-State: AC+VfDwrrRsSDduHeJoDQJ9E8nC52G2frCEyG7QGZ76sLPx+DtQ8zxCl 89gXQkzm6UtEAxSGoU7gEGVAtAEkZEa6g+vd X-Received: by 2002:a17:907:806:b0:953:47fc:3f0b with SMTP id wv6-20020a170907080600b0095347fc3f0bmr14317315ejb.53.1683735776304; Wed, 10 May 2023 09:22:56 -0700 (PDT) Received: from fedora.dev.tbscz ([85.93.123.158]) by smtp.gmail.com with ESMTPSA id m28-20020a17090677dc00b00947ed087a2csm2890149ejn.154.2023.05.10.09.22.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 10 May 2023 09:22:55 -0700 (PDT) From: =?utf-8?q?Martin_Za=C5=A5ovi=C4=8D?= To: linux-kernel@vger.kernel.org Cc: robh+dt@kernel.org, krzysztof.kozlowski+dt@linaro.org, conor+dt@kernel.org, gregkh@linuxfoundation.org, beanhuo@micron.com, nipun.gupta@amd.com, linus.walleij@linaro.org, mwen@igalia.com, bvanassche@acm.org, arnd@arndb.de, ogabbay@kernel.org, linux@zary.sk, jacek.lawrynowicz@linux.intel.com, geert+renesas@glider.be, benjamin.tissoires@redhat.com, masahiroy@kernel.org, yangyicong@hisilicon.com, devicetree@vger.kernel.org, =?utf-8?q?Martin_Za?= =?utf-8?q?=C5=A5ovi=C4=8D?= Subject: [PATCHv4 2/4] wiegand: add Wiegand bus driver Date: Wed, 10 May 2023 18:22:41 +0200 Message-Id: <20230510162243.95820-3-m.zatovic1@gmail.com> X-Mailer: git-send-email 2.40.0 In-Reply-To: <20230510162243.95820-1-m.zatovic1@gmail.com> References: <20230510162243.95820-1-m.zatovic1@gmail.com> MIME-Version: 1.0 X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS, T_SCC_BODY_TEXT_LINE,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1765525103370869893?= X-GMAIL-MSGID: =?utf-8?q?1765525103370869893?= Add a bus driver for Wiegand protocol. The bus driver handles Wiegand controller and Wiegand device managemement and driver matching. The bus driver defines the structures for Wiegand controllers and Wiegand devices. Wiegand controller structure represents a master and contains attributes such as the payload_len for configuring the size of a single Wiegand message in bits. It also stores the controller attributes defined in the devicetree. Each Wiegand controller should be associated with one Wiegand device, as Wiegand is typically a point-to-point bus. Acked-by: Linus Walleij Signed-off-by: Martin Zaťovič --- MAINTAINERS | 2 + drivers/Kconfig | 2 + drivers/Makefile | 1 + drivers/wiegand/Kconfig | 20 ++ drivers/wiegand/Makefile | 1 + drivers/wiegand/wiegand.c | 609 ++++++++++++++++++++++++++++++++++++++ include/linux/wiegand.h | 144 +++++++++ 7 files changed, 779 insertions(+) create mode 100644 drivers/wiegand/Kconfig create mode 100644 drivers/wiegand/Makefile create mode 100644 drivers/wiegand/wiegand.c create mode 100644 include/linux/wiegand.h diff --git a/MAINTAINERS b/MAINTAINERS index 55602888f084..7b7e546572e8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -22701,6 +22701,8 @@ WIEGAND BUS DRIVER M: Martin Zaťovič S: Maintained F: Documentation/devicetree/bindings/wiegand/wiegand-controller.yaml +F: drivers/wiegand/wiegand.c +F: include/linux/wiegand.h WILOCITY WIL6210 WIRELESS DRIVER L: linux-wireless@vger.kernel.org diff --git a/drivers/Kconfig b/drivers/Kconfig index 514ae6b24cb2..6609dfd6635f 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -145,6 +145,8 @@ source "drivers/vdpa/Kconfig" source "drivers/vhost/Kconfig" +source "drivers/wiegand/Kconfig" + source "drivers/hv/Kconfig" source "drivers/xen/Kconfig" diff --git a/drivers/Makefile b/drivers/Makefile index 7241d80a7b29..f53f0d83195b 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -150,6 +150,7 @@ obj-$(CONFIG_VHOST_RING) += vhost/ obj-$(CONFIG_VHOST_IOTLB) += vhost/ obj-$(CONFIG_VHOST) += vhost/ obj-$(CONFIG_VLYNQ) += vlynq/ +obj-$(CONFIG_WIEGAND) += wiegand/ obj-$(CONFIG_GREYBUS) += greybus/ obj-$(CONFIG_COMEDI) += comedi/ obj-$(CONFIG_STAGING) += staging/ diff --git a/drivers/wiegand/Kconfig b/drivers/wiegand/Kconfig new file mode 100644 index 000000000000..fc99575bc3cc --- /dev/null +++ b/drivers/wiegand/Kconfig @@ -0,0 +1,20 @@ +config WIEGAND + tristate "Wiegand Bus driver" + help + The "Wiegand Interface" is an asynchronous low-level protocol + or wiring standard. It is typically used for point-to-point + communication. The data length of Wiegand messages is not defined, + so the devices usually default to 26, 36 or 37 bits per message. + The throughput of Wiegand depends on the selected pulse length and + the intervals between pulses, in comparison to other busses it + is generally rather slow. + + Despite its higher age, Wiegand remains widely used in access + control systems to connect a card swipe mechanism. Such mechanisms + utilize the Wiegand effect to transfer data from the card to + the reader. + + Wiegand uses two wires to transmit the data D0 and D1. Both lines + are initially pulled up. When a bit of value 0 is being transmitted, + the D0 line is pulled down. Similarly, when a bit of value 1 is being + transmitted, the D1 line is pulled down. diff --git a/drivers/wiegand/Makefile b/drivers/wiegand/Makefile new file mode 100644 index 000000000000..d17ecb722c6e --- /dev/null +++ b/drivers/wiegand/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_WIEGAND) += wiegand.o diff --git a/drivers/wiegand/wiegand.c b/drivers/wiegand/wiegand.c new file mode 100644 index 000000000000..f82091d251d0 --- /dev/null +++ b/drivers/wiegand/wiegand.c @@ -0,0 +1,609 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct bus_type wiegand_bus_type; + +/** + * struct wiegand_device - Wiegand listener device + * @dev - drivers structure of the device + * @id - unique device id + * @controller - Wiegand controller associated with the device + * @modalias - Name of the driver to use with this device, or its alias. + */ +struct wiegand_device { + struct device dev; + u8 id; + struct wiegand_controller *controller; + char modalias[WIEGAND_NAME_SIZE]; +}; + +DEFINE_IDA(wiegand_controller_ida); + +static inline void wiegand_device_put(struct wiegand_device *wiegand); +static inline struct wiegand_device *to_wiegand_device(struct device *dev); + +static int wiegand_fopen(struct inode *ino, struct file *filp); +static int wiegand_frelease(struct inode *ino, struct file *filp); +static ssize_t wiegand_fwrite(struct file *filp, char __user const *buf, size_t len, + loff_t *offset); + +/** + * wiegand_controller_release - called after the final refererence decrement + * @dev: the controller device + */ +static void wiegand_controller_release(struct device *dev) +{ + struct wiegand_controller *ctlr; + + ctlr = container_of(dev, struct wiegand_controller, dev); + kfree(ctlr); +} + +/** + * wiegand_alloc_controller - allocate a new Wiegand controller + * @dev: the controller device + * @size: size of the private data to be allocated for the caller + * @secondary: true if the controller is a secondary controller(reads data) + * + * This function is only by Wiegand controller drivers to allocate a new Wiegand controller + * structure before registering it using wiegand_register_controller(). + */ +struct wiegand_controller *wiegand_alloc_controller(struct device *dev, unsigned int size, + bool secondary) +{ + struct wiegand_controller *ctlr; + size_t ctlr_size = ALIGN(sizeof(*ctlr), dma_get_cache_alignment()); + + if (!dev) + return NULL; + + ctlr = kzalloc(size + ctlr_size, GFP_KERNEL); + if (!ctlr) + return NULL; + + device_initialize(&ctlr->dev); + + ctlr->bus_num = -1; + ctlr->secondary = secondary; + ctlr->dev.parent = dev; + ctlr->dev.release = wiegand_controller_release; + + wiegand_controller_set_devdata(ctlr, (void *)ctlr + ctlr_size); + + return ctlr; +} +EXPORT_SYMBOL_GPL(wiegand_alloc_controller); + +static void devm_wiegand_release_controller(struct device *dev, void *ctlr) +{ + wiegand_controller_put(*(struct wiegand_controller **)ctlr); +} + +/** + * devm_wiegand_alloc_controller - device managed allocation of a new Wiegand controller + * @dev: physical device of Wiegand controller + * @size: size of the private data to be allocated for the caller + * @secondary: true if the controller is a secondary controller(reads data) + * + * Device managed version of wiegand_alloc_controller(). The Wiegand controller is automatically + * freed on driver detach. + */ +struct wiegand_controller *devm_wiegand_alloc_controller(struct device *dev, unsigned int size, + bool secondary) +{ + struct wiegand_controller *ctlr, **ptr; + + ptr = devres_alloc(devm_wiegand_release_controller, sizeof(*ptr), GFP_KERNEL); + if (!ptr) + return NULL; + + ctlr = wiegand_alloc_controller(dev, size, secondary); + if (ctlr) { + ctlr->devm_allocated = true; + *ptr = ctlr; + devres_add(dev, ptr); + } else { + devres_free(ptr); + } + + return ctlr; +} +EXPORT_SYMBOL_GPL(devm_wiegand_alloc_controller); + +static int wiegand_controller_check_ops(struct wiegand_controller *ctlr) +{ + if (!ctlr->transfer_message) + return -EINVAL; + return 0; +} + +/** + * register_wiegand_device - allocates and registers a new Wiegand device + * @ctlr: controller structure to attach device to + * @nc: devicetree node for the device + */ +static struct wiegand_device *register_wiegand_device(struct wiegand_controller *ctlr, + struct fwnode_handle *fwnode) +{ + struct wiegand_device *wiegand; + int ret; + + wiegand = wiegand_alloc_device(ctlr); + if (!wiegand) { + dev_err(&ctlr->dev, "wiegad_device alloc error for %pOF\n", fwnode); + ret = -ENOMEM; + goto err_out; + } + + fwnode_handle_get(fwnode); + wiegand->dev.fwnode = fwnode; + + ret = wiegand_add_device(wiegand); + if (ret) { + dev_err(&ctlr->dev, "wiegand_device register error %pOF\n", fwnode); + goto err_node_put; + } + + /* check if more devices are connected to the bus */ + if (ctlr->device_count > 1) + dev_warn(&ctlr->dev, "Wiegand is a point-to-point bus, it is advised to only connect one device per Wiegand bus. The devices may not communicate using the same pulse length, format or else.\n"); + + return wiegand; + +err_node_put: + fwnode_handle_put(fwnode); +err_out: + wiegand_device_put(wiegand); + return ERR_PTR(ret); +} + +static void register_wiegand_devices(struct wiegand_controller *ctlr) +{ + struct wiegand_device *wiegand; + struct fwnode_handle *fwnode; + + if (!ctlr->dev.fwnode) + return; + + fwnode_for_each_available_child_node(ctlr->dev.fwnode, fwnode) { + wiegand = register_wiegand_device(ctlr, fwnode); + if (IS_ERR(wiegand)) + dev_warn(&ctlr->dev, "failed to create wiegand device for %pOF\n", fwnode); + } +} + +static void wiegand_controller_parse_property(struct device *dev, const char *prop_name, + u32 *cur_val_p, u32 def_val, bool use_def) +{ + int ret; + + ret = device_property_read_u32(dev, prop_name, cur_val_p); + if ((ret && use_def) || *cur_val_p == 0) + *cur_val_p = def_val; + + dev_dbg(dev, "%s: %u\n", prop_name, *cur_val_p); +} + +#define USE_DEFAULT_VAL 1 + +static void wiegand_controller_parse_properties(struct wiegand_controller *ctlr) +{ + wiegand_controller_parse_property(&ctlr->dev, "pulse-len-us", &ctlr->pulse_len, + 50, USE_DEFAULT_VAL); + wiegand_controller_parse_property(&ctlr->dev, "interval-len-us", &ctlr->interval_len, + 2000, USE_DEFAULT_VAL); + wiegand_controller_parse_property(&ctlr->dev, "frame-gap-us", &ctlr->frame_gap, + 2000, USE_DEFAULT_VAL); +} + +static int __unregister(struct device *dev, void *null) +{ + wiegand_unregister_device(to_wiegand_device(dev)); + return 0; +} + +/** + * wiegand_unregister_controller - unregisters controller structure within Wiegand bus + * + * @ptr pointer to a wiegand_controller structure + * + * Frees all resources allocated by the wiegand_register_controller() function. + * If the controller was registered using devm_wiegand_alloc_controller() then + * this function is called automatically on driver detach.Otherwise the function needs + * to be called manually. If controller is not devm managed, then the reference to the + * controller structure is put. + */ +void wiegand_unregister_controller(void *ptr) +{ + struct wiegand_controller *ctlr = ptr; + unsigned int id = ctlr->bus_num; + + device_for_each_child(&ctlr->dev, NULL, __unregister); + ida_free(&wiegand_controller_ida, id); + device_del(&ctlr->dev); + + kfree(ctlr->miscdev.name); + misc_deregister(&ctlr->miscdev); + + if (!ctlr->devm_allocated) + put_device(&ctlr->dev); +} +EXPORT_SYMBOL_GPL(wiegand_unregister_controller); + +/** + * wiegand_register_controller - registers controller structure within bus + * @ctlr: controller structure to register + * + * Function checks that the message transfer functions is defined for passed controller structure, + * gets its attributes and finally adds the controller device and registers the controller on the + * bus. + */ +int wiegand_register_controller(struct wiegand_controller *ctlr) +{ + struct device *dev = ctlr->dev.parent; + int status, id; + + if (!dev) + return -ENODEV; + + status = wiegand_controller_check_ops(ctlr); + if (status) + return status; + + id = ida_alloc(&wiegand_controller_ida, GFP_KERNEL); + if (WARN(id < 0, "couldn't get an id\n")) + return id; + ctlr->bus_num = id; + + wiegand_controller_parse_properties(ctlr); + + dev_set_name(&ctlr->dev, "wiegand%u", ctlr->bus_num); + ctlr->miscdev.name = kasprintf(GFP_KERNEL, "wiegand1"); + if (!ctlr->miscdev.name) + return -ENOMEM; + + ctlr->fops.owner = THIS_MODULE; + ctlr->fops.open = wiegand_fopen; + ctlr->fops.release = wiegand_frelease; + ctlr->fops.write = wiegand_fwrite; + ctlr->miscdev.fops = &ctlr->fops; + ctlr->miscdev.minor = MISC_DYNAMIC_MINOR; + + status = misc_register(&ctlr->miscdev); + if (status) { + dev_err(&ctlr->dev, "couldn't register misc device\n"); + return status; + } + + mutex_init(&ctlr->file_lock); + + status = device_add(&ctlr->dev); + if (status < 0) + goto free_bus_id; + + ctlr->device_count = 0; + ctlr->miscdev.parent = &ctlr->dev; + register_wiegand_devices(ctlr); + + return status; + +free_bus_id: + ida_free(&wiegand_controller_ida, ctlr->bus_num); + misc_deregister(&ctlr->miscdev); + kfree(ctlr->miscdev.name); + return status; +} +EXPORT_SYMBOL_GPL(wiegand_register_controller); + +int devm_wiegand_register_controller(struct device *dev, struct wiegand_controller *ctlr) +{ + int ret; + + ret = wiegand_register_controller(ctlr); + if (ret < 0) + return ret; + + return devm_add_action_or_reset(dev, wiegand_unregister_controller, ctlr); +} +EXPORT_SYMBOL_GPL(devm_wiegand_register_controller); + +/* Device section */ + +static inline struct wiegand_device *to_wiegand_device(struct device *dev) +{ + return dev ? container_of(dev, struct wiegand_device, dev) : NULL; +} + +struct wiegand_controller *wiegand_device_get_controller(struct wiegand_device *dev) +{ + return dev->controller; +} +EXPORT_SYMBOL_GPL(wiegand_device_get_controller); + +static inline void wiegand_device_put(struct wiegand_device *wiegand) +{ + if (wiegand) + put_device(&wiegand->dev); + + if (wiegand->controller->cleanup) + wiegand->controller->cleanup(wiegand); +} + +/** + * wiegand_dev_release - called after the final reference count decrement + * @dev: device to release + */ +static void wiegand_dev_release(struct device *dev) +{ + struct wiegand_device *wiegand = to_wiegand_device(dev); + + wiegand_controller_put(wiegand->controller); + kfree(wiegand); +} + +struct wiegand_device *wiegand_alloc_device(struct wiegand_controller *ctlr) +{ + struct wiegand_device *wiegand; + + wiegand = kzalloc(sizeof(*wiegand), GFP_KERNEL); + if (!wiegand) { + wiegand_controller_put(ctlr); + return NULL; + } + + wiegand->controller = ctlr; + wiegand->dev.parent = &ctlr->dev; + wiegand->dev.bus = &wiegand_bus_type; + wiegand->dev.release = wiegand_dev_release; + + device_initialize(&wiegand->dev); + return wiegand; +} +EXPORT_SYMBOL_GPL(wiegand_alloc_device); + +static void wiegand_cleanup(struct wiegand_device *wiegand) +{ + if (wiegand->controller->cleanup) + wiegand->controller->cleanup(wiegand); +} + +static int wiegand_dev_set_name(struct wiegand_device *wiegand, u8 id) +{ + int ret = dev_set_name(&wiegand->dev, "%s.%u", dev_name(&wiegand->controller->dev), id); + return ret; +} + +static int __wiegand_add_device(struct wiegand_device *wiegand) +{ + struct wiegand_controller *ctlr = wiegand->controller; + struct device *dev = ctlr->dev.parent; + int status; + + status = wiegand_setup(wiegand); + if (status < 0) { + dev_err(dev, "can't setup %s, status %d\n", + dev_name(&wiegand->dev), status); + return status; + } + + status = device_add(&wiegand->dev); + if (status < 0) { + dev_err(dev, "can't add %s, status %d\n", dev_name(&wiegand->dev), status); + wiegand_cleanup(wiegand); + } else { + dev_dbg(dev, "registered child %s\n", dev_name(&wiegand->dev)); + } + + return status; +} + +int wiegand_add_device(struct wiegand_device *wiegand) +{ + struct wiegand_controller *ctlr = wiegand->controller; + int status; + + status = wiegand_dev_set_name(wiegand, ctlr->device_count); + if (status) + return status; + + status = __wiegand_add_device(wiegand); + if (!status) { + ctlr->device_count++; + wiegand->id = wiegand->controller->device_count; + } + + return status; +} + +int wiegand_setup(struct wiegand_device *wiegand) +{ + int status = 0; + + if (wiegand->controller->setup) { + status = wiegand->controller->setup(wiegand); + if (status) { + dev_err(&wiegand->controller->dev, "failed to setup device: %d\n", status); + return status; + } + } + + return status; +} +EXPORT_SYMBOL_GPL(wiegand_setup); + +void wiegand_unregister_device(struct wiegand_device *wiegand) +{ + if (!wiegand) + return; + + if (wiegand->dev.fwnode) + fwnode_handle_put(wiegand->dev.fwnode); + + fwnode_remove_software_node(wiegand->dev.fwnode); + device_del(&wiegand->dev); + wiegand_cleanup(wiegand); + put_device(&wiegand->dev); +} +EXPORT_SYMBOL_GPL(wiegand_unregister_device); + +int wiegand_send_message(struct wiegand_device *wiegand, unsigned long *msg_bmp, u8 bitlen) +{ + struct wiegand_primary *primary = wiegand->controller; + + if (msg_bmp == NULL) + return -EINVAL; + + if (primary->transfer_message) + primary->transfer_message(primary); + + return 0; +} +EXPORT_SYMBOL_GPL(wiegand_send_message); + +static ssize_t wiegand_get_user_data(struct wiegand_controller *ctlr, char __user const *buf, + size_t len) +{ + int i; + char data_buffer[WIEGAND_MAX_PAYLEN_BYTES]; + + if (len > WIEGAND_MAX_PAYLEN_BYTES) + return -EBADMSG; + + if (copy_from_user(&data_buffer[0], buf, WIEGAND_MAX_PAYLEN_BYTES)) + return -EFAULT; + + for (i = 0; i < len; i++) + bitmap_set_value8(ctlr->data_bitmap, data_buffer[i], i * 8); + + return len; +} + +static int wiegand_frelease(struct inode *ino, struct file *filp) +{ + struct wiegand_controller *ctlr = filp->private_data; + + mutex_destroy(&ctlr->file_lock); + return 0; +} + +static ssize_t wiegand_fwrite(struct file *filp, char __user const *buf, size_t len, + loff_t *offset) +{ + int ret; + struct wiegand_controller *ctlr = filp->private_data; + u32 msg_length = ctlr->payload_len; + + if (!buf || len == 0 || DIV_ROUND_UP(msg_length, 8) > len) + return -EINVAL; + + ret = wiegand_get_user_data(ctlr, buf, len); + if (ret < 0) + return ret; + + ctlr->transfer_message(ctlr); + + return len; +} + +static int wiegand_fopen(struct inode *ino, struct file *filp) +{ + int ret; + struct wiegand_controller *ctlr = container_of(filp->f_op, struct wiegand_controller, fops); + + filp->private_data = ctlr; + + mutex_lock(&ctlr->file_lock); + + if ((filp->f_flags & O_ACCMODE) == O_RDONLY || (filp->f_flags & O_ACCMODE) == O_RDWR) { + dev_err(ctlr->miscdev.this_device, "device is write only\n"); + ret = -EIO; + goto err; + } + + mutex_unlock(&ctlr->file_lock); + + return 0; +err: + mutex_unlock(&ctlr->file_lock); + mutex_destroy(&ctlr->file_lock); + return ret; +} + +static int wiegand_match_device(struct device *dev, struct device_driver *drv) +{ + struct wiegand_device *wiegand_dev = to_wiegand_device(dev); + + if (of_driver_match_device(dev, drv)) + return 1; + + return (strcmp(wiegand_dev->modalias, drv->name) == 0); +} + +static int wiegand_probe(struct device *dev) +{ + struct wiegand_device *wiegand = to_wiegand_device(dev); + const struct wiegand_driver *wdrv = to_wiegand_driver(dev->driver); + + if (wdrv->probe) + return wdrv->probe(wiegand); + + return 0; +} + +static void wiegand_remove(struct device *dev) +{ + const struct wiegand_driver *wdrv = to_wiegand_driver(dev->driver); + + if (wdrv->remove) + wdrv->remove(to_wiegand_device(dev)); +} + +static struct bus_type wiegand_bus_type = { + .name = "wiegand", + .match = wiegand_match_device, + .probe = wiegand_probe, + .remove = wiegand_remove, +}; + +int __wiegand_register_driver(struct module *owner, struct wiegand_driver *wdrv) +{ + wdrv->driver.owner = owner; + wdrv->driver.bus = &wiegand_bus_type; + + return driver_register(&wdrv->driver); +} +EXPORT_SYMBOL_GPL(__wiegand_register_driver); + +static int __init wiegand_init(void) +{ + int ret; + + ret = bus_register(&wiegand_bus_type); + if (ret < 0) { + pr_err("Wiegand bus registration failed: %d\n", ret); + return ret; + } + + return 0; +} + +static void __exit wiegand_exit(void) +{ + ida_destroy(&wiegand_controller_ida); + bus_unregister(&wiegand_bus_type); +} +postcore_initcall_sync(wiegand_init); +module_exit(wiegand_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Wiegand bus driver"); +MODULE_AUTHOR("Martin Zaťovič "); diff --git a/include/linux/wiegand.h b/include/linux/wiegand.h new file mode 100644 index 000000000000..92d46114a4a8 --- /dev/null +++ b/include/linux/wiegand.h @@ -0,0 +1,144 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef H_LINUX_INCLUDE_LINUX_WIEGAND_H +#define H_LINUX_INCLUDE_LINUX_WIEGAND_H + +#include +#include +#include +#include + +#define WIEGAND_NAME_SIZE 32 +#define WIEGAND_MAX_PAYLEN_BYTES 256 + +extern struct bus_type wiegand_type; + +struct wiegand_device; + +/** + * struct wiegand_controller - Wiegand primary or secondary interface + * @dev - Device interface of the controller + * @list - Link with the global wiegand_controller list + * @bus_num - Board-specific identifier for Wiegand controller + * @pulse_len: length of the low pulse in usec; defaults to 50us + * @interval_len: length of a whole bit (both the pulse and the high phase) in usec; + * defaults to 2000us + * @frame_gap: length of the last bit of a frame (both the pulse and the high phase) in usec; + * defaults to interval_len + * @device_count - Counter of devices connected to the same Wiegand bus(controller). + * @devm_allocated - Whether the allocation of this struct is devres-managed + * @secondary - Whether the controller is a secondary(receives data). + * @transfer_message - Send a message on the bus. + * @setup - Setup a device. + * @cleanup - Cleanup after a device. + */ +struct wiegand_controller { + struct device dev; + struct miscdevice miscdev; + + struct file_operations fops; + struct mutex file_lock; + + unsigned int bus_num; + + bool secondary; + bool devm_allocated; + + u32 pulse_len; + u32 interval_len; + u32 frame_gap; + u32 payload_len; + + u8 device_count; + + DECLARE_BITMAP(data_bitmap, WIEGAND_MAX_PAYLEN_BYTES * 8); + + int (*transfer_message)(struct wiegand_controller *ctlr); + int (*setup)(struct wiegand_device *wiegand); + void (*cleanup)(struct wiegand_device *wiegand); +}; + +struct wiegand_driver { + struct device_driver driver; + const struct wiegand_device_id *id_table; + int (*probe)(struct wiegand_device *wiegand); + void (*remove)(struct wiegand_device *wiegand); +}; + +/* Wiegand controller section */ + +#define wiegand_primary wiegand_controller +extern struct wiegand_controller *wiegand_alloc_controller(struct device *host, unsigned int size, + bool secondary); + +extern struct wiegand_controller *devm_wiegand_alloc_controller(struct device *dev, + unsigned int size, bool secondary); +static inline struct wiegand_controller *devm_wiegand_alloc_primary(struct device *dev, + unsigned int size) +{ + return devm_wiegand_alloc_controller(dev, size, false); +} + +extern int wiegand_register_controller(struct wiegand_controller *ctlr); +extern int devm_wiegand_register_controller(struct device *dev, struct wiegand_controller *ctlr); +#define wiegand_register_primary(_ctlr) wiegand_register_controller(_ctlr) +#define devm_wiegand_register_primary(_dev, _ctlr)devm_wiegand_register_controller(_dev, _ctlr) +extern void wiegand_unregister_controller(void *ctlr); +#define wiegand_unregister_primary(_ctlr) wiegand_unregister_controller(_ctlr) +extern struct wiegand_primary *wiegand_busnum_to_primary(u16 bus_num); + +static inline void *wiegand_controller_get_devdata(struct wiegand_controller *ctlr) +{ + return dev_get_drvdata(&ctlr->dev); +} + +static inline void wiegand_controller_set_devdata(struct wiegand_controller *ctlr, void *data) +{ + dev_set_drvdata(&ctlr->dev, data); +} + +#define wiegand_primary_get_devdata(_ctlr) wiegand_controller_get_devdata(_ctlr) +#define wiegand_primary_set_devdata(_ctlr, _data) wiegand_controller_set_devdata(_ctlr, _data) + +static inline struct wiegand_controller *wiegand_controller_get(struct wiegand_controller *ctlr) +{ + if (!ctlr || !get_device(&ctlr->dev)) + return NULL; + return ctlr; +} + +static inline void wiegand_controller_put(void *ptr) +{ + struct wiegand_controller *ctlr = ptr; + + if (ctlr) + put_device(&ctlr->dev); +} + +/* Wiegand device section */ + +extern struct wiegand_device *wiegand_alloc_device(struct wiegand_controller *ctlr); +extern int wiegand_add_device(struct wiegand_device *wiegand); +extern int wiegand_setup(struct wiegand_device *wiegand); +extern void wiegand_unregister_device(struct wiegand_device *wiegand); +extern struct wiegand_controller *wiegand_device_get_controller(struct wiegand_device *dev); + +extern int wiegand_send_message(struct wiegand_device *wiegand, unsigned long *msg_bmp, u8 bitlen); + +/* Wiegand driver section */ + +extern int __wiegand_register_driver(struct module *owner, struct wiegand_driver *wdrv); +#define wiegand_register_driver(driver) __wiegand_register_driver(THIS_MODULE, driver) + +static inline void wiegand_unregister_driver(struct wiegand_driver *wdrv) +{ + if (wdrv) + driver_unregister(&wdrv->driver); +} + +static inline struct wiegand_driver *to_wiegand_driver(struct device_driver *drv) +{ + return drv ? container_of(drv, struct wiegand_driver, driver) : NULL; +} + +#endif /* H_LINUX_INCLUDE_LINUX_WIEGAND_H */ From patchwork Wed May 10 16:22:42 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Martin_Za=C5=A5ovi=C4=8D?= X-Patchwork-Id: 92207 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp3757888vqo; Wed, 10 May 2023 09:32:08 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ4/JIdUwH4vgROsKRZ/yrCpj6PEf3bdt1Jg6kyHBwGfeWauIvtkMe/WDhnARRAU8tWg+xwa X-Received: by 2002:a05:6a20:8e19:b0:f3:67da:9db5 with SMTP id y25-20020a056a208e1900b000f367da9db5mr20482296pzj.38.1683736327865; Wed, 10 May 2023 09:32:07 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1683736327; cv=none; d=google.com; s=arc-20160816; b=yE1KkTIepPGPXlOi32of5bvOK6KrVbn8T6J+ENUiNf2279Lfd6iEk122ooeXo3/s8o FgL71rp5pKGcGJU18y3cJ7sKHLvkKsSZbOx4bEWvGHlFbH7ToISYGB9KZtoOxZxyKORj VUB2aD3aKHHtwLQ/rqS8pspVuj0+Vyhca2NgnXlIzLHpCiH7KZyMJdFVlnP2MPTtbwIc cVBLirE/2XAgjAr15rYeDFeLTChR4TVkrnF0uNTFRU2cX3bzndiQlG2kDc/6bnVJe1e3 uf+imx8+HL8wiXb3+tAcsBkODfy32LLRDlswddU/RK90R8lEOmKPbjtwMPDY2QFfGtfQ D1rQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=WlvpAxn2oFm+TkdV9OynILOXrU1O7YisNtXsSxDupkw=; b=Ru99EUPZTAI47ZSOvAW89YUvKspq+1WmpEDDc6LdITheC2gZNaibwCPcjv9xbm4uRf GbwKM8VKgPBhIBh/CqtDizTqQG1rUAH1rAJj9UPV0mtdTsp92D/+ALxR85ozEmcDc1E/ ujDsHQwvU0dtpdiVQRe1to8pCxto9JapK8aFM6kXtO+yRyvVxs+2C+tQstdsxRFa+Uzk xz3O3xMkJkJmEbdGcIlyjMC1ZZpoC6To5HwnAxykH0JJivSZNHsGj2NTvaps0+oVALJ0 E+Z/iQkNYPlSYoqgAS0W9ScOxsl+TvfNvtj8SWtjGjkN7ZsOMNiOr6rafgY6BkY8DN9i HZqQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20221208 header.b="pZ/dvckV"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id u132-20020a63798a000000b0052c59f647c0si4213774pgc.73.2023.05.10.09.31.54; Wed, 10 May 2023 09:32:07 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20221208 header.b="pZ/dvckV"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233875AbjEJQYI (ORCPT + 99 others); Wed, 10 May 2023 12:24:08 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48362 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230331AbjEJQXc (ORCPT ); Wed, 10 May 2023 12:23:32 -0400 Received: from mail-ej1-x635.google.com (mail-ej1-x635.google.com [IPv6:2a00:1450:4864:20::635]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A397E7DB9; Wed, 10 May 2023 09:22:59 -0700 (PDT) Received: by mail-ej1-x635.google.com with SMTP id a640c23a62f3a-9660af2499dso1056079666b.0; Wed, 10 May 2023 09:22:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1683735778; x=1686327778; 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=WlvpAxn2oFm+TkdV9OynILOXrU1O7YisNtXsSxDupkw=; b=pZ/dvckVTItDtnZRaKV0wHYX2IxgHlX/5x5Pe9dWXZZjMFqOErKcK/iNDrn6IQ3GTi QfanJxzThwJwHpZwnwcOj5127PLwFWSll76jdPMeGjeYxzlzArV3G2tE6KhikepFMSLd JKmQIZ1kcXX06B+qlUxQzL8waONWy1i7EmUpgtN4hx6KLkHdhU8GD+QMWMmxeIvKa4Vr dYwz6tMgcNUiARd8FWQsLZexZ1HOmtu5gQy9vNsrRAOP3W14KRjSBQHxKypTl/9aWjnA C4SMbY7/etkDV3S8/YzFSVYoFfVF0+2NA7BlWmCcLCweZzzTdAOy6FkyqY3a42LNoz7U 0wag== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1683735778; x=1686327778; 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=WlvpAxn2oFm+TkdV9OynILOXrU1O7YisNtXsSxDupkw=; b=gr9Ct2U/k4Nar+xGyK+pxvTp0wsAQEbcFcZ6ujQOO/nIu13wMQSYn6pkfD0mseeKX6 1m8I2fQ3X0kR1nvJJrmPouLC+FeOYT2WvBZKFutDdZjMBBQivbHoAYoiM+O/6aNw0BeR WGtjabr7YBdHsvxL6J/2XyfFqreDTpfm4B8OQ2lWNKzkJAyZohOsIMabayatlFRUyPf+ NMItPCv8O0olKlCWEjPY78NIjIG5DM4aVBh2QWNW+J40d4Fs7RzJr7w+ZySYvkg8EmZe ESuipbMKqmhkrWRmnqgAdcEjRnXMRk5pp9Jr7ByjX8DNLSQkYrgzrmjk2zr4LxTPVueo Duhw== X-Gm-Message-State: AC+VfDxuctYZelJYQtrQ5OrD3yGUW4t/1CrRs0jJk4jlyftRqM5zGDce o/fRtxPltgdIS60233BupXbwJ30Roq9PDZHv X-Received: by 2002:a17:907:724e:b0:961:8fcd:53c9 with SMTP id ds14-20020a170907724e00b009618fcd53c9mr17237360ejc.39.1683735778105; Wed, 10 May 2023 09:22:58 -0700 (PDT) Received: from fedora.dev.tbscz ([85.93.123.158]) by smtp.gmail.com with ESMTPSA id m28-20020a17090677dc00b00947ed087a2csm2890149ejn.154.2023.05.10.09.22.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 10 May 2023 09:22:57 -0700 (PDT) From: =?utf-8?q?Martin_Za=C5=A5ovi=C4=8D?= To: linux-kernel@vger.kernel.org Cc: robh+dt@kernel.org, krzysztof.kozlowski+dt@linaro.org, conor+dt@kernel.org, gregkh@linuxfoundation.org, beanhuo@micron.com, nipun.gupta@amd.com, linus.walleij@linaro.org, mwen@igalia.com, bvanassche@acm.org, arnd@arndb.de, ogabbay@kernel.org, linux@zary.sk, jacek.lawrynowicz@linux.intel.com, geert+renesas@glider.be, benjamin.tissoires@redhat.com, masahiroy@kernel.org, yangyicong@hisilicon.com, devicetree@vger.kernel.org, =?utf-8?q?Martin_Za?= =?utf-8?q?=C5=A5ovi=C4=8D?= Subject: [PATCHv4 3/4] dt-bindings: wiegand: add GPIO bitbanged Wiegand controller Date: Wed, 10 May 2023 18:22:42 +0200 Message-Id: <20230510162243.95820-4-m.zatovic1@gmail.com> X-Mailer: git-send-email 2.40.0 In-Reply-To: <20230510162243.95820-1-m.zatovic1@gmail.com> References: <20230510162243.95820-1-m.zatovic1@gmail.com> MIME-Version: 1.0 X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS, T_SCC_BODY_TEXT_LINE,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1765525503799484025?= X-GMAIL-MSGID: =?utf-8?q?1765525503799484025?= GPIO bitbanged Wiegand controller requires definitions of GPIO lines to be used on top of the common Wiegand properties. Wiegand utilizes two such lines - D0(low data line) and D1(high data line). Acked-by: Linus Walleij Signed-off-by: Martin Zaťovič --- .../bindings/wiegand/wiegand-gpio.yaml | 51 +++++++++++++++++++ MAINTAINERS | 5 ++ 2 files changed, 56 insertions(+) create mode 100644 Documentation/devicetree/bindings/wiegand/wiegand-gpio.yaml diff --git a/Documentation/devicetree/bindings/wiegand/wiegand-gpio.yaml b/Documentation/devicetree/bindings/wiegand/wiegand-gpio.yaml new file mode 100644 index 000000000000..df28929f6dae --- /dev/null +++ b/Documentation/devicetree/bindings/wiegand/wiegand-gpio.yaml @@ -0,0 +1,51 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/wiegand/wiegand-gpio.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: GPIO bitbanged Wiegand interface devicetree bindings + +maintainers: + - Martin Zaťovič + +description: + This represents the GPIO lines used for bit-banged Wiegand on dedicated GPIO + lines. + +allOf: + - $ref: /schemas/wiegand/wiegand-controller.yaml# + +properties: + compatible: + const: wiegand-gpio + + data-hi-gpios: + description: GPIO used as Wiegands data-hi line. + maxItems: 1 + + data-lo-gpios: + description: GPIO used as Wiegands data-lo line. + maxItems: 1 + +required: + - compatible + - data-hi-gpios + - data-lo-gpios + +unevaluatedProperties: false + +examples: + - | + #include + + wiegand@f00 { + compatible = "wiegand-gpio"; + pulse-len-us = <50>; + interval-len-us = <2000>; + frame-gap-us = <2000>; + data-lo-gpios = <&gpio2 6 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>; + data-hi-gpios = <&gpio2 7 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>; + + /* devices */ + }; diff --git a/MAINTAINERS b/MAINTAINERS index 7b7e546572e8..915cb36e5b2f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -22704,6 +22704,11 @@ F: Documentation/devicetree/bindings/wiegand/wiegand-controller.yaml F: drivers/wiegand/wiegand.c F: include/linux/wiegand.h +WIEGAND GPIO BITBANG DRIVER +M: Martin Zaťovič +S: Maintained +F: Documentation/devicetree/bindings/wiegand/wiegand-gpio.yaml + WILOCITY WIL6210 WIRELESS DRIVER L: linux-wireless@vger.kernel.org S: Orphan From patchwork Wed May 10 16:22:43 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Martin_Za=C5=A5ovi=C4=8D?= X-Patchwork-Id: 92205 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp3754055vqo; Wed, 10 May 2023 09:26:48 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ5UvKNBqqnNONNnw+H/ukz6XUbZqZJQ1C6uD0C0+GXif5x9M1QpHAdsoDpI/0JUAVwBefF+ X-Received: by 2002:a17:90b:4b90:b0:24e:1e2e:20ea with SMTP id lr16-20020a17090b4b9000b0024e1e2e20eamr19022482pjb.42.1683736008415; Wed, 10 May 2023 09:26:48 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1683736008; cv=none; d=google.com; s=arc-20160816; b=l7T50zuhMC4oYx/wx5UAsyrzHDYisO9BH3FVCDBwfUHAtbpJCDWJ+Epw5/QP8BLSCx 86naKjsiT/IK9GNLb91CSxDdP+8RExXX3tncYiCg1So1OrrX474rhz3g+LSAH5uAgy6R G4rE6gmrkLiJb08i8hFyO97lS5/ZQ8Lctg/9+uxpckQSgL7rUiLhGycmf4eGRLtlJU/k yAMuMKYycNB1kE4hR2JKSCJMkMuq5QFZ0PBl17VjSQAoIIRgdl43kNfECIaVBhBQlHQK WD6KR+gdLAzIlTVN7jHtth+4tjfCRm8xt0XIPN2dCfmpLRgRiggWsgLQyemPdwkSPD/h Dfaw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=goWA+TvguPVA5aRLdsk/rQMhtaF/EgTAUtAle5S7NKw=; b=xAw10xo/PJABSfDurOr7ygbdNbs3As5bnkxt3nEycZdkFUp5e+zlBMMcpnuigojDeY /zu4c/YKZRPuUAfCxSzPfNStaRxVUQ0Vs4/p3lbbIf0rGFvsFbcsVj1gN1NzETLbnZBQ U914EVxCSo/dJFysBq+yPn75/SrtQm+mFtu3gT8kFDFONGZ/chqNJor/8IkSMd5BYrsV d8yTYbMgvLxM+XEHGufFYdTTw01XIFf0GNP95mfaxG9YDoC5QO5M0qZeQscuXKBXajKe FS0Eivnv9wLdX55XfVUe+sVxG2v/acGSaRHbD011fPE0wyf5tbNEpZAXNrzsTsL8QDMu fGrA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20221208 header.b=eVaMQSVm; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id i70-20020a638749000000b0051fadd81852si4534795pge.540.2023.05.10.09.26.35; Wed, 10 May 2023 09:26:48 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20221208 header.b=eVaMQSVm; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235455AbjEJQYO (ORCPT + 99 others); Wed, 10 May 2023 12:24:14 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48362 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232394AbjEJQXc (ORCPT ); Wed, 10 May 2023 12:23:32 -0400 Received: from mail-ej1-x62a.google.com (mail-ej1-x62a.google.com [IPv6:2a00:1450:4864:20::62a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C15147EE7; Wed, 10 May 2023 09:23:01 -0700 (PDT) Received: by mail-ej1-x62a.google.com with SMTP id a640c23a62f3a-9661a1ff1e9so778280266b.1; Wed, 10 May 2023 09:23:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1683735780; x=1686327780; 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=goWA+TvguPVA5aRLdsk/rQMhtaF/EgTAUtAle5S7NKw=; b=eVaMQSVmkIUrY2yNsMPrbDZIY4fgZZa3Ny5pDZWFrxRfaY0RgaY0BAbFfpZ926zz62 RVJ4l9l1cE60eODgGOdqsp8VvYfr0sDegKJewvk1CaLMaMMDg8o7zbkcUQDY4iRaWMNi sCZIO75+qKuAIZuc+QvsAo/SEy41vzQfFts+5Kw7YXwVDCqYr1Q5TfElX6x49GGpf0OY fC4/1OhleBIGrUdIhcfIe65qjHtI6krXrREtSVFn1iM4G8fHFd+stKpSKU8yXWQ+FzmG sc7p5I5s+FlfOSkQ5ciSeutVei9zcmoJZg6qw5P4y3SxoCal/GmsnflJlG3i2GwGft6l +Wlg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1683735780; x=1686327780; 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=goWA+TvguPVA5aRLdsk/rQMhtaF/EgTAUtAle5S7NKw=; b=PYEsJmqEF0BJwcFMdClCW9E4n2kJ4lrsYiwgU2Y8dptrlGvWqaweUZfsogvmjJ+3oU RG6RzU2WeOMF5CEmeJhPf+W0dVS4JV3OcisietnTk/hacG7wU6lpA2VSa/uSpXTqJ0Wm opqRkwJvCSskWJP3kiiPn4y+z/jUONbiQa0yPKBsRjK9n8m0gg35I+1fhHunMqDfmT8f yFRg0OechLxK4ox/4iF/5Bl/ZqjOU+VbEtq3FkH/IVaw0fm2oGXKjF8SWBzBdUPs14cP zFlL5PoZq21RAkmLOZ5qNrvXHMunZGag6iaB7SZQkvNIIaHaWoUxKZVMrwhEMwCMrw8Y F+jw== X-Gm-Message-State: AC+VfDyY6xPVyAAbkYS2Uuc4vE+jL4a378uIeLzsrqxUccpWIGMLdqs1 ouY9MUPOtcm9WxhMCvxVRE4HyBNaI8Pxvaq9 X-Received: by 2002:a17:907:1c26:b0:96a:440b:d5db with SMTP id nc38-20020a1709071c2600b0096a440bd5dbmr1175560ejc.47.1683735780059; Wed, 10 May 2023 09:23:00 -0700 (PDT) Received: from fedora.dev.tbscz ([85.93.123.158]) by smtp.gmail.com with ESMTPSA id m28-20020a17090677dc00b00947ed087a2csm2890149ejn.154.2023.05.10.09.22.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 10 May 2023 09:22:59 -0700 (PDT) From: =?utf-8?q?Martin_Za=C5=A5ovi=C4=8D?= To: linux-kernel@vger.kernel.org Cc: robh+dt@kernel.org, krzysztof.kozlowski+dt@linaro.org, conor+dt@kernel.org, gregkh@linuxfoundation.org, beanhuo@micron.com, nipun.gupta@amd.com, linus.walleij@linaro.org, mwen@igalia.com, bvanassche@acm.org, arnd@arndb.de, ogabbay@kernel.org, linux@zary.sk, jacek.lawrynowicz@linux.intel.com, geert+renesas@glider.be, benjamin.tissoires@redhat.com, masahiroy@kernel.org, yangyicong@hisilicon.com, devicetree@vger.kernel.org, =?utf-8?q?Martin_Za?= =?utf-8?q?=C5=A5ovi=C4=8D?= Subject: [PATCHv4 4/4] wiegand: add Wiegand GPIO bitbanged controller driver Date: Wed, 10 May 2023 18:22:43 +0200 Message-Id: <20230510162243.95820-5-m.zatovic1@gmail.com> X-Mailer: git-send-email 2.40.0 In-Reply-To: <20230510162243.95820-1-m.zatovic1@gmail.com> References: <20230510162243.95820-1-m.zatovic1@gmail.com> MIME-Version: 1.0 X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1765525168878635623?= X-GMAIL-MSGID: =?utf-8?q?1765525168878635623?= This controller formats the data to a Wiegand format and bit-bangs the message on devicetree defined GPIO lines. Several attributes need to be defined in the devicetree in order for this driver to work, namely the data-hi-gpios, data-lo-gpios, pulse-len, frame-gap and interval-len. These attributes are documented in the devicetree bindings documentation files. The driver creates a dev file for writing messages on the bus. It also creates a sysfs file to control the payload length of messages(in bits). If a message is shorter than the set payload length, it will be discarded. On the other hand, if a message is longer, the additional bits will be stripped off. Acked-by: Linus Walleij Signed-off-by: Martin Zaťovič --- .../ABI/testing/sysfs-driver-wiegand-gpio | 9 + MAINTAINERS | 2 + drivers/wiegand/Kconfig | 8 + drivers/wiegand/Makefile | 1 + drivers/wiegand/wiegand-gpio.c | 189 ++++++++++++++++++ 5 files changed, 209 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-driver-wiegand-gpio create mode 100644 drivers/wiegand/wiegand-gpio.c diff --git a/Documentation/ABI/testing/sysfs-driver-wiegand-gpio b/Documentation/ABI/testing/sysfs-driver-wiegand-gpio new file mode 100644 index 000000000000..c3981972dbc8 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-driver-wiegand-gpio @@ -0,0 +1,9 @@ +What: /sys/devices/platform/.../wiegand-gpio-attributes/payload_len +Date: May 2023 +Contact: Martin Zaťovič +Description: + Read/set the payload length of messages sent by Wiegand GPIO + bit-banging controller in bits. The default value is 26, as + that is the most widely-used message length of Wiegand messages. + Controller will only send messages of at least the set length + and it will strip off bits of longer messages. diff --git a/MAINTAINERS b/MAINTAINERS index 915cb36e5b2f..e828a5ec8162 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -22707,7 +22707,9 @@ F: include/linux/wiegand.h WIEGAND GPIO BITBANG DRIVER M: Martin Zaťovič S: Maintained +F: Documentation/ABI/testing/sysfs-driver-wiegand-gpio F: Documentation/devicetree/bindings/wiegand/wiegand-gpio.yaml +F: drivers/wiegand/wiegand-gpio.c WILOCITY WIL6210 WIRELESS DRIVER L: linux-wireless@vger.kernel.org diff --git a/drivers/wiegand/Kconfig b/drivers/wiegand/Kconfig index fc99575bc3cc..9a8f705d4646 100644 --- a/drivers/wiegand/Kconfig +++ b/drivers/wiegand/Kconfig @@ -18,3 +18,11 @@ config WIEGAND are initially pulled up. When a bit of value 0 is being transmitted, the D0 line is pulled down. Similarly, when a bit of value 1 is being transmitted, the D1 line is pulled down. + +config WIEGAND_GPIO + tristate "GPIO-based wiegand master (write only)" + depends on WIEGAND + help + This GPIO bitbanging Wiegand controller uses the libgpiod library to + utilize GPIO lines for sending Wiegand data. Userspace may access + the Wiegand GPIO interface via a dev entry. diff --git a/drivers/wiegand/Makefile b/drivers/wiegand/Makefile index d17ecb722c6e..ddf697e21088 100644 --- a/drivers/wiegand/Makefile +++ b/drivers/wiegand/Makefile @@ -1 +1,2 @@ obj-$(CONFIG_WIEGAND) += wiegand.o +obj-$(CONFIG_WIEGAND_GPIO) += wiegand-gpio.o diff --git a/drivers/wiegand/wiegand-gpio.c b/drivers/wiegand/wiegand-gpio.c new file mode 100644 index 000000000000..a46421f515b1 --- /dev/null +++ b/drivers/wiegand/wiegand-gpio.c @@ -0,0 +1,189 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include +#include +#include +#include +#include +#include +#include + +#define UP_TO_100_USEC_DEVIATION 1 +#define MORE_THAN_100_USEC_DEVIATION 3 + +struct wiegand_gpio { + struct device *dev; + struct wiegand_controller *ctlr; + struct gpio_desc *data1_gpio; + struct gpio_desc *data0_gpio; +}; + +static ssize_t store_ulong(u32 *val, const char *buf, size_t size, unsigned long max) +{ + int rc; + u32 new; + + rc = kstrtou32(buf, 0, &new); + if (rc) + return rc; + + if (new > max) + return -EINVAL; + + *val = new; + return size; +} + +/* + * Attribute file for setting payload length of Wiegand messages. + */ +static ssize_t payload_len_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct wiegand_gpio *wiegand_gpio = dev_get_drvdata(dev); + struct wiegand_controller *ctlr = wiegand_gpio->ctlr; + + return sysfs_emit(buf, "%u\n", ctlr->payload_len); +} + +static ssize_t payload_len_store(struct device *dev, struct device_attribute *attr, const char *buf, + size_t count) +{ + struct wiegand_gpio *wiegand_gpio = dev_get_drvdata(dev); + struct wiegand_controller *ctlr = wiegand_gpio->ctlr; + + return store_ulong(&(ctlr->payload_len), buf, count, WIEGAND_MAX_PAYLEN_BYTES * 8); +} +static DEVICE_ATTR_RW(payload_len); + +static struct attribute *wiegand_gpio_attrs[] = { + &dev_attr_payload_len.attr, + NULL +}; +ATTRIBUTE_GROUPS(wiegand_gpio); + +/* + * To send a bit of value 1 following the wiegand protocol, one must set + * the wiegand_data_hi to low for the duration of pulse. Similarly to send + * a bit of value 0, the wiegand_data_lo is set to low for pulse duration. + * This way the two lines are never low at the same time. + */ +void wiegand_gpio_send_bit(struct wiegand_gpio *wiegand_gpio, bool value, bool last) +{ + u32 sleep_len; + u32 pulse_len = wiegand_gpio->ctlr->pulse_len; + u32 interval_len = wiegand_gpio->ctlr->interval_len; + u32 frame_gap = wiegand_gpio->ctlr->frame_gap; + struct gpio_desc *gpio = value ? wiegand_gpio->data1_gpio : wiegand_gpio->data0_gpio; + + gpiod_set_value_cansleep(gpio, 0); + udelay(pulse_len); + gpiod_set_value_cansleep(gpio, 1); + + if (last) + sleep_len = frame_gap - pulse_len; + else + sleep_len = interval_len - pulse_len; + + if (sleep_len < 10) + udelay(sleep_len); + else if (sleep_len < 100) + usleep_range(sleep_len - UP_TO_100_USEC_DEVIATION, + sleep_len + UP_TO_100_USEC_DEVIATION); + else + usleep_range(sleep_len - MORE_THAN_100_USEC_DEVIATION, + sleep_len + MORE_THAN_100_USEC_DEVIATION); +} + +static int wiegand_gpio_write_by_bits(struct wiegand_gpio *wiegand_gpio, u16 bitlen) +{ + size_t i; + bool bit_value, is_last_bit; + + for (i = 0; i < bitlen; i++) { + bit_value = test_bit(i, wiegand_gpio->ctlr->data_bitmap); + is_last_bit = (i + 1) == bitlen; + wiegand_gpio_send_bit(wiegand_gpio, bit_value, is_last_bit); + } + + return 0; +} + +int wiegand_gpio_transfer_message(struct wiegand_controller *ctlr) +{ + struct wiegand_gpio *wiegand_gpio = wiegand_primary_get_devdata(ctlr); + u8 msg_bitlen = ctlr->payload_len; + + wiegand_gpio_write_by_bits(wiegand_gpio, msg_bitlen); + + return 0; +} + +static int wiegand_gpio_request(struct device *dev, struct wiegand_gpio *wiegand_gpio) +{ + wiegand_gpio->data0_gpio = devm_gpiod_get(dev, "data-lo", GPIOD_OUT_HIGH); + if (IS_ERR(wiegand_gpio->data0_gpio)) + return PTR_ERR(wiegand_gpio->data0_gpio); + + wiegand_gpio->data1_gpio = devm_gpiod_get(dev, "data-hi", GPIOD_OUT_HIGH); + return PTR_ERR_OR_ZERO(wiegand_gpio->data1_gpio); +} + +static int wiegand_gpio_probe(struct platform_device *device) +{ + int status = 0; + struct wiegand_controller *primary; + struct wiegand_gpio *wiegand_gpio; + struct device *dev = &device->dev; + + primary = wiegand_alloc_controller(dev, sizeof(*wiegand_gpio), false); + if (!primary) + return -ENOMEM; + + primary->transfer_message = &wiegand_gpio_transfer_message; + primary->payload_len = 26; // set standard 26-bit format + + wiegand_gpio = wiegand_primary_get_devdata(primary); + wiegand_gpio->ctlr = primary; + + platform_set_drvdata(device, wiegand_gpio); + + primary->bus_num = device->id; + wiegand_gpio->dev = dev; + + status = wiegand_gpio_request(dev, wiegand_gpio); + if (status) + return dev_err_probe(wiegand_gpio->dev, status, "failed at requesting GPIOs\n"); + + status = gpiod_direction_output(wiegand_gpio->data1_gpio, 1); + if (status) + return dev_err_probe(wiegand_gpio->dev, status, "failed to set GPIOs direction\n"); + + status = gpiod_direction_output(wiegand_gpio->data0_gpio, 1); + if (status) + return dev_err_probe(wiegand_gpio->dev, status, "failed to set GPIOs direction\n"); + + status = wiegand_register_controller(primary); + if (status) + dev_err_probe(wiegand_gpio->dev, status, "failed to register primary\n"); + return status; +} + +static const struct of_device_id wiegand_gpio_dt_idtable[] = { + { .compatible = "wiegand-gpio", }, + {} +}; +MODULE_DEVICE_TABLE(of, wiegand_gpio_dt_idtable); + +static struct platform_driver wiegand_gpio_driver = { + .driver = { + .name = "wiegand-gpio", + .of_match_table = wiegand_gpio_dt_idtable, + .dev_groups = wiegand_gpio_groups + }, + .probe = wiegand_gpio_probe +}; +module_platform_driver(wiegand_gpio_driver); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Wiegand write-only driver realized by GPIOs"); +MODULE_AUTHOR("Martin Zaťovič ");