Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753372AbdLKOPV (ORCPT ); Mon, 11 Dec 2017 09:15:21 -0500 Received: from mail-by2nam01on0089.outbound.protection.outlook.com ([104.47.34.89]:10220 "EHLO NAM01-BY2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1753324AbdLKOPJ (ORCPT ); Mon, 11 Dec 2017 09:15:09 -0500 Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=Aleksey.Makarov@cavium.com; From: Aleksey Makarov To: netdev@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, "Goutham, Sunil" , Radoslaw Biernacki , Aleksey Makarov , Robert Richter , David Daney , Richard Cochran , Philippe Ombredanne Subject: [PATCH net-next v5 1/2] net: add support for Cavium PTP coprocessor Date: Mon, 11 Dec 2017 17:14:30 +0300 Message-Id: <20171211141435.2915-2-aleksey.makarov@cavium.com> X-Mailer: git-send-email 2.15.1 In-Reply-To: <20171211141435.2915-1-aleksey.makarov@cavium.com> References: <20171211141435.2915-1-aleksey.makarov@cavium.com> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [46.242.8.171] X-ClientProxiedBy: VI1PR0501CA0023.eurprd05.prod.outlook.com (10.172.9.161) To BN3PR07MB2484.namprd07.prod.outlook.com (10.167.4.25) X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: ce2a7bc4-4f33-43af-0e36-08d540a1951e X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:(5600026)(4604075)(4534020)(4602075)(4627115)(201703031133081)(201702281549075)(2017052603307);SRVR:BN3PR07MB2484; X-Microsoft-Exchange-Diagnostics: 1;BN3PR07MB2484;3:NO0KSUjGpIWjLGCmVz4CuGtOPqGKGcCUOpCElWhswAjI/PTJv7FkHght551XVNRyzvAKmtSpDiZv1N2g7rHgRAMJ0P+PqSAKkKsIP1Tmko3GnW3f1XrLWoGdkAB0uTMXKS6CPHrvG+ZUE9lJTljIERKZKBQbXyWH/naJ3AD1kSkNknMLIEytrIUn6zzsc2O7X2vtuP4xOzSp3S6gFCayxKdYq5jg5+NBVqhbWntREvwApg7F3v/kU+pn7HVjjNfP;25:VCmehUcG6H/9v4xPVea1YMVHiyRdm4Ld8SZsE99ZjfmJ00Y0u165imwM34b3nLmhUG3rd0QAgnVet0C2JT0flEPzEy8m4UIkXdmqbdcb5WlTz9k9awEDcxuLYZJYuxLS/ssgpVk9XGGaYEmFVNvlLHh8Prj9Bjkt3nF6glH1GbCTzbH9I44cT7cAnJ5EyS5LMf2ritsh3zx51Fp2mn24O6R5wX37VgiqloibwDsbUshX9uFXVgXhuCI7G4zc5ttV4nCnEQNmhopJYss3BpUzJh4xwu2gjnyTqGsSrArtgoQW8uNQsbO0COm2fKp1J3GLWIB8u5lEdE9Y9UHL+4NJeQ==;31:gROEJY1t//GLU4mb1M0/pyvsDSjUoUn+srOs8I/FWh0J/ppDPa28jraQXSpSyYhftdpEl6DEtbGR4xdw2G6luCDavq+iMn5ZlO4RwUbQnKz4Xt11eyFKSF42qkYnPcsjSkwCrC8ST/vIeRgBV0Lnn93zSur3NWJ/6FVZzOjiDWYFUli0Vo6KZerxiFFj9sPWRkB37rVA86vH3uOQNVEDk6qtKqnIcJUcEqigXowaeHM= X-MS-TrafficTypeDiagnostic: BN3PR07MB2484: X-Microsoft-Exchange-Diagnostics: 1;BN3PR07MB2484;20:NaQfzpCVr8Qf93SvY+bw6mBRxIkEwlIn+b+GXOQn5ipnPm8WLGmvQD/tJ2NhehW3KtRR/gO8ingPEA323lQqpe2Z8jxG3XrT2Uc98Fb/N1UjDg6sXpqpBKIXZVs+VQpPMtWIGq2KSWQUxEWinT7jVKyUVPaNkO1QrlZLiV1UthclT3Fg/iWDJZQTVxtuTClJ1trs4yrFNggBq46/JEboRWqou4mgTCfbRtQTL5y32NIsFSedLuEWVLsl2v1KqWypQtraL3LoHdRm1VnsQyNDfg/7jxMl0/lv3Q+I3Pjyii06dTwohG+c+GAc51amGRYzXCDSiwv0DUGzgJOHd7ny7rK65ezMdBgKULevIByvmW2MPqsePaMZB+q60aA3AQQikVoekoQWuNdKjraL2mg5NvK4eGFkO1qNi5wj9OLycjucsaCG6zhESIuRCRvBkioufRMArMv2pj4aIj9Dm2azQ8+t1jancXaBfam1+9RTs4n06CnyrLt3O6AxF31gdSVx;4:9Zv+sdv6E1Q3BfhRX7fcz175VS2TlvfJsfVJGayrP+9LexEw43Zl0Ee2/4zDQtaosn2HFHbRbDuqZuSHfV+obxY+Kiejvf136fNcszbMxNv/1faPIGzUNlQvhkHRJCUleYhmaIVyO4Eg4P7cDVgeq6raGQEo4AUSkyHazsdImCCYKfCnO200K7aU3vrHCT6A1kHxdG7sSXpou7hPcIhPUXzWEkEDXTpFErX7z+u8po4AzM2CfVxi+vCZIIplTtuGLaFx8OSRmYygdH2Bh8JfWg== X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(6040450)(2401047)(5005006)(8121501046)(93006095)(93001095)(3002001)(10201501046)(3231022)(6041248)(20161123562025)(20161123564025)(20161123560025)(20161123555025)(20161123558100)(201703131423075)(201702281528075)(201703061421075)(201703061406153)(6072148)(201708071742011);SRVR:BN3PR07MB2484;BCL:0;PCL:0;RULEID:(100000803101)(100110400095);SRVR:BN3PR07MB2484; X-Forefront-PRVS: 0518EEFB48 X-Forefront-Antispam-Report: SFV:NSPM;SFS:(10009020)(6069001)(366004)(376002)(346002)(199004)(189003)(7736002)(6116002)(2351001)(50226002)(3846002)(4326008)(33646002)(478600001)(52116002)(81166006)(81156014)(72206003)(8676002)(76176011)(51416003)(6512007)(105586002)(54906003)(2906002)(2361001)(5660300001)(53936002)(6486002)(47776003)(97736004)(66066001)(106356001)(1076002)(6506006)(39060400002)(8936002)(305945005)(575784001)(86362001)(2950100002)(6666003)(6916009)(16586007)(59450400001)(16526018)(36756003)(48376002)(50466002)(25786009)(68736007)(316002);DIR:OUT;SFP:1101;SCL:1;SRVR:BN3PR07MB2484;H:localhost.localdomain;FPR:;SPF:None;PTR:InfoNoRecords;A:1;MX:1;LANG:en; X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1;BN3PR07MB2484;23:kp8P3SEW9bi6LQCUy//1w058fpu0i+QjBeg++TV3X?= =?us-ascii?Q?LxKs33/Y/Ho/cHfaOvwmv0bO8jCzoAIuQqrA0+2IZJE3q/TWiDOqZRqabDlR?= =?us-ascii?Q?f1aFhmcL13TC7EgDxAR3oOJXsVH0RkNHQuBKJuxqBdwc2EAYmrTjWXjOQwaU?= =?us-ascii?Q?OcoHD7wMlRBRRe7Xaz16l5zqdsYjbyDaryrVNBOd2+sOwbhdvAIjmMsJ/5dq?= =?us-ascii?Q?ffTyU1YksvYq5zv2PVpAglUHjF3USKrQ5EWHmHKLD+NoewA5BYPQTQCzxiwA?= =?us-ascii?Q?P3+m8ljQG4QOJqlSE1PdWhoKWhOf0qavBlCUun4WnUsuYUAuoxHJJ7O3Fc68?= =?us-ascii?Q?JkHQEIu8yCfl8ecLIiPqbg+jAK4TttTZQEu8JRlM/TNjhNecPj0fBdvMxCES?= =?us-ascii?Q?r9uOBrwxCHxyeHiuMFpipEKBnGll2NCq8Kqsm4gpoUHYcVEFYlASjZTsccg+?= =?us-ascii?Q?v3q61mCtxV0bXFWI1eVyB4Hnr7Qq5+VZqnYxAdWAGTtOo0diSwvZhGr+Fg+J?= =?us-ascii?Q?9gUNL1zRer0UrxUgKtjo/ujbGY45yfkiTKgsZuLCG8ywQe30cDeysXrEGQAM?= =?us-ascii?Q?70ct0wQ7hdftUSvFgYw+QusEJhk7MoIXIAKrI4SjswrBwqPCaHbWIWDP/n5w?= =?us-ascii?Q?oJ1Xlsq3+fjs36+vE1DUc4NA27OXcMpgrfvtzfJ1dMG8N8Ngs6hElj6oczHZ?= =?us-ascii?Q?gBftC6boVvYbT8m5Ge1FxhzRdO2YH7WFuKp5qa4b97tfx3O0iDRH+flz29Tb?= =?us-ascii?Q?KtRcWXtQeFEdrkgFb0DE/fZTjllq7dIv//UA63qVE1ZD9gBOmUCt0fWfoFYF?= =?us-ascii?Q?vBMScc17D9fJHzC968FBlfiRnLQYFccCS+IDgbIDP7F790KSLo+X8Q0I5Hgf?= =?us-ascii?Q?iQe4oxxdtCtYPfIS6OxK850iTdnaQKMvgCA9L+xNtZXWpB+7PaYyOKTKBtEf?= =?us-ascii?Q?7HsIV+mOYYLwCuFbRSZi+hobqLXR/8aEceQhAmtSdD4czEd+r/rt/Kbja38n?= =?us-ascii?Q?sxDJWtj/6GZxZaGEak/Qh3RTqcCENLjnlGV0+CGYLcEprmzgG9syr/8g9Mb/?= =?us-ascii?Q?OhaPDEbDFd3nNtrcDernr+uBDKlyKhsNfJEJy+7bYh/iu2Xr4JWrO2N118FM?= =?us-ascii?Q?L0gcBnR59+tdajd5ftE6WR6wMCRsAuEFuO+jFh3gV8ZqB2GykOpLhgO5tCwo?= =?us-ascii?Q?PX6QQck1AVHhND+NJQGcJjzex+WWZc+lvAk?= X-Microsoft-Exchange-Diagnostics: 1;BN3PR07MB2484;6:aXZakUc0uyfoCFGUVUCNlFmdMSpFcoxf1kfDFkRTy8GeW+3Q3095zL0tg2UHtuieAVWxqfLutiqq1vW+RZ4pXz5VBMSyfpa9aw9LNuILrBY8vk9MWhIdMvXD4Mufjipwl66QSFClP7DTPmJhFS8VbP4oMEIo6TMWtz7Cw+415XBFCzoTyOmFpVOyP5tahFdDWYgJ9QcINWo3H9Q/d4oGVKPBNKeee6XfU+ISP9VdNJpgp5qbEC/u4/diTZmBH2ZAH5iMuylNBl2YNpncUlSDOm3xG17Xnk1RRSVTg+usWatxt1vepx0KSDdJqAN0gOnPk54iSXz9NOZ0t5ZgcrTW1ud95X3EJBPKHAR3mDU0NnY=;5:Vv2EHuoQuZnZPBhZcOyxW58bFo9uw+UH8PsuNEr6h3qFT4tJz1cd3XLlilv5DEmEd/epJQGYGF2jvL1FzXgYhxu6MEB4IxEvbvz48Ozo//3/QEuIZqfHRSZ7JcAYBRsZF5ufh9kcfev2sU42D/3s2DpG7IFfNZU71fCg8RGwBxk=;24:CkHYuUcPWVJ5WUh5sacjbD8iECoT7wNBF/2Ug5RjlLggtiRf72xSw8VXjspiveLGoj+Nv1CRw0a5+iGVavYGMfKc8f7rycywzUBk84Ja74g=;7:JlnuXsAKhDO/wsAG0Iel3lFTNWMOm1F7uSe9l7S7qYz8YIQQEaJ+C0WXmrit+Ujiq3UoQnNIOgiYpoufWzM6WGE/NYU2oxhzcGW6mSTOyyZ83apgPcybdJWC9VZwZtrd2NRolcGeWaqqujyXz4DZyT1slL+PVEzl4hrcB65x6ObaZl9BkbyyoLJi7582Z993UZhite0IvpmJT5YmT5Hq4OsVgwykWH40m8bmXLQCEvUJIDL/naK+3XPctsraNJsu SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: cavium.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 11 Dec 2017 14:15:05.3636 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: ce2a7bc4-4f33-43af-0e36-08d540a1951e X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 711e4ccf-2e9b-4bcf-a551-4094005b6194 X-MS-Exchange-Transport-CrossTenantHeadersStamped: BN3PR07MB2484 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 12933 Lines: 474 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 | 12 + drivers/net/ethernet/cavium/Makefile | 1 + drivers/net/ethernet/cavium/common/Makefile | 1 + drivers/net/ethernet/cavium/common/cavium_ptp.c | 329 ++++++++++++++++++++++++ drivers/net/ethernet/cavium/common/cavium_ptp.h | 70 +++++ 5 files changed, 413 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 63be75eb34d2..96586c0b4490 100644 --- a/drivers/net/ethernet/cavium/Kconfig +++ b/drivers/net/ethernet/cavium/Kconfig @@ -50,6 +50,18 @@ 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 + imply PTP_1588_CLOCK + 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..8b48863bfdec --- /dev/null +++ b/drivers/net/ethernet/cavium/common/cavium_ptp.c @@ -0,0 +1,329 @@ +// SPDX-License-Identifier: GPL-2.0 +/* cavium_ptp.c - PTP 1588 clock on Cavium hardware + * Copyright (c) 2003-2015, 2017 Cavium, Inc. + */ + +#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(base + RST_BOOT) >> 33) & 0x3f); + + iounmap(base); + +error_put_pdev: + pci_dev_put(pdev); + +error: + return ret; +} + +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); + } else if (!ptp->ptp_clock) { + pci_dev_put(pdev); + ptp = ERR_PTR(-ENODEV); + } + + 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); + writeq(comp, clock->reg_base + PTP_CLOCK_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 readq(clock->reg_base + 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 = readq(clock->reg_base + PTP_CLOCK_CFG); + clock_cfg |= PTP_CLOCK_CFG_PTP_EN; + writeq(clock_cfg, clock->reg_base + PTP_CLOCK_CFG); + + clock_comp = ((u64)1000000000ull << 32) / clock->clock_rate; + writeq(clock_comp, clock->reg_base + PTP_CLOCK_COMP); + + clock->ptp_clock = ptp_clock_register(&clock->ptp_info, dev); + if (IS_ERR(clock->ptp_clock)) { + clock_cfg = readq(clock->reg_base + PTP_CLOCK_CFG); + clock_cfg &= ~PTP_CLOCK_CFG_PTP_EN; + writeq(clock_cfg, clock->reg_base + PTP_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 = readq(clock->reg_base + PTP_CLOCK_CFG); + clock_cfg &= ~PTP_CLOCK_CFG_PTP_EN; + writeq(clock_cfg, clock->reg_base + PTP_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..be2bafc7beeb --- /dev/null +++ b/drivers/net/ethernet/cavium/common/cavium_ptp.h @@ -0,0 +1,70 @@ +// SPDX-License-Identifier: GPL-2.0 +/* cavium_ptp.h - PTP 1588 clock on Cavium hardware + * Copyright (c) 2003-2015, 2017 Cavium, Inc. + */ + +#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; +}; + +#if IS_ENABLED(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 -- 2.15.1