From patchwork Tue Nov 7 19:07:01 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aleksey Makarov X-Patchwork-Id: 10047157 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 750126032D for ; Tue, 7 Nov 2017 19:08:21 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6480428CD5 for ; Tue, 7 Nov 2017 19:08:21 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 58FA029205; Tue, 7 Nov 2017 19:08:21 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAD_ENC_HEADER,BAYES_00, DKIM_SIGNED, DKIM_VALID, RCVD_IN_DNSWL_MED autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 8D67028CD5 for ; Tue, 7 Nov 2017 19:08:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=j9hXAlIONBOFd4HMecTKCT0VUiCQ9aNRIkq9km/3iKY=; b=JNO3SfGHP7+F8t rpd7rwY0j3v/ik04qFvibEvFfEIv3Q6mvVMhOAa/1XSZbctVWfXZObvmd5X28pVIUpdjoQ3qkW3/0 DlZtn3gJpMsQ0tAyCHNLxaEtLuE/Cr/T2KtntSEwFrdMlizIsosKnTLStBt9X8k9am/8zL/h63JWu 88A0PWaX4juR7aFoC8E9toUZeGSLbG7KD6e6FEpPGyVg1HHfLI9xW19J4YNVMw9+X9CK5pB7ozkek t01vVD2DSn6dY6riIuiEh05v7slziuUShqVLXOSfYSOgwHuxENccG1HMYh/ZRq0pHTBkC6tWuVUyw fXIsZP9q9b5xl/8cdD7Q==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1eC9ER-0007kg-Ll; Tue, 07 Nov 2017 19:08:19 +0000 Received: from mail-by2nam01on0608.outbound.protection.outlook.com ([2a01:111:f400:fe42::608] helo=NAM01-BY2-obe.outbound.protection.outlook.com) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1eC9E8-0007N4-T8 for linux-arm-kernel@lists.infradead.org; Tue, 07 Nov 2017 19:08:04 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=CAVIUMNETWORKS.onmicrosoft.com; s=selector1-cavium-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version; bh=di40m+KI+Es6CaZ/gLgco6RZVPE/4FxSsMYCNaSrS4A=; b=k3szR+PxEgQWgdD4889wViCPliPDeBTzhs8qurCU66cvsKsRSpnAKqL7KArI4J0m8E7/rZGHDu7WwOhxqb4l1H3gZEQfGkV82t6SZy4nYVfblgGyp6L9gHw4ZZ2FIdJSxtLJBLR8DFpqdqCt9ai+19IhO4G3FUQi+YgqseJoICI= Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=Aleksey.Makarov@cavium.com; Received: from localhost.localdomain (46.242.12.6) by CO2PR07MB2488.namprd07.prod.outlook.com (10.166.200.146) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P256) id 15.20.197.13; Tue, 7 Nov 2017 19:07:41 +0000 From: Aleksey Makarov To: netdev@vger.kernel.org Subject: [PATCH net-next 1/2] net: add support for Cavium PTP coprocessor Date: Tue, 7 Nov 2017 22:07:01 +0300 Message-Id: <20171107190704.15458-2-aleksey.makarov@cavium.com> X-Mailer: git-send-email 2.15.0 In-Reply-To: <20171107190704.15458-1-aleksey.makarov@cavium.com> References: <20171107190704.15458-1-aleksey.makarov@cavium.com> MIME-Version: 1.0 X-Originating-IP: [46.242.12.6] X-ClientProxiedBy: AM5PR0701CA0059.eurprd07.prod.outlook.com (10.169.145.149) To CO2PR07MB2488.namprd07.prod.outlook.com (10.166.200.146) X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 9f81c53f-e74d-4a86-0adc-08d52612d2d0 X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(22001)(4534020)(4602075)(4627115)(201703031133081)(201702281549075)(2017052603199); SRVR:CO2PR07MB2488; X-Microsoft-Exchange-Diagnostics: 1; CO2PR07MB2488; 3:cfUQLJvKAoWJF5bs6+oPtu8WuBLaPjU6eajFiGAlne8W0dvxcYx5uuthSY29GJWSMHAfidhlXmNUS4qmMJR8ek7LwjXBWmPJRmYcvYRVwg1L+Lp44vcjrpM8bv+Xcc1U2bOhLIXADxQI+VPoMrWmZhbdrTKz5vmfRJUoQzHPUIH0H3mE5bRkWm2U7HVoahhNjeqnfsMAY8SHXRUYXTrYKvKOB5r3GY7H4cMU1iG68n9/3Rpn7IjsBmp6iccTpNph; 25:jBsOStC6B5GeX11aiZuktuuJX4Xtu3ay/wcxLFMjMNCGfewKZVEbPd3Tkr9S4IOb12b+1Xsvn2umoHPoedqKiM18vHUqCg7zRA0XIQx3RYL2GdF0gwn9nEQYWDUKSgmRmYBxX5EDkagHZCxTKHgnxqJYlxdSCF5Re6Pd1h1vhCwwX7GrSSNm412QxS/hAMSXQGlc4/M7uiI6lTCnTNUnjvqJryg9ETAJAfuXAyp+ILNe/sHtQtxIdYTQ8x7J3LmcJczux0f3IKN5oUhYdWpJdReJDcW9HkFQay2YsBrEw+D6JwrP9X1S/JIAS3zhQlMbZXPCwrohPiGsm7QmLyOE2Q==; 31:7vvYLnjL/wepsDCmYEs951k7jdJQlzrr1XFUnVYXldf8qJG1WyYgRBGOiOJOc/7qVNLeyk/YykJWZrTr4ydBudlUKfUDiSy6s/f9chFGghenXlvuoUTLoWk9JJoMw4eW0N9aE6zgJvMmxeRiJtJ4wcE6kSZvjs/ybfUiV/gJ0AuOeDP6DlYf28LVfzLaqzziU8CSIvHiUmCl8f93nbWUbskKE5kOxH5buMEQRcgQ63w= X-MS-TrafficTypeDiagnostic: CO2PR07MB2488: X-Microsoft-Exchange-Diagnostics: 1; CO2PR07MB2488; 20:+KzMduRye28E285AMaldLNkd2SD8QdA0EX8+Nk+QU5UjfLn9eHi2kgIiWzZgAn3Zd7ZW6eOuBNpfWEnYUEMhqWaJ8KPT3ZBcA8GQnZ2sLIbuSkGLqtl1pd2n9e+wHSmbIm3BF7Sk7kxMoJmo5NyDk1LLMEQCf57+76JfS/Rol9MOzCQVNQVC0mcLAeiGw7Iw3jfWVyND8VYRyhEL62T4Ygd9UINpUSeZbou2YLCN8pMl62vMB4Zg1AudR5LCyAupF0upnlu4+HIhUH52sO3jQHyBaH51DjXWMsqdUQtFccp8LyIo9sL//7/s2YG0uid8B8iRY7jC/ujbGihpi9p1y8onrKrTSASwhzU4iTWS0T8kGaVhhx6DzWg7TuCxkqkTxYUM2bfVXlVbGLomQNxZUfKhIyKi+PPHkwaVj0A6RNJymeZ3ZkD1InftPPnAl0OgSsD4S5u+7DVkbdUjrHLCO/cJjuSWI1vHSfLaBsXC7wbtL+qsgeUb16S04aDqRCzt; 4:zRU6DtTi4j7QVjcDapQrKtjbbZWbrHfG/P7UrGe14DXzur6qMJiTeZh0kUdU/WQPLX6LW8dp9buW0SXhFKtG/Wmip2EOOjlZkExapXzgdKcA+E+nJvocwgzTvyNl/XE+W8Jg+7iOOkVOO7WRrZQHdUWq0M0dyWnoWkW/Ga0yEnC+dIOhzvHbuZ5BE3FuETMiJa7DF47FrfVCThYEnpPHp+kkUOF19DxhV3SIqwU2VB6DSgpJhjSJjP4bPUL5tt9sBlp3sln40aHKMvN4qfhWXA== X-Exchange-Antispam-Report-Test: UriScan:; X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(100000700101)(100105000095)(100000701101)(100105300095)(100000702101)(100105100095)(6040450)(2401047)(5005006)(8121501046)(3002001)(10201501046)(3231021)(93006095)(93001095)(100000703101)(100105400095)(6041248)(20161123555025)(201703131423075)(201702281528075)(201703061421075)(201703061406153)(20161123562025)(20161123558100)(20161123564025)(20161123560025)(6072148)(201708071742011)(100000704101)(100105200095)(100000705101)(100105500095); SRVR:CO2PR07MB2488; BCL:0; PCL:0; RULEID:(100000800101)(100110000095)(100000801101)(100110300095)(100000802101)(100110100095)(100000803101)(100110400095)(100000804101)(100110200095)(100000805101)(100110500095); SRVR:CO2PR07MB2488; X-Forefront-PRVS: 0484063412 X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10009020)(979002)(6069001)(6009001)(376002)(346002)(199003)(189002)(316002)(6916009)(101416001)(50986999)(6506006)(25786009)(6666003)(6486002)(72206003)(5660300001)(6116002)(3846002)(36756003)(86362001)(1076002)(2950100002)(478600001)(76176999)(105586002)(106356001)(47776003)(66066001)(2361001)(2351001)(5003940100001)(50466002)(53936002)(68736007)(81166006)(81156014)(8676002)(7736002)(8936002)(48376002)(50226002)(33646002)(305945005)(54906003)(97736004)(16526018)(189998001)(16586007)(2906002)(4326008)(6512007)(2004002)(969003)(989001)(999001)(1009001)(1019001); DIR:OUT; SFP:1101; SCL:1; SRVR:CO2PR07MB2488; H:localhost.localdomain; FPR:; SPF:None; PTR:InfoNoRecords; A:1; MX:1; LANG:en; Received-SPF: None (protection.outlook.com: cavium.com does not designate permitted sender hosts) X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; CO2PR07MB2488; 23:Qvl0kYL2vrunOzZqQvUunOjq7mw6oPPBRROYEYD+T?= =?us-ascii?Q?icurZbBCzhY1NTeTJrH5X8q56WaQgJO0xyYMcgWx+qhpQ+IeluFphuOlYR+s?= =?us-ascii?Q?zPgEKghd5kpfj1AdKNXkmRxEi3yLiTOnXbFdCeZCTDk2oN0itAzl6NXjvqc8?= =?us-ascii?Q?gB/eY16XisBC7FysqzlSZkRxMpqN/c0/UsD9t+N9Ofk051veMuu0BJ31t0qW?= =?us-ascii?Q?OtNQ79IIi8YS1+K5sTQkT48v+ZCsFIT2wfk0cccPcT3ypsfJbGrdid1shmE4?= =?us-ascii?Q?bxtcSihGw5mUV7Zb8I67rr9Be8Wzv339DJNY9sqpObSFqgzX0vbMMt+3zpj8?= =?us-ascii?Q?cvCGX5zm6CMgbCFKVWZqOs8WFKzZHygVFrCAAGJdVxFdwLbZ+5tgmtaoLmoa?= =?us-ascii?Q?8jfSgcUxIeBv2Fz+IyDO+7/aNcVXH7h5qZwJAtqipi1kjiObudZjGM3/A4YC?= =?us-ascii?Q?gSFFWzAK0LPQxH4HKg9nAwiD4HUbSKSnKE/N88Iz+7yrohvPodc5t6qRvDVT?= =?us-ascii?Q?bQxoZcHHNaWuaiK4X15ZU3HKlougE7FSEO7/HKWa4fbHk1f3nIY3eH6qrotj?= =?us-ascii?Q?WF/Lt2EVqRXdDGpMfRvWJ1cNX63hE3eu3i2kqSt5x6ehbImteYq7YCQpeXJz?= =?us-ascii?Q?4NCHPtiVC1eTmBeIQ4q/JGmOTj3dgFiFs0JHh/1rHO8XsjmnNfX1aVAaj+cn?= =?us-ascii?Q?vb49bt/1JYPaE4czRKxGgjfJ4Tqw8JHnGX6twwhfQMBpBt3dGYB4F0MNbnAS?= =?us-ascii?Q?JWJtN/Ba1mblEvYw+p/W9Jy1R6Aya7vImwU+K6/6gyxyXO3T+1DKQPl7qHJ0?= =?us-ascii?Q?LHWa/KVEc3Vfogj4wlwiq5Qm1UTfw8clLm/1VttEpF53joE49qv+yk4LNU0k?= =?us-ascii?Q?DzGXEwWW2hbMbW2uto2sUe9/8GugKWnK1Vdei4+E70BGlaWn7pBUUNmcxDxQ?= =?us-ascii?Q?5veuzmcIQaqG8Fw1AxXO8ANFUM3W/ByMTx54GrCqfqb1YU9h26LYIGVjrJFi?= =?us-ascii?Q?g3Q63jwUyQZ8rJ69ZkKX+kVGoW2X8EuxUTkHnhZxVOtnVsnQ1Q8/8ze8CIzx?= =?us-ascii?Q?gp7WVRVzGdqXk2zXgZe9pJUu0/rv9VwkAoFaGYJVFYF0gJ4T3JZWyquFVzP/?= =?us-ascii?Q?TviGcxO49HubhJErV7ERxZnVlf7ZkYuaxV49ZUox/PYhWVzc+3Pq0U6sK8q5?= =?us-ascii?Q?iTr94niPEloqIyPVQrQ/kJHDrCIrD4hMYMDwVNrVR8b1aT8kN6VJlxnjX1aD?= =?us-ascii?Q?Wi2DuXoEadofX/3kIDle+9pjnh9PLGqRydKI3NnvoiVzmP4TxOXLR1SRbM54?= =?us-ascii?B?Zz09?= X-Microsoft-Exchange-Diagnostics: 1; CO2PR07MB2488; 6:LM0KvAkEDEq2KqBVG1U7TgPHY6JcDRXx/106W20o9LrLy+x8jMNvqP/ywskX+KkuDEiwdZas4TwKaJD5fQyvVtveEkIrUwa5QgYYugug3YQOC5taXqGIZasLHcZdetcEeA3MOCnx3lXlZgxIlNzorU0XDbpG3m5wQoMDEpJezCq5fFxaE6rR4AKP+9YmImxHmU/n/HMPOtNgxnb5u2E78sc0ka3+fCY7Il9OMYaYuqqZjzyKAca7vMxtzBZhIbrXFLldJ5shhMM0VU/T/LPWFt4YVr4Mce5jLH4slIFKhxFemv5ZHmhKdp7/MWG0yqzFBoI/11VAlGsTuG29SFFCKl5f8Fu+BIWh0WNS6bqpeOg=; 5:uZvvzQEGTSoEWR7nnGHcCMofe/dbJGhpPtpD+TbKcR8IoSAmR7PRuwUHQVgfBI1CZ5MrXR4CbEcRhEipLlwwWWW0wzD87cfq2NljwAGB7or9x9N1qyS7Ypiez1I34GhOMKmUpuXa4m5rbLuCFOF/EwNat6Ngrk2OmfH3j88QbzM=; 24:LqF7eF8xEqDhSgTwBwD+43tU7Oo3Id5cxCIdhlk06fupXQZulcqx/63QlbxWb2HfVgXq6ITpVqNHn/5VUmxIOK89wxgK68ukifLac22mSx8=; 7:L5hDMDMFHA9I6DgMRSb8jCuSVpXs2nECUCoDrvUQBa3hUlVvlz6c7TGjAdTksdFdedIyC/mFf+TTtRxYaaLB//ovZ+RYNBzz5ZjMNvL1RnNNlFFjQkGNMeXFxUWxkjEDjTk2pwd5CKecyOQos7ETe8dU756MFYm8S4n+w9SENq3FASzVIz4PKy5v1zXsM3PjD6XVClySPaxw1pUunTiZQIgb8woQGXeQ+k7VB2iVUdvHaLosV1hzulq/ywV3/YFQ SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: cavium.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 07 Nov 2017 19:07:41.2183 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 9f81c53f-e74d-4a86-0adc-08d52612d2d0 X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 711e4ccf-2e9b-4bcf-a551-4094005b6194 X-MS-Exchange-Transport-CrossTenantHeadersStamped: CO2PR07MB2488 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20171107_110801_022406_EF0B4D34 X-CRM114-Status: GOOD ( 21.84 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Robert Richter , Aleksey Makarov , "Goutham, Sunil" , Radoslaw Biernacki , linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP From: Radoslaw Biernacki This patch adds support for the Precision Time Protocol Clocks and Timestamping hardware found on Cavium ThunderX processors. Signed-off-by: Radoslaw Biernacki Signed-off-by: Aleksey Makarov --- drivers/net/ethernet/cavium/Kconfig | 13 + drivers/net/ethernet/cavium/Makefile | 1 + drivers/net/ethernet/cavium/common/Makefile | 1 + drivers/net/ethernet/cavium/common/cavium_ptp.c | 353 ++++++++++++++++++++++++ drivers/net/ethernet/cavium/common/cavium_ptp.h | 78 ++++++ 5 files changed, 446 insertions(+) create mode 100644 drivers/net/ethernet/cavium/common/Makefile create mode 100644 drivers/net/ethernet/cavium/common/cavium_ptp.c create mode 100644 drivers/net/ethernet/cavium/common/cavium_ptp.h diff --git a/drivers/net/ethernet/cavium/Kconfig b/drivers/net/ethernet/cavium/Kconfig index dcbce6cac63e..634c79a8c812 100644 --- a/drivers/net/ethernet/cavium/Kconfig +++ b/drivers/net/ethernet/cavium/Kconfig @@ -50,6 +50,19 @@ config THUNDER_NIC_RGX This driver supports configuring XCV block of RGX interface present on CN81XX chip. +config CAVIUM_PTP + tristate "Cavium PTP coprocessor as PTP clock" + depends on 64BIT + depends on PTP_1588_CLOCK + select CAVIUM_RST + default y + ---help--- + This driver adds support for the Precision Time Protocol Clocks and + Timestamping coprocessor (PTP) found on Cavium processors. + PTP provides timestamping mechanism that is suitable for use in IEEE 1588 + Precision Time Protocol or other purposes. Timestamps can be used in + BGX, TNS, GTI, and NIC blocks. + config LIQUIDIO tristate "Cavium LiquidIO support" depends on 64BIT diff --git a/drivers/net/ethernet/cavium/Makefile b/drivers/net/ethernet/cavium/Makefile index 872da9f7c31a..946bba84e81d 100644 --- a/drivers/net/ethernet/cavium/Makefile +++ b/drivers/net/ethernet/cavium/Makefile @@ -1,6 +1,7 @@ # # Makefile for the Cavium ethernet device drivers. # +obj-$(CONFIG_NET_VENDOR_CAVIUM) += common/ obj-$(CONFIG_NET_VENDOR_CAVIUM) += thunder/ obj-$(CONFIG_NET_VENDOR_CAVIUM) += liquidio/ obj-$(CONFIG_NET_VENDOR_CAVIUM) += octeon/ diff --git a/drivers/net/ethernet/cavium/common/Makefile b/drivers/net/ethernet/cavium/common/Makefile new file mode 100644 index 000000000000..dd8561b8060b --- /dev/null +++ b/drivers/net/ethernet/cavium/common/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_CAVIUM_PTP) += cavium_ptp.o diff --git a/drivers/net/ethernet/cavium/common/cavium_ptp.c b/drivers/net/ethernet/cavium/common/cavium_ptp.c new file mode 100644 index 000000000000..6c6f162bedbf --- /dev/null +++ b/drivers/net/ethernet/cavium/common/cavium_ptp.c @@ -0,0 +1,353 @@ +/* + * cavium_ptp.c - PTP 1588 clock on Cavium hardware + * + * Copyright (c) 2003-2015, 2017 Cavium, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License. + * + * This file may also be available under a different license from Cavium. + * Contact Cavium, Inc. for more information + */ + +#include +#include +#include +#include + +#include "cavium_ptp.h" + +#define DRV_NAME "Cavium PTP Driver" + +#define PCI_DEVICE_ID_CAVIUM_PTP 0xA00C +#define PCI_DEVICE_ID_CAVIUM_RST 0xA00E + +#define PCI_PTP_BAR_NO 0 +#define PCI_RST_BAR_NO 0 + +#define PTP_CLOCK_CFG 0xF00ULL +#define PTP_CLOCK_CFG_PTP_EN BIT(0) +#define PTP_CLOCK_LO 0xF08ULL +#define PTP_CLOCK_HI 0xF10ULL +#define PTP_CLOCK_COMP 0xF18ULL + +#define RST_BOOT 0x1600ULL +#define CLOCK_BASE_RATE 50000000ULL + +static u64 ptp_cavium_clock_get(void) +{ + struct pci_dev *pdev; + void __iomem *base; + u64 ret = CLOCK_BASE_RATE * 16; + + pdev = pci_get_device(PCI_VENDOR_ID_CAVIUM, + PCI_DEVICE_ID_CAVIUM_RST, NULL); + if (!pdev) + goto error; + + base = pci_ioremap_bar(pdev, PCI_RST_BAR_NO); + if (!base) + goto error_put_pdev; + + ret = CLOCK_BASE_RATE * ((readq_relaxed(base + RST_BOOT) >> 33) & 0x3f); + + iounmap(base); + +error_put_pdev: + pci_dev_put(pdev); + +error: + return ret; +} + +/* The Cavium PTP can *only* be found in SoCs containing the ThunderX + * ARM64 CPU implementation. All accesses to the device registers on this + * platform are implicitly strongly ordered with respect to memory + * accesses. So writeq_relaxed() and readq_relaxed() are safe to use with + * no memory barriers in this driver. The readq()/writeq() functions add + * explicit ordering operation which in this case are redundant, and only + * add overhead. + */ + +static u64 cavium_ptp_reg_read(struct cavium_ptp *clock, u64 offset) +{ + return readq_relaxed(clock->reg_base + offset); +} + +static void cavium_ptp_reg_write(struct cavium_ptp *clock, u64 offset, u64 val) +{ + writeq_relaxed(val, clock->reg_base + offset); +} + +struct cavium_ptp *cavium_ptp_get(void) +{ + struct cavium_ptp *ptp; + struct pci_dev *pdev; + + pdev = pci_get_device(PCI_VENDOR_ID_CAVIUM, + PCI_DEVICE_ID_CAVIUM_PTP, NULL); + if (!pdev) + return ERR_PTR(-ENODEV); + + ptp = pci_get_drvdata(pdev); + if (!ptp) { + pci_dev_put(pdev); + ptp = ERR_PTR(-EPROBE_DEFER); + } + + return ptp; +} +EXPORT_SYMBOL(cavium_ptp_get); + +void cavium_ptp_put(struct cavium_ptp *ptp) +{ + pci_dev_put(ptp->pdev); +} +EXPORT_SYMBOL(cavium_ptp_put); + +/** + * cavium_ptp_adjfreq() - Adjust ptp frequency + * @ptp: PTP clock info + * @ppb: how much to adjust by, in parts-per-billion + */ +static int cavium_ptp_adjfreq(struct ptp_clock_info *ptp_info, s32 ppb) +{ + struct cavium_ptp *clock = + container_of(ptp_info, struct cavium_ptp, ptp_info); + unsigned long flags; + u64 comp; + u64 adj; + bool neg_adj = false; + + if (ppb < 0) { + neg_adj = true; + ppb = -ppb; + } + + /* The hardware adds the clock compensation value to the PTP clock + * on every coprocessor clock cycle. Typical convention is that it + * represent number of nanosecond betwen each cycle. In this + * convention compensation value is in 64 bit fixed-point + * representation where upper 32 bits are number of nanoseconds + * and lower is fractions of nanosecond. + * The ppb represent the ratio in "parts per bilion" by which the + * compensation value should be corrected. + * To calculate new compenstation value we use 64bit fixed point + * arithmetic on following formula comp = tbase + tbase * ppb / 1G + * where tbase is the basic compensation value calculated initialy + * in cavium_ptp_init() -> tbase = 1/Hz. Then we use endian + * independent structure definition to write data to PTP register. + */ + comp = ((u64)1000000000ull << 32) / clock->clock_rate; + adj = comp * ppb; + adj = div_u64(adj, 1000000000ull); + comp = neg_adj ? comp - adj : comp + adj; + + spin_lock_irqsave(&clock->spin_lock, flags); + cavium_ptp_reg_write(clock, PTP_CLOCK_COMP, comp); + spin_unlock_irqrestore(&clock->spin_lock, flags); + + return 0; +} + +/** + * cavium_ptp_adjtime() - Adjust ptp time + * @ptp: PTP clock info + * @delta: how much to adjust by, in nanosecs + */ +static int cavium_ptp_adjtime(struct ptp_clock_info *ptp_info, s64 delta) +{ + struct cavium_ptp *clock = + container_of(ptp_info, struct cavium_ptp, ptp_info); + unsigned long flags; + + spin_lock_irqsave(&clock->spin_lock, flags); + timecounter_adjtime(&clock->time_counter, delta); + spin_unlock_irqrestore(&clock->spin_lock, flags); + + /* Sync, for network driver to get latest value */ + smp_mb(); + + return 0; +} + +/** + * cavium_ptp_gettime() - Get hardware clock time with adjustment + * @ptp: PTP clock info + * @ts: timespec + */ +static int cavium_ptp_gettime(struct ptp_clock_info *ptp_info, + struct timespec64 *ts) +{ + struct cavium_ptp *clock = + container_of(ptp_info, struct cavium_ptp, ptp_info); + unsigned long flags; + u64 nsec; + + spin_lock_irqsave(&clock->spin_lock, flags); + nsec = timecounter_read(&clock->time_counter); + spin_unlock_irqrestore(&clock->spin_lock, flags); + + *ts = ns_to_timespec64(nsec); + + return 0; +} + +/** + * cavium_ptp_settime() - Set hardware clock time. Reset adjustment + * @ptp: PTP clock info + * @ts: timespec + */ +static int cavium_ptp_settime(struct ptp_clock_info *ptp_info, + const struct timespec64 *ts) +{ + struct cavium_ptp *clock = + container_of(ptp_info, struct cavium_ptp, ptp_info); + unsigned long flags; + u64 nsec; + + nsec = timespec64_to_ns(ts); + + spin_lock_irqsave(&clock->spin_lock, flags); + timecounter_init(&clock->time_counter, &clock->cycle_counter, nsec); + spin_unlock_irqrestore(&clock->spin_lock, flags); + + return 0; +} + +/** + * cavium_ptp_enable() - Check if PTP is enabled + * @ptp: PTP clock info + * @rq: request + * @on: is it on + */ +static int cavium_ptp_enable(struct ptp_clock_info *ptp_info, + struct ptp_clock_request *rq, int on) +{ + return -EOPNOTSUPP; +} + +static u64 cavium_ptp_cc_read(const struct cyclecounter *cc) +{ + struct cavium_ptp *clock = + container_of(cc, struct cavium_ptp, cycle_counter); + + return cavium_ptp_reg_read(clock, PTP_CLOCK_HI); +} + +static int cavium_ptp_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + struct device *dev = &pdev->dev; + struct cavium_ptp *clock; + struct cyclecounter *cc; + u64 clock_cfg; + u64 clock_comp; + int err; + + clock = devm_kzalloc(dev, sizeof(*clock), GFP_KERNEL); + if (!clock) + return -ENOMEM; + + clock->pdev = pdev; + + err = pcim_enable_device(pdev); + if (err) + return err; + + err = pcim_iomap_regions(pdev, 1 << PCI_PTP_BAR_NO, pci_name(pdev)); + if (err) + return err; + + clock->reg_base = pcim_iomap_table(pdev)[PCI_PTP_BAR_NO]; + + spin_lock_init(&clock->spin_lock); + + cc = &clock->cycle_counter; + cc->read = cavium_ptp_cc_read; + cc->mask = CYCLECOUNTER_MASK(64); + cc->mult = 1; + cc->shift = 0; + + timecounter_init(&clock->time_counter, &clock->cycle_counter, + ktime_to_ns(ktime_get_real())); + + clock->clock_rate = ptp_cavium_clock_get(); + + clock->ptp_info = (struct ptp_clock_info) { + .owner = THIS_MODULE, + .name = "ThunderX PTP", + .max_adj = 1000000000ull, + .n_ext_ts = 0, + .n_pins = 0, + .pps = 0, + .adjfreq = cavium_ptp_adjfreq, + .adjtime = cavium_ptp_adjtime, + .gettime64 = cavium_ptp_gettime, + .settime64 = cavium_ptp_settime, + .enable = cavium_ptp_enable, + }; + + clock_cfg = cavium_ptp_reg_read(clock, PTP_CLOCK_CFG); + clock_cfg |= PTP_CLOCK_CFG_PTP_EN; + cavium_ptp_reg_write(clock, PTP_CLOCK_CFG, clock_cfg); + + clock_comp = ((u64)1000000000ull << 32) / clock->clock_rate; + cavium_ptp_reg_write(clock, PTP_CLOCK_COMP, clock_comp); + + clock->ptp_clock = ptp_clock_register(&clock->ptp_info, dev); + if (IS_ERR(clock->ptp_clock)) { + clock_cfg = cavium_ptp_reg_read(clock, PTP_CLOCK_CFG); + clock_cfg &= ~PTP_CLOCK_CFG_PTP_EN; + cavium_ptp_reg_write(clock, PTP_CLOCK_CFG, clock_cfg); + return PTR_ERR(clock->ptp_clock); + } + + pci_set_drvdata(pdev, clock); + return 0; +} + +static void cavium_ptp_remove(struct pci_dev *pdev) +{ + struct cavium_ptp *clock = pci_get_drvdata(pdev); + u64 clock_cfg; + + pci_set_drvdata(pdev, NULL); + + ptp_clock_unregister(clock->ptp_clock); + + clock_cfg = cavium_ptp_reg_read(clock, PTP_CLOCK_CFG); + clock_cfg &= ~PTP_CLOCK_CFG_PTP_EN; + cavium_ptp_reg_write(clock, PTP_CLOCK_CFG, clock_cfg); +} + +static const struct pci_device_id cavium_ptp_id_table[] = { + { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVICE_ID_CAVIUM_PTP) }, + { 0, } +}; + +static struct pci_driver cavium_ptp_driver = { + .name = DRV_NAME, + .id_table = cavium_ptp_id_table, + .probe = cavium_ptp_probe, + .remove = cavium_ptp_remove, +}; + +static int __init cavium_ptp_init_module(void) +{ + return pci_register_driver(&cavium_ptp_driver); +} + +static void __exit cavium_ptp_cleanup_module(void) +{ + pci_unregister_driver(&cavium_ptp_driver); +} + +module_init(cavium_ptp_init_module); +module_exit(cavium_ptp_cleanup_module); + +MODULE_DESCRIPTION(DRV_NAME); +MODULE_AUTHOR("Cavium Networks "); +MODULE_LICENSE("GPL v2"); +MODULE_DEVICE_TABLE(pci, cavium_ptp_id_table); diff --git a/drivers/net/ethernet/cavium/common/cavium_ptp.h b/drivers/net/ethernet/cavium/common/cavium_ptp.h new file mode 100644 index 000000000000..7a9dcb027a93 --- /dev/null +++ b/drivers/net/ethernet/cavium/common/cavium_ptp.h @@ -0,0 +1,78 @@ +/* + * cavium_ptp.h - PTP 1588 clock on Cavium hardware + * + * Copyright (c) 2003-2015, 2017 Cavium, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License. + * + * This file may also be available under a different license from Cavium. + * Contact Cavium, Inc. for more information + */ + +#ifndef CAVIUM_PTP_H +#define CAVIUM_PTP_H + +#include +#include + +struct cavium_ptp { + struct pci_dev *pdev; + + /* Serialize access to cycle_counter, time_counter and hw_registers */ + spinlock_t spin_lock; + struct cyclecounter cycle_counter; + struct timecounter time_counter; + void __iomem *reg_base; + + u32 clock_rate; + + struct ptp_clock_info ptp_info; + struct ptp_clock *ptp_clock; +}; + +#ifdef CONFIG_CAVIUM_PTP + +struct cavium_ptp *cavium_ptp_get(void); +void cavium_ptp_put(struct cavium_ptp *ptp); + +static inline u64 cavium_ptp_tstamp2time(struct cavium_ptp *ptp, u64 tstamp) +{ + unsigned long flags; + u64 ret; + + spin_lock_irqsave(&ptp->spin_lock, flags); + ret = timecounter_cyc2time(&ptp->time_counter, tstamp); + spin_unlock_irqrestore(&ptp->spin_lock, flags); + + return ret; +} + +static inline int cavium_ptp_clock_index(struct cavium_ptp *clock) +{ + return ptp_clock_index(clock->ptp_clock); +} + +#else + +static inline struct cavium_ptp *cavium_ptp_get(void) +{ + return ERR_PTR(-ENODEV); +} + +static inline void cavium_ptp_put(struct cavium_ptp *ptp) {} + +static inline u64 cavium_ptp_tstamp2time(struct cavium_ptp *ptp, u64 tstamp) +{ + return 0; +} + +static inline int cavium_ptp_clock_index(struct cavium_ptp *clock) +{ + return -1; +} + +#endif + +#endif