From patchwork Wed Jan 29 04:27:23 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sandeep Singh X-Patchwork-Id: 208244 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.7 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, URIBL_BLOCKED, 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 AAEBCC33CB2 for ; Wed, 29 Jan 2020 04:27:59 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 6E0D8207FD for ; Wed, 29 Jan 2020 04:27:59 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=amdcloud.onmicrosoft.com header.i=@amdcloud.onmicrosoft.com header.b="SCF6NUFc" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726623AbgA2E1z (ORCPT ); Tue, 28 Jan 2020 23:27:55 -0500 Received: from mail-bn8nam12on2073.outbound.protection.outlook.com ([40.107.237.73]:1633 "EHLO NAM12-BN8-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1726401AbgA2E1y (ORCPT ); Tue, 28 Jan 2020 23:27:54 -0500 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=aPfa6QthMoXE0nEyYgmIHaXMcMUsRAWK9K0MX8L0k5vOyCUHuO2oTYq9PGxyZZhEMcVYMZX4nw1jUHatwBaOU+Y5LwmDzhswlv/jx5Vf8gG4xKu+nOL8u77hktH0CmeGNhfN1xM4tRcbvTmvglBsaFWVDWYtq1IdyYArZe3zpoXy/Gv2Y+4VzcDlvLJF97XvLpznYYPL9fmYvH91PvIXHBMfR6CczjUYfX4RZ8iOuDHBg0DdtRHSlHQ9osu1Lfg9OhnXoQOj4WOAl8f4zQbGNjHww3/PUoMnKm/n7DM3uLKI47AkL+NglppwrJ9rH7vvb8kbKwzwYHFDmwGLnKUKVg== 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=UhibI3wKRG7eVi7tQUnFa7CArJGmyTQxJvbyR/oilfY=; b=J5SWheJqJWXByc7rrc5EK+jQ9n4zJCMM3nCKNyjFu/SEdi8xxIJQb6iiNuL9iOisuPUdP6zTnIA8qnAcwZoi+kOX6sWUGDWhEihjepEbhk2FbvqWGDWcJ8RvXxpvvrpiyGRg7q2zdZnVCv5eD1QS6Q3+N3hvpUF/uxmPOCk1Tmu1/rw2slFM+TT+eX/g+CcSI9+Q5PjFW/nD+PgLRAM/QjkaDx4+eSzYOwH2+gu8VrmTdFIxSMKyvA8DkW+Av7opDfII18be9lXw4p5fOVHC3gMqrvihpGeDtCzmCu+SYGG9M8zTMjEDCoWx+qwcvJEyuz0D80IUhIMKBz4ja0Auxw== 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=UhibI3wKRG7eVi7tQUnFa7CArJGmyTQxJvbyR/oilfY=; b=SCF6NUFcrUZe25bMGHn3fjpWwGYy/ojEnICuDlCgAQAsnbnYZiTCsOo0Bi7G71D/vOyKJuzkR2sLeuuqjdM/FRQBh0j6585PfkDsilTmanh9pqvIxk/0o+VptO5u6jIgn1rZXhAe6j9Jy+MkAs7ww/393VM5i4ZAijawSDXkZVM= Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=Sandeep.Singh@amd.com; Received: from MN2PR12MB3598.namprd12.prod.outlook.com (20.178.244.84) by MN2PR12MB3501.namprd12.prod.outlook.com (20.178.241.225) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.2665.23; Wed, 29 Jan 2020 04:27:51 +0000 Received: from MN2PR12MB3598.namprd12.prod.outlook.com ([fe80::10ce:b4fb:586d:8b9c]) by MN2PR12MB3598.namprd12.prod.outlook.com ([fe80::10ce:b4fb:586d:8b9c%3]) with mapi id 15.20.2665.026; Wed, 29 Jan 2020 04:27:51 +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 Cc: Shyam-sundar.S-k@amd.com, Sandeep Singh , Nehal Shah Subject: [PATCH v2 1/4] SFH: Add maintainer list and documentation for AMD SFH based on HID framework Date: Wed, 29 Jan 2020 09:57:23 +0530 Message-Id: <1580272046-32101-2-git-send-email-Sandeep.Singh@amd.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1580272046-32101-1-git-send-email-Sandeep.Singh@amd.com> References: <1580272046-32101-1-git-send-email-Sandeep.Singh@amd.com> X-ClientProxiedBy: MA1PR0101CA0006.INDPRD01.PROD.OUTLOOK.COM (2603:1096:a00:21::16) To MN2PR12MB3598.namprd12.prod.outlook.com (2603:10b6:208:d1::20) MIME-Version: 1.0 Received: from andbang2.amd.com (165.204.156.251) by MA1PR0101CA0006.INDPRD01.PROD.OUTLOOK.COM (2603:1096:a00:21::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) id 15.20.2665.22 via Frontend Transport; Wed, 29 Jan 2020 04:27:48 +0000 X-Mailer: git-send-email 2.7.4 X-Originating-IP: [165.204.156.251] X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-HT: Tenant X-MS-Office365-Filtering-Correlation-Id: 51c014c2-0bec-4434-ee1c-08d7a4739a37 X-MS-TrafficTypeDiagnostic: MN2PR12MB3501:|MN2PR12MB3501: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:3968; X-Forefront-PRVS: 02973C87BC X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10009020)(4636009)(366004)(376002)(346002)(39860400002)(136003)(396003)(189003)(199004)(2906002)(4326008)(5660300002)(66556008)(66476007)(16526019)(956004)(2616005)(26005)(186003)(66946007)(36756003)(6486002)(8676002)(81156014)(81166006)(478600001)(7696005)(8936002)(316002)(86362001)(6666004)(52116002)(54906003); DIR:OUT; SFP:1101; SCL:1; SRVR:MN2PR12MB3501; H:MN2PR12MB3598.namprd12.prod.outlook.com; FPR:; SPF:None; LANG:en; PTR:InfoNoRecords; MX:1; A:1; Received-SPF: None (protection.outlook.com: amd.com does not designate permitted sender hosts) X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: jWv+UDhOyem0U5ZNAbVcJYtkBf3lTWp17TfayDYDmxVV4Gr/NvIZmvuIm3YMZ0Kr4DH3IzuUYiJoE/4fHR0cmZlov6W92xDuSlkRnpbyIIoYoYyPsTGm1t1PcNMT63+sy4Yi4nB53cImscA3r3kEzbc3ttiG6CQIBZ2bh/mWAORYm1A5zkNFljCjfpSKk8RF1pKWokSr4YJO3NNzO/atgBAZevbOkK+3iqa0lH5V3EBNXP7TJ3Rlhog8a8G7+E3elYI7GMWXfLPfTr7x5EUc4Yc5QpcblNgVgzFyYv9XhUTx4Cry4jIqrCtGq4zvvCfmku+ZyTBn7DPXVNWyArfE4pt8smHt5ywToQT054gSnCDOA1wTRwDMFJQSl28Y95qmhf4R6uF+qzkNAIkYCVaRjFhkL4Z7cmVgS8eSbla0BGpxWgHnFSWH8cK0HHduQK3w X-MS-Exchange-AntiSpam-MessageData: 16iVnkvOyZX9K/yp+gXoASYi+CDlCRtH1kPjj9683NFVYHiQ7/SEGFIFX0fhfxXdnURRPwlcqyjdFahAci+KJM2kHM2+HOXr481nFfKCw2Pe3OTb1EoMUXmxQn1ftbnfRLGQLdHGCeRYJgDzI7kA1Q== X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-Network-Message-Id: 51c014c2-0bec-4434-ee1c-08d7a4739a37 X-MS-Exchange-CrossTenant-OriginalArrivalTime: 29 Jan 2020 04:27:51.3194 (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: jB6gFv4/SkyI+bGztXtot5b94F8TUqVeeQnA/AVCXa2U0wKg6mRCXyjKz092fd84 X-MS-Exchange-Transport-CrossTenantHeadersStamped: MN2PR12MB3501 Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org From: Sandeep Singh Add Maintainer list for AMD SFH Solution and work flow document. Signed-off-by: Nehal Shah Signed-off-by: Sandeep Singh --- Documentation/hid/amd-sfh-hid.rst | 159 ++++++++++++++++++++++++++++++++++++++ MAINTAINERS | 8 ++ 2 files changed, 167 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 0000000..1183350 --- /dev/null +++ b/Documentation/hid/amd-sfh-hid.rst @@ -0,0 +1,159 @@ +.. SPDX-License-Identifier: GPL-2.0 + +AMD Sensor Fusion Hub:- +====================== +AMD sensor fushion Hub is part of a SOC starting from ryzon based platforms. +The solution is working well on windows OS in several +OEM products. AMD SFH uses HID over PCIe bus. In terms of architecture +it is much more resmebles like ISH .However the major diffrence is all +The hid reports are generated as part of kernel driver. + +Block Diagram:- +============= + ------------------------------- + | HID User Space Applications | + ------------------------------- +--------------------------------------------- + --------------------------------- + | HID Core | + --------------------------------- + + --------------------------------- + | AMD HID Transport Driver | + --------------------------------- + + -------------------------------- + | AMD HID Client Driver | + | 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. +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 synchronous calls. + +AMD HID Client Driver:- +********************** +This driver is responsible to implement HID request and descriptors. +As firmware is OS agnostic, HID client driver fills the HID request +structure and descriptors. HID client driver is in complex in nature +as it is interface between MP2 PCIe driver and HID. HID client driver +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 driver 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 driver 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 Driver:- +******************** +MP2 PCIe driver is responsible for making all transaction with the firmware over +PCIe.The connection establishment between firmware and MP2 PCIe driver 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 + +Commands are sent to MP2 using C2P Mail Box registers. These C2P registers +are mapped in PCIe address space.Writing into C2P Message register generate +interrupt to MP2. The client driver allocates the physical memory and send +the same to MP2 for data transfer. MP2 firmware uses DRAM interface registers +to indirectly 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 Driver Driver 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| | | + | | | requsted 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 56765f5..7cfeb5a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -884,6 +884,14 @@ S: Supported F: drivers/net/ethernet/amd/xgbe/ F: arch/arm64/boot/dts/amd/amd-seattle-xgbe*.dtsi +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: Stefan Popa L: linux-pm@vger.kernel.org From patchwork Wed Jan 29 04:27:25 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sandeep Singh X-Patchwork-Id: 208243 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.7 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, URIBL_BLOCKED, 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 35D9CC35246 for ; Wed, 29 Jan 2020 04:28:08 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id EEB7822522 for ; Wed, 29 Jan 2020 04:28:07 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=amdcloud.onmicrosoft.com header.i=@amdcloud.onmicrosoft.com header.b="qKgeuRX1" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726715AbgA2E2H (ORCPT ); Tue, 28 Jan 2020 23:28:07 -0500 Received: from mail-mw2nam12on2046.outbound.protection.outlook.com ([40.107.244.46]:60960 "EHLO NAM12-MW2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1726401AbgA2E2G (ORCPT ); Tue, 28 Jan 2020 23:28:06 -0500 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=lsVOX9fdrPeDNkcBnMKTby6+16DUTEp8aCYw6upMy6W4yFYrPf0W7qZg4mLuoABz1Y/neivaob866ZL4P/llde6TDIHXDy5JDfWQLAQVR4vIZNH3b56K63gDYFTsuB7JtS7AwkvkLoVJNYR8Dzh1C3p25+EVnFr/FNOVJaXhXrMYQIeKZHrIbVMJ2VaYvKNVA+Y5WWcbcqsAuQo6PfMHE/czKW6ivhZGzH8r8nKoWLd2pqK0TYvnkIdH6sX/HaIVT6qWA/3rn/bHJdOrMby8I7SI1mmhxlTqYej0WdWDKWCDDQCCkCBQbk44Xg6dSARwZf0NseQkX/CVRtd1gcli3A== 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=OAZGp88yGT1F3+MRq73gfGFuwMuK5CX+3s3Eb8AIoII=; b=jL8irzfN//c3FCIpds+59zKAOw/ywMaPwIf6xccNIrDOC3n/U/iY2GyZy+uSpyHP09/ksOx1/0wETysIyP2jczz8UZZJRiUqSas4ccFeHUZjRFt9aAD1shqAiMOSwF6xnxOd5pHlvjwtLUY+UInTYY38slT/aWbjksKBSTl6XDrRBaeSZp5FQZnEpiqd3Y9BslwavgsCEheClJOBmCBzPFXBN+vRld/bvSTqGGl56fe3+ud6IK/hbe6y5nM9ny0QC44D0XSP855CzOpKBJJk1Niqb/0hl3F2Es9/QIQJSngyLaRNxBMInfXh/UFCRHLDHRMk0B964hyj+pg2uTjPww== 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=OAZGp88yGT1F3+MRq73gfGFuwMuK5CX+3s3Eb8AIoII=; b=qKgeuRX1rysvO2bIF9RZb0Wkni8fNm9a/R1kBV9xySX9v4HLvTGBPwvgh3wFq6GY+tq9LFFxAXadpjirEjFWeXQ4UIQ3cBEvSEtC5EJUl1aASJIIkv3387JwhH/G3YWcn34rSUiMJ00I3Oeh4PrFgVq2aOcQofTpq55OonIB37s= Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=Sandeep.Singh@amd.com; Received: from MN2PR12MB3598.namprd12.prod.outlook.com (20.178.244.84) by MN2PR12MB3501.namprd12.prod.outlook.com (20.178.241.225) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.2665.23; Wed, 29 Jan 2020 04:28:02 +0000 Received: from MN2PR12MB3598.namprd12.prod.outlook.com ([fe80::10ce:b4fb:586d:8b9c]) by MN2PR12MB3598.namprd12.prod.outlook.com ([fe80::10ce:b4fb:586d:8b9c%3]) with mapi id 15.20.2665.026; Wed, 29 Jan 2020 04:28:02 +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 Cc: Shyam-sundar.S-k@amd.com, Sandeep Singh , Nehal Shah Subject: [PATCH v2 3/4] SFH: Transport Driver to add support of AMD sensor fusion Hub (SFH) Date: Wed, 29 Jan 2020 09:57:25 +0530 Message-Id: <1580272046-32101-4-git-send-email-Sandeep.Singh@amd.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1580272046-32101-1-git-send-email-Sandeep.Singh@amd.com> References: <1580272046-32101-1-git-send-email-Sandeep.Singh@amd.com> X-ClientProxiedBy: MA1PR0101CA0006.INDPRD01.PROD.OUTLOOK.COM (2603:1096:a00:21::16) To MN2PR12MB3598.namprd12.prod.outlook.com (2603:10b6:208:d1::20) MIME-Version: 1.0 Received: from andbang2.amd.com (165.204.156.251) by MA1PR0101CA0006.INDPRD01.PROD.OUTLOOK.COM (2603:1096:a00:21::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) id 15.20.2665.22 via Frontend Transport; Wed, 29 Jan 2020 04:27:59 +0000 X-Mailer: git-send-email 2.7.4 X-Originating-IP: [165.204.156.251] X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-HT: Tenant X-MS-Office365-Filtering-Correlation-Id: a331c8a6-34a7-40e7-e918-08d7a473a08f X-MS-TrafficTypeDiagnostic: MN2PR12MB3501:|MN2PR12MB3501: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:23; X-Forefront-PRVS: 02973C87BC X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10009020)(4636009)(366004)(376002)(346002)(39860400002)(136003)(396003)(189003)(199004)(2906002)(4326008)(5660300002)(66556008)(66476007)(16526019)(956004)(2616005)(26005)(186003)(66946007)(30864003)(36756003)(6486002)(8676002)(81156014)(81166006)(478600001)(7696005)(8936002)(316002)(86362001)(6666004)(52116002)(54906003); DIR:OUT; SFP:1101; SCL:1; SRVR:MN2PR12MB3501; H:MN2PR12MB3598.namprd12.prod.outlook.com; FPR:; SPF:None; LANG:en; PTR:InfoNoRecords; MX:1; A:1; Received-SPF: None (protection.outlook.com: amd.com does not designate permitted sender hosts) X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: SbAgQsYa9SPmxn7KlkLKx6501vh6fzE6UJILIbG3IValF5xOvkbEeMuVfv8/EjxyHdt8CHxhpgyBS4H+7NMPV/FvckVqV9yg4CvXQcPkANzLFKfowIewM3BlPS3hRJ7h8lZ4g78OgBgcSRa55VjnuXg/kkaA9Gxr45ui+H7toWjVeAvKt7Fh+p6PqUIwIkxaNNn32iI3hVwXJ8ZjRh2Qd0tqpciTOmX28757xihR8t9eTyunWai40rl8aW2coe3/0Jr4Fdewn07vbfgK3sddbND3ywG1ecMKUKKjauGymQHXg0jytlW7LhwIavRaYL7cd66BiKeWNJyL/FC1JUaPaDy/1sJbi9K6WlRA6gV5bEsE1MSLIWcr7+3px49c9UxMNDUwg5POvctA6UeDX4WGldA07Q67cW7bMHCRQGDxG18vc391hmpz7DqIgaAlEMQ7 X-MS-Exchange-AntiSpam-MessageData: hcm7bWkD0wxN9hytH06tEqjVql58lgoeS0jLduz6I59ynwycpcl7NRUcjO7+P/wsDtJG8HE/Ku66i5L66wI2Ad6zzo8teRgZxWvEhWAclEJBUNd9RkbAth0VwX00eNtXa7s5XZ/BSx6UbRjc+Rxexw== X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-Network-Message-Id: a331c8a6-34a7-40e7-e918-08d7a473a08f X-MS-Exchange-CrossTenant-OriginalArrivalTime: 29 Jan 2020 04:28:01.9803 (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: 7D60tR0ov5MS2JzYERSQSZIZv8ovKX/kFJAdc7CYYqvStpZUUNn68FTevfIMMbYD X-MS-Exchange-Transport-CrossTenantHeadersStamped: MN2PR12MB3501 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 driver.This modules will registered client driver with HID framework. Signed-off-by: Sandeep Singh Signed-off-by: Nehal Shah Reported-by: kbuild test robot Reported-by: Dan Carpenter --- drivers/hid/amd-sfh-hid/amdsfh-debugfs.c | 251 ++++++++++++++++++++++++++ drivers/hid/amd-sfh-hid/amdsfh-debugfs.h | 14 ++ drivers/hid/amd-sfh-hid/amdsfh-hid-client.c | 261 ++++++++++++++++++++++++++++ drivers/hid/amd-sfh-hid/amdsfh-hid.c | 179 +++++++++++++++++++ drivers/hid/amd-sfh-hid/amdsfh-hid.h | 85 +++++++++ 5 files changed, 790 insertions(+) create mode 100644 drivers/hid/amd-sfh-hid/amdsfh-debugfs.c create mode 100644 drivers/hid/amd-sfh-hid/amdsfh-debugfs.h create mode 100644 drivers/hid/amd-sfh-hid/amdsfh-hid-client.c create mode 100644 drivers/hid/amd-sfh-hid/amdsfh-hid.c create mode 100644 drivers/hid/amd-sfh-hid/amdsfh-hid.h diff --git a/drivers/hid/amd-sfh-hid/amdsfh-debugfs.c b/drivers/hid/amd-sfh-hid/amdsfh-debugfs.c new file mode 100644 index 0000000..20859d4 --- /dev/null +++ b/drivers/hid/amd-sfh-hid/amdsfh-debugfs.c @@ -0,0 +1,251 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * AMD SFH DebugFS + * This part of module will provide sensors raw value data + * for AMD SFH debugging. + * cat /sys/kernel/debug/amd_sfhtp_hid + * Author: Nehal Bakulchandra Shah + */ + +#include +#include "amd_mp2_pcie.h" +#include "amdsfh-debugfs.h" + +/* DebugFS helpers */ +#define OBUFP (obuf + oboff) +#define OBUFLEN 512 +#define OBUFSPC (OBUFLEN - oboff) +#define OSCNPRINTF(fmt, ...) \ + scnprintf(OBUFP, OBUFSPC, fmt, ## __VA_ARGS__) + +static ssize_t amdsfh_debugfs_accel_read(struct file *filp, char __user *ubuf, + size_t count, loff_t *offp) +{ + unsigned int oboff = 0, i; + struct amdtp_cl_data *cl_data = filp->private_data; + bool found = false; + ssize_t ret; + char *obuf; + + for (i = 0; i < cl_data->num_hid_devices; i++) { + if (cl_data->sensor_idx[i] == ACCEL_IDX) { + found = true; + break; + } + } + + if (!found) + return -1; + + obuf = kmalloc(OBUFLEN, GFP_KERNEL); + if (!obuf) + return -ENOMEM; + + oboff += OSCNPRINTF("Accel_X_Raw:%d\n", + (int)cl_data->sensor_virt_addr[i][0]); + oboff += OSCNPRINTF("Accel_Y_Raw:%d\n", + (int)cl_data->sensor_virt_addr[i][1]); + oboff += OSCNPRINTF("Accel_Z_Raw:%d\n", + (int)cl_data->sensor_virt_addr[i][2]); + ret = simple_read_from_buffer(ubuf, count, offp, obuf, oboff); + + kfree(obuf); + + return ret; +} + +static ssize_t amdsfh_debugfs_gyro_read(struct file *filp, char __user *ubuf, + size_t count, loff_t *offp) +{ + unsigned int oboff = 0, i; + bool found = false; + struct amdtp_cl_data *cl_data = filp->private_data; + ssize_t ret; + char *obuf; + + for (i = 0; i < cl_data->num_hid_devices; i++) { + if (cl_data->sensor_idx[i] == GYRO_IDX) { + found = true; + break; + } + } + + if (!found) + return -1; + + obuf = kmalloc(OBUFLEN, GFP_KERNEL); + if (!obuf) + return -ENOMEM; + + oboff += OSCNPRINTF("Gyro_X_Raw:%d\n", + (int)cl_data->sensor_virt_addr[i][0]); + oboff += OSCNPRINTF("Gyro_Y_Raw:%d\n", + (int)cl_data->sensor_virt_addr[i][1]); + oboff += OSCNPRINTF("Gyro_Z_Raw:%d\n", + (int)cl_data->sensor_virt_addr[i][2]); + ret = simple_read_from_buffer(ubuf, count, offp, obuf, oboff); + + kfree(obuf); + + return ret; +} + +static ssize_t amdsfh_debugfs_mag_read(struct file *filp, char __user *ubuf, + size_t count, loff_t *offp) +{ + unsigned int oboff = 0, i; + bool found = false; + ssize_t ret; + char *obuf; + struct amdtp_cl_data *cl_data = filp->private_data; + + for (i = 0; i < cl_data->num_hid_devices; i++) { + if (cl_data->sensor_idx[i] == MAG_IDX) { + found = true; + break; + } + } + + if (!found) + return -1; + + obuf = kmalloc(OBUFLEN, GFP_KERNEL); + if (!obuf) + return -ENOMEM; + + oboff += OSCNPRINTF("Mag_X_Raw:%d\n", + (int)cl_data->sensor_virt_addr[i][0]); + oboff += OSCNPRINTF("Mag_Y_Raw:%d\n", + (int)cl_data->sensor_virt_addr[i][1]); + oboff += OSCNPRINTF("Mag_Z_Raw:%d\n", + (int)cl_data->sensor_virt_addr[i][2]); + ret = simple_read_from_buffer(ubuf, count, offp, obuf, oboff); + + kfree(obuf); + + return ret; +} + +static ssize_t amdsfh_debugfs_als_read(struct file *filp, char __user *ubuf, + size_t count, loff_t *offp) +{ + unsigned int oboff = 0, i; + bool found = false; + ssize_t ret; + char *obuf; + struct amdtp_cl_data *cl_data = filp->private_data; + + for (i = 0; i < cl_data->num_hid_devices; i++) { + if (cl_data->sensor_idx[i] == AMBIENT_LIGHT_IDX) { + found = true; + break; + } + } + + if (!found) + return -1; + + obuf = kmalloc(OBUFLEN, GFP_KERNEL); + if (!obuf) + return -ENOMEM; + + oboff += OSCNPRINTF("Gyro_X_Raw:%d\n", + (int)cl_data->sensor_virt_addr[i][0]); + oboff += OSCNPRINTF("Gyro_Y_Raw:%d\n", + (int)cl_data->sensor_virt_addr[i][1]); + oboff += OSCNPRINTF("Gyro_Z_Raw:%d\n", + (int)cl_data->sensor_virt_addr[i][2]); + ret = simple_read_from_buffer(ubuf, count, offp, obuf, oboff); + + kfree(obuf); + + return ret; +} + +static const struct file_operations amdsfh_debugfs_accel_ops = { + .owner = THIS_MODULE, + .open = simple_open, + .read = amdsfh_debugfs_accel_read, +}; + +static const struct file_operations amdsfh_debugfs_gyro_ops = { + .owner = THIS_MODULE, + .open = simple_open, + .read = amdsfh_debugfs_gyro_read, +}; + +static const struct file_operations amdsfh_debugfs_mag_ops = { + .owner = THIS_MODULE, + .open = simple_open, + .read = amdsfh_debugfs_mag_read, +}; + +static const struct file_operations amdsfh_debugfs_als_ops = { + .owner = THIS_MODULE, + .open = simple_open, + .read = amdsfh_debugfs_als_read, +}; + +int amdsfh_debugfs_setup(struct amdtp_cl_data *cl_data) +{ + /* DebugFS info */ + struct dentry *dbgfs; + int i; + + if (!debugfs_initialized()) + return -1; + + if (!cl_data->amd_debugfs_dir) + cl_data->amd_debugfs_dir = debugfs_create_dir + (KBUILD_MODNAME, NULL); + + if (!cl_data->amd_debugfs_dir) + return -1; + + for (i = 0; i < cl_data->num_hid_devices; i++) { + switch (cl_data->sensor_idx[i]) { + case ACCEL_IDX: + dbgfs = debugfs_create_dir("accel", + cl_data->amd_debugfs_dir); + debugfs_create_file("raw_value", 0400, + dbgfs, cl_data, + &amdsfh_debugfs_accel_ops); + break; + + case GYRO_IDX: + dbgfs = debugfs_create_dir("gyro", + cl_data->amd_debugfs_dir); + debugfs_create_file("raw_value", 0400, + dbgfs, cl_data, + &amdsfh_debugfs_gyro_ops); + break; + + case MAG_IDX: + dbgfs = debugfs_create_dir("magnetometer", + cl_data->amd_debugfs_dir); + debugfs_create_file("raw_value", 0400, + dbgfs, cl_data, + &amdsfh_debugfs_mag_ops); + break; + + case AMBIENT_LIGHT_IDX: + dbgfs = debugfs_create_dir("als", + cl_data->amd_debugfs_dir); + debugfs_create_file("raw_value", 0400, + dbgfs, cl_data, + &amdsfh_debugfs_als_ops); + break; + + default: + return 0; + } + } + return 0; +} +EXPORT_SYMBOL(amdsfh_debugfs_setup); + +void amdsfh_debugfs_destroy(struct amdtp_cl_data *cl_data) +{ + debugfs_remove_recursive(cl_data->amd_debugfs_dir); +} +EXPORT_SYMBOL(amdsfh_debugfs_destroy); diff --git a/drivers/hid/amd-sfh-hid/amdsfh-debugfs.h b/drivers/hid/amd-sfh-hid/amdsfh-debugfs.h new file mode 100644 index 0000000..470f1f12 --- /dev/null +++ b/drivers/hid/amd-sfh-hid/amdsfh-debugfs.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * AMD SFH DebugFS + * Author: Nehal Bakulchandra Shah + */ +#include "amdsfh-hid.h" + +#ifndef AMDSFH_DEBUGFS_H +#define AMDSFH_DEBUGFS_H + +int amdsfh_debugfs_setup(struct amdtp_cl_data *cl_data); +void amdsfh_debugfs_destroy(struct amdtp_cl_data *cl_data); + +#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 0000000..b59cb2f --- /dev/null +++ b/drivers/hid/amd-sfh-hid/amdsfh-hid-client.c @@ -0,0 +1,261 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +/* + * AMD SFH Client Driver + * Author: Nehal Bakulchandra Shah + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "amdsfh-hid.h" +#include "amd_mp2_pcie.h" +#include "hid_descriptor/amd_sfh_hid_descriptor.h" +#include "amdsfh-debugfs.h" + +#define DRIVER_DESC "AMD(R) PCIe MP2 Communication Client Driver" +#define DRIVER_VER "1.0" +#define DRIVER_NAME "AMD_SFH_HID_CLIENT" +#define PERIOD 200 + +struct request_list { + u8 report_id; + u8 sensor_idx; + u8 report_type; + u8 current_index; + struct hid_device *hid; + struct list_head list; +}; + +static struct request_list req_list; +static struct amdtp_cl_data *cl_data_context; + +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); +} +EXPORT_SYMBOL(amd_sfh_set_report); + +void 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_request = kzalloc + (sizeof(*new_request), GFP_KERNEL); + new_request->current_index = i; + new_request->sensor_idx = cli_data->sensor_idx[i]; + new_request->hid = hid; + new_request->report_type = report_type; + new_request->report_id = report_id; + cli_data->report_id[i] = report_id; + cli_data->request_done[i] = false; + list_add(&new_request->list, &req_list.list); + break; + } + } + schedule_delayed_work(&cli_data->work, 0); +} +EXPORT_SYMBOL(amd_sfh_get_report); + +static void amd_sfh_work(struct work_struct *work) +{ + struct amdtp_cl_data *cli_data = amd_sfh_cldata(work); + struct request_list *req_node; + u8 report_size = 0; + u8 current_index; + u8 sensor_index; + u8 report_id; + u8 node_type; + + 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->current_index; + 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]); + } 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]); + } + + 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); + cli_data->cur_hid_dev = current_index; + cli_data->sensor_requested_cnt[current_index] = 0; + kfree(req_node); + 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 = cl_data_context; + unsigned int i; + u8 report_size = 0; + + 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); +} + +static int amd_sfh_hid_client_probe(struct platform_device *pdev) +{ + struct amd_mp2_sensor_info info; + int rc = 0; + int i; + struct amdtp_cl_device *cl_dev; + struct amdtp_cl_data *cl_data; + u32 feature_report_size = 0; + u32 input_report_size = 0; + + cl_dev = devm_kzalloc(&pdev->dev, sizeof(*cl_dev), GFP_KERNEL); + if (!cl_dev) + return -ENOMEM; + + cl_dev->pdev = pci_get_device(PCI_VENDOR_ID_AMD, + PCI_DEVICE_ID_AMD_MP2, NULL); + if (!cl_dev->pdev) + return -ENOMEM; + + cl_data = kzalloc(sizeof(*cl_data), GFP_KERNEL); + cl_data->num_hid_devices = amd_mp2_get_sensor_num + (cl_dev->pdev, &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); + + amdsfh_debugfs_setup(cl_data); + + for (i = 0; i < cl_data->num_hid_devices; i++) { + cl_data->sensor_virt_addr[i] = dma_alloc_coherent + (&pdev->dev, sizeof(int) * 8, + &cl_data->sensor_phy_addr[i], GFP_KERNEL); + cl_data->sensor_sts[i] = 0; + cl_data->sensor_requested_cnt[i] = 0; + cl_data->cur_hid_dev = i; + + cl_data->report_descr_size[i] = get_descriptor_size + (cl_data->sensor_idx[i], descr_size); + + feature_report_size = get_descriptor_size + (cl_data->sensor_idx[i], feature_size); + + input_report_size = get_descriptor_size + (cl_data->sensor_idx[i], input_size); + + cl_data->feature_report[i] = kzalloc(feature_report_size, + GFP_KERNEL); + cl_data->input_report[i] = kzalloc(input_report_size, + GFP_KERNEL); + info.period = PERIOD; + info.sensor_idx = cl_data->sensor_idx[i]; + info.phy_address = cl_data->sensor_phy_addr[i]; + cl_data->report_descr[i] = kzalloc + (cl_data->report_descr_size[i], GFP_KERNEL); + if (!cl_data->report_descr[i]) + return -ENOMEM; + rc = get_report_descriptor(cl_data->sensor_idx[i], + cl_data->report_descr[i]); + rc = amdtp_hid_probe(cl_data->cur_hid_dev, cl_data); + rc = amd_start_sensor(cl_dev->pdev, info); + cl_data->sensor_sts[i] = 1; + } + + cl_dev->cl_data = cl_data; + cl_data_context = cl_data; + platform_set_drvdata(pdev, cl_dev); + schedule_delayed_work(&cl_data->work_buffer, PERIOD); + return 0; +} + +static int amd_sfh_hid_client_remove(struct platform_device *pdev) +{ + int i; + struct amdtp_cl_device *cl_dev; + struct amdtp_cl_data *cl_data; + + cl_dev = platform_get_drvdata(pdev); + if (!(cl_dev)) + return -EINVAL; + + cl_data = cl_dev->cl_data; + if (!(cl_data)) + return -EINVAL; + + for (i = 0; i < cl_data->num_hid_devices; i++) + amd_stop_sensor(cl_dev->pdev, i); + cancel_delayed_work_sync(&cl_data->work); + cancel_delayed_work_sync(&cl_data->work_buffer); + amdsfh_debugfs_destroy(cl_data); + 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(&pdev->dev, 8 * sizeof(int), + cl_data->sensor_virt_addr[i], + cl_data->sensor_phy_addr[i]); + } + + kfree(cl_data); + pr_info("%s:%s Exit\n", DRIVER_NAME, __func__); + return 0; +} + +static const struct acpi_device_id amd_sfh_acpi_match[] = { { + "AMDI0080" }, + { }, +}; + +MODULE_DEVICE_TABLE(acpi, amd_sfh_acpi_match); +static struct platform_driver amd_sfh_plat_driver = { + .probe = amd_sfh_hid_client_probe, + .remove = amd_sfh_hid_client_remove, + .driver = { + .name = "amd_sfh_platform", + .acpi_match_table = ACPI_PTR(amd_sfh_acpi_match), + }, +}; +module_platform_driver(amd_sfh_plat_driver); +MODULE_DESCRIPTION("AMD(R) SFH Client Driver"); +MODULE_AUTHOR("Nehal Shah "); +MODULE_LICENSE("Dual BSD/GPL"); 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 0000000..89fe35a8 --- /dev/null +++ b/drivers/hid/amd-sfh-hid/amdsfh-hid.c @@ -0,0 +1,179 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +/* + * AMD MP2 Sensors transport driver + * + * Authors: Sandeep Singh + * Nehal Bakulchandra Shah + */ +#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; + int rc; + + rc = hid_parse_report(hid, cli_data->report_descr[hid_data->index], + cli_data->report_descr_size[hid_data->index]); + if (rc) + return rc; + return 0; +} + +/* 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, unsigned char reportnum, + u8 *buf, size_t len, unsigned char rtype, + int reqtype) +{ + return 0; +} + +static void amdtp_hid_request(struct hid_device *hid, struct hid_report *rep, + int reqtype) +{ + switch (reqtype) { + case HID_REQ_GET_REPORT: + amd_sfh_get_report(hid, rep->id, rep->type); + break; + case HID_REQ_SET_REPORT: + amd_sfh_set_report(hid, rep->id, reqtype); + 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 = 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]) + wait_event_interruptible_timeout(hid_data->hid_wait, + cli_data->request_done[i], + 1500); + if (!cli_data->request_done[i]) { + hid_err(hid, + "timeout waiting for response from device\n"); + return -ETIMEDOUT; + } + cli_data->request_done[i] = false; + + return 0; +} + +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(unsigned int cur_hid_dev, + struct amdtp_cl_data *cli_data) +{ + int rc; + struct hid_device *hid; + struct amdtp_hid_data *hid_data; + + hid = hid_allocate_device(); + if (IS_ERR(hid)) { + rc = PTR_ERR(hid); + return -ENOMEM; + } + + 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->version = AMD_SFH_HID_VERSION; + 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 0000000..8bbe40c --- /dev/null +++ b/drivers/hid/amd-sfh-hid/amdsfh-hid.h @@ -0,0 +1,85 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * AMD MP2 Sensors transport driver + * + * Authors: Sandeep Singh + * Nehal Bakulchandra Shah + */ + +#ifndef AMDSFH_HID_H +#define AMDSFH_HID_H +#include + +#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 +#define AMD_SFH_HID_VERSION 0x0001 + +struct amdtp_cl_device { + struct pci_dev *pdev; + struct amdtp_cl_data *cl_data; +}; + +struct amdtp_cl_data { + u8 init_done; + unsigned int cur_hid_dev; + unsigned int hid_dev_count; + unsigned int num_hid_devices; + struct device_info *hid_devices; + unsigned char *report_descr[MAX_HID_DEVICES]; + int report_descr_size[MAX_HID_DEVICES]; + struct hid_device *hid_sensor_hubs[MAX_HID_DEVICES]; + unsigned char *hid_descr[MAX_HID_DEVICES]; + int hid_descr_size[MAX_HID_DEVICES]; + phys_addr_t phy_addr_base; + u32 *sensor_virt_addr[MAX_HID_DEVICES]; + phys_addr_t sensor_phy_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 dentry *amd_debugfs_dir; + +}; + +/** + * 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, unsigned int len, + int report_id); +void hid_amdtp_get_report(struct hid_device *hid, int report_id, + int report_type); +int amdtp_hid_probe(unsigned int cur_hid_dev, + struct amdtp_cl_data *cli_data); +void amdtp_hid_remove(struct amdtp_cl_data *cli_data); +void 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); + +#define amd_sfh_cldata(__work) container_of(__work,\ + struct amdtp_cl_data, work.work) +#endif /* AMDSFH_HID */