From patchwork Sun Feb 16 23:32:05 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff LaBundy X-Patchwork-Id: 204739 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.8 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI, MSGID_FROM_MTA_HEADER, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 55A94C3B1BF for ; Sun, 16 Feb 2020 23:32:44 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 191D5208C3 for ; Sun, 16 Feb 2020 23:32:44 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=NETORG5796793.onmicrosoft.com header.i=@NETORG5796793.onmicrosoft.com header.b="qjq4butP" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728108AbgBPXcn (ORCPT ); Sun, 16 Feb 2020 18:32:43 -0500 Received: from mail-dm6nam12on2059.outbound.protection.outlook.com ([40.107.243.59]:23617 "EHLO NAM12-DM6-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1727772AbgBPXcl (ORCPT ); Sun, 16 Feb 2020 18:32:41 -0500 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=oZLa+bLg2ZMBgtgHpQCFQmlMiMNgt+Ex0+ZMN7bB2ly1C3f3rs6zYBPec4VGhceOGf2KUxYRz2c4SQ7+54pDzj11jzeWaiIhtYKF0utL/cKabUe0Ixu365rj7e9WEsfpDhOFI2Sj5/3Cu6Li/nZq4k2rcGxSHBWckU0KfBMaER13T9R0tHGGq3hUe5DVsXGlOD7fGsA1GM/+M6wS4LOeIt/ITLBEFD2I6jhEJxwbzKpd5XhR+jSIpg0IPJ2EOacP2xlNbmHbtRd5hTzGuPV+QLVLtSxEAhNb10MffhfN8+8DBlAGcureiG1Ro3lw6MoOIZZ0MVPC/QcE13ak4wi7Bw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=7mSzQIvlOX0HEucYtfZCom9OhFCJPDdav7rj7VFWXqE=; b=BEOzX+D7E+3eoblVtpA99rRCsE5BbhMQoSYFQ+ohhMbRnLGw+X2CjmMhWdFsbJr9vzAbjLMjII2+xe+WMvFIWt7w4Qmi+58N6b2bHTMW8T8TL9QqAaxzJVUZqYESVX79cRyT2RhaCLcA7EDN2/wv1BdzGk5peimNQiZwSqcZMOxKBZ0HGovOLo/wsxWnq+0ENHfF5qKKuw5ZxFDWiV20VZuqIHTf+g1EVTEZfj4VWLwLNxCm8f8d1NvrbTJOErUqCTwTShGapHLI/cSO1nUAl/W2wyUJJ7TVg23zioLJ7yWm9eOda58Geg0KbOPsiqxvjpKax9cFwaZaJXicxyF/Cg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=labundy.com; dmarc=pass action=none header.from=labundy.com; dkim=pass header.d=labundy.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=NETORG5796793.onmicrosoft.com; s=selector1-NETORG5796793-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=7mSzQIvlOX0HEucYtfZCom9OhFCJPDdav7rj7VFWXqE=; b=qjq4butPx0stmheG0Tdjfi+DQvEJ8MwpsH9Nnlw42DSf2/RSGzPfovQPGQiB+fgwFUaHAkydnizP3Socod8BIiNMJIdMAUP8hBajcnyYn7s/KE2jsl6qoePVxScnuKozFbeN/kYRuc3myYMfkqkkGUeSYdBbAMRRIerFB9/8iOY= Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=jeff@labundy.com; Received: from SN6PR08MB5053.namprd08.prod.outlook.com (52.135.107.153) by SN6PR08MB5406.namprd08.prod.outlook.com (52.135.117.208) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.2729.22; Sun, 16 Feb 2020 23:32:38 +0000 Received: from SN6PR08MB5053.namprd08.prod.outlook.com ([fe80::2cd0:e164:fe88:3945]) by SN6PR08MB5053.namprd08.prod.outlook.com ([fe80::2cd0:e164:fe88:3945%4]) with mapi id 15.20.2729.025; Sun, 16 Feb 2020 23:32:38 +0000 From: Jeff LaBundy To: lee.jones@linaro.org, dmitry.torokhov@gmail.com, thierry.reding@gmail.com, jic23@kernel.org, devicetree@vger.kernel.org Cc: linux-input@vger.kernel.org, u.kleine-koenig@pengutronix.de, linux-pwm@vger.kernel.org, knaack.h@gmx.de, lars@metafoo.de, pmeerw@pmeerw.net, linux-iio@vger.kernel.org, robh+dt@kernel.org, mark.rutland@arm.com, Jeff LaBundy Subject: [PATCH v5 1/7] dt-bindings: Add bindings for Azoteq IQS620A/621/622/624/625 Date: Sun, 16 Feb 2020 17:32:05 -0600 Message-Id: <1581895931-6056-2-git-send-email-jeff@labundy.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1581895931-6056-1-git-send-email-jeff@labundy.com> References: <1581895931-6056-1-git-send-email-jeff@labundy.com> X-ClientProxiedBy: SN4PR0501CA0142.namprd05.prod.outlook.com (2603:10b6:803:2c::20) To SN6PR08MB5053.namprd08.prod.outlook.com (2603:10b6:805:78::25) MIME-Version: 1.0 Received: from localhost.localdomain (136.49.227.119) by SN4PR0501CA0142.namprd05.prod.outlook.com (2603:10b6:803:2c::20) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) id 15.20.2750.9 via Frontend Transport; Sun, 16 Feb 2020 23:32:38 +0000 X-Mailer: git-send-email 2.7.4 X-Originating-IP: [136.49.227.119] X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 8bdfcfdd-4966-4fad-9ec9-08d7b3388293 X-MS-TrafficTypeDiagnostic: SN6PR08MB5406: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:8273; X-Forefront-PRVS: 03152A99FF X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10009020)(346002)(136003)(366004)(39830400003)(396003)(376002)(199004)(189003)(8676002)(107886003)(8936002)(4326008)(7416002)(69590400006)(956004)(66556008)(2616005)(81156014)(81166006)(16526019)(26005)(5660300002)(6506007)(186003)(66946007)(6666004)(66476007)(316002)(6486002)(36756003)(52116002)(508600001)(966005)(6512007)(2906002)(86362001)(30864003); DIR:OUT; SFP:1101; SCL:1; SRVR:SN6PR08MB5406; H:SN6PR08MB5053.namprd08.prod.outlook.com; FPR:; SPF:None; LANG:en; PTR:InfoNoRecords; A:1; MX:1; Received-SPF: None (protection.outlook.com: labundy.com does not designate permitted sender hosts) X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: E9zh8SIIRwNEO6J8nCQL9CZ0eDZIS6FTXGf9OipE0Pwai0greq2hy2TLYHwvsvvr0o8DxBR2c7c80G3J7NUjKqQi9wDpCauTktbcuxfCrWrYAAzkQzlSpQ1S9GIRsfexZq+JlRD0b1Jw2Xl1oJdTiwADgXwqRh/YUCpSux6sldKW+B3+wNxkSQKYEr64RLF6b3/cknEv9liAX0AmH+RJU7lL9tmaOXAbLUsNCHTUuLpMpDV+dPQWnBs2DKlr/P5EweD2zdk+3lkJCEcV6p4+3CQgr1Z+hnCUYlAst85q5jVLJOHQDEtQuzC8dnYdTadxFCqjK/suoCXLtkPdJnJgNcmv7jAkGjuN7Zs++bIWXnsZecW8fi9CQWORyraRJib1Xto+zO0viv4diVg+OzC9FFqGLApFe/WpIfKla+DUpmxIIWp1e3P56C5JL1a4DjP6JXA0p0s6Z1YqicU0gX6acYeVt5l+Ka84yGLl4mTVvuGCa+cUxGv7s7soawT0NNMsCTMopTk3dhJwpvIoib7xvpRGHgI39PxpDLpx3UXjnodm2oDdDLIz19KPqwyrmY10mM71w/ffPsH5kLaCBVbWWauj4UXHgFpR9f5FF7gRNA4= X-MS-Exchange-AntiSpam-MessageData: pJst6+hTKvyYy+DD1d67gd4pZspMlj0866zfNcbAfGrFf6G0MBgqiWsgkKDqo158bZE2XQqfT+iq0UugX9uB5N6KWuxVaRy0KNs5Tu2qtvw9ZXdHWNntDnaJGLHbz+qqjQImI9+Ym9Gw7usfQ0Js2A== X-OriginatorOrg: labundy.com X-MS-Exchange-CrossTenant-Network-Message-Id: 8bdfcfdd-4966-4fad-9ec9-08d7b3388293 X-MS-Exchange-CrossTenant-OriginalArrivalTime: 16 Feb 2020 23:32:38.9286 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 00b69d09-acab-4585-aca7-8fb7c6323e6f X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: ij97Psw/SYMqHtqJVMngdXSOa4zwE6DWLBGsJFEs6fzndXCFv3fYPxB51fA/otRSaBARxT/xpDGPAiatF2E+uQ== X-MS-Exchange-Transport-CrossTenantHeadersStamped: SN6PR08MB5406 Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org This patch adds device tree bindings for the Azoteq IQS620A, IQS621, IQS622, IQS624 and IQS625 multi-function sensors. A total of three bindings are presented (one MFD and two child nodes); they are submitted as a single patch because the child node bindings have no meaning in the absence of the MFD binding. Signed-off-by: Jeff LaBundy Reviewed-by: Rob Herring --- Changes in v5: - Corrected spelling of "data sheets" to "datasheets" - Replaced words "additional air button" with "proximity-activated function" in comment above first example Changes in v4: - None Changes in v3: - Specified 'additionalProperties: false' within the parent MFD node and all child nodes ("keys", "hall-switch-north/south" and "pwm") - Defined the "hall-switch-north/south" child nodes unconditionally and then inverted the subsequent if/then to filter them from devices for which that functionality is unavailable - Added Reviewed-by trailer Changes in v2: - Removed "prox" child node and moved "keys" and "pwm" child nodes to their own bindings - Replaced linux,fw-file property with more common firmware-name property - Converted all bindings to YAML .../devicetree/bindings/input/iqs62x-keys.yaml | 132 +++++++++++++++ Documentation/devicetree/bindings/mfd/iqs62x.yaml | 179 +++++++++++++++++++++ .../devicetree/bindings/pwm/iqs620a-pwm.yaml | 32 ++++ 3 files changed, 343 insertions(+) create mode 100644 Documentation/devicetree/bindings/input/iqs62x-keys.yaml create mode 100644 Documentation/devicetree/bindings/mfd/iqs62x.yaml create mode 100644 Documentation/devicetree/bindings/pwm/iqs620a-pwm.yaml -- 2.7.4 diff --git a/Documentation/devicetree/bindings/input/iqs62x-keys.yaml b/Documentation/devicetree/bindings/input/iqs62x-keys.yaml new file mode 100644 index 0000000..5625c22 --- /dev/null +++ b/Documentation/devicetree/bindings/input/iqs62x-keys.yaml @@ -0,0 +1,132 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/input/iqs62x-keys.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Azoteq IQS620A/621/622/624/625 Keys and Switches + +maintainers: + - Jeff LaBundy + +description: | + The Azoteq IQS620A, IQS621, IQS622, IQS624 and IQS625 multi-function sensors + feature a variety of self-capacitive, mutual-inductive and Hall-effect sens- + ing capabilities that can facilitate a variety of contactless key and switch + applications. + + These functions are collectively represented by a "keys" child node from the + parent MFD driver. See Documentation/devicetree/bindings/mfd/iqs62x.yaml for + further details and examples. Sensor hardware configuration (self-capacitive + vs. mutual-inductive, etc.) is selected based on the device's firmware. + +properties: + compatible: + enum: + - azoteq,iqs620a-keys + - azoteq,iqs621-keys + - azoteq,iqs622-keys + - azoteq,iqs624-keys + - azoteq,iqs625-keys + + linux,keycodes: + allOf: + - $ref: /schemas/types.yaml#/definitions/uint32-array + - minItems: 1 + maxItems: 16 + description: | + Specifies the numeric keycodes associated with each available touch or + proximity event according to the following table. An 'x' indicates the + event is supported for a given device. Specify 0 for unused events. + + ------------------------------------------------------------------------- + | # | Event | IQS620A | IQS621 | IQS622 | IQS624 | IQS625 | + ------------------------------------------------------------------------- + | 0 | CH0 Touch | x | x | x | x | x | + | | Antenna 1 Touch* | x | | | | | + ------------------------------------------------------------------------- + | 1 | CH0 Proximity | x | x | x | x | x | + | | Antenna 1 Prox.* | x | | | | | + ------------------------------------------------------------------------- + | 2 | CH1 Touch | x | x | x | x | x | + | | Ant. 1 Deep Touch* | x | | | | | + ------------------------------------------------------------------------- + | 3 | CH1 Proximity | x | x | x | x | x | + ------------------------------------------------------------------------- + | 4 | CH2 Touch | x | | | | | + ------------------------------------------------------------------------- + | 5 | CH2 Proximity | x | | | | | + | | Antenna 2 Prox.* | x | | | | | + ------------------------------------------------------------------------- + | 6 | Metal (+) Touch** | x | x | | | | + | | Ant. 2 Deep Touch* | x | | | | | + ------------------------------------------------------------------------- + | 7 | Metal (+) Prox.** | x | x | | | | + | | Antenna 2 Touch* | x | | | | | + ------------------------------------------------------------------------- + | 8 | Metal (-) Touch** | x | x | | | | + ------------------------------------------------------------------------- + | 9 | Metal (-) Prox.** | x | x | | | | + ------------------------------------------------------------------------- + | 10 | SAR Active*** | x | | x | | | + ------------------------------------------------------------------------- + | 11 | SAR Quick Rel.*** | x | | x | | | + ------------------------------------------------------------------------- + | 12 | SAR Movement*** | x | | x | | | + ------------------------------------------------------------------------- + | 13 | SAR Filter Halt*** | x | | x | | | + ------------------------------------------------------------------------- + | 14 | Wheel Up | | | | x | | + ------------------------------------------------------------------------- + | 15 | Wheel Down | | | | x | | + ------------------------------------------------------------------------- + * Two-channel SAR. Replaces CH0-2 plus metal touch and proximity events + if enabled via firmware. + ** "+" and "-" refer to the polarity of a channel's delta (LTA - counts), + where "LTA" is defined as the channel's long-term average. + *** One-channel SAR. Replaces CH0-2 touch and proximity events if enabled + via firmware. + +patternProperties: + "^hall-switch-(north|south)$": + type: object + description: + Represents north/south-field Hall-effect sensor touch or proximity + events. Note that north/south-field orientation is reversed on the + IQS620AXzCSR device due to its flip-chip package. + + properties: + linux,code: + $ref: /schemas/types.yaml#/definitions/uint32 + description: Numeric switch code associated with the event. + + azoteq,use-prox: + $ref: /schemas/types.yaml#/definitions/flag + description: + If present, specifies that Hall-effect sensor reporting should + use the device's wide-range proximity threshold instead of its + close-range touch threshold (default). + + required: + - linux,code + + additionalProperties: false + +if: + properties: + compatible: + contains: + enum: + - azoteq,iqs624-keys + - azoteq,iqs625-keys +then: + patternProperties: + "^hall-switch-(north|south)$": false + +required: + - compatible + - linux,keycodes + +additionalProperties: false + +... diff --git a/Documentation/devicetree/bindings/mfd/iqs62x.yaml b/Documentation/devicetree/bindings/mfd/iqs62x.yaml new file mode 100644 index 0000000..541b06d --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/iqs62x.yaml @@ -0,0 +1,179 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mfd/iqs62x.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Azoteq IQS620A/621/622/624/625 Multi-Function Sensors + +maintainers: + - Jeff LaBundy + +description: | + The Azoteq IQS620A, IQS621, IQS622, IQS624 and IQS625 multi-function sensors + integrate multiple sensing technologies in a single package. + + Link to datasheets: https://www.azoteq.com/ + +properties: + compatible: + enum: + - azoteq,iqs620a + - azoteq,iqs621 + - azoteq,iqs622 + - azoteq,iqs624 + - azoteq,iqs625 + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + firmware-name: + $ref: /schemas/types.yaml#/definitions/string + description: + Specifies the name of the calibration and configuration file selected by + the driver. If this property is omitted, the name is chosen based on the + device name with ".bin" as the extension (e.g. iqs620a.bin for IQS620A). + + keys: + $ref: ../input/iqs62x-keys.yaml + + pwm: + $ref: ../pwm/iqs620a-pwm.yaml + +required: + - compatible + - reg + - interrupts + +additionalProperties: false + +examples: + - | + /* + * Dual capacitive buttons with proximity-activated function, unipolar lid + * switch and panel-mounted LED. + */ + #include + #include + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + iqs620a@44 { + compatible = "azoteq,iqs620a"; + reg = <0x44>; + interrupt-parent = <&gpio>; + interrupts = <17 IRQ_TYPE_LEVEL_LOW>; + + keys { + compatible = "azoteq,iqs620a-keys"; + + linux,keycodes = , + , + , + ; + + hall-switch-south { + linux,code = ; + azoteq,use-prox; + }; + }; + + iqs620a_pwm: pwm { + compatible = "azoteq,iqs620a-pwm"; + #pwm-cells = <2>; + }; + }; + }; + + pwmleds { + compatible = "pwm-leds"; + + panel { + pwms = <&iqs620a_pwm 0 1000000>; + max-brightness = <255>; + }; + }; + + - | + /* Single inductive button with bipolar dock/tablet-mode switch. */ + #include + #include + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + iqs620a@44 { + compatible = "azoteq,iqs620a"; + reg = <0x44>; + interrupt-parent = <&gpio>; + interrupts = <17 IRQ_TYPE_LEVEL_LOW>; + + firmware-name = "iqs620a_coil.bin"; + + keys { + compatible = "azoteq,iqs620a-keys"; + + linux,keycodes = <0>, + <0>, + <0>, + <0>, + <0>, + <0>, + ; + + hall-switch-north { + linux,code = ; + }; + + hall-switch-south { + linux,code = ; + }; + }; + }; + }; + + - | + /* Dual capacitive buttons with volume knob. */ + #include + #include + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + iqs624@44 { + compatible = "azoteq,iqs624"; + reg = <0x44>; + interrupt-parent = <&gpio>; + interrupts = <17 IRQ_TYPE_LEVEL_LOW>; + + keys { + compatible = "azoteq,iqs624-keys"; + + linux,keycodes = , + <0>, + , + <0>, + <0>, + <0>, + <0>, + <0>, + <0>, + <0>, + <0>, + <0>, + <0>, + <0>, + , + ; + }; + }; + }; + +... diff --git a/Documentation/devicetree/bindings/pwm/iqs620a-pwm.yaml b/Documentation/devicetree/bindings/pwm/iqs620a-pwm.yaml new file mode 100644 index 0000000..1d7c27b --- /dev/null +++ b/Documentation/devicetree/bindings/pwm/iqs620a-pwm.yaml @@ -0,0 +1,32 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pwm/iqs620a-pwm.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Azoteq IQS620A PWM Generator + +maintainers: + - Jeff LaBundy + +description: | + The Azoteq IQS620A multi-function sensor generates a fixed-frequency PWM + output represented by a "pwm" child node from the parent MFD driver. See + Documentation/devicetree/bindings/mfd/iqs62x.yaml for further details as + well as an example. + +properties: + compatible: + enum: + - azoteq,iqs620a-pwm + + "#pwm-cells": + const: 2 + +required: + - compatible + - "#pwm-cells" + +additionalProperties: false + +... From patchwork Sun Feb 16 23:32:07 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff LaBundy X-Patchwork-Id: 204738 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.8 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI, MSGID_FROM_MTA_HEADER, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 55BCFC7619E for ; Sun, 16 Feb 2020 23:32:55 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 11F582086A for ; Sun, 16 Feb 2020 23:32:55 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=NETORG5796793.onmicrosoft.com header.i=@NETORG5796793.onmicrosoft.com header.b="o8Ig9Fhe" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728171AbgBPXcy (ORCPT ); Sun, 16 Feb 2020 18:32:54 -0500 Received: from mail-dm6nam12on2070.outbound.protection.outlook.com ([40.107.243.70]:49361 "EHLO NAM12-DM6-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1728115AbgBPXcy (ORCPT ); Sun, 16 Feb 2020 18:32:54 -0500 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=ABCrvJmL1iLvdKvbvP7OvebcCGucTuj0l8GschMP+m9CL8jHXmZ1NsvBMlMW8lT/rmk8qC4klTkIQNAfQBiDJuG6qK46i5De7QSlSsO5pInVDTQiHnjUWHatsVXvl+KO0WJ9FApgKJYtJqRtqGQAuJ4AgUhoTp/TC2S5lSdk34KDjG7zbcG5c5LVZSpPZVH+QArVjA5mh6yDiBA0KVG0fbWsx8StyIcIJVBg3FaCZYfcG/QWyDCUuqZNfMXx1gj5IykSEvCUtglY2CULDQpUz3xy8tQzJdpVMFrcxRlXe5GkEOIHb3fXxBhKjxIQpOB8E/taV5+zocgilEHTh+StFA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=v6ZyZllvlwKGYN0NcRahORFD9ZL53jdVvLOrWIJIKo8=; b=D3r9hS7QCsm5KxMW0TZ3W9nknUymIncGJNAU1FDECfMrKY9qUNwpUBf1fIoVfKDk1acRvI0WG4Gi34prGDF+ZmMGCjaynRIFDqXSG7LhncpCivo7GUTar2DG/qyrfpLJilL5YI7gs+TNP5D3go57o/utL8Sz3v+J4v6u8Z14DFS1DsmqxEIrEnuzgIuc7IZAiWsN1QWroofVHIMOyLqxNy44wryLdz1Z+pgqMLMVmkq/VYfdnZRMBdKicjmR9gqfuY7rz/ZkpBbqrVNEwtNmFfDDdp7wUFKHqK06z+GxLoCdYwEHhfMu9X0waiuhJ70yYMD8MvKP9mQVUVXJ2qONoQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=labundy.com; dmarc=pass action=none header.from=labundy.com; dkim=pass header.d=labundy.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=NETORG5796793.onmicrosoft.com; s=selector1-NETORG5796793-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=v6ZyZllvlwKGYN0NcRahORFD9ZL53jdVvLOrWIJIKo8=; b=o8Ig9FhexVeNb8ofyHtH54ibzKTYSaFSObQodEkS1EWwrOHlW5Njgj0vSr7i0xc7yCzhGADDmZxWc1vF3z0jxFn9+SQ/UFNz9L0kDxrzyJSQOgumPMHJXDOZkoxYrMeUmrcPNzNkB0avrqCFKQM9uhTMPQvLgWhC+eczLJz4Hos= Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=jeff@labundy.com; Received: from SN6PR08MB5053.namprd08.prod.outlook.com (52.135.107.153) by SN6PR08MB5406.namprd08.prod.outlook.com (52.135.117.208) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.2729.22; Sun, 16 Feb 2020 23:32:45 +0000 Received: from SN6PR08MB5053.namprd08.prod.outlook.com ([fe80::2cd0:e164:fe88:3945]) by SN6PR08MB5053.namprd08.prod.outlook.com ([fe80::2cd0:e164:fe88:3945%4]) with mapi id 15.20.2729.025; Sun, 16 Feb 2020 23:32:45 +0000 From: Jeff LaBundy To: lee.jones@linaro.org, dmitry.torokhov@gmail.com, thierry.reding@gmail.com, jic23@kernel.org, devicetree@vger.kernel.org Cc: linux-input@vger.kernel.org, u.kleine-koenig@pengutronix.de, linux-pwm@vger.kernel.org, knaack.h@gmx.de, lars@metafoo.de, pmeerw@pmeerw.net, linux-iio@vger.kernel.org, robh+dt@kernel.org, mark.rutland@arm.com, Jeff LaBundy Subject: [PATCH v5 3/7] input: keyboard: Add support for Azoteq IQS620A/621/622/624/625 Date: Sun, 16 Feb 2020 17:32:07 -0600 Message-Id: <1581895931-6056-4-git-send-email-jeff@labundy.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1581895931-6056-1-git-send-email-jeff@labundy.com> References: <1581895931-6056-1-git-send-email-jeff@labundy.com> X-ClientProxiedBy: SN4PR0501CA0142.namprd05.prod.outlook.com (2603:10b6:803:2c::20) To SN6PR08MB5053.namprd08.prod.outlook.com (2603:10b6:805:78::25) MIME-Version: 1.0 Received: from localhost.localdomain (136.49.227.119) by SN4PR0501CA0142.namprd05.prod.outlook.com (2603:10b6:803:2c::20) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) id 15.20.2750.9 via Frontend Transport; Sun, 16 Feb 2020 23:32:44 +0000 X-Mailer: git-send-email 2.7.4 X-Originating-IP: [136.49.227.119] X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 733c0ff4-5b0c-4548-fbe6-08d7b3388673 X-MS-TrafficTypeDiagnostic: SN6PR08MB5406: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:3826; X-Forefront-PRVS: 03152A99FF X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10009020)(346002)(136003)(366004)(39830400003)(396003)(376002)(199004)(189003)(8676002)(107886003)(8936002)(4326008)(7416002)(69590400006)(956004)(66556008)(2616005)(81156014)(81166006)(16526019)(26005)(5660300002)(6506007)(186003)(66946007)(6666004)(66476007)(316002)(6486002)(36756003)(52116002)(508600001)(6512007)(2906002)(86362001)(30864003); DIR:OUT; SFP:1101; SCL:1; SRVR:SN6PR08MB5406; H:SN6PR08MB5053.namprd08.prod.outlook.com; FPR:; SPF:None; LANG:en; PTR:InfoNoRecords; A:1; MX:1; Received-SPF: None (protection.outlook.com: labundy.com does not designate permitted sender hosts) X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: E7gVlkFnPDHRFPicQyB66Rn1VT/Rew9MlvfcgXkAY6pKm8CqikO4IzYHM5l85nr13KYozNyhFHj8kBMwxD7vtdfBSNdyKJmuoRTS+AjXzjbfHNwkqSOdKVBSQ9Ht5IZWBJeEINx6THWAgj1DsfmOvLSpt1741ItcQQUyEsxpvRBJHYjFKYnVNQn+Rzh94My8UFhoemU4iJVRrNe7TXtk/t8wgKg7n83IbovVCX2zofnUEB9LEng9p9BY27vZ8H97TGXiw84Sp/bzvmfz9EJCV/CAbs71xWI/qC4zd7Os+xoQ/eTmxr+Ug9OkQUaH8dGmSXkduoSEqH9wVoJkL7t5pn4p+AfOVKxHyfVU3bAhPbQrwbOiDjDjpdp9RbjtqoNEYsAuSPaDzxAHcthZcYVIAmjVGByRaNBXDwv7CfFaMqGhn8JqqeP23INO0hktfcXk/qVPBW2Mlv7oduGBIIV3uXEAw6OIWmjxw8bS0TtpkV5A3ogPO72fyZezftFNiB1FBBea4srlXT1o/Mm+p2Q6ivVepGphNHJwxM5FbsST01Q= X-MS-Exchange-AntiSpam-MessageData: 1Cx17KK0sQROWiiuePOz/CeVk20pfU++QVLfoWMtSeBvk6X2mIbBbMmIG9hkP9luuLxh505IGkc9snIRLka4bN/7wsLeMzM0WB4lhhETrjzvhQzGZcCPrzooTgu5iI9XbnlWhUXeIxwQ/N6XtW6lYQ== X-OriginatorOrg: labundy.com X-MS-Exchange-CrossTenant-Network-Message-Id: 733c0ff4-5b0c-4548-fbe6-08d7b3388673 X-MS-Exchange-CrossTenant-OriginalArrivalTime: 16 Feb 2020 23:32:45.3132 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 00b69d09-acab-4585-aca7-8fb7c6323e6f X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: FfiKRuLSQ7WD6EdLZO2PWs79LQex4YED5hxT8YIotHOoMx+F89FDKANu7Q32Mvi/OEc2M6+lGO9UOABwaNO+mQ== X-MS-Exchange-Transport-CrossTenantHeadersStamped: SN6PR08MB5406 Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org This patch adds key and switch support for the Azoteq IQS620A, IQS621, IQS622, IQS624 and IQS625 multi-function sensors. Signed-off-by: Jeff LaBundy Acked-by: Dmitry Torokhov --- Changes in v5: - Replaced iqs62x->map with iqs62x->regmap throughout - Updated iqs62x_keys_parse_prop to use device_property_count_u32 instead of device_property_read_u32_array to count available keycodes - Used input_set_capability to signal available keys and switches instead of __set_bit and __clear_bit within iqs62x_keys_probe - Dropped #defines for platform_driver name and alias in favor of the actual string names - Added Acked-by trailer Changes in v4: - None Changes in v3: - None Changes in v2: - Merged 'Copyright' and 'Author' lines into one in introductory comments - Replaced 'error' with 'ret' throughout - Updated iqs62x_keys_parse_prop to use unified device property interface - Clarified the comment in iqs62x_keys_notifier to state that wheel up or down events elicit an emulated release cycle - Eliminated tabbed alignment of platform_driver struct members drivers/input/keyboard/Kconfig | 10 ++ drivers/input/keyboard/Makefile | 1 + drivers/input/keyboard/iqs62x-keys.c | 335 +++++++++++++++++++++++++++++++++++ 3 files changed, 346 insertions(+) create mode 100644 drivers/input/keyboard/iqs62x-keys.c -- 2.7.4 diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 4706ff0..28de965 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -663,6 +663,16 @@ config KEYBOARD_IPAQ_MICRO To compile this driver as a module, choose M here: the module will be called ipaq-micro-keys. +config KEYBOARD_IQS62X + tristate "Azoteq IQS620A/621/622/624/625 keys and switches" + depends on MFD_IQS62X + help + Say Y here to enable key and switch support for the Azoteq IQS620A, + IQS621, IQS622, IQS624 and IQS625 multi-function sensors. + + To compile this driver as a module, choose M here: the module will + be called iqs62x-keys. + config KEYBOARD_OMAP tristate "TI OMAP keypad support" depends on ARCH_OMAP1 diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index f5b1752..1d689fd 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile @@ -28,6 +28,7 @@ obj-$(CONFIG_KEYBOARD_TCA8418) += tca8418_keypad.o obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o obj-$(CONFIG_KEYBOARD_IPAQ_MICRO) += ipaq-micro-keys.o +obj-$(CONFIG_KEYBOARD_IQS62X) += iqs62x-keys.o obj-$(CONFIG_KEYBOARD_IMX) += imx_keypad.o obj-$(CONFIG_KEYBOARD_IMX_SC_KEY) += imx_sc_key.o obj-$(CONFIG_KEYBOARD_HP6XX) += jornada680_kbd.o diff --git a/drivers/input/keyboard/iqs62x-keys.c b/drivers/input/keyboard/iqs62x-keys.c new file mode 100644 index 0000000..93446b2 --- /dev/null +++ b/drivers/input/keyboard/iqs62x-keys.c @@ -0,0 +1,335 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Azoteq IQS620A/621/622/624/625 Keys and Switches + * + * Copyright (C) 2019 Jeff LaBundy + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum { + IQS62X_SW_HALL_N, + IQS62X_SW_HALL_S, +}; + +static const char * const iqs62x_switch_names[] = { + [IQS62X_SW_HALL_N] = "hall-switch-north", + [IQS62X_SW_HALL_S] = "hall-switch-south", +}; + +struct iqs62x_switch_desc { + enum iqs62x_event_flag flag; + unsigned int code; + bool enabled; +}; + +struct iqs62x_keys_private { + struct iqs62x_core *iqs62x; + struct input_dev *input; + struct notifier_block notifier; + struct iqs62x_switch_desc switches[ARRAY_SIZE(iqs62x_switch_names)]; + unsigned int keycode[IQS62X_NUM_KEYS]; + unsigned int keycodemax; + u8 interval; +}; + +static int iqs62x_keys_parse_prop(struct platform_device *pdev, + struct iqs62x_keys_private *iqs62x_keys) +{ + struct fwnode_handle *child; + unsigned int val; + int ret, i; + + ret = device_property_count_u32(&pdev->dev, "linux,keycodes"); + if (ret > IQS62X_NUM_KEYS) { + dev_err(&pdev->dev, "Too many keycodes present\n"); + return -EINVAL; + } else if (ret < 0) { + dev_err(&pdev->dev, "Failed to count keycodes: %d\n", ret); + return ret; + } + iqs62x_keys->keycodemax = ret; + + ret = device_property_read_u32_array(&pdev->dev, "linux,keycodes", + iqs62x_keys->keycode, + iqs62x_keys->keycodemax); + if (ret) { + dev_err(&pdev->dev, "Failed to read keycodes: %d\n", ret); + return ret; + } + + for (i = 0; i < ARRAY_SIZE(iqs62x_keys->switches); i++) { + child = device_get_named_child_node(&pdev->dev, + iqs62x_switch_names[i]); + if (!child) + continue; + + ret = fwnode_property_read_u32(child, "linux,code", &val); + if (ret) { + dev_err(&pdev->dev, "Failed to read switch code: %d\n", + ret); + return ret; + } + iqs62x_keys->switches[i].code = val; + iqs62x_keys->switches[i].enabled = true; + + if (fwnode_property_present(child, "azoteq,use-prox")) + iqs62x_keys->switches[i].flag = (i == IQS62X_SW_HALL_N ? + IQS62X_EVENT_HALL_N_P : + IQS62X_EVENT_HALL_S_P); + else + iqs62x_keys->switches[i].flag = (i == IQS62X_SW_HALL_N ? + IQS62X_EVENT_HALL_N_T : + IQS62X_EVENT_HALL_S_T); + } + + return 0; +} + +static int iqs62x_keys_init(struct iqs62x_keys_private *iqs62x_keys) +{ + struct iqs62x_core *iqs62x = iqs62x_keys->iqs62x; + enum iqs62x_event_flag flag; + unsigned int event_reg, val; + unsigned int event_mask = 0; + int ret, i; + + switch (iqs62x->dev_desc->prod_num) { + case IQS620_PROD_NUM: + case IQS621_PROD_NUM: + case IQS622_PROD_NUM: + event_reg = IQS620_GLBL_EVENT_MASK; + + /* + * Discreet button, hysteresis and SAR UI flags represent keys + * and are unmasked if mapped to a valid keycode. + */ + for (i = 0; i < iqs62x_keys->keycodemax; i++) { + if (iqs62x_keys->keycode[i] == KEY_RESERVED) + continue; + + if (iqs62x_events[i].reg == IQS62X_EVENT_PROX) + event_mask |= iqs62x->dev_desc->prox_mask; + else if (iqs62x_events[i].reg == IQS62X_EVENT_HYST) + event_mask |= (iqs62x->dev_desc->hyst_mask | + iqs62x->dev_desc->sar_mask); + } + + ret = regmap_read(iqs62x->regmap, iqs62x->dev_desc->hall_flags, + &val); + if (ret) + return ret; + + /* + * Hall UI flags represent switches and are unmasked if their + * corresponding child nodes are present. + */ + for (i = 0; i < ARRAY_SIZE(iqs62x_keys->switches); i++) { + if (!(iqs62x_keys->switches[i].enabled)) + continue; + + flag = iqs62x_keys->switches[i].flag; + + if (iqs62x_events[flag].reg != IQS62X_EVENT_HALL) + continue; + + event_mask |= iqs62x->dev_desc->hall_mask; + + input_report_switch(iqs62x_keys->input, + iqs62x_keys->switches[i].code, + (val & iqs62x_events[flag].mask) == + iqs62x_events[flag].val); + } + + input_sync(iqs62x_keys->input); + break; + + case IQS624_PROD_NUM: + event_reg = IQS624_HALL_UI; + + /* + * Interval change events represent keys and are unmasked if + * either wheel movement flag is mapped to a valid keycode. + */ + if (iqs62x_keys->keycode[IQS62X_EVENT_WHEEL_UP] != KEY_RESERVED) + event_mask |= IQS624_HALL_UI_INT_EVENT; + + if (iqs62x_keys->keycode[IQS62X_EVENT_WHEEL_DN] != KEY_RESERVED) + event_mask |= IQS624_HALL_UI_INT_EVENT; + + ret = regmap_read(iqs62x->regmap, iqs62x->dev_desc->interval, + &val); + if (ret) + return ret; + + iqs62x_keys->interval = val; + break; + + default: + return 0; + } + + return regmap_update_bits(iqs62x->regmap, event_reg, event_mask, 0); +} + +static int iqs62x_keys_notifier(struct notifier_block *notifier, + unsigned long event_flags, void *context) +{ + struct iqs62x_event_data *event_data = context; + struct iqs62x_keys_private *iqs62x_keys; + int ret, i; + + iqs62x_keys = container_of(notifier, struct iqs62x_keys_private, + notifier); + + if (event_flags & BIT(IQS62X_EVENT_SYS_RESET)) { + ret = iqs62x_keys_init(iqs62x_keys); + if (ret) { + dev_err(iqs62x_keys->input->dev.parent, + "Failed to re-initialize device: %d\n", ret); + return NOTIFY_BAD; + } + + return NOTIFY_OK; + } + + for (i = 0; i < iqs62x_keys->keycodemax; i++) { + if (iqs62x_events[i].reg == IQS62X_EVENT_WHEEL && + event_data->interval == iqs62x_keys->interval) + continue; + + input_report_key(iqs62x_keys->input, iqs62x_keys->keycode[i], + event_flags & BIT(i)); + } + + for (i = 0; i < ARRAY_SIZE(iqs62x_keys->switches); i++) + if (iqs62x_keys->switches[i].enabled) + input_report_switch(iqs62x_keys->input, + iqs62x_keys->switches[i].code, + event_flags & + BIT(iqs62x_keys->switches[i].flag)); + + input_sync(iqs62x_keys->input); + + if (event_data->interval == iqs62x_keys->interval) + return NOTIFY_OK; + + /* + * Each frame contains at most one wheel event (up or down), in which + * case a complementary release cycle is emulated. + */ + if (event_flags & BIT(IQS62X_EVENT_WHEEL_UP)) { + input_report_key(iqs62x_keys->input, + iqs62x_keys->keycode[IQS62X_EVENT_WHEEL_UP], + 0); + input_sync(iqs62x_keys->input); + } else if (event_flags & BIT(IQS62X_EVENT_WHEEL_DN)) { + input_report_key(iqs62x_keys->input, + iqs62x_keys->keycode[IQS62X_EVENT_WHEEL_DN], + 0); + input_sync(iqs62x_keys->input); + } + + iqs62x_keys->interval = event_data->interval; + + return NOTIFY_OK; +} + +static int iqs62x_keys_probe(struct platform_device *pdev) +{ + struct iqs62x_core *iqs62x = dev_get_drvdata(pdev->dev.parent); + struct iqs62x_keys_private *iqs62x_keys; + struct input_dev *input; + int ret, i; + + iqs62x_keys = devm_kzalloc(&pdev->dev, sizeof(*iqs62x_keys), + GFP_KERNEL); + if (!iqs62x_keys) + return -ENOMEM; + + platform_set_drvdata(pdev, iqs62x_keys); + + ret = iqs62x_keys_parse_prop(pdev, iqs62x_keys); + if (ret) + return ret; + + input = devm_input_allocate_device(&pdev->dev); + if (!input) + return -ENOMEM; + + input->keycodemax = iqs62x_keys->keycodemax; + input->keycode = iqs62x_keys->keycode; + input->keycodesize = sizeof(*iqs62x_keys->keycode); + + input->name = iqs62x->dev_desc->dev_name; + input->id.bustype = BUS_I2C; + + for (i = 0; i < iqs62x_keys->keycodemax; i++) + if (iqs62x_keys->keycode[i] != KEY_RESERVED) + input_set_capability(input, EV_KEY, + iqs62x_keys->keycode[i]); + + for (i = 0; i < ARRAY_SIZE(iqs62x_keys->switches); i++) + if (iqs62x_keys->switches[i].enabled) + input_set_capability(input, EV_SW, + iqs62x_keys->switches[i].code); + + iqs62x_keys->iqs62x = iqs62x; + iqs62x_keys->input = input; + + ret = iqs62x_keys_init(iqs62x_keys); + if (ret) { + dev_err(&pdev->dev, "Failed to initialize device: %d\n", ret); + return ret; + } + + ret = input_register_device(iqs62x_keys->input); + if (ret) { + dev_err(&pdev->dev, "Failed to register device: %d\n", ret); + return ret; + } + + iqs62x_keys->notifier.notifier_call = iqs62x_keys_notifier; + ret = blocking_notifier_chain_register(&iqs62x_keys->iqs62x->nh, + &iqs62x_keys->notifier); + if (ret) + dev_err(&pdev->dev, "Failed to register notifier: %d\n", ret); + + return ret; +} + +static int iqs62x_keys_remove(struct platform_device *pdev) +{ + struct iqs62x_keys_private *iqs62x_keys = platform_get_drvdata(pdev); + int ret; + + ret = blocking_notifier_chain_unregister(&iqs62x_keys->iqs62x->nh, + &iqs62x_keys->notifier); + if (ret) + dev_err(&pdev->dev, "Failed to unregister notifier: %d\n", ret); + + return ret; +} + +static struct platform_driver iqs62x_keys_platform_driver = { + .driver = { + .name = "iqs62x-keys", + }, + .probe = iqs62x_keys_probe, + .remove = iqs62x_keys_remove, +}; +module_platform_driver(iqs62x_keys_platform_driver); + +MODULE_AUTHOR("Jeff LaBundy "); +MODULE_DESCRIPTION("Azoteq IQS620A/621/622/624/625 Keys and Switches"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:iqs62x-keys"); From patchwork Sun Feb 16 23:32:09 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff LaBundy X-Patchwork-Id: 204737 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.8 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI, MSGID_FROM_MTA_HEADER, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id BE00EC7619B for ; Sun, 16 Feb 2020 23:33:02 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 9496F22B48 for ; Sun, 16 Feb 2020 23:33:02 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=NETORG5796793.onmicrosoft.com header.i=@NETORG5796793.onmicrosoft.com header.b="xKx6GIBZ" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728209AbgBPXdC (ORCPT ); Sun, 16 Feb 2020 18:33:02 -0500 Received: from mail-dm6nam12on2066.outbound.protection.outlook.com ([40.107.243.66]:6039 "EHLO NAM12-DM6-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1727772AbgBPXdB (ORCPT ); Sun, 16 Feb 2020 18:33:01 -0500 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=CKo/M6bGh++zYusqa/yjG2B7x9rlgA0qFSk4msslBg7TE/3cVYhb7ZAd/HlIRTi5EVmoTGHJk8E+qS9JJ+Iw++bv5X5+i9GuAHmnJRvRuLy6CcnmHJJWxDR6HGfJ9hQIuW4n8Ips1aorOwF+9jr+tDO8Bev353hCeMaRMC1fPrclT0gbmu7o4oZG+c8fqGsCUA1Xm+YXeabF0HiUHYx/l0ZOY2mnfzE3sMNVL65D2NUQb25gEEp57Crw7Kl7EFrnOuPEqYJBNumzrer6n5Zq7Dj7fQhXO4w94buvtZfH1NOSW5dtoaAv55DriIFmutgKNurp1eI6tXj/obPrklyHEA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=h3/FsqTrxs6qAiBaff9VLduu9rfmSydYk/omu7VTH6g=; b=O5S2IrrTAIloRKHtxGxbklQgh7VhlU+4ljCRiSSoPhedjuVZFEmNqdsXCbHqmL1XCjhtHGf+oGqiMzg9Prqb+Dn4ASTV1g4+WeLbK8s6KzZwXrmmApjey1RnTqj+oBHucFT1ofkf/vxmfZ0B75oVinYrHtVjq6YsTS5KyT1tML91kjZHZ7j/Ky9Pab/yxyII/e5upWSh0rRSYiAdoMYSsLse6BvByYiaijmwnMDQE4k9bVJpmLYhkjYNco7eA1AMZcVmn7xOtKvA8zu1ZVWT0cl/2lzvMdi0Sumo/MUOoQdk0JW52vEHaBcYmbnNZMRst6QjXufvVFyhOfIgDB4bZA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=labundy.com; dmarc=pass action=none header.from=labundy.com; dkim=pass header.d=labundy.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=NETORG5796793.onmicrosoft.com; s=selector1-NETORG5796793-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=h3/FsqTrxs6qAiBaff9VLduu9rfmSydYk/omu7VTH6g=; b=xKx6GIBZnraGImtnyFkolzRh7GGO8cmTj7169GL/eKeyLKoZ3bOK2szFxj/Qd9UXi68559bEQMhzJlrDVat0IaqzXvTy6RV4DD35vAe7ABnFPuR2wX2zdjv2VgJpt3qQRhe77phzB72WciApk8ICyGyEcbi/xNdZQKTNJI6Sbgs= Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=jeff@labundy.com; Received: from SN6PR08MB5053.namprd08.prod.outlook.com (52.135.107.153) by SN6PR08MB5406.namprd08.prod.outlook.com (52.135.117.208) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.2729.22; Sun, 16 Feb 2020 23:32:57 +0000 Received: from SN6PR08MB5053.namprd08.prod.outlook.com ([fe80::2cd0:e164:fe88:3945]) by SN6PR08MB5053.namprd08.prod.outlook.com ([fe80::2cd0:e164:fe88:3945%4]) with mapi id 15.20.2729.025; Sun, 16 Feb 2020 23:32:57 +0000 From: Jeff LaBundy To: lee.jones@linaro.org, dmitry.torokhov@gmail.com, thierry.reding@gmail.com, jic23@kernel.org, devicetree@vger.kernel.org Cc: linux-input@vger.kernel.org, u.kleine-koenig@pengutronix.de, linux-pwm@vger.kernel.org, knaack.h@gmx.de, lars@metafoo.de, pmeerw@pmeerw.net, linux-iio@vger.kernel.org, robh+dt@kernel.org, mark.rutland@arm.com, Jeff LaBundy Subject: [PATCH v5 5/7] iio: temperature: Add support for Azoteq IQS620AT temperature sensor Date: Sun, 16 Feb 2020 17:32:09 -0600 Message-Id: <1581895931-6056-6-git-send-email-jeff@labundy.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1581895931-6056-1-git-send-email-jeff@labundy.com> References: <1581895931-6056-1-git-send-email-jeff@labundy.com> X-ClientProxiedBy: SN4PR0501CA0142.namprd05.prod.outlook.com (2603:10b6:803:2c::20) To SN6PR08MB5053.namprd08.prod.outlook.com (2603:10b6:805:78::25) MIME-Version: 1.0 Received: from localhost.localdomain (136.49.227.119) by SN4PR0501CA0142.namprd05.prod.outlook.com (2603:10b6:803:2c::20) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) id 15.20.2750.9 via Frontend Transport; Sun, 16 Feb 2020 23:32:56 +0000 X-Mailer: git-send-email 2.7.4 X-Originating-IP: [136.49.227.119] X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 7ec44e43-6566-407c-7a8e-08d7b3388dcb X-MS-TrafficTypeDiagnostic: SN6PR08MB5406: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:7219; X-Forefront-PRVS: 03152A99FF X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10009020)(346002)(136003)(366004)(39830400003)(396003)(376002)(199004)(189003)(8676002)(107886003)(8936002)(4326008)(7416002)(69590400006)(956004)(66556008)(2616005)(81156014)(81166006)(16526019)(26005)(5660300002)(6506007)(186003)(66946007)(6666004)(66476007)(316002)(6486002)(36756003)(52116002)(508600001)(6512007)(2906002)(86362001); DIR:OUT; SFP:1101; SCL:1; SRVR:SN6PR08MB5406; H:SN6PR08MB5053.namprd08.prod.outlook.com; FPR:; SPF:None; LANG:en; PTR:InfoNoRecords; A:1; MX:1; Received-SPF: None (protection.outlook.com: labundy.com does not designate permitted sender hosts) X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: yXIeI8JxsZZ5XxBo9xRvlt/yC9YcsCs607w0KaJFRCu2hxgBIF+COmBN5dp8TR/YwYee1SC8Wzri45h6r+5oiTjeSZkl1Txi6Jl1ks4g8eyzosjyu1Exu9FcqAByD8ng1V1jsxKRoel04SiK50GbZhPtaCMZdHtLtj71cS0KoaXeJ4HdRf8jPKfm595KejM6O7MA4RccwfSyTv7oDyUdH1VGZcT8UA+89xONwjzkfhC2QL8HX5j9zURH1Tm8CkFYdPZ/Dg8bBpwmbqT/5XzZ008N39tac7rgJMWw9L/AKnMRKt2vEtr6JtS196TRdKTeCQn5aiFPUVON0nlTFLTQoHU41KnFYG9aBodaAi7Nvs99/4yNDLi9NlJR8oE4LINqC4a9I0fez7PGcdX4VozLz7/nnAVygvRC90xRLuJA87gmo25r2v0shFrvsD9AY88J9ZRyZiYPAlLbd6Z775K4LT/EwbKtanovdGN6fdQalb0fBNfe0IxQmJ06gFxTic7ugFDpvD7vfLeLSco4UdQhLmG0H5NUCGtv4DihP2fNQFs= X-MS-Exchange-AntiSpam-MessageData: o0SKgtCZJ26FHCVCjryYMPFxcrp8CvIJQgrW0YtI4axtXnWZ8H6gXPy99zQm674fil3IfOGkpkfBEIvmfwoIs9DLsHeTR1gJuHsnxJ1mhVY0D8zChV7tHqNrXyKTUrbrfzkA3VNKhnIkNMpDUbt9WA== X-OriginatorOrg: labundy.com X-MS-Exchange-CrossTenant-Network-Message-Id: 7ec44e43-6566-407c-7a8e-08d7b3388dcb X-MS-Exchange-CrossTenant-OriginalArrivalTime: 16 Feb 2020 23:32:57.6236 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 00b69d09-acab-4585-aca7-8fb7c6323e6f X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: hneN2LxOg+rY5yIRVb53KIHRTYVv49laBBZQNc581sY5LnTzngf01dKVMsXZR6VRt99QoD1mEJI9JWfPOiKkfw== X-MS-Exchange-Transport-CrossTenantHeadersStamped: SN6PR08MB5406 Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org This patch adds support for the Azoteq IQS620AT temperature sensor, capable of reporting its absolute die temperature. Signed-off-by: Jeff LaBundy Reviewed-by: Jonathan Cameron --- Changes in v5: - Replaced iqs62x->map with iqs62x->regmap throughout - Dropped #defines for platform_driver name and alias in favor of the actual string names Changes in v4: - None Changes in v3: - Added Reviewed-by trailer Changes in v2: - Moved the driver from hwmon to iio - Merged 'Copyright' and 'Author' lines into one in introductory comments - Replaced 'error' with 'ret' throughout - Eliminated tabbed alignment of platform_driver struct members - Changed Kconfig "depends on" logic to MFD_IQS62X || COMPILE_TEST drivers/iio/temperature/Kconfig | 10 ++++ drivers/iio/temperature/Makefile | 1 + drivers/iio/temperature/iqs620at-temp.c | 97 +++++++++++++++++++++++++++++++++ 3 files changed, 108 insertions(+) create mode 100644 drivers/iio/temperature/iqs620at-temp.c -- 2.7.4 diff --git a/drivers/iio/temperature/Kconfig b/drivers/iio/temperature/Kconfig index e1ccb40..f1f2a14 100644 --- a/drivers/iio/temperature/Kconfig +++ b/drivers/iio/temperature/Kconfig @@ -4,6 +4,16 @@ # menu "Temperature sensors" +config IQS620AT_TEMP + tristate "Azoteq IQS620AT temperature sensor" + depends on MFD_IQS62X || COMPILE_TEST + help + Say Y here if you want to build support for the Azoteq IQS620AT + temperature sensor. + + To compile this driver as a module, choose M here: the module + will be called iqs620at-temp. + config LTC2983 tristate "Analog Devices Multi-Sensor Digital Temperature Measurement System" depends on SPI diff --git a/drivers/iio/temperature/Makefile b/drivers/iio/temperature/Makefile index d6b850b..90c1131 100644 --- a/drivers/iio/temperature/Makefile +++ b/drivers/iio/temperature/Makefile @@ -3,6 +3,7 @@ # Makefile for industrial I/O temperature drivers # +obj-$(CONFIG_IQS620AT_TEMP) += iqs620at-temp.o obj-$(CONFIG_LTC2983) += ltc2983.o obj-$(CONFIG_HID_SENSOR_TEMP) += hid-sensor-temperature.o obj-$(CONFIG_MAXIM_THERMOCOUPLE) += maxim_thermocouple.o diff --git a/drivers/iio/temperature/iqs620at-temp.c b/drivers/iio/temperature/iqs620at-temp.c new file mode 100644 index 0000000..3fd52b3 --- /dev/null +++ b/drivers/iio/temperature/iqs620at-temp.c @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Azoteq IQS620AT Temperature Sensor + * + * Copyright (C) 2019 Jeff LaBundy + */ + +#include +#include +#include +#include +#include +#include +#include + +#define IQS620_TEMP_UI_OUT 0x1A + +#define IQS620_TEMP_SCALE 1000 +#define IQS620_TEMP_OFFSET (-100) + +static int iqs620_temp_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct iqs62x_core *iqs62x = iio_device_get_drvdata(indio_dev); + int ret; + __le16 val_buf; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret = regmap_raw_read(iqs62x->regmap, IQS620_TEMP_UI_OUT, + &val_buf, sizeof(val_buf)); + if (ret) + return ret; + + *val = le16_to_cpu(val_buf); + return IIO_VAL_INT; + + case IIO_CHAN_INFO_SCALE: + *val = IQS620_TEMP_SCALE; + return IIO_VAL_INT; + + case IIO_CHAN_INFO_OFFSET: + *val = IQS620_TEMP_OFFSET; + return IIO_VAL_INT; + + default: + return -EINVAL; + } +} + +static const struct iio_info iqs620_temp_info = { + .read_raw = &iqs620_temp_read_raw, +}; + +static const struct iio_chan_spec iqs620_temp_channels[] = { + { + .type = IIO_TEMP, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE) | + BIT(IIO_CHAN_INFO_OFFSET), + }, +}; + +static int iqs620_temp_probe(struct platform_device *pdev) +{ + struct iqs62x_core *iqs62x = dev_get_drvdata(pdev->dev.parent); + struct iio_dev *indio_dev; + + indio_dev = devm_iio_device_alloc(&pdev->dev, 0); + if (!indio_dev) + return -ENOMEM; + + iio_device_set_drvdata(indio_dev, iqs62x); + + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->dev.parent = &pdev->dev; + indio_dev->channels = iqs620_temp_channels; + indio_dev->num_channels = ARRAY_SIZE(iqs620_temp_channels); + indio_dev->name = iqs62x->dev_desc->dev_name; + indio_dev->info = &iqs620_temp_info; + + return devm_iio_device_register(&pdev->dev, indio_dev); +} + +static struct platform_driver iqs620_temp_platform_driver = { + .driver = { + .name = "iqs620at-temp", + }, + .probe = iqs620_temp_probe, +}; +module_platform_driver(iqs620_temp_platform_driver); + +MODULE_AUTHOR("Jeff LaBundy "); +MODULE_DESCRIPTION("Azoteq IQS620AT Temperature Sensor"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:iqs620at-temp"); From patchwork Sun Feb 16 23:32:10 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff LaBundy X-Patchwork-Id: 204736 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.8 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI, MSGID_FROM_MTA_HEADER,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS, TVD_PH_BODY_ACCOUNTS_PRE,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 69321C7619D for ; Sun, 16 Feb 2020 23:33:06 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 40FBB208C3 for ; Sun, 16 Feb 2020 23:33:06 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=NETORG5796793.onmicrosoft.com header.i=@NETORG5796793.onmicrosoft.com header.b="pfExkRFZ" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728254AbgBPXdF (ORCPT ); Sun, 16 Feb 2020 18:33:05 -0500 Received: from mail-dm6nam12on2066.outbound.protection.outlook.com ([40.107.243.66]:6039 "EHLO NAM12-DM6-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1728205AbgBPXdF (ORCPT ); Sun, 16 Feb 2020 18:33:05 -0500 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=J7tZlP6YtPS+bF4My7v+hUckJrWbE/VZkU4DtRCUS2RcE5zMrexv+6WViM5dlLAMIRrF4KpmRcSjUco0otFcOGiEnjvvFCBOq05/Ii8SEM1m/tdRagRqymP2EJHsHUJQ492VqxmP/jvlYlrErJq00lwHL1mx+R/S5dy+tPsGAQJbpd0GXHC+ZrMWgejgAqh8dIsc8G8hHHyE0j4Gmo2a4xo322vK/YsJat97GAEVhwyVxz0Pz2cqzDQW9s5WjH3LtvIYLiVGJj5vJ228C/4hi3Z2q0IC45YDCaiN97FKHmAJ/NUMmTbHJqaBsYvDe9KLdCJ3otnWM0DW3KylVHrB3Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=Ri2WXjlmX3IbfJZeQPe555l0EyfIijpPGjVJNKwO6Ok=; b=D2YKFK9fJ8TBdV6B6upw3kLYf195zaMoQAZ+FJubV6McPVXpBOOyw+QZQZO3Ps1BquFd1z2IpZFR+eeTx09eH/CJNOkAnEo8s6bQGAkAGehE6oYd63Kye7vzgnQnOTbk67H+C3ocq3ES5P8Qohi4kD74hYrhNQnbn2QqWRpCdLMmoikaU9J0AIOBb4YFPtIZb4q10X8Grd3lXUm7yImTPVmTmNLDKSsZzcIH96tHkyuZXAkWxDYlrNfZ6T0hu52uRaF2vjyjRLXH9sDP41RM51lqrTSJKiR+uSsMUqJ03kA98RwrrO7SNdTBR7zqUUqxpuzVwdlhkrTA3HyjyPzo+Q== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=labundy.com; dmarc=pass action=none header.from=labundy.com; dkim=pass header.d=labundy.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=NETORG5796793.onmicrosoft.com; s=selector1-NETORG5796793-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=Ri2WXjlmX3IbfJZeQPe555l0EyfIijpPGjVJNKwO6Ok=; b=pfExkRFZw9Om26r6GVQmjbf2QGXox8o5xB6h1hlzi9U8xVLIUzZIkU/SAwT5d6U+PM7aLnhAF+cb+QiAG/o/Va5oaskd6MvNjm2yVaMVXu253KaVCFV0Ll7WCMyq8wTZFJSKrdanVOOFLzSumkOAdx/gzL3qye7WJDXRE4JYTM4= Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=jeff@labundy.com; Received: from SN6PR08MB5053.namprd08.prod.outlook.com (52.135.107.153) by SN6PR08MB5406.namprd08.prod.outlook.com (52.135.117.208) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.2729.22; Sun, 16 Feb 2020 23:33:01 +0000 Received: from SN6PR08MB5053.namprd08.prod.outlook.com ([fe80::2cd0:e164:fe88:3945]) by SN6PR08MB5053.namprd08.prod.outlook.com ([fe80::2cd0:e164:fe88:3945%4]) with mapi id 15.20.2729.025; Sun, 16 Feb 2020 23:33:00 +0000 From: Jeff LaBundy To: lee.jones@linaro.org, dmitry.torokhov@gmail.com, thierry.reding@gmail.com, jic23@kernel.org, devicetree@vger.kernel.org Cc: linux-input@vger.kernel.org, u.kleine-koenig@pengutronix.de, linux-pwm@vger.kernel.org, knaack.h@gmx.de, lars@metafoo.de, pmeerw@pmeerw.net, linux-iio@vger.kernel.org, robh+dt@kernel.org, mark.rutland@arm.com, Jeff LaBundy Subject: [PATCH v5 6/7] iio: light: Add support for Azoteq IQS621/622 ambient light sensors Date: Sun, 16 Feb 2020 17:32:10 -0600 Message-Id: <1581895931-6056-7-git-send-email-jeff@labundy.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1581895931-6056-1-git-send-email-jeff@labundy.com> References: <1581895931-6056-1-git-send-email-jeff@labundy.com> X-ClientProxiedBy: SN4PR0501CA0142.namprd05.prod.outlook.com (2603:10b6:803:2c::20) To SN6PR08MB5053.namprd08.prod.outlook.com (2603:10b6:805:78::25) MIME-Version: 1.0 Received: from localhost.localdomain (136.49.227.119) by SN4PR0501CA0142.namprd05.prod.outlook.com (2603:10b6:803:2c::20) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) id 15.20.2750.9 via Frontend Transport; Sun, 16 Feb 2020 23:33:00 +0000 X-Mailer: git-send-email 2.7.4 X-Originating-IP: [136.49.227.119] X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 5b0dc72e-f88f-441f-9e2f-08d7b3388fb7 X-MS-TrafficTypeDiagnostic: SN6PR08MB5406: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:10000; X-Forefront-PRVS: 03152A99FF X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10009020)(346002)(136003)(366004)(39830400003)(396003)(376002)(199004)(189003)(8676002)(107886003)(8936002)(4326008)(7416002)(69590400006)(956004)(66556008)(2616005)(81156014)(81166006)(16526019)(26005)(5660300002)(6506007)(186003)(66946007)(6666004)(66476007)(316002)(6486002)(36756003)(52116002)(508600001)(6512007)(2906002)(86362001)(30864003); DIR:OUT; SFP:1101; SCL:1; SRVR:SN6PR08MB5406; H:SN6PR08MB5053.namprd08.prod.outlook.com; FPR:; SPF:None; LANG:en; PTR:InfoNoRecords; A:1; MX:1; Received-SPF: None (protection.outlook.com: labundy.com does not designate permitted sender hosts) X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: PfLEsecIV/h2Ip2DjJAV+Ab5Gd52a4psXuG1F5Is+AcpXZll1nwr51cPxa+NppzbWkPQ13MAaUJKDCEjLLz8fF/UsNjPf/xdmuYRO5+68e9nVn3NVAeEVcElHqYBN6a2lAhRfIMK+SUVSnhRDPG4VrwW6MZ1pbIYvyLoywGEdBmjbF7ZrL77RCFxp8q/1hCaetBfJSTEmbyQ79vbtHG5bsYlsMbfqtAT8SmrCk6CiKL6r/K2CyPCY7bS5OH0xd6lH1CFFC8pkDOEWZ5HXS1gJlE3kgzCxcCiV2hljL8iZ/O2kfHbUlbPlon+fBx6XnIEYcIuFUuBvzc/o5RIo4KAV6RddJcKsVCg/4f0j5qrqkl0ZMdf1FkJwxyxeXB3J0NdQZ6x1gPfL9sMBNQj1B7vduoyhWtz3fI77WuzywiQp7vclUQsBxfImSK7pk7KwhbnidyIgbND/EYvfXjbAp7928rTOv9fcFsrmDrnpntsC/kM1HhiNMCDoRxFtAeQpLWtpoA4nZMxHknFkdvPY4qCd5/qOBS50MI7t97sMT4gMz8= X-MS-Exchange-AntiSpam-MessageData: 0g6V7NMNxadzwdy1DzbdAZ9EXB1aH5iU1D9XrQb4Z4WiClYAI/eMOV1ToHXk/NzTaVCoTgFlNaNrWN3L8UzjuVAwxK0nzRUSOP0dDD3/uEXXYqQ6YEdf+uQWjYd1Jhy23RvI0y094mYR0uj4gNSdjA== X-OriginatorOrg: labundy.com X-MS-Exchange-CrossTenant-Network-Message-Id: 5b0dc72e-f88f-441f-9e2f-08d7b3388fb7 X-MS-Exchange-CrossTenant-OriginalArrivalTime: 16 Feb 2020 23:33:00.8999 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 00b69d09-acab-4585-aca7-8fb7c6323e6f X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: qIgEpepDPwinXNctP0nDdqNBEvZLW9z0mxsfZwTMQMVmkiMvferuS8UQpHeobpdGybPEasnILEG3DQW519pkgQ== X-MS-Exchange-Transport-CrossTenantHeadersStamped: SN6PR08MB5406 Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org This patch adds support for the Azoteq IQS621 and IQS622 ambient light sensors, both of which can report a four-bit representation of ambient light intensity. The IQS621 can additionally report illuminace directly in units of lux, while the IQS622 can report a four-bit representation of infrared light intensity. Furthermore, the IQS622 can report a unitless measurement of a target's proximity to the device. Signed-off-by: Jeff LaBundy Reviewed-by: Jonathan Cameron --- Changes in v5: - Replaced iqs62x->map with iqs62x->regmap throughout - Replaced use of bitwise-OR operators in iqs621_als_write_event_config with logical-OR operators as was originally intended - Dropped #defines for platform_driver name and alias in favor of the actual string names Changes in v4: - None Changes in v3: - Added Reviewed-by trailer Changes in v2: - Merged 'Copyright' and 'Author' lines into one in introductory comments - Replaced 'error' with 'ret' throughout - Merged support for the closely related IQS622 (formerly represented by a separate iio/proximity driver) - Added support for unitless ambient light intensity (IQS621 and IQS622) and infrared light intensity (IQS622 only) - Moved the read of IQS621_ALS_FLAGS to iqs621_als_write_event_config to account for the fact that IQS621_ALS_FLAGS may have changed in between having first been read in iqs621_als_init and the time at which events are enabled, thereby eliminating the need to call iqs621_als_init from iqs621_als_probe - Refactored the logic in iqs621_als_notifier and added a lock to safely evaluate variables that may change in response to user action - Added locks to iqs621_als_read_event_config/value to account for cases in which the corresponding hardware state is in the process of being updated - Refactored the logic in iqs621_als_read/write_event_value and removed all #defines that could instead be represented by simple math - Based the decision whether to select the IQS622 IR touch vs. proximity threshold on the single proximity threshold written by user space, and added a comment to describe the difference between either threshold - Replaced IIO_CHAN_INFO_RAW with IIO_CHAN_INFO_PROCESSED for the IIO_LIGHT channel (IQS621 only) - Removed devm_add_action_or_reset failure message - Eliminated tabbed alignment of platform_driver struct members - Changed Kconfig "depends on" logic to MFD_IQS62X || COMPILE_TEST drivers/iio/light/Kconfig | 10 + drivers/iio/light/Makefile | 1 + drivers/iio/light/iqs621-als.c | 617 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 628 insertions(+) create mode 100644 drivers/iio/light/iqs621-als.c -- 2.7.4 diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig index 9968f98..baf7958b 100644 --- a/drivers/iio/light/Kconfig +++ b/drivers/iio/light/Kconfig @@ -173,6 +173,16 @@ config GP2AP020A00F To compile this driver as a module, choose M here: the module will be called gp2ap020a00f. +config IQS621_ALS + tristate "Azoteq IQS621/622 ambient light sensors" + depends on MFD_IQS62X || COMPILE_TEST + help + Say Y here if you want to build support for the Azoteq IQS621 + and IQS622 ambient light sensors. + + To compile this driver as a module, choose M here: the module + will be called iqs621-als. + config SENSORS_ISL29018 tristate "Intersil 29018 light and proximity sensor" depends on I2C diff --git a/drivers/iio/light/Makefile b/drivers/iio/light/Makefile index c98d1ce..988e8f4 100644 --- a/drivers/iio/light/Makefile +++ b/drivers/iio/light/Makefile @@ -21,6 +21,7 @@ obj-$(CONFIG_IIO_CROS_EC_LIGHT_PROX) += cros_ec_light_prox.o obj-$(CONFIG_GP2AP020A00F) += gp2ap020a00f.o obj-$(CONFIG_HID_SENSOR_ALS) += hid-sensor-als.o obj-$(CONFIG_HID_SENSOR_PROX) += hid-sensor-prox.o +obj-$(CONFIG_IQS621_ALS) += iqs621-als.o obj-$(CONFIG_SENSORS_ISL29018) += isl29018.o obj-$(CONFIG_SENSORS_ISL29028) += isl29028.o obj-$(CONFIG_ISL29125) += isl29125.o diff --git a/drivers/iio/light/iqs621-als.c b/drivers/iio/light/iqs621-als.c new file mode 100644 index 0000000..b2988a7 --- /dev/null +++ b/drivers/iio/light/iqs621-als.c @@ -0,0 +1,617 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Azoteq IQS621/622 Ambient Light Sensors + * + * Copyright (C) 2019 Jeff LaBundy + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define IQS621_ALS_FLAGS_LIGHT BIT(7) +#define IQS621_ALS_FLAGS_RANGE GENMASK(3, 0) + +#define IQS621_ALS_UI_OUT 0x17 + +#define IQS621_ALS_THRESH_DARK 0x80 +#define IQS621_ALS_THRESH_LIGHT 0x81 + +#define IQS622_IR_RANGE 0x15 +#define IQS622_IR_FLAGS 0x16 +#define IQS622_IR_FLAGS_TOUCH BIT(1) +#define IQS622_IR_FLAGS_PROX BIT(0) + +#define IQS622_IR_UI_OUT 0x17 + +#define IQS622_IR_THRESH_PROX 0x91 +#define IQS622_IR_THRESH_TOUCH 0x92 + +struct iqs621_als_private { + struct iqs62x_core *iqs62x; + struct notifier_block notifier; + struct mutex lock; + bool light_en; + bool range_en; + bool prox_en; + u8 als_flags; + u8 ir_flags_mask; + u8 ir_flags; + u8 thresh_light; + u8 thresh_dark; + u8 thresh_prox; +}; + +static int iqs621_als_init(struct iqs621_als_private *iqs621_als) +{ + struct iqs62x_core *iqs62x = iqs621_als->iqs62x; + unsigned int event_mask = 0; + int ret; + + switch (iqs621_als->ir_flags_mask) { + case IQS622_IR_FLAGS_TOUCH: + ret = regmap_write(iqs62x->regmap, IQS622_IR_THRESH_TOUCH, + iqs621_als->thresh_prox); + break; + + case IQS622_IR_FLAGS_PROX: + ret = regmap_write(iqs62x->regmap, IQS622_IR_THRESH_PROX, + iqs621_als->thresh_prox); + break; + + default: + ret = regmap_write(iqs62x->regmap, IQS621_ALS_THRESH_LIGHT, + iqs621_als->thresh_light); + if (ret) + return ret; + + ret = regmap_write(iqs62x->regmap, IQS621_ALS_THRESH_DARK, + iqs621_als->thresh_dark); + } + + if (ret) + return ret; + + if (iqs621_als->light_en || iqs621_als->range_en) + event_mask |= iqs62x->dev_desc->als_mask; + + if (iqs621_als->prox_en) + event_mask |= iqs62x->dev_desc->ir_mask; + + return regmap_update_bits(iqs62x->regmap, IQS620_GLBL_EVENT_MASK, + event_mask, 0); +} + +static int iqs621_als_notifier(struct notifier_block *notifier, + unsigned long event_flags, void *context) +{ + struct iqs62x_event_data *event_data = context; + struct iqs621_als_private *iqs621_als; + struct iio_dev *indio_dev; + bool light_new, light_old; + bool prox_new, prox_old; + u8 range_new, range_old; + s64 timestamp; + int ret; + + iqs621_als = container_of(notifier, struct iqs621_als_private, + notifier); + indio_dev = iio_priv_to_dev(iqs621_als); + timestamp = iio_get_time_ns(indio_dev); + + mutex_lock(&iqs621_als->lock); + + if (event_flags & BIT(IQS62X_EVENT_SYS_RESET)) { + ret = iqs621_als_init(iqs621_als); + if (ret) { + dev_err(indio_dev->dev.parent, + "Failed to re-initialize device: %d\n", ret); + ret = NOTIFY_BAD; + } else { + ret = NOTIFY_OK; + } + + goto err_mutex; + } + + if (!iqs621_als->light_en && !iqs621_als->range_en && + !iqs621_als->prox_en) { + ret = NOTIFY_DONE; + goto err_mutex; + } + + /* IQS621 only */ + light_new = event_data->als_flags & IQS621_ALS_FLAGS_LIGHT; + light_old = iqs621_als->als_flags & IQS621_ALS_FLAGS_LIGHT; + + if (iqs621_als->light_en && light_new && !light_old) + iio_push_event(indio_dev, + IIO_UNMOD_EVENT_CODE(IIO_LIGHT, 0, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_RISING), + timestamp); + else if (iqs621_als->light_en && !light_new && light_old) + iio_push_event(indio_dev, + IIO_UNMOD_EVENT_CODE(IIO_LIGHT, 0, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_FALLING), + timestamp); + + /* IQS621 and IQS622 */ + range_new = event_data->als_flags & IQS621_ALS_FLAGS_RANGE; + range_old = iqs621_als->als_flags & IQS621_ALS_FLAGS_RANGE; + + if (iqs621_als->range_en && (range_new > range_old)) + iio_push_event(indio_dev, + IIO_UNMOD_EVENT_CODE(IIO_INTENSITY, 0, + IIO_EV_TYPE_CHANGE, + IIO_EV_DIR_RISING), + timestamp); + else if (iqs621_als->range_en && (range_new < range_old)) + iio_push_event(indio_dev, + IIO_UNMOD_EVENT_CODE(IIO_INTENSITY, 0, + IIO_EV_TYPE_CHANGE, + IIO_EV_DIR_FALLING), + timestamp); + + /* IQS622 only */ + prox_new = event_data->ir_flags & iqs621_als->ir_flags_mask; + prox_old = iqs621_als->ir_flags & iqs621_als->ir_flags_mask; + + if (iqs621_als->prox_en && prox_new && !prox_old) + iio_push_event(indio_dev, + IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, 0, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_RISING), + timestamp); + else if (iqs621_als->prox_en && !prox_new && prox_old) + iio_push_event(indio_dev, + IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, 0, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_FALLING), + timestamp); + + iqs621_als->als_flags = event_data->als_flags; + iqs621_als->ir_flags = event_data->ir_flags; + ret = NOTIFY_OK; + +err_mutex: + mutex_unlock(&iqs621_als->lock); + + return ret; +} + +static void iqs621_als_notifier_unregister(void *context) +{ + struct iqs621_als_private *iqs621_als = context; + struct iio_dev *indio_dev = iio_priv_to_dev(iqs621_als); + int ret; + + ret = blocking_notifier_chain_unregister(&iqs621_als->iqs62x->nh, + &iqs621_als->notifier); + if (ret) + dev_err(indio_dev->dev.parent, + "Failed to unregister notifier: %d\n", ret); +} + +static int iqs621_als_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct iqs621_als_private *iqs621_als = iio_priv(indio_dev); + struct iqs62x_core *iqs62x = iqs621_als->iqs62x; + int ret; + __le16 val_buf; + + switch (chan->type) { + case IIO_INTENSITY: + ret = regmap_read(iqs62x->regmap, chan->address, val); + if (ret) + return ret; + + *val &= IQS621_ALS_FLAGS_RANGE; + return IIO_VAL_INT; + + case IIO_PROXIMITY: + case IIO_LIGHT: + ret = regmap_raw_read(iqs62x->regmap, chan->address, &val_buf, + sizeof(val_buf)); + if (ret) + return ret; + + *val = le16_to_cpu(val_buf); + return IIO_VAL_INT; + + default: + return -EINVAL; + } +} + +static int iqs621_als_read_event_config(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir) +{ + struct iqs621_als_private *iqs621_als = iio_priv(indio_dev); + int ret; + + mutex_lock(&iqs621_als->lock); + + switch (chan->type) { + case IIO_LIGHT: + ret = iqs621_als->light_en; + break; + + case IIO_INTENSITY: + ret = iqs621_als->range_en; + break; + + case IIO_PROXIMITY: + ret = iqs621_als->prox_en; + break; + + default: + ret = -EINVAL; + } + + mutex_unlock(&iqs621_als->lock); + + return ret; +} + +static int iqs621_als_write_event_config(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + int state) +{ + struct iqs621_als_private *iqs621_als = iio_priv(indio_dev); + struct iqs62x_core *iqs62x = iqs621_als->iqs62x; + unsigned int val; + int ret; + + mutex_lock(&iqs621_als->lock); + + ret = regmap_read(iqs62x->regmap, iqs62x->dev_desc->als_flags, &val); + if (ret) + goto err_mutex; + iqs621_als->als_flags = val; + + switch (chan->type) { + case IIO_LIGHT: + ret = regmap_update_bits(iqs62x->regmap, IQS620_GLBL_EVENT_MASK, + iqs62x->dev_desc->als_mask, + iqs621_als->range_en || state ? 0 : + 0xFF); + if (!ret) + iqs621_als->light_en = state; + break; + + case IIO_INTENSITY: + ret = regmap_update_bits(iqs62x->regmap, IQS620_GLBL_EVENT_MASK, + iqs62x->dev_desc->als_mask, + iqs621_als->light_en || state ? 0 : + 0xFF); + if (!ret) + iqs621_als->range_en = state; + break; + + case IIO_PROXIMITY: + ret = regmap_read(iqs62x->regmap, IQS622_IR_FLAGS, &val); + if (ret) + goto err_mutex; + iqs621_als->ir_flags = val; + + ret = regmap_update_bits(iqs62x->regmap, IQS620_GLBL_EVENT_MASK, + iqs62x->dev_desc->ir_mask, + state ? 0 : 0xFF); + if (!ret) + iqs621_als->prox_en = state; + break; + + default: + ret = -EINVAL; + } + +err_mutex: + mutex_unlock(&iqs621_als->lock); + + return ret; +} + +static int iqs621_als_read_event_value(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int *val, int *val2) +{ + struct iqs621_als_private *iqs621_als = iio_priv(indio_dev); + int ret = IIO_VAL_INT; + + mutex_lock(&iqs621_als->lock); + + switch (dir) { + case IIO_EV_DIR_RISING: + *val = iqs621_als->thresh_light * 16; + break; + + case IIO_EV_DIR_FALLING: + *val = iqs621_als->thresh_dark * 4; + break; + + case IIO_EV_DIR_EITHER: + if (iqs621_als->ir_flags_mask == IQS622_IR_FLAGS_TOUCH) + *val = iqs621_als->thresh_prox * 4; + else + *val = iqs621_als->thresh_prox; + break; + + default: + ret = -EINVAL; + } + + mutex_unlock(&iqs621_als->lock); + + return ret; +} + +static int iqs621_als_write_event_value(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int val, int val2) +{ + struct iqs621_als_private *iqs621_als = iio_priv(indio_dev); + struct iqs62x_core *iqs62x = iqs621_als->iqs62x; + unsigned int thresh_reg, thresh_val; + u8 ir_flags_mask, *thresh_cache; + int ret = -EINVAL; + + mutex_lock(&iqs621_als->lock); + + switch (dir) { + case IIO_EV_DIR_RISING: + thresh_reg = IQS621_ALS_THRESH_LIGHT; + thresh_val = val / 16; + + thresh_cache = &iqs621_als->thresh_light; + ir_flags_mask = 0; + break; + + case IIO_EV_DIR_FALLING: + thresh_reg = IQS621_ALS_THRESH_DARK; + thresh_val = val / 4; + + thresh_cache = &iqs621_als->thresh_dark; + ir_flags_mask = 0; + break; + + case IIO_EV_DIR_EITHER: + /* + * The IQS622 supports two detection thresholds, both measured + * in the same arbitrary units reported by read_raw: proximity + * (0 through 255 in steps of 1), and touch (0 through 1020 in + * steps of 4). + * + * Based on the single detection threshold chosen by the user, + * select the hardware threshold that gives the best trade-off + * between range and resolution. + * + * By default, the close-range (but coarse) touch threshold is + * chosen during probe. + */ + switch (val) { + case 0 ... 255: + thresh_reg = IQS622_IR_THRESH_PROX; + thresh_val = val; + + ir_flags_mask = IQS622_IR_FLAGS_PROX; + break; + + case 256 ... 1020: + thresh_reg = IQS622_IR_THRESH_TOUCH; + thresh_val = val / 4; + + ir_flags_mask = IQS622_IR_FLAGS_TOUCH; + break; + + default: + goto err_mutex; + } + + thresh_cache = &iqs621_als->thresh_prox; + break; + + default: + goto err_mutex; + } + + if (thresh_val > 0xFF) + goto err_mutex; + + ret = regmap_write(iqs62x->regmap, thresh_reg, thresh_val); + if (ret) + goto err_mutex; + + *thresh_cache = thresh_val; + iqs621_als->ir_flags_mask = ir_flags_mask; + +err_mutex: + mutex_unlock(&iqs621_als->lock); + + return ret; +} + +static const struct iio_info iqs621_als_info = { + .read_raw = &iqs621_als_read_raw, + .read_event_config = iqs621_als_read_event_config, + .write_event_config = iqs621_als_write_event_config, + .read_event_value = iqs621_als_read_event_value, + .write_event_value = iqs621_als_write_event_value, +}; + +static const struct iio_event_spec iqs621_als_range_events[] = { + { + .type = IIO_EV_TYPE_CHANGE, + .dir = IIO_EV_DIR_EITHER, + .mask_separate = BIT(IIO_EV_INFO_ENABLE), + }, +}; + +static const struct iio_event_spec iqs621_als_light_events[] = { + { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_EITHER, + .mask_separate = BIT(IIO_EV_INFO_ENABLE), + }, + { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_RISING, + .mask_separate = BIT(IIO_EV_INFO_VALUE), + }, + { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_FALLING, + .mask_separate = BIT(IIO_EV_INFO_VALUE), + }, +}; + +static const struct iio_chan_spec iqs621_als_channels[] = { + { + .type = IIO_INTENSITY, + .address = IQS621_ALS_FLAGS, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .event_spec = iqs621_als_range_events, + .num_event_specs = ARRAY_SIZE(iqs621_als_range_events), + }, + { + .type = IIO_LIGHT, + .address = IQS621_ALS_UI_OUT, + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), + .event_spec = iqs621_als_light_events, + .num_event_specs = ARRAY_SIZE(iqs621_als_light_events), + }, +}; + +static const struct iio_event_spec iqs622_als_prox_events[] = { + { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_EITHER, + .mask_separate = BIT(IIO_EV_INFO_ENABLE) | + BIT(IIO_EV_INFO_VALUE), + }, +}; + +static const struct iio_chan_spec iqs622_als_channels[] = { + { + .type = IIO_INTENSITY, + .channel2 = IIO_MOD_LIGHT_BOTH, + .address = IQS622_ALS_FLAGS, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .event_spec = iqs621_als_range_events, + .num_event_specs = ARRAY_SIZE(iqs621_als_range_events), + .modified = true, + }, + { + .type = IIO_INTENSITY, + .channel2 = IIO_MOD_LIGHT_IR, + .address = IQS622_IR_RANGE, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .modified = true, + }, + { + .type = IIO_PROXIMITY, + .address = IQS622_IR_UI_OUT, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .event_spec = iqs622_als_prox_events, + .num_event_specs = ARRAY_SIZE(iqs622_als_prox_events), + }, +}; + +static int iqs621_als_probe(struct platform_device *pdev) +{ + struct iqs62x_core *iqs62x = dev_get_drvdata(pdev->dev.parent); + struct iqs621_als_private *iqs621_als; + struct iio_dev *indio_dev; + unsigned int val; + int ret; + + indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*iqs621_als)); + if (!indio_dev) + return -ENOMEM; + + iqs621_als = iio_priv(indio_dev); + iqs621_als->iqs62x = iqs62x; + + if (iqs62x->dev_desc->prod_num == IQS622_PROD_NUM) { + ret = regmap_read(iqs62x->regmap, IQS622_IR_THRESH_TOUCH, + &val); + if (ret) + return ret; + iqs621_als->thresh_prox = val; + iqs621_als->ir_flags_mask = IQS622_IR_FLAGS_TOUCH; + + indio_dev->channels = iqs622_als_channels; + indio_dev->num_channels = ARRAY_SIZE(iqs622_als_channels); + } else { + ret = regmap_read(iqs62x->regmap, IQS621_ALS_THRESH_LIGHT, + &val); + if (ret) + return ret; + iqs621_als->thresh_light = val; + + ret = regmap_read(iqs62x->regmap, IQS621_ALS_THRESH_DARK, + &val); + if (ret) + return ret; + iqs621_als->thresh_dark = val; + + indio_dev->channels = iqs621_als_channels; + indio_dev->num_channels = ARRAY_SIZE(iqs621_als_channels); + } + + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->dev.parent = &pdev->dev; + indio_dev->name = iqs62x->dev_desc->dev_name; + indio_dev->info = &iqs621_als_info; + + mutex_init(&iqs621_als->lock); + + iqs621_als->notifier.notifier_call = iqs621_als_notifier; + ret = blocking_notifier_chain_register(&iqs621_als->iqs62x->nh, + &iqs621_als->notifier); + if (ret) { + dev_err(&pdev->dev, "Failed to register notifier: %d\n", ret); + return ret; + } + + ret = devm_add_action_or_reset(&pdev->dev, + iqs621_als_notifier_unregister, + iqs621_als); + if (ret) + return ret; + + return devm_iio_device_register(&pdev->dev, indio_dev); +} + +static struct platform_driver iqs621_als_platform_driver = { + .driver = { + .name = "iqs621-als", + }, + .probe = iqs621_als_probe, +}; +module_platform_driver(iqs621_als_platform_driver); + +MODULE_AUTHOR("Jeff LaBundy "); +MODULE_DESCRIPTION("Azoteq IQS621/622 Ambient Light Sensors"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:iqs621-als");