From patchwork Tue Nov 15 07:37:17 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Gerald Loacker X-Patchwork-Id: 13043297 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 26939C43219 for ; Tue, 15 Nov 2022 07:37:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232517AbiKOHhp (ORCPT ); Tue, 15 Nov 2022 02:37:45 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51008 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232406AbiKOHhi (ORCPT ); Tue, 15 Nov 2022 02:37:38 -0500 Received: from EUR01-VE1-obe.outbound.protection.outlook.com (mail-eopbgr140042.outbound.protection.outlook.com [40.107.14.42]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7E4E6209AA; Mon, 14 Nov 2022 23:37:37 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=Qf14vd/QAF/eq4K3W5wei5FPizC3v+3YTG6HWiwjw6lS8htHJSOk1cTsVvu7Szhk9Mkvmq5fPamjc4Jhm5O9efK7ftfI8WBMjrAh7q2UeUzvaxPSUe2nhh+pl3MDP/QOyd6TN/8KltuXrZjxF+9yyECWi2oWS9xdRNfyNzx3cPAf513nuH3NpBq788KcdxlmN1J+A5xMYcicm+R59u+2nLcGGGZLVki8mxogjlk2F86plIPhVOKLJfAhhz5Aa2bXyAXc21L1UGRcaw+svcIYJax4mnKUiq2LLOHUm6zOYZNY6FtRyIOmPoLolHmAdDFj4SH5nyIaEu3Gn0Urc4BxiA== 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-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=bKkktckgcoLhaPIuecgGEjPGNGph/Tl8jonJhS5cOP8=; b=YzxDM3+lOgvwz8nl9uXbux31BeD1a+iIgGXbLGuiT5QJk9mgF78CdyaN4Bmz9KiIfPQCdtlCvJ3UkgVSgYgqXgOQalPkkNXUb3FIn/da7NjrnuU5MvVIa9ZL/Mu7AjBIYhOk3HU5qZ+q5Yvj6YC3QJSS2aLYV8Jr4BM5KjSZmMJywyP0nQnGwbZm7gD2HAbZ79MyrIVHUWXnZV7had3biD7I4Qpnqk7YCg9XlvDe1f9aFWSE0wUpoaVNmBv2vU4ICMXi7baWxJW910TUenBuvpjmrNAS3OlhnyAqA9baSVM5UqBRYShHMB95vWrLYNMAo2kyUOdA4UE4G6lIWlxcOQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=wolfvision.net; dmarc=pass action=none header.from=wolfvision.net; dkim=pass header.d=wolfvision.net; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=wolfvision.net; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=bKkktckgcoLhaPIuecgGEjPGNGph/Tl8jonJhS5cOP8=; b=OWYhJuLqkCtLrgmyy5BAnMn37leSH9Z6nqhHmSUKzCoa44MK5dk7ICqNaJBtQdDzRgi6K7tRQw9z1mx89oONJMUd4WrJ636gHUnbO7e18xakpRbG7A7Kl0xDp1IZqbHhq6idX9hEeTtI0m6D7n+XeSa3Vvy9XTeP5izVDEw5ayI= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=wolfvision.net; Received: from VI1PR08MB4544.eurprd08.prod.outlook.com (2603:10a6:803:100::13) by AS2PR08MB9572.eurprd08.prod.outlook.com (2603:10a6:20b:608::8) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5834.7; Tue, 15 Nov 2022 07:37:36 +0000 Received: from VI1PR08MB4544.eurprd08.prod.outlook.com ([fe80::bcc7:bc51:bf44:1454]) by VI1PR08MB4544.eurprd08.prod.outlook.com ([fe80::bcc7:bc51:bf44:1454%6]) with mapi id 15.20.5834.006; Tue, 15 Nov 2022 07:37:36 +0000 From: Gerald Loacker To: linux-iio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Jonathan Cameron , Lars-Peter Clausen , Rob Herring , Krzysztof Kozlowski , Andy Shevchenko , Nikita Yushchenko , Jakob Hauser , Michael Riesch , Gerald Loacker Subject: [PATCH 1/2] dt-bindings: iio: magnetometer: add ti tmag5273 documentation file Date: Tue, 15 Nov 2022 08:37:17 +0100 Message-Id: <20221115073718.2377311-2-gerald.loacker@wolfvision.net> X-Mailer: git-send-email 2.37.2 In-Reply-To: <20221115073718.2377311-1-gerald.loacker@wolfvision.net> References: <20221115073718.2377311-1-gerald.loacker@wolfvision.net> X-ClientProxiedBy: VE1PR08CA0017.eurprd08.prod.outlook.com (2603:10a6:803:104::30) To VI1PR08MB4544.eurprd08.prod.outlook.com (2603:10a6:803:100::13) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: VI1PR08MB4544:EE_|AS2PR08MB9572:EE_ X-MS-Office365-Filtering-Correlation-Id: c3af0130-8ea1-4106-8205-08dac6dc43fc X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: csp/AlVOXbsny1iREfL4sQikfzqsdwegwy8ePmCuUn3QHkr5l0ZlI3YD3YTCpQn71jRffOoVgtB/tEwznHKJy3tHAtEJ/Y9x4rUVkhhr5snHZsmHeE4TJaHP6YNrC0e05Lb0GBH6L5zr2LSsP+wKL9eRC2Ta2HMdDBpqan17fOSSAaYBmk5hwApA/28jPb3V0X924ht10/po2AzOU2BhfVjLN4FtRTBhvU7pVgSgWnvMI7dvVwcYLxHrYBzjijc6D1mPn3Q/Q63SsY2kLQ+ZJsBjxE8M8/1Z6hB14VTMxmvlMkmrs8uhC3h2Z3LAUlEm0e40eadFDTOj0l1z0LXs0OurI5nEpXByUPlVm/m0TBUei2hF7yFc3IjS9rWyYIfAyc4HoMvsG0D/VrOmUGrGp1TqyZVFXcD7YRk/hoXNQPClCI74pW6gRsJOeykODD96nDuJsUJ+fxiad5mEei+lXokS4m1ealy8GBW4pevmGP661GA3l5gRrgPiKUXSudVgNf7HSOyUoksILEbblFprTyUbqSaXi1S2JhH/IurHrJKg1ojTwgy88QMC1q9JfAaXIoZUai7TCHzhKctnAQzxJsqNlEwCEP0pdryBdvKG9ngd4hx/w+eP/610cy+mj0Sh6Ud4JagJo4SH1p65j0RMLoPAbppDn6MrOqwmz+mwsjg/vuqNWY9DllxC1mHTBWxtWaaOiD5uk425/Gp+GCmvZ7qYoPav5G7ZaADxlee/MYDVrE+ty5xy9FBSZhjXdcdE10fBgwwddFoeQridthWoPyquu7XS3sIXrLLHTahT2CVTPecTLapfDBXrH7c1BCY3sYO2bYqQhyBjaKauqKD/PA== X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:VI1PR08MB4544.eurprd08.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230022)(4636009)(396003)(366004)(136003)(346002)(39850400004)(376002)(451199015)(186003)(107886003)(86362001)(41300700001)(2616005)(26005)(6512007)(6666004)(6506007)(38100700002)(4326008)(8676002)(1076003)(54906003)(38350700002)(66556008)(66476007)(2906002)(5660300002)(36756003)(66946007)(966005)(6486002)(7416002)(316002)(8936002)(52116002)(478600001)(44832011);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?q?xY27eR9+JYTnI9Bi10cZbbzGPLBQ?= =?utf-8?q?sBnQVE37jNkvVGrjz3JqCmguGjRsG3YS442tj2bs7wKWWmx9PillelSIkeuyKZbJ8?= =?utf-8?q?ZhwVgxiUFInoA2kDOHAgG6RCbhTGue3ncgh14sAvdGxp3ZM1J0bc2qdf1tklvaZ+d?= =?utf-8?q?M2O8KvTmvjhdWU4YxXtThMrFisSyk1YIY0IkCKOUvUKFdGBn5ptHJYL9pWPOxxYQs?= =?utf-8?q?kCTJA8vNT0jyubgaHuZdHCXDMIgJR5ro3ZYy9OlNdyI4SApLVzULdBSo/X8jsJdlI?= =?utf-8?q?1cslHyOBc4oOFifeYUUsStpBXQAsPng0dCO3zrwIvEl2s969kuY7jxlx0xV92R+YD?= =?utf-8?q?fEPtO80PHObgtXG2Hh7GMVNZTECEYbt8lL6qHXt258DQ8OOthwBNDFBEOSRIKEEJH?= =?utf-8?q?uMmFPsuvn/0RkI/lSdXZ7hxsJhQUwSPp3yYhkaA1LpqPcMOSPx2yjy5iI/jm1rrc1?= =?utf-8?q?E8Uq3WmZL6t230KCz8+xIws+TrydPnlKc+b1/0t3sv5KoFyFuw3d2DiB+/n4/akfR?= =?utf-8?q?BI6j0PKdkJzr5aIOJtAWcDf9PYIr/FgdVdvWpyr+SdjD82KE1mTXzaG7elAqPZVce?= =?utf-8?q?XSzYFTJ/tDZk6l+LZ/rgHQ0jS8b5Q95KPNOtwHV9y3HQiav3YFg7kPUvwn+uN+0Ur?= =?utf-8?q?A0BhgG7wNMYLiJO8tjSYCnazNVqK19QOGeWFfYraw0UugE/t8hEUtkeCu9i+lrcam?= =?utf-8?q?49JCXR1BLdYmgtYuQVt/kE38aP4Tzcn0i+dPyxYIwqGXNg9PIt7sRbIp49ytZxwxh?= =?utf-8?q?o2xtn8NAcHPeEJM4y08TbAe9hbEQyo7VWzDjtTVQibHk/eCnxolvyXnXfWh1IxlbT?= =?utf-8?q?P3my45HQy7Z+h8bvIIuU73RDcwTkOhPOis8YCfcirACJrswJy0PyxcVLrEAnIe99R?= =?utf-8?q?rOEtwvpGLuP3UPGTMvelfF/xq4rmKe18OyR9ZZvgfHK2DwaeM4J+p2ybqAEATPM0k?= =?utf-8?q?gjRM4g5oDKPxtYYoToVX+QDibqofLLM7pHF5vnvITYm0G+G7EDjI68cCagK4uMXHQ?= =?utf-8?q?8lF8VyCJHyeCAdTjEVhLXua7S/WFi7JixsRy0p4+cZbKAlDyef/a6L7qvPcUlqV+T?= =?utf-8?q?s/RlI7hJFya3OaxLI73qLPpBS6CqVxbbwCx9A1D+sW9sHL5H0due00ZeBsh4GyI24?= =?utf-8?q?TwoHDpDqKb3o25eV7X7/AeOo8h7S7NxseWi8w1nCrCdEDKgZH0R5eSMvz1FbdyLaN?= =?utf-8?q?4ckdv6F9qULgJIL+rUCm1IlqRX2+MUq8hbthx8UvNkQwnmy3xahTWuAhsl1K+3SvU?= =?utf-8?q?TeOCZID0bCqUMVdypBSKZjhNMONaEGTs2GyKCQB5STzZ9QuX6zXdb+50zlLkNw4we?= =?utf-8?q?R6YHfw0+pjemTAMoPW/sN4HG3+LAE2ZEffyvTBTdhQpU/FQBlTR2GYL6nmT2z1zLd?= =?utf-8?q?YoNdr96ma33gv7nKvbiJYb5aXYLswb/IgOdJfxq1m+kTBzIq1PR5v23kC6DZexODW?= =?utf-8?q?yyCvAokQYr7F79yUDft0qz78K64d+Ch2Mvs3YbqAhbtGtA9OoBzPNgm8b1SmMwkr/?= =?utf-8?q?lKR/ww8Z7KP0Vbi4tgJVKK47JIuhcN1HLA=3D=3D?= X-OriginatorOrg: wolfvision.net X-MS-Exchange-CrossTenant-Network-Message-Id: c3af0130-8ea1-4106-8205-08dac6dc43fc X-MS-Exchange-CrossTenant-AuthSource: VI1PR08MB4544.eurprd08.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 15 Nov 2022 07:37:36.3323 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: e94ec9da-9183-471e-83b3-51baa8eb804f X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: 5tR4d29R+w+HOSID9VpahhKL4H1Uheb/PGcrZJmBC12D7lIUD3n1GyWE14VSgdZAE3NcrFwWXSTQ63r6O9bKoGAsikxGfxEIgjxzAaIjm5w= X-MS-Exchange-Transport-CrossTenantHeadersStamped: AS2PR08MB9572 Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org Add bindings documentation file for TI TMAG5273. Signed-off-by: Gerald Loacker --- .../iio/magnetometer/ti,tmag5273.yaml | 72 +++++++++++++++++++ MAINTAINERS | 6 ++ 2 files changed, 78 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/magnetometer/ti,tmag5273.yaml diff --git a/Documentation/devicetree/bindings/iio/magnetometer/ti,tmag5273.yaml b/Documentation/devicetree/bindings/iio/magnetometer/ti,tmag5273.yaml new file mode 100644 index 000000000000..2f5b0a4d2f40 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/magnetometer/ti,tmag5273.yaml @@ -0,0 +1,72 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/magnetometer/ti,tmag5273.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: TI TMAG5273 Low-Power Linear 3D Hall-Effect Sensor + +maintainers: + - Gerald Loacker + +description: + The TI TMAG5273 is a low-power linear 3D Hall-effect sensor. This device + integrates three independent Hall-effect sensors in the X, Y, and Z axes. + The device has an integrated temperature sensor available. The TMAG5273 + can be configured through the I2C interface to enable any combination of + magnetic axes and temperature measurements. An integrated angle calculation + engine (CORDIC) provides full 360° angular position information for both + on-axis and off-axis angle measurement topologies. The angle calculation is + performed using two user-selected magnetic axes. + +properties: + $nodename: + pattern: '^magnetometer@[0-9a-f]+$' + + compatible: + const: ti,tmag5273 + + reg: + maxItems: 1 + + "#io-channel-cells": + const: 1 + + ti,angle-enable: + description: + Enables angle measurement in the selected plane. + 0 = OFF + 1 = X-Y (default) + 2 = Y-Z + 3 = X-Z + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 3 + + vcc-supply: + description: + A regulator providing 1.7 V to 3.6 V supply voltage on the VCC pin, + typically 3.3 V. + +required: + - compatible + - reg + - vcc-supply + +additionalProperties: false + +examples: + - | + i2c-0 { + #address-cells = <1>; + #size-cells = <0>; + + magnetometer@35 { + compatible = "ti,tmag5273"; + reg = <0x35>; + #io-channel-cells = <1>; + ti,angle-enable = <3>; + vcc-supply = <&vcc3v3>; + }; + }; +... diff --git a/MAINTAINERS b/MAINTAINERS index cf0f18502372..ea7acec52f8b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -20613,6 +20613,12 @@ L: alsa-devel@alsa-project.org (moderated for non-subscribers) S: Odd Fixes F: sound/soc/codecs/tas571x* +TI TMAG5273 MAGNETOMETER DRIVER +M: Gerald Loacker +L: linux-iio@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/iio/magnetometer/ti,tmag5273.yaml + TI TRF7970A NFC DRIVER M: Mark Greer L: linux-wireless@vger.kernel.org From patchwork Tue Nov 15 07:37:18 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gerald Loacker X-Patchwork-Id: 13043298 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6F3FAC4167B for ; Tue, 15 Nov 2022 07:37:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232475AbiKOHho (ORCPT ); Tue, 15 Nov 2022 02:37:44 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51910 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231501AbiKOHhm (ORCPT ); Tue, 15 Nov 2022 02:37:42 -0500 Received: from EUR01-VE1-obe.outbound.protection.outlook.com (mail-eopbgr140049.outbound.protection.outlook.com [40.107.14.49]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1E476209B1; Mon, 14 Nov 2022 23:37:40 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=THAfdgfv9JfEt3ftVbfymylgna8vMkWxriqldG1nwxPlMwXtS35aYSMFV/YfPZFMd44IUOVMnfWuQ8hYuqsC8ia0WOTeZLHL+OQlNR1eK+0j/lmsf5swCdTsegFzS6FAoUYqFa76gG1Z41+U0i7+sDB3xRePCrl455X1c3NWmQ5cWmY/arukcNEvOXa9x6nVkIWsMc3D5wtJmh1n/b5ST8pkMW7hR1UOshN8n+EVoe2Htp0rBVnXtpZPfG55zpVH2q/ILy1OjbvhJszIsbKvGtEO6t++gYfyXYVQTpNKFaJbfRWFAXq7WqbpUyaE0f2pjJCJGJHs+UGo3m/fj60yPQ== 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-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=hLXFf/8BGPone5aUboXz5O+mbjujruOKb3Pz+GfZalo=; b=agzKjai/jg5g7Rmr9P049aFyQYK+5Y5KR6jkD0OyOiJTkqq3J33uwYH6w5EwSkyY7W0KwrjID5bAxvfyG+nPYp+zwmHvmu/kXJ7+Il0i3/wRDl3ScKRlpgpYW6GTGXKsnSVDZeBU322QRigmLpX5y6iJaasDqnikRRyjbhsoPh4k8NgjvZLD5oWcNzFX1KE6tpuXBNdRAlzeHdtnhc2uAAYy7K69T73mroB6E0tpDWiKqP+LVgXhDRaorFIe4TwWdD3dljCzKHAlZ+Xk78ghWRRzrMptAvTYsrWzKATrcWx/vs2KRJGrT0Oz7+087iv4R5wQD2EhhnDfXzhuGH9a8w== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=wolfvision.net; dmarc=pass action=none header.from=wolfvision.net; dkim=pass header.d=wolfvision.net; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=wolfvision.net; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=hLXFf/8BGPone5aUboXz5O+mbjujruOKb3Pz+GfZalo=; b=IUpCB59O/8cAaS9X2PTp+k1h9HMiXzGgFKDfFd9Y3UCNl+yh9PAXP9GTGGw4ez9pUcHwie0AgWIORVyklurBcQrp8ma0szf5I6OEoALYtIEGSbZiw15/E1EHuc5rySbjYM/tkdGaHzLs7XKrDAyQ+9+OwDVoE0GcFMgfDihGvYE= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=wolfvision.net; Received: from VI1PR08MB4544.eurprd08.prod.outlook.com (2603:10a6:803:100::13) by AS2PR08MB9572.eurprd08.prod.outlook.com (2603:10a6:20b:608::8) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5834.7; Tue, 15 Nov 2022 07:37:37 +0000 Received: from VI1PR08MB4544.eurprd08.prod.outlook.com ([fe80::bcc7:bc51:bf44:1454]) by VI1PR08MB4544.eurprd08.prod.outlook.com ([fe80::bcc7:bc51:bf44:1454%6]) with mapi id 15.20.5834.006; Tue, 15 Nov 2022 07:37:37 +0000 From: Gerald Loacker To: linux-iio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Jonathan Cameron , Lars-Peter Clausen , Rob Herring , Krzysztof Kozlowski , Andy Shevchenko , Nikita Yushchenko , Jakob Hauser , Michael Riesch , Gerald Loacker Subject: [PATCH 2/2] iio: magnetometer: add ti tmag5273 driver Date: Tue, 15 Nov 2022 08:37:18 +0100 Message-Id: <20221115073718.2377311-3-gerald.loacker@wolfvision.net> X-Mailer: git-send-email 2.37.2 In-Reply-To: <20221115073718.2377311-1-gerald.loacker@wolfvision.net> References: <20221115073718.2377311-1-gerald.loacker@wolfvision.net> X-ClientProxiedBy: VE1PR08CA0017.eurprd08.prod.outlook.com (2603:10a6:803:104::30) To VI1PR08MB4544.eurprd08.prod.outlook.com (2603:10a6:803:100::13) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: VI1PR08MB4544:EE_|AS2PR08MB9572:EE_ X-MS-Office365-Filtering-Correlation-Id: 1f67ba72-dd1f-45d5-c622-08dac6dc44a5 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: zxlrSQqcdSN7WhY9pHgBuJiCyonARLedAG1gumayZWZMKlpahPCedRQEQniLp3OBOsc24K94+a92PFV4Xbl8dwYJiZfbldSOA3LZoInTUlu/CAFhVS39Jj40kw5qK3ucgZfhlLt2xD2Qgza7p+CaKyvdisKb/wXUwGT4AU8huzPtm6iW38o4On+idi70rElCU31M3N9c8LpIUIKx9m/dPeAvjIsQXCjhZzGQe+mZwGlOtKaFO6EYqwaeE83t1z7Pvsa8vtK8aXlwiR9KffmdF3ow2cQx1G4mdJZXg1EZI4APQ4GPcMAKsanD1tR0uFP52ooajOG9cOCJRQHSik4HSy2YLdsWp2UGAd16TFWPscTwLiwXUzzrQRLWFnssYfd1xmIe40VEXKwS1hsOqONpf51sXXkQ2wCmEi1orsZxfocjRcmC6HEVp1C+ybdnSfJ01oKXebBHMcYyv1O09IioZ7Hsrs2uwhLQ64txlXUgkgBKRRnvZyT7k4yw71rB0DgPqyrZuHFWm9+tzZhwLU5QgTNn1tiYNV3jp7WxXzJziktNa4eSA5uFu9y36LiAHTc5gE3qiv/GiJg8P/TOnKhxTwW2frCRNC4jEOBa3P7cp4H7dLBc5stfEPuaIuaT+lMiOjh15t7NHfN4YNomAIaz53j+uOf+I20ENWGrJeduUHDDCFE9ZwZNGN0LlOIqEzb6ovLixCIUm52/t0sAUJ51eyAPwy3+6fXEAn9Ym46wnjj5EHncBw8Z1AJu6s0QLdQrRxG8VdnYpagQZp1H6BUoOrDxi7nw3y8Q844fH9J8Ob8= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:VI1PR08MB4544.eurprd08.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230022)(4636009)(396003)(366004)(136003)(346002)(39850400004)(376002)(451199015)(186003)(107886003)(86362001)(41300700001)(2616005)(26005)(83380400001)(6512007)(6666004)(6506007)(38100700002)(4326008)(8676002)(1076003)(54906003)(38350700002)(66556008)(66476007)(2906002)(5660300002)(36756003)(66946007)(966005)(6486002)(7416002)(316002)(8936002)(52116002)(478600001)(44832011)(30864003);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: qmbXmq23Zayk0YcZLoUD2fMCa2rFzOokv9TaqR5CRJm1OGGyo1UyOicCab3xhhLycs4lLlGIEiZmEDeVeCF/GwbyQiDI7RWep7WkDgL/UNaJ6vJLE0wwekmWHzRu1pYKw3Xf/hzwKSlFrPfDn+zViiCTLgAmXGRkcrNTKVJHSTA0Qb5IFWnqi9CDZ96zyunvFJLIN+FZkxmUcq68p/Hn1gtACrnDfB1VoGn9xPVlCKRKEkFSqDokXAZCgSOfy44NKrU7VlV/IeA3Tq6yXIPYLCnus3GeKb0B/fEvQGFXelzNRpyPdofACJjq0c3CNFBme1knLefRBUaa3J2ATXJ3TRzsCM2z3y4cQCoCYUU2WGU/scTv2FrVfM4ImoAFczEwfv+bEtZwuknSuOJPXfZoB5+zLNywYZDNFZMTm5PTcdLvwZlzs8UuaYi1NBdU0lEjSj2HzWUshCvHdkGemgkXk4TbuuL58QDuaf5BomPJg+OWXRg+zlBpRI/xn3Q1yBoUjQ5iTHgSAuTqMPZCtGyZUvt0cFGr8YHuolGEo2WyJV3Nj6EytW25FdyprAJVHYsKmtCvsqj9B73ejg/xhzbHlELkK6oHZU0xW/bg7q+nTrLSGyycIjs8cYcxUX8VhcxGxyQwqyA/QdX7OI2Iw8yaXppoZ0BVmcr1ER6bqk0BHU/K7agJeSbqz3GwP51ExfMidxlN2T0AKbTzdYVb9b4EbKHU/BMdDnivpsPFKQjn+Rddcw4tklsPlbLCLFW3Z0dr6U0OFCIaAMw+e3GvsKTjNbAbFnWLPWxCZwN7NKn5O2BRMcxR/mgDgufoijsQel+w80wemb85gO5JkXaeoSsfOBIDPhvoLQ1LbqgI02yncPbaCfK1fQKQCxLUV10fU+0m6uzhd7gmjSZFeit2qBw3KAtKKoKxMD3okEKOxDVdjXi/u5jiwnXDom8Y0WEb6J3AycaZIFA8nKsLjfW9BulnqNREyV+uTQZJ5fTciauZYtwu52KjpSnm6oFYzixSdhFfQg09MplH2IHN/uxW7S6fmpGiTHF3z31hEd5sBU4LtNpKNSo/Uas0H9pDNZNaVMXM4cSbgZrpkXsNKu51h0qge52vCIZFFu6vLMREc9uHC2YRKlqvADPvPGi6zLpthIZhv8cCDFyfcf5UDDfawLLBDfuDvTIRNtFDO9Xj+ZEs18VtSE8j+SKgGUXYkEPcbDAy8rEmoeAMDAEXWd0bPoU9n8PWQIFPgIyYEcU++PwIyiWfTIFSY2UcjNq83CJSxotyqfWTePkU3NlmgcatrBY5cQgdNwVD8ehTJ+UnclyNcAsrpqlWZP//GbJ4R0bdktSzdx3pyuehL0QSrrJ6ezPh6ARZWbThJBS0imDdRs/WAm/eTDSiIGP7bW0YcEVowYgFzrE0btnysHJ0jllqKnuNDYrTBAoS5+xyxjPhEV5zaibUzVFiC0o2d8l5hJ1GmE4I6boUacMcumpz1X4BJZ6oOiguyfu9WdraCLyMF4R3m6iNOzU6GahKc76/QSM2GsAIjEbkFTzZxdK9OQuOGab2QzqPrMQyPWTUNs45T1NZMwnnqso9bVCYVxnSK24nSp2hjvrme4cl6OjgQEjRMAx0eA== X-OriginatorOrg: wolfvision.net X-MS-Exchange-CrossTenant-Network-Message-Id: 1f67ba72-dd1f-45d5-c622-08dac6dc44a5 X-MS-Exchange-CrossTenant-AuthSource: VI1PR08MB4544.eurprd08.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 15 Nov 2022 07:37:37.4572 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: e94ec9da-9183-471e-83b3-51baa8eb804f X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: 2lpKjZVRfemm8BzxL3PhxiRifwGewVwY+KBicnw4t/S5pLSma3P00zb10Rm4rP3Ku/Et8yaEUDVBIAYt0Kr+sdizurxzcBj/tj4lNp+y29c= X-MS-Exchange-Transport-CrossTenantHeadersStamped: AS2PR08MB9572 Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org Add support for TI TMAG5273 Low-Power Linear 3D Hall-Effect Sensor. Additionally to temperature and magnetic X, Y and Z-axes the angle and magnitude are reported. The sensor is operating in continuous measurement mode and changes to sleep mode if not used for 5 seconds. Datasheet: https://www.ti.com/lit/gpn/tmag5273 Signed-off-by: Gerald Loacker --- MAINTAINERS | 1 + drivers/iio/magnetometer/Kconfig | 12 + drivers/iio/magnetometer/Makefile | 2 + drivers/iio/magnetometer/tmag5273.c | 809 ++++++++++++++++++++++++++++ 4 files changed, 824 insertions(+) create mode 100644 drivers/iio/magnetometer/tmag5273.c diff --git a/MAINTAINERS b/MAINTAINERS index ea7acec52f8b..9d20b5780051 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -20618,6 +20618,7 @@ M: Gerald Loacker L: linux-iio@vger.kernel.org S: Maintained F: Documentation/devicetree/bindings/iio/magnetometer/ti,tmag5273.yaml +F: drivers/iio/magnetometer/tmag5273.c TI TRF7970A NFC DRIVER M: Mark Greer diff --git a/drivers/iio/magnetometer/Kconfig b/drivers/iio/magnetometer/Kconfig index b91fc5e6a26e..467819335588 100644 --- a/drivers/iio/magnetometer/Kconfig +++ b/drivers/iio/magnetometer/Kconfig @@ -208,6 +208,18 @@ config SENSORS_RM3100_SPI To compile this driver as a module, choose M here: the module will be called rm3100-spi. +config TI_TMAG5273 + tristate "TI TMAG5273 Low-Power Linear 3D Hall-Effect Sensor" + depends on I2C + select REGMAP_I2C + help + Say Y here to add support for the TI TMAG5273 Low-Power + Linear 3D Hall-Effect Sensor. + + This driver can also be compiled as a module. + To compile this driver as a module, choose M here: the module + will be called tmag5273. + config YAMAHA_YAS530 tristate "Yamaha YAS530 family of 3-Axis Magnetometers (I2C)" depends on I2C diff --git a/drivers/iio/magnetometer/Makefile b/drivers/iio/magnetometer/Makefile index b9f45b7fafc3..b1c784ea71c8 100644 --- a/drivers/iio/magnetometer/Makefile +++ b/drivers/iio/magnetometer/Makefile @@ -29,4 +29,6 @@ obj-$(CONFIG_SENSORS_RM3100) += rm3100-core.o obj-$(CONFIG_SENSORS_RM3100_I2C) += rm3100-i2c.o obj-$(CONFIG_SENSORS_RM3100_SPI) += rm3100-spi.o +obj-$(CONFIG_TI_TMAG5273) += tmag5273.o + obj-$(CONFIG_YAMAHA_YAS530) += yamaha-yas530.o diff --git a/drivers/iio/magnetometer/tmag5273.c b/drivers/iio/magnetometer/tmag5273.c new file mode 100644 index 000000000000..549ed1ddba61 --- /dev/null +++ b/drivers/iio/magnetometer/tmag5273.c @@ -0,0 +1,809 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Driver for the TI TMAG5273 Low-Power Linear 3D Hall-Effect Sensor + * + * Copyright (C) 2022 WolfVision GmbH + * + * Author: Gerald Loacker + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#define TMAG5273_DEVICE_CONFIG_1 0x00 +#define TMAG5273_DEVICE_CONFIG_2 0x01 +#define TMAG5273_SENSOR_CONFIG_1 0x02 +#define TMAG5273_SENSOR_CONFIG_2 0x03 +#define TMAG5273_X_THR_CONFIG 0x04 +#define TMAG5273_Y_THR_CONFIG 0x05 +#define TMAG5273_Z_THR_CONFIG 0x06 +#define TMAG5273_T_CONFIG 0x07 +#define TMAG5273_INT_CONFIG_1 0x08 +#define TMAG5273_MAG_GAIN_CONFIG 0x09 +#define TMAG5273_MAG_OFFSET_CONFIG_1 0x0A +#define TMAG5273_MAG_OFFSET_CONFIG_2 0x0B +#define TMAG5273_I2C_ADDRESS 0x0C +#define TMAG5273_DEVICE_ID 0x0D +#define TMAG5273_MANUFACTURER_ID_LSB 0x0E +#define TMAG5273_MANUFACTURER_ID_MSB 0x0F +#define TMAG5273_T_MSB_RESULT 0x10 +#define TMAG5273_T_LSB_RESULT 0x11 +#define TMAG5273_X_MSB_RESULT 0x12 +#define TMAG5273_X_LSB_RESULT 0x13 +#define TMAG5273_Y_MSB_RESULT 0x14 +#define TMAG5273_Y_LSB_RESULT 0x15 +#define TMAG5273_Z_MSB_RESULT 0x16 +#define TMAG5273_Z_LSB_RESULT 0x17 +#define TMAG5273_CONV_STATUS 0x18 +#define TMAG5273_ANGLE_RESULT_MSB 0x19 +#define TMAG5273_ANGLE_RESULT_LSB 0x1A +#define TMAG5273_MAGNITUDE_RESULT 0x1B +#define TMAG5273_DEVICE_STATUS 0x1C + +#define TMAG5273_MANUFACTURER_ID 0x5449 + +#define TMAG5273_AUTOSLEEP_DELAY 5000 + +/* Bits in the TMAG5273_DEVICE_CONFIG_1 register */ +#define TMAG5273_AVG_MODE_MASK GENMASK(4, 2) +#define TMAG5273_AVG_1_MODE FIELD_PREP(TMAG5273_AVG_MODE_MASK, 0) +#define TMAG5273_AVG_2_MODE FIELD_PREP(TMAG5273_AVG_MODE_MASK, 1) +#define TMAG5273_AVG_4_MODE FIELD_PREP(TMAG5273_AVG_MODE_MASK, 2) +#define TMAG5273_AVG_8_MODE FIELD_PREP(TMAG5273_AVG_MODE_MASK, 3) +#define TMAG5273_AVG_16_MODE FIELD_PREP(TMAG5273_AVG_MODE_MASK, 4) +#define TMAG5273_AVG_32_MODE FIELD_PREP(TMAG5273_AVG_MODE_MASK, 5) + +/* bits in the TMAG5273_DEVICE_CONFIG_2 register */ +#define TMAG5273_OP_MODE_MASK GENMASK(1, 0) +#define TMAG5273_OP_MODE_STANDBY FIELD_PREP(TMAG5273_OP_MODE_MASK, 0) +#define TMAG5273_OP_MODE_SLEEP FIELD_PREP(TMAG5273_OP_MODE_MASK, 1) +#define TMAG5273_OP_MODE_CONT FIELD_PREP(TMAG5273_OP_MODE_MASK, 2) +#define TMAG5273_OP_MODE_WAKEUP FIELD_PREP(TMAG5273_OP_MODE_MASK, 3) + +/* bits in the TMAG5273_SENSOR_CONFIG_1 register */ +#define TMAG5273_MAG_CH_EN_MASK GENMASK(7, 4) +#define TMAG5273_MAG_CH_EN_X_Y_Z 0x07 + +/* bits in the TMAG5273_SENSOR_CONFIG_2 register */ +#define TMAG5273_Z_RANGE_MASK BIT(0) +#define TMAG5273_X_Y_RANGE_MASK BIT(1) +#define TMAG5273_ANGLE_EN_MASK GENMASK(3, 2) +#define TMAG5273_ANGLE_EN_X_Y 1 +#define TMAG5273_ANGLE_EN_Y_Z 2 +#define TMAG5273_ANGLE_EN_X_Z 3 + +/* bits in the TMAG5273_T_CONFIG register */ +#define TMAG5273_T_CH_EN BIT(0) + +/* bits in the TMAG5273_DEVICE_ID register */ +#define TMAG5273_VERSION_MASK GENMASK(1, 0) + +/* bits in the TMAG5273_CONV_STATUS register */ +#define TMAG5273_CONV_STATUS_COMPLETE BIT(0) + +/* state container for the TMAG5273 driver */ +struct tmag5273_data { + struct device *dev; + unsigned int devid; + unsigned int version; + char name[16]; + int conv_avg; + int max_avg; + int range; + u32 angle_en; + struct regmap *map; + struct regulator *vcc; + /* Locks the sensor for exclusive use during a measurement (which + * involves several register transactions so the regmap lock is not + * enough) so that measurements get serialized in a first-come-first- + * serve manner. + */ + struct mutex lock; +}; + +static const struct { + int avg; + u8 reg_val; +} tmag5273_avg_table[] = { + { 1, 0x00 }, { 2, 0x01 }, { 4, 0x02 }, + { 8, 0x03 }, { 16, 0x04 }, { 32, 0x05 }, +}; + +/* + * magnetic range in mT for different TMAG5273 versions + * only version 1 and 2 are valid, version 0 and 3 are reserved + */ +static const struct { + int range; + u8 reg_val; +} tmag5273_range_table[4][2] = { + { { 0, 0 }, { 0, 3 } }, + { { 40, 0 }, { 80, 3 } }, + { { 133, 0 }, { 266, 3 } }, + { { 0, 0 }, { 0, 3 } }, +}; + +/* + * tmag5273_measure() - Make a measure from the hardware + * @tmag5273: The device state + * @t: the processed temperature measurement + * @x: the raw x axis measurement + * @y: the raw x axis measurement + * @z: the raw x axis measurement + * @angle: the calculated angle + * @magnitude: the calculated magnitude + * @return: 0 on success or error code + */ +static int tmag5273_measure(struct tmag5273_data *data, u16 *t, u16 *x, u16 *y, + u16 *z, u16 *angle, u16 *magnitude) +{ + unsigned int status; + u8 reg_data[12]; + int ret; + u16 val; + + mutex_lock(&data->lock); + ret = regmap_read(data->map, TMAG5273_CONV_STATUS, &status); + if (ret < 0) + goto out_unlock; + + /* + * Conversion time is 2425 us in 32x averaging mode for all three + * channels. Since we are in continuous measurement mode, a measurement + * may already be there, so poll for completed measurement with + * timeout. + */ + ret = regmap_read_poll_timeout(data->map, TMAG5273_CONV_STATUS, status, + status & TMAG5273_CONV_STATUS_COMPLETE, + 100, 10000); + if (ret) { + dev_err_probe(data->dev, ret, "timeout waiting for measurement\n"); + goto out_unlock; + } + + ret = regmap_bulk_read(data->map, TMAG5273_T_MSB_RESULT, reg_data, + sizeof(reg_data)); + if (ret) + goto out_unlock; + + ret = regmap_read(data->map, TMAG5273_CONV_STATUS, &status); + if (ret < 0) + goto out_unlock; + + mutex_unlock(&data->lock); + + *t = get_unaligned_be16(®_data[0]); + *x = get_unaligned_be16(®_data[2]); + *y = get_unaligned_be16(®_data[4]); + *z = get_unaligned_be16(®_data[6]); + /* + * angle has 9 bits integer value and 4 bits fractional part + * 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 + * 0 0 0 a a a a a a a a a f f f f + */ + val = get_unaligned_be16(®_data[9]); + *angle = FIELD_GET(GENMASK(12, 0), val); + *magnitude = reg_data[11]; + return ret; + +out_unlock: + mutex_unlock(&data->lock); + return ret; +} + +/* + * tmag5273_get_measure() - Measure a sample of all axis and process + * @tmag5273: The device state + * @to: Temperature out + * @xo: X axis out + * @yo: Y axis out + * @zo: Z axis out + * @ao: Angle out + * @mo: Magnitude out + * @return: 0 on success or error code + */ +static int tmag5273_get_measure(struct tmag5273_data *data, s32 *to, s32 *xo, + s32 *yo, s32 *zo, u16 *ao, u16 *mo) +{ + u16 t, x, y, z, angle, magnitude; + int ret; + + ret = tmag5273_measure(data, &t, &x, &y, &z, &angle, &magnitude); + if (ret) + return ret; + + /* + * convert device specific value to millicelsius + * use multiply by 16639 and divide by 10000 to achieve divide by 60.1 + * and convert to millicelsius + */ + *to = (((s32)t - 17508) * 16639) / 1000 + 25000; + *xo = (s16)x; + *yo = (s16)y; + *zo = (s16)z; + *ao = angle; + *mo = magnitude; + return 0; +} + +static int tmag5273_read_raw(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, int *val, + int *val2, long mask) +{ + struct tmag5273_data *data = iio_priv(indio_dev); + s32 t, x, y, z; + u16 angle, magnitude; + int ret; + + switch (mask) { + case IIO_CHAN_INFO_PROCESSED: + case IIO_CHAN_INFO_RAW: + ret = pm_runtime_resume_and_get(data->dev); + if (ret < 0) + return ret; + ret = tmag5273_get_measure(data, &t, &x, &y, &z, &angle, + &magnitude); + if (ret) + return ret; + pm_runtime_mark_last_busy(data->dev); + pm_runtime_put_autosuspend(data->dev); + switch (chan->scan_index) { + case 0: + *val = t; + break; + case 1: + *val = x; + break; + case 2: + *val = y; + break; + case 3: + *val = z; + break; + case 4: + *val = angle; + break; + case 5: + *val = magnitude; + break; + default: + return dev_err_probe(data->dev, -EINVAL, "unknown channel\n"); + } + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_TEMP: + /* 1 LSB = 1 millidegree Celsius */ + *val = 1; + return IIO_VAL_INT; + case IIO_MAGN: + /* + * The axis values are in stored in 2^15 / range LSB/mT. + * Since 1 mT = 10 Gauss, we need to multiply by 10 and + * divide by [range] to get Gauss from the raw value. + */ + *val = data->range * 10; + *val2 = 32768; + return IIO_VAL_FRACTIONAL; + case IIO_ANGL: + /* + * Angle is in degrees and has four fractional bits, + * therefore use 1/16 * pi/180 to convert to radiants. + */ + *val = 1000; + *val2 = 916732; + return IIO_VAL_FRACTIONAL; + case IIO_DISTANCE: + /* Magnitude is unscaled */ + *val = 1; + return IIO_VAL_INT; + default: + return -EINVAL; + } + default: + /* Unknown request */ + return -EINVAL; + } +} + +static ssize_t tmag5273_show_conv_avg(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct tmag5273_data *data = iio_priv(indio_dev); + + return sprintf(buf, "%d\n", data->conv_avg); +} + +static ssize_t tmag5273_write_conv_avg(struct tmag5273_data *data, + unsigned int val) +{ + int ret; + int i; + + for (i = 0; i < ARRAY_SIZE(tmag5273_avg_table); i++) { + if (tmag5273_avg_table[i].avg == val) + break; + } + + if (i == ARRAY_SIZE(tmag5273_avg_table)) + return -EINVAL; + + ret = regmap_update_bits(data->map, TMAG5273_DEVICE_CONFIG_1, + TMAG5273_AVG_MODE_MASK, + tmag5273_avg_table[i].reg_val); + if (ret) + return ret; + + data->conv_avg = val; + + return 0; +} + +static ssize_t tmag5273_store_conv_avg(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct tmag5273_data *data = iio_priv(indio_dev); + int ret; + int integer; + + ret = kstrtoint(buf, 0, &integer); + if (ret) + return ret; + + ret = tmag5273_write_conv_avg(data, integer); + if (ret < 0) + return ret; + + return len; +} + +static IIO_DEVICE_ATTR(conv_avg, 0644, tmag5273_show_conv_avg, + tmag5273_store_conv_avg, 0); + +static ssize_t tmag5273_conv_avg_available(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct tmag5273_data *data = iio_priv(indio_dev); + ssize_t len = 0; + int i; + + for (i = 0; i < ARRAY_SIZE(tmag5273_avg_table); i++) { + if (tmag5273_avg_table[i].avg > data->max_avg) + break; + len += scnprintf(buf + len, PAGE_SIZE - len, "%d ", + tmag5273_avg_table[i].avg); + } + /* replace last space with a newline */ + if (len > 0) + buf[len - 1] = '\n'; + + return len; +} + +static IIO_DEVICE_ATTR(conv_avg_available, 0444, tmag5273_conv_avg_available, + NULL, 0); + +static ssize_t tmag5273_show_range(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct tmag5273_data *data = iio_priv(indio_dev); + + return sprintf(buf, "%d\n", data->range); +} + +static ssize_t tmag5273_write_range(struct tmag5273_data *data, + unsigned int val) +{ + int i, ret; + + for (i = 0; i < ARRAY_SIZE(tmag5273_range_table[0]); i++) { + if (tmag5273_range_table[data->version][i].range == val) + break; + } + + if (i == ARRAY_SIZE(tmag5273_range_table[0])) + return -EINVAL; + + ret = regmap_update_bits(data->map, + TMAG5273_SENSOR_CONFIG_2, + TMAG5273_Z_RANGE_MASK | TMAG5273_X_Y_RANGE_MASK, + tmag5273_range_table[data->version][i].reg_val); + if (ret) + return ret; + + data->range = val; + + return 0; +} + +static ssize_t tmag5273_store_range(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct tmag5273_data *data = iio_priv(indio_dev); + int range, ret; + + ret = kstrtoint(buf, 0, &range); + if (ret) + return ret; + + ret = tmag5273_write_range(data, range); + if (ret < 0) + return ret; + + return len; +} + +static IIO_DEVICE_ATTR(range, 0644, tmag5273_show_range, + tmag5273_store_range, 0); + +static ssize_t tmag5273_range_available(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct tmag5273_data *data = iio_priv(indio_dev); + ssize_t len = 0; + int i; + + for (i = 0; i < ARRAY_SIZE(tmag5273_range_table[0]); i++) { + len += scnprintf(buf + len, PAGE_SIZE - len, "%d ", + tmag5273_range_table[data->version][i].range); + } + /* replace last space with a newline */ + if (len > 0) + buf[len - 1] = '\n'; + + return len; +} + +static IIO_DEVICE_ATTR(range_available, 0444, tmag5273_range_available, NULL, + 0); + +static struct attribute *tmag5273_attributes[] = { + &iio_dev_attr_conv_avg.dev_attr.attr, + &iio_dev_attr_conv_avg_available.dev_attr.attr, + &iio_dev_attr_range.dev_attr.attr, + &iio_dev_attr_range_available.dev_attr.attr, + NULL, +}; + +static const struct attribute_group tmag5273_attrs_group = { + .attrs = tmag5273_attributes, +}; + +#define TMAG5273_AXIS_CHANNEL(axis, index) \ + { \ + .type = IIO_MAGN, \ + .modified = 1, \ + .channel2 = IIO_MOD_##axis, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_SCALE), \ + .scan_index = index, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 32, \ + .storagebits = 32, \ + .endianness = IIO_CPU, \ + }, \ + } + +static const struct iio_chan_spec tmag5273_channels[] = { + { + .type = IIO_TEMP, + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), + .scan_index = 0, + .scan_type = { + .sign = 's', + .realbits = 32, + .storagebits = 32, + .endianness = IIO_CPU, + }, + }, + TMAG5273_AXIS_CHANNEL(X, 1), + TMAG5273_AXIS_CHANNEL(Y, 2), + TMAG5273_AXIS_CHANNEL(Z, 3), + { + .type = IIO_ANGL, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), + .scan_index = 4, + .scan_type = { + .sign = 'u', + .realbits = 16, + .storagebits = 16, + .endianness = IIO_CPU, + }, + }, + { + .type = IIO_DISTANCE, + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), + .scan_index = 5, + .scan_type = { + .sign = 'u', + .realbits = 16, + .storagebits = 16, + .endianness = IIO_CPU, + }, + }, + IIO_CHAN_SOFT_TIMESTAMP(6), +}; + +static const struct iio_info tmag5273_info = { + .attrs = &tmag5273_attrs_group, + .read_raw = &tmag5273_read_raw, +}; + +static bool tmag5273_volatile_reg(struct device *dev, unsigned int reg) +{ + return (reg >= TMAG5273_T_MSB_RESULT && + reg <= TMAG5273_MAGNITUDE_RESULT); +} + +static const struct regmap_config tmag5273_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = 0xff, + .volatile_reg = tmag5273_volatile_reg, +}; + +static int tmag5273_set_operating_mode(struct tmag5273_data *data, + unsigned int val) +{ + return regmap_write(data->map, TMAG5273_DEVICE_CONFIG_2, val); +} + +static int tmag5273_chip_init(struct tmag5273_data *data) +{ + int ret; + + ret = regmap_write(data->map, TMAG5273_DEVICE_CONFIG_1, + TMAG5273_AVG_32_MODE); + if (ret) + return ret; + data->conv_avg = 32; + ret = regmap_write(data->map, TMAG5273_DEVICE_CONFIG_2, + TMAG5273_OP_MODE_CONT); + if (ret) + return ret; + ret = regmap_write(data->map, TMAG5273_SENSOR_CONFIG_1, + FIELD_PREP(TMAG5273_MAG_CH_EN_MASK, + TMAG5273_MAG_CH_EN_X_Y_Z)); + if (ret) + return ret; + ret = regmap_write(data->map, TMAG5273_SENSOR_CONFIG_2, + FIELD_PREP(TMAG5273_ANGLE_EN_MASK, data->angle_en)); + if (ret) + return ret; + + data->range = tmag5273_range_table[data->version][0].range; + return regmap_write(data->map, TMAG5273_T_CONFIG, TMAG5273_T_CH_EN); +} + +static int tmag5273_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct iio_dev *indio_dev; + struct device *dev = &i2c->dev; + struct device_node *node = dev->of_node; + struct tmag5273_data *data; + int val, ret; + + indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); + if (!indio_dev) + return -ENOMEM; + + data = iio_priv(indio_dev); + i2c_set_clientdata(i2c, indio_dev); + data->dev = dev; + mutex_init(&data->lock); + + data->vcc = devm_regulator_get(dev, "vcc"); + if (IS_ERR(data->vcc)) + return dev_err_probe(dev, PTR_ERR(data->vcc), + "failed to get VCC regulator\n"); + + /* Operating voltage 1.7V .. 3.6V according to datasheet */ + ret = regulator_set_voltage(data->vcc, 1700000, 3600000); + if (ret) + return dev_err_probe(dev, ret, "failed to set VCC voltage\n"); + + ret = regulator_enable(data->vcc); + if (ret) + return dev_err_probe(dev, ret, + "failed to enable VCC regulator\n"); + + /* + * Regulators have to ramp up with 3V/ms, additional time to go to + * stand-by mode is 270us typically. We give 1 ms to 2 ms time. + */ + usleep_range(1000, 2000); + + data->map = devm_regmap_init_i2c(i2c, &tmag5273_regmap_config); + if (IS_ERR(data->map)) { + ret = PTR_ERR(data->map); + dev_err_probe(dev, ret, "failed to allocate register map\n"); + goto out_disable_vcc; + } + + ret = regmap_read(data->map, TMAG5273_DEVICE_ID, &val); + if (ret) { + /* + * If we come from sleep with power already activated, the + * first I2C command wakes up the chip but will fail. + * Time to go to stand-by mode from sleep mode is 50us + * typically. During this time no I2C access is possible. + */ + usleep_range(80, 200); + + ret = regmap_read(data->map, TMAG5273_DEVICE_ID, &val); + if (ret) + goto out_disable_vcc; + } + data->version = FIELD_PREP(TMAG5273_VERSION_MASK, val); + + ret = regmap_bulk_read(data->map, TMAG5273_MANUFACTURER_ID_LSB, + &data->devid, 2); + if (ret) + goto out_disable_vcc; + + switch (data->devid) { + case TMAG5273_MANUFACTURER_ID: + strncpy(data->name, "TMAG5273", sizeof(data->name) - 2); + switch (data->version) { + case 1: + strncat(data->name, "x1", 2); + break; + case 2: + strncat(data->name, "x2", 2); + break; + default: + break; + } + dev_info(dev, "%s", data->name); + data->max_avg = 32; + break; + default: + ret = -ENODEV; + dev_err_probe(dev, ret, "unhandled device ID 0x%x\n", data->devid); + goto out_disable_vcc; + } + + /* + * Angle-enable is optional and set to 1 (enable X-Y plane) by default, + * the value is modified only if a valid u32 value can be decoded. + */ + data->angle_en = TMAG5273_ANGLE_EN_X_Y; + of_property_read_u32(node, "tmag5273,angle-enable", &data->angle_en); + + ret = tmag5273_chip_init(data); + if (ret) + goto out_disable_vcc; + + indio_dev->info = &tmag5273_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->name = data->name; + indio_dev->channels = tmag5273_channels; + indio_dev->num_channels = ARRAY_SIZE(tmag5273_channels); + + pm_runtime_set_autosuspend_delay(dev, TMAG5273_AUTOSLEEP_DELAY); + pm_runtime_use_autosuspend(dev); + pm_runtime_mark_last_busy(dev); + ret = pm_runtime_set_active(dev); + if (ret < 0) + goto out_disable_vcc; + pm_runtime_enable(dev); + pm_runtime_idle(dev); + + ret = iio_device_register(indio_dev); + if (ret) { + dev_err_probe(dev, ret, "device register failed\n"); + goto cleanup_runtime; + } + + return 0; + +cleanup_runtime: + pm_runtime_dont_use_autosuspend(dev); + pm_runtime_disable(dev); +out_disable_vcc: + tmag5273_set_operating_mode(data, TMAG5273_OP_MODE_SLEEP); + regulator_disable(data->vcc); + return ret; +} + +static void tmag5273_remove(struct i2c_client *i2c) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(i2c); + struct tmag5273_data *data = iio_priv(indio_dev); + struct device *dev = &i2c->dev; + + iio_device_unregister(indio_dev); + + pm_runtime_dont_use_autosuspend(dev); + pm_runtime_disable(dev); + pm_runtime_set_suspended(dev); + + tmag5273_set_operating_mode(data, TMAG5273_OP_MODE_SLEEP); + regulator_disable(data->vcc); +} + +static int tmag5273_runtime_suspend(struct device *dev) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct tmag5273_data *data = iio_priv(indio_dev); + + tmag5273_set_operating_mode(data, TMAG5273_OP_MODE_SLEEP); + + return 0; +} + +static int tmag5273_runtime_resume(struct device *dev) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct tmag5273_data *data = iio_priv(indio_dev); + int ret; + + ret = tmag5273_set_operating_mode(data, TMAG5273_OP_MODE_CONT); + if (ret) { + /* + * Time to go to stand-by mode from sleep mode is 50us + * typically. During this time no I2C access is possible. + */ + usleep_range(80, 200); + ret = tmag5273_set_operating_mode(data, TMAG5273_OP_MODE_CONT); + } + + return ret; +} + +static const struct dev_pm_ops tmag5273_pm_ops = { + SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) + RUNTIME_PM_OPS(tmag5273_runtime_suspend, tmag5273_runtime_resume, NULL) +}; + +static const struct i2c_device_id tmag5273_id[] = { + { + "tmag5273", + }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(i2c, tmag5273_id); + +static const struct of_device_id tmag5273_of_match[] = { + { + .compatible = "ti,tmag5273", + }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, tmag5273_of_match); + +static struct i2c_driver tmag5273_driver = { + .driver = { + .name = "tmag5273", + .of_match_table = tmag5273_of_match, + .pm = pm_ptr(&tmag5273_pm_ops), + }, + .probe = tmag5273_probe, + .remove = tmag5273_remove, + .id_table = tmag5273_id, +}; +module_i2c_driver(tmag5273_driver); + +MODULE_DESCRIPTION("TI TMAG5273 Low-Power Linear 3D Hall-Effect Sensor driver"); +MODULE_AUTHOR("Gerald Loacker "); +MODULE_LICENSE("GPL");