Received: by 10.223.176.46 with SMTP id f43csp1361557wra; Wed, 24 Jan 2018 15:22:46 -0800 (PST) X-Google-Smtp-Source: AH8x225BabdQLuW8qfn/gUwLIvdGtbwR3E5cOAHUL3XP7W2cKcTZoPAJ4p16hSdFvnRYemFxLCg9 X-Received: by 10.101.83.195 with SMTP id z3mr11962922pgr.133.1516836166113; Wed, 24 Jan 2018 15:22:46 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1516836166; cv=none; d=google.com; s=arc-20160816; b=lFh9+z3NmAiOgm9mmY65TS4IYAYsq6AnD96MYrDV8r05OhJ6N9QBKDTZvsf2p/2+J9 WDTPbmdhsSgiI5Z4Zfh4BqFCVfDzOAWW2bQrAhYnqhM34efpXn24l8Vgm5S8OfMNTQvt NatRRik/0cFfKFkAimHp3M/2vJO0CGMfBKPNzUpwoXVvLgFFpm/XoltVc93HlvELCsOk TVf8F7S9KG9zJbq2q9SSm8WFZ9eLeZ/m9f+9TuEidnkVA025SoslCJZTaa4RbIKmWPBq vSXbrX5btrMmkLzYId6l17LfpjP3JM+y0ONFQzRGdZVDq50X3L1lOTBRzA2Zq47ojjig 7wqw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:spamdiagnosticmetadata :spamdiagnosticoutput:mime-version:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature:arc-authentication-results; bh=V83yHAZ4S/aRsJ+3gCnjFwUVmv47VTO5zKixOwuHBZo=; b=KayXAEAs1jpvPzw5oiM6bLzIkae56xsGSHpeCL56GiSTRQL71NOCu7eZ6D62tfRVaJ i252cxGVEk9s/bfruPn0IeLhEUtQTaaHkDgB5rOfbox47TIVEykuqg0OmWPB0MV2ggtL YyoDsLn9Zf6y1Bqyss+JLuEZFx4KQ893HgJAFwPsyW1YSYkcnME64MLB4y8YtMUf7Rws IrJH/sKJmxticY/Znsefv2U/D5iQ0pgEq/cd9gxcrVwsNZ/URIqKl9J7JsDyZoX2bOaA coBuUWViTGvTHMb7+rFgNFeLoaSxIwdQ4gUkQOLYAUKbdcLkZSew04DtFfLSPaWLo2rM 3u1A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@xilinx.onmicrosoft.com header.s=selector1-xilinx-com header.b=Uxc3PhCh; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id r80si3593334pfa.358.2018.01.24.15.22.32; Wed, 24 Jan 2018 15:22:46 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@xilinx.onmicrosoft.com header.s=selector1-xilinx-com header.b=Uxc3PhCh; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933164AbeAXXWC (ORCPT + 99 others); Wed, 24 Jan 2018 18:22:02 -0500 Received: from mail-dm3nam03on0057.outbound.protection.outlook.com ([104.47.41.57]:6739 "EHLO NAM03-DM3-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S932987AbeAXXVz (ORCPT ); Wed, 24 Jan 2018 18:21:55 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=xilinx.onmicrosoft.com; s=selector1-xilinx-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version; bh=V83yHAZ4S/aRsJ+3gCnjFwUVmv47VTO5zKixOwuHBZo=; b=Uxc3PhChIjRYixr1/2FsWoAb5dYS8aCd0D+du0SwTol1+ZV0hJ6gt40gTI0y3IIwnDOkO8ExPCpq4cac/6ilcl7uxM49T04LfWle+FMkpfFO1u5soKnSJPgFlnOP9sWMOqgielu43mO/W9ceKkC9oFbTUIPmFF/akO/Bkt2SMlo= Received: from BN6PR02CA0097.namprd02.prod.outlook.com (10.161.158.38) by DM5PR02MB3274.namprd02.prod.outlook.com (10.164.148.28) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P256) id 15.20.444.14; Wed, 24 Jan 2018 23:21:50 +0000 Received: from SN1NAM02FT029.eop-nam02.prod.protection.outlook.com (2a01:111:f400:7e44::203) by BN6PR02CA0097.outlook.office365.com (2603:10b6:405:60::38) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.20.444.14 via Frontend Transport; Wed, 24 Jan 2018 23:21:49 +0000 Authentication-Results: spf=pass (sender IP is 149.199.60.83) smtp.mailfrom=xilinx.com; vger.kernel.org; dkim=none (message not signed) header.d=none;vger.kernel.org; dmarc=bestguesspass action=none header.from=xilinx.com; Received-SPF: Pass (protection.outlook.com: domain of xilinx.com designates 149.199.60.83 as permitted sender) receiver=protection.outlook.com; client-ip=149.199.60.83; helo=xsj-pvapsmtpgw01; Received: from xsj-pvapsmtpgw01 (149.199.60.83) by SN1NAM02FT029.mail.protection.outlook.com (10.152.72.110) with Microsoft SMTP Server (version=TLS1_0, cipher=TLS_RSA_WITH_AES_256_CBC_SHA) id 15.20.444.13 via Frontend Transport; Wed, 24 Jan 2018 23:21:43 +0000 Received: from unknown-38-66.xilinx.com ([149.199.38.66] helo=xsj-pvapsmtp01) by xsj-pvapsmtpgw01 with esmtp (Exim 4.63) (envelope-from ) id 1eeUMQ-0001td-Uk; Wed, 24 Jan 2018 15:21:42 -0800 Received: from [127.0.0.1] (helo=localhost) by xsj-pvapsmtp01 with smtp (Exim 4.63) (envelope-from ) id 1eeUMQ-0001C0-SG; Wed, 24 Jan 2018 15:21:42 -0800 Received: from xsj-pvapsmtp01 (xsj-pvapsmtp01.xilinx.com [149.199.38.66]) by xsj-smtp-dlp1.xlnx.xilinx.com (8.13.8/8.13.1) with ESMTP id w0ONLcKM020806; Wed, 24 Jan 2018 15:21:38 -0800 Received: from [172.19.2.91] (helo=xsjjollys50.xilinx.com) by xsj-pvapsmtp01 with esmtp (Exim 4.63) (envelope-from ) id 1eeUMM-0001B7-6b; Wed, 24 Jan 2018 15:21:38 -0800 From: Jolly Shah To: , , , , , , , , , , CC: , , , Jolly Shah , Rajan Vaja Subject: [PATCH v3 4/4] drivers: firmware: xilinx: Add debugfs interface Date: Wed, 24 Jan 2018 15:21:14 -0800 Message-ID: <1516836074-4149-5-git-send-email-jollys@xilinx.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1516836074-4149-1-git-send-email-jollys@xilinx.com> References: <1516836074-4149-1-git-send-email-jollys@xilinx.com> X-RCIS-Action: ALLOW X-TM-AS-Product-Ver: IMSS-7.1.0.1224-8.2.0.1013-23616.006 X-TM-AS-User-Approved-Sender: Yes;Yes X-EOPAttributedMessage: 0 X-MS-Office365-Filtering-HT: Tenant X-Forefront-Antispam-Report: CIP:149.199.60.83;IPV:NLI;CTRY:US;EFV:NLI;SFV:NSPM;SFS:(10009020)(346002)(376002)(39380400002)(396003)(39860400002)(2980300002)(438002)(199004)(189003)(288314003)(2950100002)(6666003)(4326008)(106466001)(186003)(36756003)(81166006)(8676002)(81156014)(50226002)(8936002)(9786002)(107886003)(39060400002)(72206003)(7416002)(305945005)(2906002)(356003)(63266004)(36386004)(48376002)(478600001)(5660300001)(50466002)(316002)(7696005)(51416003)(336011)(26005)(106002)(54906003)(2201001)(16586007)(110136005)(575784001)(77096007)(76176011)(47776003)(59450400001)(107986001)(921003)(1121003);DIR:OUT;SFP:1101;SCL:1;SRVR:DM5PR02MB3274;H:xsj-pvapsmtpgw01;FPR:;SPF:Pass;PTR:unknown-60-83.xilinx.com;A:1;MX:1;LANG:en; X-Microsoft-Exchange-Diagnostics: 1;SN1NAM02FT029;1:zRPF41d6OBnTWYchdFWMFu2mZ68eF3FJoKGn/BWP0dAdvklAvtW86LBj53VgPNBiLon3YuMVBTM2jPrL9HnWTWlSoI4p+JObNjIhXoYUWoVTSdyx8aI8jk2j2oEgOy4I MIME-Version: 1.0 Content-Type: text/plain X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: af6bdbe8-304c-46d6-0377-08d563813e20 X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:(7020095)(4652020)(4534165)(4627221)(201703031133081)(201702281549075)(5600026)(4604075)(4608076)(2017052603307)(7153060);SRVR:DM5PR02MB3274; X-Microsoft-Exchange-Diagnostics: 1;DM5PR02MB3274;3:jV2+lIy133rHq6BRWNq1qkHL7YE0wFk99d/n5YmhUNyDlkK499TWgA5+XrNWyMYFKcOq2dx6bjNnxC+jV1lrpiM8Pr5o6LMkRGqH5WL7oM8s7b9GQKDV0Uu3OqlmcwODqIduNng9F9kBrBzVmtnzUIzX8h0YYDuJV36fHQL9PzRtnpfPAzTffApd0swa93t0Ur7qlMgHY6oDIk50SYqh0IWrisCIh9herY/TK200MnVfiqeL4MP9jYXx7zpULDJiCGSRCTLLIJhJ2LkQZbgVLzDnuiLj2vHl8TRJ3wDvuaY75js8VbLpB+6HL5rfNdR4+HBwdB7u2XwylxX6d0xfjffXj5n2AgZiE2QUPS93948=;25:hCKACQJyQmRxC3Q9zDGflXcRMXsAQo7uMCASYiczJq9GB07LMyBtxvhk07oBdJRdAjipyGQBz4ZlGCJi1HmZ7QmhlFrL8NYrIoacqDO1ZJTZwW4lHgkb49+mwcRY80EebiO6je3xR5e1B8lsHLsKErHORVy7nxWu7qc/eUTEZMyigsDTkCzrvHHDIiO//Rbjij7tdFq0ksVrdtZjdL3Gj/Cb3Lf8HQ96t9LeDeHXSd9fHgrLYZBMPm3h0hc7NEpYO89R+Cc8VnDj2XKRUdkqZanfqQ0c5w9GBv1YtxkjLzkzptfj3/5qGDApzjZ37BYsfntj60aXvgIwr8mWb86y0Q== X-MS-TrafficTypeDiagnostic: DM5PR02MB3274: X-Microsoft-Exchange-Diagnostics: 1;DM5PR02MB3274;31:cX3Ql1tmbbrO+0qRdMmhO59+D36LmO5rFcgeUN1Xl0teLRmK4/YoBPQmDvGd7wgSG2oR9Eb9EHB7pFbAohY+wy43hHIhVl6C3Xger+b3Cwso9xaB/td48EMy+EDpQ8jvD5SkqpyKzd3XCEZmBuWB0mUoCpFtk4cwz2mZZW64zuYOZtPQFqudx1KQpxInmPjGf8ph51HzkTxkv8J7XwqYoSow9C6HGTilUgUBH7ge27s=;20:OHgSaPmpOe3CUQ3X2fvYgL1wSngpSlqUNLgmL2zsO1PrEdLTc+YR+9BgCU71N4cRkIzzeZDpIYnAOmwwNkrupRsbUKX5O4aGf54pFLhW+DrmNA3douIZPGf7m2DZ5TAJhY5JfML9KnHGVSHrMkrdvCJk6Vm5m+uxS4vF+mk9QF/9eIGTp1iLuTMK+cxHXoj2uO/yjyEaFPYDjyPD9nDDfokhB1VGDseczXcV7CkOax7YW1f6uS8WZqffsMe7/OGUxJZTxV+byOUDUYASi1GfmnLL+YVSTCm6eNHSkyqKO5hKfJ9lArCIzb/k91DBiN5nSFZSj5H6a4IePfaDV1VDB1I5ncXbFd0Ra8L9hH7nMYmtwFfcHQIfxg7B/edU0XyMQsuysTADDO36fZ/AZWPz8fCNk1NGjmj/9yOOKhLZdppTN9K1aQwNClhvX/M6xu//oDXjg89+AyPHlR9A3RlTkwMbdXfhhUmRkIHcookzPGefLud9Y+OKmFuzE9A+FNMA X-Auto-Response-Suppress: DR, RN, NRN, OOF, AutoReply X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(192813158149592); X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(6040501)(2401047)(8121501046)(5005006)(3231023)(2400081)(944501161)(10201501046)(93006095)(93004095)(3002001)(6055026)(6041288)(20161123562045)(20161123558120)(20161123564045)(201703131423095)(201702281528075)(20161123555045)(201703061421075)(201703061406153)(20161123560045)(6072148)(201708071742011);SRVR:DM5PR02MB3274;BCL:0;PCL:0;RULEID:;SRVR:DM5PR02MB3274; X-Microsoft-Exchange-Diagnostics: 1;DM5PR02MB3274;4:02TTcsNXSovU24QdPTTN4zrlVUNMF6EjIqFOl8DNce8/EJvqefNGooR/pN9f1HKC6w0Xf1xVBk7w5HbcNBdvqW9b57+UR/mKfTgy+1bQDT8rAhRwRUV0bZEg6tsym4L9Z14rvdqotTQ9uw56KPqCmAbcpYEU+UjgzAgECm1785+jRGE1QKP6Q34p/O7N74cQxopj1+GO0K3+eDKSkShFqV5CKs3KZZXxedA4p/Z5lyxITylsqPgNQRJgFbyeT7dUObhTYAdgobUjG/Ovsfa/EA+wQ267Qx1u5jo7l8Du+8Ooi5PzoTRwlIagLQFzLp8o X-Forefront-PRVS: 056297E276 X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1;DM5PR02MB3274;23:uBiIutrC4JIHWtEBcbYMa8S/MtdKeWcx2ab0SOc33?= =?us-ascii?Q?OMH7O+FTBWpjKuEoq63QHB2n0iT4mc2dzHpWPsK8onA9C5lJTkobgh7Yy9Vc?= =?us-ascii?Q?SujDcJ5QkcPxNkoDROeY4Z1BRrhReqt8CYGtW9ApLgk3z1b7is0V1MM5UgFZ?= =?us-ascii?Q?3Af5l/QWWkiP/+jVIqEtElpabhUbSP4QPMADnwh/C32oLchXaHzOOdd9WlMW?= =?us-ascii?Q?kWZq1B8EZj/qp/tolYg4/KeDt8+2+0gtJr/UDmUYwfKbIV5Sm3i+DKBBowxo?= =?us-ascii?Q?U+UB7And8iExUCXjVU/oVp9a4U/bifV260eaHAuPUPzkhVGr9dsDir5I6HQn?= =?us-ascii?Q?VxXVsE5JPhoC042qq7cLY10HLABlfj/0r3c9vIZd+9cOQYSbFqs21yV0oAJf?= =?us-ascii?Q?sbzF6d+wTyXl+Ris6/17c1zuJobDzdjafQGRyF/NwxA+eQEFcOKmu5WtNFxk?= =?us-ascii?Q?gOVzWZhw3ulDjSH/WLz75CmlIm5ku/QvTK2DVtEkLBgCtkEehSfcdrHl1SlY?= =?us-ascii?Q?pomVOwn5R4pr+jVkGFtcBlgEADAkIZrWlyujxN9+pCfczN5FJmVwoLrW3/sv?= =?us-ascii?Q?K6Gb2cN0huX33OZwfLvTXfQAVwv5KR3rmcSBACdW9o5TfSHuxOuzbE2uquMb?= =?us-ascii?Q?OyonJ0uAac4lMcDzpBOsm4lbukWT1Lb2jkjfK8JnOsE9i6DxhjUb4N64g7f7?= =?us-ascii?Q?U/b3zGrDkV67KTazR/nSymUlo8a9ihc85T2j5KvHPKnD+H+a1bpsNmWnvn5a?= =?us-ascii?Q?Pz+bz1IriY7CCS4wF6VmW1siHxMIoerpgkOhDfr4hQVMH09tQX+hACpdeJVQ?= =?us-ascii?Q?AStPV8sTHiE2TtbtyWLewSVmoGXjYjVaDYHpVNDZ9TzSETP6dTd12uXFL4Gx?= =?us-ascii?Q?58og306NkRs4yDjc5R86S1cJxoEvAnwambgCtatoesbL4/WyGC2zmZ6vNplT?= =?us-ascii?Q?bO4fGTHpjqOEViZkNfEbPVjXpEwXccAYV5BOsQi0aiDQhLiUj8k8bB9wPe7o?= =?us-ascii?Q?CCHPM3FbCItXV+MhRFfkHlY1emR7T2D4RHt53UBANHLQ7wAu+LrxLpBk2GG7?= =?us-ascii?Q?qzFGnXJJQshk24tdV98cJjbxUKimh1on/bzXuSozbSbaOm3x/Qbh/jxxPq3d?= =?us-ascii?Q?XvHfpbShOJyht2zMgsFKnhroEzI983NmnlIgQgqZ10sCJBE4MVG/Jku5RlBA?= =?us-ascii?Q?r7iP61W4pVAQKSn/B4SsiE0UA5dNH+ji5+meBE8EaJ/UkIbtuRS5/dPrQ=3D?= =?us-ascii?Q?=3D?= X-Microsoft-Exchange-Diagnostics: 1;DM5PR02MB3274;6:hy1S9XTRhODM0SLH7ytUU2r5eIKyGrkjBgetWjMEDFI8HXYehEpcPVqxDljcves6vUtSLkb/Uy9g/X79Dm0XbEjvUlClP1UkgCRy7u0++n0thpp7MDuFH67EEkGSCPOBITpWBerB9MdwFBix2avubzaoiVxdNT1SzJ/whZFXcU2CF3rke5pJ+Rzsu/H3OaYIaFSizoKpgEDhe9fDkiCl42zaAlCLbyKXgEGuK1BDZlXopMJQ9KkAeJcl5bUDgjnhYj8o2+3xU6xRKtRfLuiuWge8HBe28ODJGll/yQ/ecRG+TPRi1bCgzgvDxZdCDBcUU/RIGCklPsnGovT/XidPKBjnjosuiFX+2+zKgazS6I0=;5:wNoisoYd/OdWy9FK/usR+shZVdAMR/K9N7lpo/07EAIB0PfqBIzfaOxUCfIHXN/LlgLfuWla4/aFN0LECIKyrCgPyyhWyJcvdivM6z9rsqovGYc/AsHRfD71n8VSVULVYGsv4uE/7BeGXaGA7uBUHQeD9lF6sMyVACxL/+cX3S4=;24:oaDQ034ZYcWaooBxRJYJDy5DsJLS5PGTczQlkPqKF94BTfhI1yEQSmHpjTy1CkLuUxfApU0AX5a1V5g3I8dHc9WaYATqxvaF13V1Kqrqh+A=;7:PpFmdejy4RSosWu+gUX5wJfKg+Z0YVJ32iQ0ynTvQiL6yCiI0ZQDlbrN2GJsqGZWJrbEXuVO7DN5CLLvbzlquBnvMLt/7g+I1mMn8xCCY0aam9wk4JPEmA66KefjDaMyTeyAUNHMTdgnia60lZPnLiDmYz2jgsPZ0zB88YNipGWcn77PYWHaSitBQWmGG18bxhbbauKzLRTERUENmsSS6h3AX66WNZcdN2SmpLKLfbeKXOA2mTtRIfqhoYeDu43I SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: xilinx.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 24 Jan 2018 23:21:43.8390 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: af6bdbe8-304c-46d6-0377-08d563813e20 X-MS-Exchange-CrossTenant-Id: 657af505-d5df-48d0-8300-c31994686c5c X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=657af505-d5df-48d0-8300-c31994686c5c;Ip=[149.199.60.83];Helo=[xsj-pvapsmtpgw01] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM5PR02MB3274 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Firmware-debug provides debugfs interface to all APIs. Signed-off-by: Jolly Shah Signed-off-by: Rajan Vaja --- drivers/firmware/xilinx/zynqmp/Kconfig | 7 + drivers/firmware/xilinx/zynqmp/Makefile | 1 + drivers/firmware/xilinx/zynqmp/firmware-debug.c | 511 +++++++++++++++++++++ drivers/firmware/xilinx/zynqmp/firmware.c | 7 +- .../linux/firmware/xilinx/zynqmp/firmware-debug.h | 31 ++ 5 files changed, 556 insertions(+), 1 deletion(-) create mode 100644 drivers/firmware/xilinx/zynqmp/firmware-debug.c create mode 100644 include/linux/firmware/xilinx/zynqmp/firmware-debug.h diff --git a/drivers/firmware/xilinx/zynqmp/Kconfig b/drivers/firmware/xilinx/zynqmp/Kconfig index 8f7709d..bdd0188 100644 --- a/drivers/firmware/xilinx/zynqmp/Kconfig +++ b/drivers/firmware/xilinx/zynqmp/Kconfig @@ -13,4 +13,11 @@ config ZYNQMP_FIRMWARE Say yes to enable zynqmp firmware interface driver. In doubt, say N +config ZYNQMP_FIRMWARE_DEBUG + bool "Enable Xilinx Zynq MPSoC firmware debug APIs" + default ARCH_ZYNQMP && ZYNQMP_FIRMWARE && DEBUG_FS + help + Say yes to enable zynqmp firmware interface debug APIs. + In doubt, say N + endmenu diff --git a/drivers/firmware/xilinx/zynqmp/Makefile b/drivers/firmware/xilinx/zynqmp/Makefile index 6629781..02f0c9a 100644 --- a/drivers/firmware/xilinx/zynqmp/Makefile +++ b/drivers/firmware/xilinx/zynqmp/Makefile @@ -2,3 +2,4 @@ # Makefile for Xilinx firmwares obj-$(CONFIG_ZYNQMP_FIRMWARE) += firmware.o firmware-ggs.o +obj-$(CONFIG_ZYNQMP_FIRMWARE_DEBUG) += firmware-debug.o diff --git a/drivers/firmware/xilinx/zynqmp/firmware-debug.c b/drivers/firmware/xilinx/zynqmp/firmware-debug.c new file mode 100644 index 0000000..daefc62 --- /dev/null +++ b/drivers/firmware/xilinx/zynqmp/firmware-debug.c @@ -0,0 +1,511 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Xilinx Zynq MPSoC Firmware layer for debugfs APIs + * + * Copyright (C) 2014-2018 Xilinx, Inc. + * + * Michal Simek + * Davorin Mista + * Jolly Shah + * Rajan Vaja + */ + +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_NAME "zynqmp-firmware" + +#define PM_API_NAME_LEN 50 +#define MAX_API_VERSION_RESP_LEN 50 + +struct pm_api_info { + u32 api_id; + char api_name[PM_API_NAME_LEN]; + char api_name_len; +}; + +#define PM_API(id) {id, #id, strlen(#id)} +static struct pm_api_info pm_api_list[] = { + PM_API(PM_REQUEST_SUSPEND), + PM_API(PM_SELF_SUSPEND), + PM_API(PM_FORCE_POWERDOWN), + PM_API(PM_ABORT_SUSPEND), + PM_API(PM_REQUEST_WAKEUP), + PM_API(PM_SET_WAKEUP_SOURCE), + PM_API(PM_SYSTEM_SHUTDOWN), + PM_API(PM_REQUEST_NODE), + PM_API(PM_RELEASE_NODE), + PM_API(PM_SET_REQUIREMENT), + PM_API(PM_SET_MAX_LATENCY), + PM_API(PM_GET_API_VERSION), + PM_API(PM_SET_CONFIGURATION), + PM_API(PM_GET_NODE_STATUS), + PM_API(PM_GET_OPERATING_CHARACTERISTIC), + PM_API(PM_REGISTER_NOTIFIER), + PM_API(PM_RESET_ASSERT), + PM_API(PM_RESET_GET_STATUS), + PM_API(PM_MMIO_READ), + PM_API(PM_MMIO_WRITE), + PM_API(PM_GET_CHIPID), + PM_API(PM_PINCTRL_GET_FUNCTION), + PM_API(PM_PINCTRL_SET_FUNCTION), + PM_API(PM_PINCTRL_CONFIG_PARAM_GET), + PM_API(PM_PINCTRL_CONFIG_PARAM_SET), + PM_API(PM_IOCTL), + PM_API(PM_CLOCK_ENABLE), + PM_API(PM_CLOCK_DISABLE), + PM_API(PM_CLOCK_GETSTATE), + PM_API(PM_CLOCK_SETDIVIDER), + PM_API(PM_CLOCK_GETDIVIDER), + PM_API(PM_CLOCK_SETRATE), + PM_API(PM_CLOCK_GETRATE), + PM_API(PM_CLOCK_SETPARENT), + PM_API(PM_CLOCK_GETPARENT), + PM_API(PM_QUERY_DATA), +}; + +/** + * zynqmp_pm_self_suspend - PM call for master to suspend itself + * @node: Node ID of the master or subsystem + * @latency: Requested maximum wakeup latency (not supported) + * @state: Requested state (not supported) + * + * Return: Returns status, either success or error+reason + */ +int zynqmp_pm_self_suspend(const u32 node, + const u32 latency, + const u32 state) +{ + return invoke_pm_fn(PM_SELF_SUSPEND, node, latency, state, 0, NULL); +} + +/** + * zynqmp_pm_abort_suspend - PM call to announce that a prior suspend request + * is to be aborted. + * @reason: Reason for the abort + * + * Return: Returns status, either success or error+reason + */ +int zynqmp_pm_abort_suspend(const enum zynqmp_pm_abort_reason reason) +{ + return invoke_pm_fn(PM_ABORT_SUSPEND, reason, 0, 0, 0, NULL); +} + +/** + * zynqmp_pm_register_notifier - Register the PU to be notified of PM events + * @node: Node ID of the slave + * @event: The event to be notified about + * @wake: Wake up on event + * @enable: Enable or disable the notifier + * + * Return: Returns status, either success or error+reason + */ +int zynqmp_pm_register_notifier(const u32 node, const u32 event, + const u32 wake, const u32 enable) +{ + return invoke_pm_fn(PM_REGISTER_NOTIFIER, node, event, + wake, enable, NULL); +} + +/** + * zynqmp_pm_argument_value - Extract argument value from a PM-API request + * @arg: Entered PM-API argument in string format + * + * Return: Argument value in unsigned integer format on success + * 0 otherwise + */ +static u64 zynqmp_pm_argument_value(char *arg) +{ + u64 value; + + if (!arg) + return 0; + + if (!kstrtou64(arg, 0, &value)) + return value; + + return 0; +} + +static int get_pm_api_id(char *pm_api_req, u32 *pm_id) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(pm_api_list) ; i++) { + if (!strncasecmp(pm_api_req, pm_api_list[i].api_name, + pm_api_list[i].api_name_len)) { + *pm_id = pm_api_list[i].api_id; + break; + } + } + + /* If no name was entered look for PM-API ID instead */ + if (i == ARRAY_SIZE(pm_api_list) && kstrtouint(pm_api_req, 10, pm_id)) + return -EINVAL; + + return 0; +} + +static int process_api_request(u32 pm_id, u64 *pm_api_arg, u32 *pm_api_ret) +{ + const struct zynqmp_eemi_ops *eemi_ops = get_eemi_ops(); + u32 pm_api_version; + int ret; + + if (!eemi_ops) + return -ENXIO; + + switch (pm_id) { + case PM_GET_API_VERSION: + eemi_ops->get_api_version(&pm_api_version); + pr_info("%s PM-API Version = %d.%d\n", __func__, + pm_api_version >> 16, pm_api_version & 0xffff); + break; + case PM_REQUEST_SUSPEND: + ret = eemi_ops->request_suspend(pm_api_arg[0], + pm_api_arg[1] ? pm_api_arg[1] : + ZYNQMP_PM_REQUEST_ACK_NO, + pm_api_arg[2] ? pm_api_arg[2] : + ZYNQMP_PM_MAX_LATENCY, 0); + break; + case PM_SELF_SUSPEND: + ret = zynqmp_pm_self_suspend(pm_api_arg[0], + pm_api_arg[1] ? pm_api_arg[1] : + ZYNQMP_PM_MAX_LATENCY, 0); + break; + case PM_FORCE_POWERDOWN: + ret = eemi_ops->force_powerdown(pm_api_arg[0], + pm_api_arg[1] ? pm_api_arg[1] : + ZYNQMP_PM_REQUEST_ACK_NO); + break; + case PM_ABORT_SUSPEND: + ret = zynqmp_pm_abort_suspend(pm_api_arg[0] ? pm_api_arg[0] : + ZYNQMP_PM_ABORT_REASON_UNKNOWN); + break; + case PM_REQUEST_WAKEUP: + ret = eemi_ops->request_wakeup(pm_api_arg[0], + pm_api_arg[1], pm_api_arg[2], + pm_api_arg[3] ? pm_api_arg[3] : + ZYNQMP_PM_REQUEST_ACK_NO); + break; + case PM_SET_WAKEUP_SOURCE: + ret = eemi_ops->set_wakeup_source(pm_api_arg[0], pm_api_arg[1], + pm_api_arg[2]); + break; + case PM_SYSTEM_SHUTDOWN: + ret = eemi_ops->system_shutdown(pm_api_arg[0], pm_api_arg[1]); + break; + case PM_REQUEST_NODE: + ret = eemi_ops->request_node(pm_api_arg[0], + pm_api_arg[1] ? pm_api_arg[1] : + ZYNQMP_PM_CAPABILITY_ACCESS, + pm_api_arg[2] ? pm_api_arg[2] : 0, + pm_api_arg[3] ? pm_api_arg[3] : + ZYNQMP_PM_REQUEST_ACK_BLOCKING); + break; + case PM_RELEASE_NODE: + ret = eemi_ops->release_node(pm_api_arg[0]); + break; + case PM_SET_REQUIREMENT: + ret = eemi_ops->set_requirement(pm_api_arg[0], + pm_api_arg[1] ? pm_api_arg[1] : + ZYNQMP_PM_CAPABILITY_CONTEXT, + pm_api_arg[2] ? + pm_api_arg[2] : 0, + pm_api_arg[3] ? pm_api_arg[3] : + ZYNQMP_PM_REQUEST_ACK_BLOCKING); + break; + case PM_SET_MAX_LATENCY: + ret = eemi_ops->set_max_latency(pm_api_arg[0], + pm_api_arg[1] ? pm_api_arg[1] : + ZYNQMP_PM_MAX_LATENCY); + break; + case PM_SET_CONFIGURATION: + ret = eemi_ops->set_configuration(pm_api_arg[0]); + break; + case PM_GET_NODE_STATUS: + ret = eemi_ops->get_node_status(pm_api_arg[0], + &pm_api_ret[0], + &pm_api_ret[1], + &pm_api_ret[2]); + if (!ret) + pr_info("GET_NODE_STATUS:\n\tNodeId: %llu\n\tStatus: %u\n\tRequirements: %u\n\tUsage: %u\n", + pm_api_arg[0], pm_api_ret[0], + pm_api_ret[1], pm_api_ret[2]); + break; + case PM_GET_OPERATING_CHARACTERISTIC: + ret = eemi_ops->get_operating_characteristic(pm_api_arg[0], + pm_api_arg[1] ? pm_api_arg[1] : + ZYNQMP_PM_OPERATING_CHARACTERISTIC_POWER, + &pm_api_ret[0]); + if (!ret) + pr_info("GET_OPERATING_CHARACTERISTIC:\n\tNodeId: %llu\n\tType: %llu\n\tResult: %u\n", + pm_api_arg[0], pm_api_arg[1], pm_api_ret[0]); + break; + case PM_REGISTER_NOTIFIER: + ret = zynqmp_pm_register_notifier(pm_api_arg[0], + pm_api_arg[1] ? + pm_api_arg[1] : 0, + pm_api_arg[2] ? + pm_api_arg[2] : 0, + pm_api_arg[3] ? + pm_api_arg[3] : 0); + break; + case PM_RESET_ASSERT: + ret = eemi_ops->reset_assert(pm_api_arg[0], pm_api_arg[1]); + break; + case PM_RESET_GET_STATUS: + ret = eemi_ops->reset_get_status(pm_api_arg[0], &pm_api_ret[0]); + pr_info("%s Reset status: %u\n", __func__, pm_api_ret[0]); + break; + case PM_GET_CHIPID: + ret = eemi_ops->get_chipid(&pm_api_ret[0], &pm_api_ret[1]); + pr_info("%s idcode: %#x, version:%#x\n", + __func__, pm_api_ret[0], pm_api_ret[1]); + break; + case PM_PINCTRL_GET_FUNCTION: + ret = eemi_ops->pinctrl_get_function(pm_api_arg[0], + &pm_api_ret[0]); + pr_info("%s Current set function for the pin: %u\n", + __func__, pm_api_ret[0]); + break; + case PM_PINCTRL_SET_FUNCTION: + ret = eemi_ops->pinctrl_set_function(pm_api_arg[0], + pm_api_arg[1]); + break; + case PM_PINCTRL_CONFIG_PARAM_GET: + ret = eemi_ops->pinctrl_get_config(pm_api_arg[0], pm_api_arg[1], + &pm_api_ret[0]); + pr_info("%s pin: %llu, param: %llu, value: %u\n", + __func__, pm_api_arg[0], pm_api_arg[1], + pm_api_ret[0]); + break; + case PM_PINCTRL_CONFIG_PARAM_SET: + ret = eemi_ops->pinctrl_set_config(pm_api_arg[0], + pm_api_arg[1], + pm_api_arg[2]); + break; + case PM_IOCTL: + ret = eemi_ops->ioctl(pm_api_arg[0], pm_api_arg[1], + pm_api_arg[2], pm_api_arg[3], + &pm_api_ret[0]); + if (pm_api_arg[1] == IOCTL_GET_RPU_OPER_MODE || + pm_api_arg[1] == IOCTL_GET_PLL_FRAC_MODE || + pm_api_arg[1] == IOCTL_GET_PLL_FRAC_DATA || + pm_api_arg[1] == IOCTL_READ_GGS || + pm_api_arg[1] == IOCTL_READ_PGGS) + pr_info("%s Value: %u\n", + __func__, pm_api_ret[1]); + break; + case PM_CLOCK_ENABLE: + ret = eemi_ops->clock_enable(pm_api_arg[0]); + break; + case PM_CLOCK_DISABLE: + ret = eemi_ops->clock_disable(pm_api_arg[0]); + break; + case PM_CLOCK_GETSTATE: + ret = eemi_ops->clock_getstate(pm_api_arg[0], &pm_api_ret[0]); + pr_info("%s state: %u\n", __func__, pm_api_ret[0]); + break; + case PM_CLOCK_SETDIVIDER: + ret = eemi_ops->clock_setdivider(pm_api_arg[0], pm_api_arg[1]); + break; + case PM_CLOCK_GETDIVIDER: + ret = eemi_ops->clock_getdivider(pm_api_arg[0], &pm_api_ret[0]); + pr_info("%s Divider Value: %d\n", __func__, pm_api_ret[0]); + break; + case PM_CLOCK_SETRATE: + ret = eemi_ops->clock_setrate(pm_api_arg[0], pm_api_arg[1]); + break; + case PM_CLOCK_GETRATE: + ret = eemi_ops->clock_getrate(pm_api_arg[0], &pm_api_ret[0]); + pr_info("%s Rate Value: %u\n", __func__, pm_api_ret[0]); + break; + case PM_CLOCK_SETPARENT: + ret = eemi_ops->clock_setparent(pm_api_arg[0], pm_api_arg[1]); + break; + case PM_CLOCK_GETPARENT: + ret = eemi_ops->clock_getparent(pm_api_arg[0], &pm_api_ret[0]); + pr_info("%s Parent Index: %u\n", __func__, pm_api_ret[0]); + break; + case PM_QUERY_DATA: + { + struct zynqmp_pm_query_data qdata = {0}; + + qdata.qid = pm_api_arg[0]; + qdata.arg1 = pm_api_arg[1]; + qdata.arg2 = pm_api_arg[2]; + qdata.arg3 = pm_api_arg[3]; + + ret = eemi_ops->query_data(qdata, pm_api_ret); + + pr_info("%s: data[0] = 0x%08x\n", __func__, pm_api_ret[0]); + pr_info("%s: data[1] = 0x%08x\n", __func__, pm_api_ret[1]); + pr_info("%s: data[2] = 0x%08x\n", __func__, pm_api_ret[2]); + pr_info("%s: data[3] = 0x%08x\n", __func__, pm_api_ret[3]); + break; + } + default: + pr_err("%s Unsupported PM-API request\n", __func__); + ret = -EINVAL; + } + + return ret; +} + +/** + * zynqmp_pm_debugfs_api_write - debugfs write function + * @file: User file structure + * @ptr: User entered PM-API string + * @len: Length of the userspace buffer + * @off: Offset within the file + * + * Return: Number of bytes copied if PM-API request succeeds, + * the corresponding error code otherwise + * + * Used for triggering pm api functions by writing + * echo > /sys/kernel/debug/zynqmp_pm/power or + * echo > /sys/kernel/debug/zynqmp_pm/power + */ +static ssize_t zynqmp_pm_debugfs_api_write(struct file *file, + const char __user *ptr, size_t len, + loff_t *off) +{ + char *kern_buff, *tmp_buff; + char *pm_api_req; + u32 pm_id = 0; + u64 pm_api_arg[4] = {0, 0, 0, 0}; + /* Return values from PM APIs calls */ + u32 pm_api_ret[4] = {0, 0, 0, 0}; + + int ret; + int i = 0; + + if (*off != 0 || len == 0) + return -EINVAL; + + kern_buff = memdup_user(ptr, len); + if (IS_ERR(kern_buff)) + return PTR_ERR(kern_buff); + + tmp_buff = kern_buff; + + /* Read the API name from a user request */ + pm_api_req = strsep(&kern_buff, " "); + + ret = get_pm_api_id(pm_api_req, &pm_id); + if (ret < 0) + goto err; + + /* Read node_id and arguments from the PM-API request */ + pm_api_req = strsep(&kern_buff, " "); + while ((i < ARRAY_SIZE(pm_api_arg)) && pm_api_req) { + pm_api_arg[i++] = zynqmp_pm_argument_value(pm_api_req); + pm_api_req = strsep(&kern_buff, " "); + } + + ret = process_api_request(pm_id, pm_api_arg, pm_api_ret); + +err: + kfree(tmp_buff); + if (ret) + return ret; + else + return len; +} + +/** + * zynqmp_pm_debugfs_api_version_read - debugfs read function + * @file: User file structure + * @ptr: Requested pm_api_version string + * @len: Length of the userspace buffer + * @off: Offset within the file + * + * Return: Length of the version string on success + * -EFAULT otherwise + * + * Used to display the pm api version. + * cat /sys/kernel/debug/zynqmp_pm/pm_api_version + */ +static ssize_t zynqmp_pm_debugfs_api_version_read(struct file *file, + char __user *ptr, size_t len, + loff_t *off) +{ + int ret; + u32 pm_api_version; + const struct zynqmp_eemi_ops *eemi_ops = get_eemi_ops(); + char resp[MAX_API_VERSION_RESP_LEN]; + u32 resp_len; + + if (!eemi_ops || !eemi_ops->get_api_version) + return -ENXIO; + + if (*off != 0) + return 0; + + eemi_ops->get_api_version(&pm_api_version); + resp_len = snprintf(resp, MAX_API_VERSION_RESP_LEN, + "PM-API Version = %d.%d\n", + pm_api_version >> 16, + pm_api_version & 0xffff); + + if (len < resp_len) + return -EINVAL; + + ret = copy_to_user(ptr, resp, resp_len); + if (ret) + return -EFAULT; + + *off = resp_len + 1; + + return resp_len; +} + +/* Setup debugfs fops */ +static const struct file_operations fops_zynqmp_pm_dbgfs = { + .owner = THIS_MODULE, + .write = zynqmp_pm_debugfs_api_write, + .read = zynqmp_pm_debugfs_api_version_read, +}; + +/** + * zynqmp_pm_api_debugfs_init - Initialize debugfs interface + * + * Return: None + */ +void zynqmp_pm_api_debugfs_init(void) +{ + struct dentry *root_dir; + struct dentry *d; + + /* Initialize debugfs interface */ + root_dir = debugfs_create_dir(DRIVER_NAME, NULL); + if (!root_dir) { + pr_warn("debugfs_create_dir failed\n"); + return; + } + + d = debugfs_create_file("pm", 0220, root_dir, NULL, + &fops_zynqmp_pm_dbgfs); + if (!d) { + pr_warn("debugfs_create_file power failed\n"); + goto err_dbgfs; + } + + d = debugfs_create_file("api_version", 0444, root_dir, + NULL, &fops_zynqmp_pm_dbgfs); + if (!d) { + pr_warn("debugfs_create_file api_version failed\n"); + goto err_dbgfs; + } + + return; + +err_dbgfs: + debugfs_remove_recursive(root_dir); +} diff --git a/drivers/firmware/xilinx/zynqmp/firmware.c b/drivers/firmware/xilinx/zynqmp/firmware.c index fe7b044..1731b86 100644 --- a/drivers/firmware/xilinx/zynqmp/firmware.c +++ b/drivers/firmware/xilinx/zynqmp/firmware.c @@ -20,6 +20,7 @@ #include #include +#include #define DRIVER_NAME "zynqmp_firmware" @@ -1011,9 +1012,13 @@ static int zynqmp_firmware_probe(struct platform_device *pdev) int ret; ret = zynqmp_pm_ggs_init(&pdev->dev); - if (ret) + if (ret) { dev_err(&pdev->dev, "%s() GGS init fail with error %d\n", __func__, ret); + return ret; + } + + zynqmp_pm_api_debugfs_init(); return ret; } diff --git a/include/linux/firmware/xilinx/zynqmp/firmware-debug.h b/include/linux/firmware/xilinx/zynqmp/firmware-debug.h new file mode 100644 index 0000000..a298dce --- /dev/null +++ b/include/linux/firmware/xilinx/zynqmp/firmware-debug.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Xilinx Zynq MPSoC Firmware layer + * + * Copyright (C) 2014-2018 Xilinx + * + * Michal Simek + * Davorin Mista + * Jolly Shah + * Rajan Vaja + */ + +#ifndef __SOC_ZYNQMP_FIRMWARE_DEBUG_H__ +#define __SOC_ZYNQMP_FIRMWARE_DEBUG_H__ + +#include + +int zynqmp_pm_self_suspend(const u32 node, + const u32 latency, + const u32 state); +int zynqmp_pm_abort_suspend(const enum zynqmp_pm_abort_reason reason); +int zynqmp_pm_register_notifier(const u32 node, const u32 event, + const u32 wake, const u32 enable); + +#if IS_REACHABLE(CONFIG_ZYNQMP_FIRMWARE_DEBUG) +void zynqmp_pm_api_debugfs_init(void); +#else +static inline void zynqmp_pm_api_debugfs_init(void) { return; } +#endif + +#endif /* __SOC_ZYNQMP_FIRMWARE_DEBUG_H__ */ -- 2.7.4