From patchwork Mon Aug 10 21:30:52 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Sandeep Singh X-Patchwork-Id: 255122 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=-13.0 required=3.0 tests=BAYES_00,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 5D292C433DF for ; Mon, 10 Aug 2020 21:31:39 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 2032C206DA for ; Mon, 10 Aug 2020 21:31:39 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=amdcloud.onmicrosoft.com header.i=@amdcloud.onmicrosoft.com header.b="a3vCBPQ5" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726816AbgHJVbi (ORCPT ); Mon, 10 Aug 2020 17:31:38 -0400 Received: from mail-bn8nam08on2048.outbound.protection.outlook.com ([40.107.100.48]:25249 "EHLO NAM04-BN8-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1726809AbgHJVbh (ORCPT ); Mon, 10 Aug 2020 17:31:37 -0400 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=L3u5pOOtU6Kdx9djmxAeXfUhJK1Cwrll9PyBhhnrvW8cOmRyxXTBvkG/J+mGhymDJNF6unkiIGzFY+fhXLc3Zgzwad/wjMbwah+VKZK8ZVYpYIu724CO74wM6q1bR8zcGnGPMfILGAJrPn9scnTBrCIG19NxVjmCgz5y8B0RUVmMzr6OS62KQQNCyrDZGUqXvel5tvUYvVB+F7DV9e06lLDPh1NEz4tQHSHGiaM2tiU0I5f6kTB4/YmkR5zXf+Uld364FAhkZ8wE313mavMHv8kazWwMPmUXcIxhaiPaKKj6nrAewclahtzCX3HJG2dWrTywjbIDcKPZk3CGuBebhA== 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=yv8pEQqlT0Q9ZMr1zBBMj5HC+xnStEschhTKQ5f9mmY=; b=XJ1EkeWdOCKmihl9fhYO4qPsxpUdpNLxCb4vr1vRVSEhH2AiwFzgMp+4dKBrZOGDtpfgamKYY6ko0g21pJ00KJ1VmmWG52+UoBmZiglnyRJ5TvDSyuuw1dPohpBKLbNdVsLl2APepKxFSjXd/cAasIf5yh4Ncf6R0DQSVA5M6HjsQ4PLWqzAhS92ytmgTJ3Tq9rwH91qnw42MHrlXXPAmPII4O86WudcZ6GRqVE1ApXTbTajTuXWvoT6+yYpgyoQh1OwAcRk92fXo1NluhmPDdDFH+H2G2EEfe1pHngoqDv21iS/wDCX/fnoGEUtigvMbpWRV0Zx/4+BD3PNC8SNsg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=amd.com; dmarc=pass action=none header.from=amd.com; dkim=pass header.d=amd.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amdcloud.onmicrosoft.com; s=selector2-amdcloud-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=yv8pEQqlT0Q9ZMr1zBBMj5HC+xnStEschhTKQ5f9mmY=; b=a3vCBPQ50l+jCs5iYhiNzpQp66e0sQBUMhWSjriEZvdxlJi4W+LbEFDvLJ751YOL9JVh4hEkzh319j0X9p/4lkquCE/cGDtTeHgLy2fpkg3ZV5NOn4BGdJe0Vg3qwJvjQdU8d8v0TwQE5Rn3uyH5uTgNwXyK5ieRscxVaKvC8d0= Authentication-Results: kernel.org; dkim=none (message not signed) header.d=none; kernel.org; dmarc=none action=none header.from=amd.com; Received: from BYAPR12MB2726.namprd12.prod.outlook.com (2603:10b6:a03:66::17) by BY5PR12MB3714.namprd12.prod.outlook.com (2603:10b6:a03:1a9::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3261.22; Mon, 10 Aug 2020 21:31:32 +0000 Received: from BYAPR12MB2726.namprd12.prod.outlook.com ([fe80::8503:3713:6ed0:af09]) by BYAPR12MB2726.namprd12.prod.outlook.com ([fe80::8503:3713:6ed0:af09%6]) with mapi id 15.20.3261.024; Mon, 10 Aug 2020 21:31:32 +0000 From: Sandeep Singh To: jikos@kernel.org, benjamin.tissoires@redhat.com, linux-kernel@vger.kernel.org, linux-input@vger.kernel.org, srinivas.pandruvada@linux.intel.com, jic23@kernel.org, linux-iio@vger.kernel.org, hdegoede@redhat.com, Nehal-bakulchandra.Shah@amd.com, andy.shevchenko@gmail.com, mail@richard-neumann.de, m.felsch@pengutronix.de, rdunlap@infradead.org Cc: Shyam-sundar.S-k@amd.com, Sandeep Singh Subject: [PATCH v7 1/4] SFH: Add maintainers and documentation for AMD SFH based on HID framework Date: Mon, 10 Aug 2020 21:30:52 +0000 Message-Id: <20200810213055.103962-2-Sandeep.Singh@amd.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200810213055.103962-1-Sandeep.Singh@amd.com> References: <20200810213055.103962-1-Sandeep.Singh@amd.com> X-ClientProxiedBy: MA1PR0101CA0025.INDPRD01.PROD.OUTLOOK.COM (2603:1096:a00:22::11) To BYAPR12MB2726.namprd12.prod.outlook.com (2603:10b6:a03:66::17) MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 Received: from jatayu.amd.com (165.204.156.251) by MA1PR0101CA0025.INDPRD01.PROD.OUTLOOK.COM (2603:1096:a00:22::11) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3261.18 via Frontend Transport; Mon, 10 Aug 2020 21:31:29 +0000 X-Mailer: git-send-email 2.25.1 X-Originating-IP: [165.204.156.251] X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-HT: Tenant X-MS-Office365-Filtering-Correlation-Id: 36f08ab5-a323-4ebf-f6e0-08d83d74c058 X-MS-TrafficTypeDiagnostic: BY5PR12MB3714: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:3968; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: oHwzkcMuHTR3IjJTTXnCzw2RYdBF/lKsriMmSa8WKh2feTBFVO01yLi0N57FfqU/UV2vSPyQbxxfi8Tnc5FgjNnWxn/3hVw7mo8oz1dqOQfnBbRml4UWKozK4DubyODbxLP4oaKJWy/qFlxo3QQoQsZxUjIo7U9Y2bMDQVL5AOdXTYamdm5H+A7qC9GQYO1GmBxddozn08qk4dPxN+mNyc+GkpxjPsTwieorVMCz4AoQvKpQd20+MD02pJ8pVopOWqcO/TV//Hco+lfCdqYsVGc7ePuyJJYBVu8mJeWPhV589tBTOmuggCsyVAGet310nOCo7wZkp0b0RTlLnaekPo0bnh6I97QQgIlCOv7xxmi9U77m8JApiXWVIAciidZ/ X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:BYAPR12MB2726.namprd12.prod.outlook.com; PTR:; CAT:NONE; SFTY:; SFS:(4636009)(366004)(39860400002)(136003)(376002)(346002)(396003)(2906002)(1076003)(7416002)(83380400001)(478600001)(6666004)(52116002)(66946007)(7696005)(8676002)(66476007)(66556008)(26005)(6486002)(5660300002)(8936002)(36756003)(956004)(2616005)(316002)(16526019)(4326008)(86362001)(186003)(921003); DIR:OUT; SFP:1101; X-MS-Exchange-AntiSpam-MessageData: W0nL9Mdc2cbbX2i45T2GYrTyrvGYZNC7xmcjpUNowdJPc71hskM5ph3mB4Saf+ZYI6VTxvJ4q7sjaOboL1/U2jXI+IQDnJsh+LU+K9c9jUGOALLSxehbnskUXk2fRdVonUUyn4LXFqW5eqx++X415NoPi4XWH04lW1KTbqwQgZTbLuvT6J/MU+6ucJvW6BWUt/sOteHARUSr3OuVF1ceqEsAD+KSaWGElN1vEAkjbVDqD1Gqh13/kNRhf4agdUVXIKZpmtBDBLIWR5tJ96Yu+kzZm7HybW5LDIFgHw2MPTHFJL3KA1Tbkd29aN0l7hEJg3fuBCiwjd3SZQnolb5eQgIxx+ZtFjqSJ8iHihp7Jxcnd895ia8XJQjzZU5XZlY47cg/7m/3e4vMeJa6uj8MMGJqsHeznEGAVtV/9IhRCcg+NBc7+0XNfNZC60fTKMR+kwDh/SPp/PhEHFpPvEAWU/0cYTbRVGEs096EAEf0BQxciv9cfpoMoyK/isnGrxpdrGuppBruBvgmG7tXnCN3pX/ZKFgmfzaApjuPuj/5eTk4BcnIeZ31ecZ9EEZoLSfAr83rX0G5oNU8ZsKhwrf0R3FzbvkEKqKO6F4DeS43TNoEx+1p3U2LpztP2h5lcFj/N2TJ+JLCtVcFb5vWoBh+Rg== X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-Network-Message-Id: 36f08ab5-a323-4ebf-f6e0-08d83d74c058 X-MS-Exchange-CrossTenant-AuthSource: BYAPR12MB2726.namprd12.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 10 Aug 2020 21:31:32.7720 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: GX4rQkZf7FXKeYQe8+bc77xPIj5Z/Q1rPgKdP5tptanmMO/3uiwmOIwj41P5uWX5 X-MS-Exchange-Transport-CrossTenantHeadersStamped: BY5PR12MB3714 Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org From: Sandeep Singh Add Maintainers for AMD SFH(SENSOR FUSION HUB) Solution and work flow document. Signed-off-by: Nehal Shah Signed-off-by: Sandeep Singh --- Documentation/hid/amd-sfh-hid.rst | 153 ++++++++++++++++++++++++++++++ MAINTAINERS | 8 ++ 2 files changed, 161 insertions(+) create mode 100644 Documentation/hid/amd-sfh-hid.rst diff --git a/Documentation/hid/amd-sfh-hid.rst b/Documentation/hid/amd-sfh-hid.rst new file mode 100644 index 000000000000..0ee9003013f2 --- /dev/null +++ b/Documentation/hid/amd-sfh-hid.rst @@ -0,0 +1,153 @@ +.. SPDX-License-Identifier: GPL-2.0 + +AMD Sensor Fusion Hub:- +====================== +AMD Sensor Fusion Hub is part of a SOC starting from Ryzen based platforms. +The solution is working well on several OEM products. AMD SFH uses HID over PCIe bus. +In terms of architecture it resembles ISH .However the major difference is all +The hid reports are generated as part of kernel driver. + +Block Diagram:- +============= + ------------------------------- + | HID User Space Applications | + ------------------------------- +--------------------------------------------- + --------------------------------- + | HID Core | + --------------------------------- + + --------------------------------- + | AMD HID Transport | + --------------------------------- + + -------------------------------- + | AMD HID Client | + | with HID Report Generator| + -------------------------------- + + -------------------------------- + | AMD MP2 PCIe Driver | + -------------------------------- +--------------------------------------------- + ------------------------------- + | SFH MP2 Processor | + -------------------------------- + + +AMD HID Transport Layer :- +*************************** +AMD SFH transport is also implemented as a bus. Each client application executing in the AMD MP2 +is registered as a device on this bus. MP2 which is an ARMĀ® Cortex-M4 core based co-processor to +x86. The driver, which binds each device (AMD SFH HID driver) identifies the device type and +registers with the hid core. Transport drivers attach a constant "struct hid_ll_driver" object with +each device. Once a device is registered with HID core, the callbacks provided via this struct are +used by HID core to communicate with the device. AMD HID Transport driver implements the synchronouscalls. + +AMD HID Client Layer:- +********************** +This layer is responsible to implement HID request and descriptors. As firmware is OS agnostic, +HID client layer fills the HID request structure and descriptors. HID client layer is in complex +in nature as it is interface between MP2 PCIe driver and HID. HID client layer initialized +the MP2 PCIe driver and holds the instance of MP2 driver.It identified the number of sensors +connected using MP2-PCIe driver and based on that allocate the DRAM address for each and every +sensor and pass it to MP2-PCIe driver.On enumeration of each sensor, client layer fills out the HID +Descriptor structure and HID input report structure. HID Feature report structure can be optional. +The report descriptor structure varies sensor to sensor. Now on enumeration client layer does +two major things +1. Register the HID sensor client to virtual bus (Platform driver) and bind it. +2. Probes the AMD HID transport driver. Which in turns register device to the core. + +AMD MP2 PCIe layer:- +******************** +MP2 PCIe Layer is responsible for making all transaction with the firmware over PCIe. +The connection establishment between firmware and PCIe happens here. + +The communication between X86 and MP2 is spilt into three parts. +1. Command Transfer => C2P Mailbox Register are used +2. Data Transfer => DRAM +3. Supported sensor info => P2C Register + +Commands are sent to MP2 using C2P Mail Box registers. These C2P registers are common between x86 +and MP2. Writing into C2P Message register generate interrupt to MP2. The client layer allocates +the physical memory and send the same to MP2 for data transfer. MP2 firmware uses HUBIF interface +to access DRAM memory. For Firmware always write minimum 32 bytes into DRAM.So it is expected that +driver shall allocate minimum 32 bytes DRAM space. + +Enumeration and Probing flow:- +***************************** + HID AMD AMD AMD -PCIe MP2 + Core Transport Client layer layer FW + | | | | | + | | | on Boot Driver Loaded | + | | | | | + | | | MP2-PCIe Int | + | | | | | + | | |---Get Number of sensors-> | | + | | | Read P2C | + | | | Register | + | | | | | + | | | Loop(for No of Sensors) | | + | | |----------------------| | | + | | | Create HID Descriptor| | | + | | | Create Input report | | | + | | | Descriptor Map | | | + | | | the MP2 FW Index to | | | + | | | HID Index | | | + | | | Allocate the DRAM | Enable | + | | | address | Sensors | + | | |----------------------| | | + | | HID transport| | Enable | + | |<--Probe------| |---Sensor CMD--> | + | | Create the | | | + | | HID device | | | + | | (MFD) | | | + | | by Populating| | | + | | the HID | | | + | | ll_driver | | | + | HID | | | | + | add | | | | + |Device | | | | + |<------------- | | | | + + +Data Flow from Application to the AMD SFH Driver:- +************************************************* + + | | | | | +Get | | | | | +Input | | | | | +Report | | | | | +---> | | | | | + |HID_req | | | | + |get_report | | | | + |------------->| | | | + | | HID_get_input| | | + | | report | | | + | |------------->|------------------------| | | + | | | Read the DRAM data for| | | + | | | requested sensor and | | | + | | | create the HID input | | | + | | | report | | | + | | |------------------------| | | + | |Data received | | | + | | in HID report| | | + To |<-------------|<-------------| | | +Applications | | | | +<-------| | | | | + + +Data Flow from AMD SFH Driver to Application:- +********************************************** + | | | | | + | | |------------------------| | | + | | |Periodically Read | | | + | | |the data for all | | | + | | |enumerated sensors | | | + | | |from the dram and create| | | + | | | HID Input reports | | | + | | |------------------------| | | + | |HID Input | | | + | |Input report | | | + <----submit to Application-----| | | + | | | | | diff --git a/MAINTAINERS b/MAINTAINERS index d53db30d1365..fc6a712893fb 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -934,6 +934,14 @@ S: Supported F: arch/arm64/boot/dts/amd/amd-seattle-xgbe*.dtsi F: drivers/net/ethernet/amd/xgbe/ +AMD SENSOR FUSION HUB DRIVER +M: Nehal Shah +M: Sandeep Singh +L: linux-input@vger.kernel.org +S: Maintained +F: Documentation/hid/amd-sfh* +F: drivers/hid/amd-sfh-hid/ + ANALOG DEVICES INC AD5686 DRIVER M: Michael Hennerich L: linux-pm@vger.kernel.org From patchwork Mon Aug 10 21:30:54 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sandeep Singh X-Patchwork-Id: 255121 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=-13.0 required=3.0 tests=BAYES_00,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 E206BC433DF for ; Mon, 10 Aug 2020 21:31:52 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id B0BBB206DA for ; Mon, 10 Aug 2020 21:31:52 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=amdcloud.onmicrosoft.com header.i=@amdcloud.onmicrosoft.com header.b="LJmsUykF" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726918AbgHJVbv (ORCPT ); Mon, 10 Aug 2020 17:31:51 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35628 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726867AbgHJVbu (ORCPT ); Mon, 10 Aug 2020 17:31:50 -0400 Received: from NAM04-CO1-obe.outbound.protection.outlook.com (mail-co1nam04on0615.outbound.protection.outlook.com [IPv6:2a01:111:f400:fe4d::615]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 766FCC061756; Mon, 10 Aug 2020 14:31:50 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=MFfmIM+iHUSBUB9HhOxvd1qV1r+OZY8b3zMahW56j3wIXJT37TYMXYMJiP/WgpmW5FRvYitbIb1XCaxfqoi+BDPv+NCraZTNWhcTYUWVTTOREIgPoZlovr05Pnse1oHLoGCtkk7PXGaMA2lv9uk/QuMNWWH7YCi2+oEclGnRHX7evQXmN6SzatIDAsJlenGK/dW4f6++ZHT6EKZN3ec7dc6VP8UloUTGeo82hErcjf3ACF2+BHgVcRQOGVQkekzU87c8dN5CAjmSy3SazbkbeDzd/5F6Z24kybjKKOkLlUzJ614qx8vC+fTzl/c/5gmA0DmLmytJ/v9vgY084drpwg== 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=dg1WkJZUHxoqLn8+AP90dW6v6FLtC06fMfXlnHGQOMo=; b=hFPqSNIptTCH4/qvTBNwrGir0+cewLPQisQDO3xriXUtva7F04XiHJMY0fSoWZzpOKBwTKvBvKNqWtcsNIBRqW8nxIib64HA23ZdurNxrRXUJt6NyY8rN8hWpFR1Xl5yHeIbn5Ib4/Ra5FZMD1d/FBOc+M6UsexTG2q7kiXp3c4NQ+yJryVcJlFF94Pc8eaLFEbmHogUblhPyr8B3Z0CY7RJ+eE1HMKi3bjRyScGXm+a2iFa/IfLCOtgm5otGukGKpioMQsSQh9FUSCuXc2/bxs85OlhhgLyd60/JpAwGhKk7NHbkexfTs08Nq+rfwdkvHKuTMOLBQaQe6yO5qAz0w== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=amd.com; dmarc=pass action=none header.from=amd.com; dkim=pass header.d=amd.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amdcloud.onmicrosoft.com; s=selector2-amdcloud-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=dg1WkJZUHxoqLn8+AP90dW6v6FLtC06fMfXlnHGQOMo=; b=LJmsUykFTey2Xj84asZOFuwpuFkvFuxJsBHAy9GCX2BQESVDiA9yZHfPTsVlOr8Z9nXqiCK2mEr2IcizmLwYt7MixMPlme5RfpHuQOeMsya014RFDs+oyaU1qDIqy21U4Y8MtLfgHgZ/05R66kO+bH0L4N+Mi6u71N6lVH94lBY= Authentication-Results: kernel.org; dkim=none (message not signed) header.d=none; kernel.org; dmarc=none action=none header.from=amd.com; Received: from BYAPR12MB2726.namprd12.prod.outlook.com (2603:10b6:a03:66::17) by BY5PR12MB3715.namprd12.prod.outlook.com (2603:10b6:a03:1a5::12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3261.18; Mon, 10 Aug 2020 21:31:48 +0000 Received: from BYAPR12MB2726.namprd12.prod.outlook.com ([fe80::8503:3713:6ed0:af09]) by BYAPR12MB2726.namprd12.prod.outlook.com ([fe80::8503:3713:6ed0:af09%6]) with mapi id 15.20.3261.024; Mon, 10 Aug 2020 21:31:48 +0000 From: Sandeep Singh To: jikos@kernel.org, benjamin.tissoires@redhat.com, linux-kernel@vger.kernel.org, linux-input@vger.kernel.org, srinivas.pandruvada@linux.intel.com, jic23@kernel.org, linux-iio@vger.kernel.org, hdegoede@redhat.com, Nehal-bakulchandra.Shah@amd.com, andy.shevchenko@gmail.com, mail@richard-neumann.de, m.felsch@pengutronix.de, rdunlap@infradead.org Cc: Shyam-sundar.S-k@amd.com, Sandeep Singh Subject: [PATCH v7 3/4] SFH: Transport Driver to add support of AMD Sensor Fusion Hub (SFH) Date: Mon, 10 Aug 2020 21:30:54 +0000 Message-Id: <20200810213055.103962-4-Sandeep.Singh@amd.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200810213055.103962-1-Sandeep.Singh@amd.com> References: <20200810213055.103962-1-Sandeep.Singh@amd.com> X-ClientProxiedBy: MA1PR0101CA0025.INDPRD01.PROD.OUTLOOK.COM (2603:1096:a00:22::11) To BYAPR12MB2726.namprd12.prod.outlook.com (2603:10b6:a03:66::17) MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 Received: from jatayu.amd.com (165.204.156.251) by MA1PR0101CA0025.INDPRD01.PROD.OUTLOOK.COM (2603:1096:a00:22::11) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3261.18 via Frontend Transport; Mon, 10 Aug 2020 21:31:44 +0000 X-Mailer: git-send-email 2.25.1 X-Originating-IP: [165.204.156.251] X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-HT: Tenant X-MS-Office365-Filtering-Correlation-Id: 30a29b8e-04bd-4cbe-2bc9-08d83d74c977 X-MS-TrafficTypeDiagnostic: BY5PR12MB3715: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:117; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: +o4GRYFTcLu5ivP2sKhLGPOHzqkaQIt3GFpG8F1StE/JF3pWRfFfPskCtZi/8hNoCxKBOvam5c2LK5jbCac2U1MFp4Z3EiJXqeBVsLcyvK4Cd5qUta1NjGHbh9f8nPhA0rhi39aYcjwMPx7Tu6L07Xk54lzyAcVe1gRq1nLHllMrGfJqI9PeV4em5tItRCF+uNBHmVPnmLaX18ewyZW4lLI0RG293PjN6WPA0z/0TcHAQ18rR63Ce93TLXEMfymQZl/UqCqanK6Z2LCaaaRVRes38jbReHvZb6b1PQVE9cKnE3UiQ5wvr08xcX75Ki2icEpuc97lPqLAN1Q2DkmwPe81Ct1L81jWjUWHo7Jv5vMaui3FanUFqow9tkztWrJc X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:BYAPR12MB2726.namprd12.prod.outlook.com; PTR:; CAT:NONE; SFTY:; SFS:(4636009)(346002)(136003)(366004)(39860400002)(396003)(376002)(2906002)(6486002)(26005)(30864003)(186003)(7696005)(52116002)(16526019)(5660300002)(66556008)(66476007)(4326008)(6666004)(66946007)(1076003)(478600001)(8936002)(36756003)(83380400001)(2616005)(956004)(86362001)(8676002)(316002)(7416002)(921003); DIR:OUT; SFP:1101; X-MS-Exchange-AntiSpam-MessageData: AImzlPXB2dLWwm9OX8/GEfytTqqwsqrJqWJCFMtlVtY27WcDd2BmvoIuEnGIUNMk8wnn8V4yGsEqTEUMzWpLjxGQnbVDFeuuKviw4LFvu7yzhlqrfHkWxrQ6txCVgD8cwXD+WmiRBzxXWM2rMqoVD1o+6obhkkWq3vCrVuiv37hQnZ54BYuipC+7RvaubGvkaUUcs+BRkVf27yUDMr3di4Wb15OC/94aDk5R7luSIlV52VbT3VIyThc6731mF79SOggzWxc/La5piODoBFwNYM8z9s6LFWX6qLlJ2/uuX1cBB3SY1TdELN/wD3yQpn3tahK1EzSesEghidxkjVUBY7BCLcfpT7DK8J/ScnKPRDUJZTGbw3fO5rtp571wk+iJ8Wad+pxWJE9bVq5IUaYdgZTPDuC817roZMhQm4KzygEXvCQaE6mRpyaPvpXwbZDBYWu1B0TKEoT1f8+7jCg8S1O2COul5YYpHUoniS3MyMKaGOVglUV4VbBH70VrCguMeMdQ/3TLIFjZec2Q2IGhnV82DBQHFLV0MaS1zTNhTWCvxAecjPdDCJXitcI0BeCPn4rHs1tpb/G8U075zZtj4El4yRNg4ccHnLEVZMkaHZ3NDzZNDZdi0EeAFYIv7BB2dme5qb2Cqr3TkMxq8X/HmA== X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-Network-Message-Id: 30a29b8e-04bd-4cbe-2bc9-08d83d74c977 X-MS-Exchange-CrossTenant-AuthSource: BYAPR12MB2726.namprd12.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 10 Aug 2020 21:31:48.1274 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: GK9EsP7mmPBFV7rXm2tjFgXFVJNML5QMYFJ9F1OvmMm0Ha5XsW+91PhkzlQHk/Vv X-MS-Exchange-Transport-CrossTenantHeadersStamped: BY5PR12MB3715 Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org From: Sandeep Singh This part of module will provide the interaction between HID framework and client layer.This module will registered client layer with HID framework. Signed-off-by: Nehal Shah Signed-off-by: Sandeep Singh --- drivers/hid/amd-sfh-hid/amdsfh_hid.c | 175 ++++++++++++++ drivers/hid/amd-sfh-hid/amdsfh_hid.h | 68 ++++++ drivers/hid/amd-sfh-hid/amdsfh_hid_client.c | 244 ++++++++++++++++++++ 3 files changed, 487 insertions(+) create mode 100644 drivers/hid/amd-sfh-hid/amdsfh_hid.c create mode 100644 drivers/hid/amd-sfh-hid/amdsfh_hid.h create mode 100644 drivers/hid/amd-sfh-hid/amdsfh_hid_client.c diff --git a/drivers/hid/amd-sfh-hid/amdsfh_hid.c b/drivers/hid/amd-sfh-hid/amdsfh_hid.c new file mode 100644 index 000000000000..645c41174bca --- /dev/null +++ b/drivers/hid/amd-sfh-hid/amdsfh_hid.c @@ -0,0 +1,175 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * AMD MP2 Sensors transport driver + * + * Authors: Nehal Bakulchandra Shah + * Sandeep Singh + */ +#include +#include +#include +#include "amdsfh_hid.h" + +#define DRIVER_NAME "AMD_MP2_SENSORS_TRANSPORT" + +/* + * amdtp_hid_parse() - hid-core .parse() callback + * @hid: hid device instance + * + * This function gets called during call to hid_add_device + * + * Return: 0 on success and non zero on error + */ +static int amdtp_hid_parse(struct hid_device *hid) +{ + struct amdtp_hid_data *hid_data = hid->driver_data; + struct amdtp_cl_data *cli_data = hid_data->cli_data; + + return hid_parse_report(hid, cli_data->report_descr[hid_data->index], + cli_data->report_descr_sz[hid_data->index]); +} + +/* Empty callbacks with success return code */ +static int amdtp_hid_start(struct hid_device *hid) +{ + return 0; +} + +static void amdtp_hid_stop(struct hid_device *hid) +{ +} + +static int amdtp_hid_open(struct hid_device *hid) +{ + return 0; +} + +static void amdtp_hid_close(struct hid_device *hid) +{ +} + +static int amdtp_raw_request(struct hid_device *hdev, u8 reportnum, + u8 *buf, size_t len, u8 rtype, int reqtype) +{ + return 0; +} + +static void amdtp_hid_request(struct hid_device *hid, struct hid_report *rep, int reqtype) +{ + int rc; + + switch (reqtype) { + case HID_REQ_GET_REPORT: + rc = amd_sfh_get_report(hid, rep->id, rep->type); + if (rc) + pr_err("AMDSFH get report error "); + break; + case HID_REQ_SET_REPORT: + amd_sfh_set_report(hid, rep->id, reqtype); + break; + default: + break; + } +} + +static int amdtp_wait_for_response(struct hid_device *hid) +{ + struct amdtp_hid_data *hid_data = hid->driver_data; + struct amdtp_cl_data *cli_data = hid_data->cli_data; + int i, ret = 0; + + for (i = 0; i < cli_data->num_hid_devices; i++) { + if (cli_data->hid_sensor_hubs[i] == hid) + break; + } + + if (!cli_data->request_done[i]) + ret = wait_event_interruptible_timeout(hid_data->hid_wait, + cli_data->request_done[i], 1500); + if (ret > 0) + return 0; + else if (ret == -ERESTARTSYS) + return -ERESTARTSYS; + else + return -ETIMEDOUT; +} + +void amdtp_hid_wakeup(struct hid_device *hid) +{ + struct amdtp_hid_data *hid_data = hid->driver_data; + struct amdtp_cl_data *cli_data = hid_data->cli_data; + + cli_data->request_done[cli_data->cur_hid_dev] = true; + wake_up_interruptible(&hid_data->hid_wait); +} + +static struct hid_ll_driver amdtp_hid_ll_driver = { + .parse = amdtp_hid_parse, + .start = amdtp_hid_start, + .stop = amdtp_hid_stop, + .open = amdtp_hid_open, + .close = amdtp_hid_close, + .request = amdtp_hid_request, + .wait = amdtp_wait_for_response, + .raw_request = amdtp_raw_request, +}; + +int amdtp_hid_probe(u32 cur_hid_dev, + struct amdtp_cl_data *cli_data) +{ + struct hid_device *hid; + struct amdtp_hid_data *hid_data; + int rc; + + hid = hid_allocate_device(); + if (IS_ERR(hid)) { + rc = PTR_ERR(hid); + return rc; + } + + hid_data = kzalloc(sizeof(*hid_data), GFP_KERNEL); + if (!hid_data) { + rc = -ENOMEM; + goto err_hid_data; + } + + hid->ll_driver = &amdtp_hid_ll_driver; + hid_data->index = cur_hid_dev; + hid_data->cli_data = cli_data; + init_waitqueue_head(&hid_data->hid_wait); + + hid->driver_data = hid_data; + cli_data->hid_sensor_hubs[cur_hid_dev] = hid; + hid->bus = BUS_AMD_AMDTP; + hid->vendor = AMD_SFH_HID_VENDOR; + hid->product = AMD_SFH_HID_PRODUCT; + snprintf(hid->name, sizeof(hid->name), "%s %04X:%04X", "hid-amdtp", + hid->vendor, hid->product); + + rc = hid_add_device(hid); + if (rc) + goto err_hid_device; + return 0; + +err_hid_device: + kfree(hid_data); +err_hid_data: + hid_destroy_device(hid); + return rc; +} + +void amdtp_hid_remove(struct amdtp_cl_data *cli_data) +{ + int i; + + for (i = 0; i < cli_data->num_hid_devices; ++i) { + kfree(cli_data->feature_report[i]); + kfree(cli_data->input_report[i]); + kfree(cli_data->report_descr[i]); + if (cli_data->hid_sensor_hubs[i]) { + kfree(cli_data->hid_sensor_hubs[i]->driver_data); + hid_destroy_device(cli_data->hid_sensor_hubs[i]); + cli_data->hid_sensor_hubs[i] = NULL; + } + } +} diff --git a/drivers/hid/amd-sfh-hid/amdsfh_hid.h b/drivers/hid/amd-sfh-hid/amdsfh_hid.h new file mode 100644 index 000000000000..b4b14b46f2e1 --- /dev/null +++ b/drivers/hid/amd-sfh-hid/amdsfh_hid.h @@ -0,0 +1,68 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * AMD MP2 Sensors transport driver + * + * Authors: Nehal Bakulchandra Shah + * Sandeep Singh + */ + +#ifndef AMDSFH_HID_H +#define AMDSFH_HID_H + +#define MAX_HID_DEVICES 4 +#define DCD_DATA_SIZE_CHAR 512 +#define BUS_AMD_AMDTP 0x20 +#define AMD_SFH_HID_VENDOR 1022 +#define AMD_SFH_HID_PRODUCT 0x0001 + +struct amdtp_cl_data { + u8 init_done; + u32 cur_hid_dev; + u32 hid_dev_count; + u32 num_hid_devices; + struct device_info *hid_devices; + u8 *report_descr[MAX_HID_DEVICES]; + int report_descr_sz[MAX_HID_DEVICES]; + struct hid_device *hid_sensor_hubs[MAX_HID_DEVICES]; + u8 *hid_descr[MAX_HID_DEVICES]; + int hid_descr_size[MAX_HID_DEVICES]; + phys_addr_t phys_addr_base; + u32 *sensor_virt_addr[MAX_HID_DEVICES]; + phys_addr_t sensor_phys_addr[MAX_HID_DEVICES]; + u32 sensor_sts[MAX_HID_DEVICES]; + u32 sensor_requested_cnt[MAX_HID_DEVICES]; + u8 report_type[MAX_HID_DEVICES]; + u8 report_id[MAX_HID_DEVICES]; + u8 sensor_idx[MAX_HID_DEVICES]; + u8 *feature_report[MAX_HID_DEVICES]; + u8 *input_report[MAX_HID_DEVICES]; + u8 request_done[MAX_HID_DEVICES]; + struct delayed_work work; + struct delayed_work work_buffer; +}; + +/** + * struct amdtp_hid_data - Per instance HID data + * @index: Device index in the order of enumeration + * @request_done: Get Feature/Input report complete flag + * used during get/set request from hid core + * @cli_data: Link to the client instance + * @hid_wait: Completion waitq + * + * Used to tie hid hid->driver data to driver client instance + */ +struct amdtp_hid_data { + int index; + struct amdtp_cl_data *cli_data; + wait_queue_head_t hid_wait; +}; + +/* Interface functions between HID LL driver and AMD SFH client */ +void hid_amdtp_set_feature(struct hid_device *hid, char *buf, u32 len, int report_id); +void hid_amdtp_get_report(struct hid_device *hid, int report_id, int report_type); +int amdtp_hid_probe(u32 cur_hid_dev, struct amdtp_cl_data *cli_data); +void amdtp_hid_remove(struct amdtp_cl_data *cli_data); +int amd_sfh_get_report(struct hid_device *hid, int report_id, int report_type); +void amd_sfh_set_report(struct hid_device *hid, int report_id, int report_type); +void amdtp_hid_wakeup(struct hid_device *hid); +#endif diff --git a/drivers/hid/amd-sfh-hid/amdsfh_hid_client.c b/drivers/hid/amd-sfh-hid/amdsfh_hid_client.c new file mode 100644 index 000000000000..17d59b787c3c --- /dev/null +++ b/drivers/hid/amd-sfh-hid/amdsfh_hid_client.c @@ -0,0 +1,244 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * AMD SFH Client Layer + * Copyright 2020 Advanced Micro Devices, Inc. + * Authors: Nehal Bakulchandra Shah + * Sandeep Singh + */ + +#include +#include +#include +#include +#include +#include +#include "hid_descriptor/amd_sfh_hid_descriptor.h" +#include "amdsfh_hid.h" +#include "amd_mp2_pcie.h" + +#define PERIOD 200 + +struct request_list { + struct hid_device *hid; + struct list_head list; + u8 report_id; + u8 sensor_idx; + u8 report_type; + u8 current_index; +}; + +static struct request_list req_list; + +void amd_sfh_set_report(struct hid_device *hid, int report_id, + int report_type) +{ + struct amdtp_hid_data *hid_data = hid->driver_data; + struct amdtp_cl_data *cli_data = hid_data->cli_data; + int i; + + for (i = 0; i < cli_data->num_hid_devices; i++) { + if (cli_data->hid_sensor_hubs[i] == hid) { + cli_data->cur_hid_dev = i; + break; + } + } + amdtp_hid_wakeup(hid); +} + +int amd_sfh_get_report(struct hid_device *hid, int report_id, int report_type) +{ + struct amdtp_hid_data *hid_data = hid->driver_data; + struct amdtp_cl_data *cli_data = hid_data->cli_data; + int i; + + for (i = 0; i < cli_data->num_hid_devices; i++) { + if (cli_data->hid_sensor_hubs[i] == hid) { + struct request_list *new = kzalloc(sizeof(*new), GFP_KERNEL); + + if (!new) + return -ENOMEM; + new->current_index = i; + new->sensor_idx = cli_data->sensor_idx[i]; + new->hid = hid; + new->report_type = report_type; + new->report_id = report_id; + cli_data->report_id[i] = report_id; + cli_data->request_done[i] = false; + list_add(&new->list, &req_list.list); + break; + } + } + schedule_delayed_work(&cli_data->work, 0); + return 0; +} + +static void amd_sfh_work(struct work_struct *work) +{ + struct amdtp_cl_data *cli_data = container_of(work, struct amdtp_cl_data, work.work); + struct request_list *req_node; + u8 current_index, sensor_index; + u8 report_id, node_type; + u8 report_size = 0; + + req_node = list_last_entry(&req_list.list, struct request_list, list); + list_del(&req_node->list); + current_index = req_node->current_index; + sensor_index = req_node->sensor_idx; + report_id = req_node->report_id; + node_type = req_node->report_type; + + if (node_type == HID_FEATURE_REPORT) { + report_size = get_feature_report(sensor_index, report_id, + cli_data->feature_report[current_index]); + if (report_size) + hid_input_report(cli_data->hid_sensor_hubs[current_index], + cli_data->report_type[current_index], + cli_data->feature_report[current_index], report_size, 0); + else + pr_err("AMDSFH: Invalid report size\n"); + + } else if (node_type == HID_INPUT_REPORT) { + report_size = get_input_report(sensor_index, report_id, + cli_data->input_report[current_index], + cli_data->sensor_virt_addr[current_index]); + if (report_size) + hid_input_report(cli_data->hid_sensor_hubs[current_index], + cli_data->report_type[current_index], + cli_data->input_report[current_index], report_size, 0); + else + pr_err("AMDSFH: Invalid report size\n"); + } + cli_data->cur_hid_dev = current_index; + cli_data->sensor_requested_cnt[current_index] = 0; + amdtp_hid_wakeup(cli_data->hid_sensor_hubs[current_index]); +} + +static void amd_sfh_work_buffer(struct work_struct *work) +{ + struct amdtp_cl_data *cli_data = container_of(work, struct amdtp_cl_data, work_buffer.work); + u8 report_size; + int i; + + for (i = 0; i < cli_data->num_hid_devices; i++) { + report_size = get_input_report(cli_data->sensor_idx[i], cli_data->report_id[i], + cli_data->input_report[i], + cli_data->sensor_virt_addr[i]); + hid_input_report(cli_data->hid_sensor_hubs[i], HID_INPUT_REPORT, + cli_data->input_report[i], report_size, 0); + } + schedule_delayed_work(&cli_data->work_buffer, PERIOD); +} + +int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata) +{ + struct amdtp_cl_data *cl_data = privdata->cl_data; + struct amd_mp2_sensor_info info; + struct device *dev; + u32 feature_report_size; + u32 input_report_size; + u8 cl_idx; + int rc, i; + + dev = &privdata->pdev->dev; + cl_data = kzalloc(sizeof(*cl_data), GFP_KERNEL); + if (!cl_data) + return -ENOMEM; + + cl_data->num_hid_devices = amd_mp2_get_sensor_num(privdata, &cl_data->sensor_idx[0]); + + INIT_DELAYED_WORK(&cl_data->work, amd_sfh_work); + INIT_DELAYED_WORK(&cl_data->work_buffer, amd_sfh_work_buffer); + INIT_LIST_HEAD(&req_list.list); + + for (i = 0; i < cl_data->num_hid_devices; i++) { + cl_data->sensor_virt_addr[i] = dma_alloc_coherent(dev, sizeof(int) * 8, + &cl_data->sensor_phys_addr[i], + GFP_KERNEL); + cl_data->sensor_sts[i] = 0; + cl_data->sensor_requested_cnt[i] = 0; + cl_data->cur_hid_dev = i; + cl_idx = cl_data->sensor_idx[i]; + cl_data->report_descr_sz[i] = get_descr_sz(cl_idx, descr_size); + if (!cl_data->report_descr_sz[i]) { + rc = -EINVAL; + goto cleanup; + } + feature_report_size = get_descr_sz(cl_idx, feature_size); + if (!feature_report_size) { + rc = -EINVAL; + goto cleanup; + } + input_report_size = get_descr_sz(cl_idx, input_size); + if (!input_report_size) { + rc = -EINVAL; + goto cleanup; + } + cl_data->feature_report[i] = kzalloc(feature_report_size, GFP_KERNEL); + if (!cl_data->feature_report[i]) { + rc = -ENOMEM; + goto cleanup; + } + cl_data->input_report[i] = kzalloc(input_report_size, GFP_KERNEL); + if (!cl_data->input_report[i]) { + rc = -ENOMEM; + goto cleanup; + } + info.period = PERIOD; + info.sensor_idx = cl_idx; + info.phys_address = cl_data->sensor_phys_addr[i]; + + cl_data->report_descr[i] = kzalloc(cl_data->report_descr_sz[i], GFP_KERNEL); + if (!cl_data->report_descr[i]) { + rc = -ENOMEM; + goto cleanup; + } + rc = get_report_descriptor(cl_idx, cl_data->report_descr[i]); + if (rc) + return rc; + rc = amdtp_hid_probe(cl_data->cur_hid_dev, cl_data); + if (rc) + return rc; + amd_start_sensor(privdata, info); + cl_data->sensor_sts[i] = 1; + } + privdata->cl_data = cl_data; + schedule_delayed_work(&cl_data->work_buffer, PERIOD); + return 0; + +cleanup: + for (i = 0; i < cl_data->num_hid_devices; i++) { + if (cl_data->sensor_virt_addr[i]) { + dma_free_coherent(&privdata->pdev->dev, 8 * sizeof(int), + cl_data->sensor_virt_addr[i], + cl_data->sensor_phys_addr[i]); + } + kfree(cl_data->feature_report[i]); + kfree(cl_data->input_report[i]); + kfree(cl_data->report_descr[i]); + } + kfree(cl_data); + return rc; +} + +int amd_sfh_hid_client_deinit(struct amd_mp2_dev *privdata) +{ + struct amdtp_cl_data *cl_data = privdata->cl_data; + int i; + + for (i = 0; i < cl_data->num_hid_devices; i++) + amd_stop_sensor(privdata, i); + + cancel_delayed_work_sync(&cl_data->work); + cancel_delayed_work_sync(&cl_data->work_buffer); + amdtp_hid_remove(cl_data); + + for (i = 0; i < cl_data->num_hid_devices; i++) { + if (cl_data->sensor_virt_addr[i]) { + dma_free_coherent(&privdata->pdev->dev, 8 * sizeof(int), + cl_data->sensor_virt_addr[i], + cl_data->sensor_phys_addr[i]); + } + } + kfree(cl_data); + return 0; +}