Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753537AbdLHKfo (ORCPT ); Fri, 8 Dec 2017 05:35:44 -0500 Received: from mail-co1nam03on0044.outbound.protection.outlook.com ([104.47.40.44]:60672 "EHLO NAM03-CO1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1753173AbdLHKfV (ORCPT ); Fri, 8 Dec 2017 05:35:21 -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 Subject: [PATCH net-next v4 1/2] net: add support for Cavium PTP coprocessor Date: Fri, 8 Dec 2017 13:34:39 +0300 Message-Id: <20171208103442.19354-2-aleksey.makarov@cavium.com> X-Mailer: git-send-email 2.15.1 In-Reply-To: <20171208103442.19354-1-aleksey.makarov@cavium.com> References: <20171208103442.19354-1-aleksey.makarov@cavium.com> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [46.242.8.171] X-ClientProxiedBy: DB6PR07CA0024.eurprd07.prod.outlook.com (10.175.239.34) To BN3PR07MB2481.namprd07.prod.outlook.com (10.167.4.22) X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: e63c759f-b666-4380-ceae-08d53e275bbc X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:(5600026)(4604075)(4534020)(4602075)(4627115)(201703031133081)(201702281549075)(2017052603307);SRVR:BN3PR07MB2481; X-Microsoft-Exchange-Diagnostics: 1;BN3PR07MB2481;3:wMTiR5HqXcEakpdIaV51aqeQDpVzQolJr7mF5arQIqhTUVKvULDwARxODLDQARBS+Q5X/6JdaK/Tx4p3NbQFhMRtkqaA0BW+09OckY+kKvCTG2GYgXaeTpR7IO7ERdC265crJgvwiBO3ijHWoCW4hXXwQtJTjNHb9aRSz9oBWCDTT2XaCICAKjE1NKuGPayK2EgIb0xX72mvdQVceYxTGrKsA1TuhAJ8kbdW9DhWBfOYgsuOgGQsId+WzLxNLb0y;25:CAzzM9KpQD7ZipqtP4nSHqeAUqIUp/tdAGgxEOQNybuJllnOkUWsGv6c6lstgh0S+q+rv2qCDHQy14zW+nmThTitRs48YbIlG+t2jNFw7gJ687dwWxhOPwHGEUreTUvnNWu+RSVWiuuG/k4SXuNpiFz4jxJj8CueE79HMeDZkBXVbpX5IADIrdKBNbZP9n8UAvncz4+DTZAWFi7m4bTTead1HPJ9BRNCE7rVeqyQ8KTyu2P7V+eZKbRQ2dfp1fxRY1JuLecq7U5R7+60MU8b9ecHIVT8r0rB9GLwhkyS78cRaQVUiCR+GRnlpkCkRJ7lXjOj2Kodjq+29XHADLaskw==;31:jMvOAa2AsDOxG/883H4T00PCdrRO6RYItBshO43gXl7ENCWBZNncVevO6OP9Uu6+sdY9MwegWGyiDhd6N1Inqj43ov8IRbYbqOzId3nQ9Ejf8pftQcdhfmIjBcmLU9ZB7AQc4i0aKPqxiEOev/NJ0QaqBqJhjC3nHtwTNIZsHzKKRUu+7SvFAG9Vy0oph+mNDFpwgYC554ZtQYk1RUoWv9sErTwq8NN/+mkZjsHkHrU= X-MS-TrafficTypeDiagnostic: BN3PR07MB2481: X-Microsoft-Exchange-Diagnostics: 1;BN3PR07MB2481;20:19R64EetMLW61Ooxmw6Om2e+hiF0pfwCzN6AgMTn4f+W4Wij8xiu8AYe4uUhHYCy/sN2ZoYWSWIzNaZqo7II6k+vwXT9GSP/5XNcy7JSh3YDtTmVKH6/zAcziik/BO+PqbKJeTLyaEgC+jgOXC6+E46C0BI30pWRJZpa//roJJbIRRkRAU/wjzUX74pWzMW+W3qjPM1rXpya4lr4HtTQjrWj3vyXcWO2KgP3OdPhA1GLlfHAancqUgHDB8twE9cWBJdDkoe7oXJLyp67QvToWyWj3aIoUAuCccWjSrGGw3QG+u6AMFTOJxqqZik5tPLRe5eF8lyYnP9BOQcdgbKkk5E1FNpdxMnCLIGUFc3UKARuyJO2L9bxyDBbdkjiHsXay9403IpypdV70Jq/lmcH78VsX8xLRcCfUDlv0oQ8Ix+h96ivTrYZwClSwHhdlqPPxklzcojMClX5PmvazYJ8QTp4O25r4X/oQarQ9Be3oI6Ff8X7wXTUVxLmCAUvCGL+;4:v/J1K3bXksN2hcaLtgpWBFhZXj7TVOAGp5t7gsyw7c8cLJ3rv+ctkq4To7xTaXNBHEUK4T1/gArPbGy3ZTxtFuIFcZBgm1TBQ1h2RWNPDujgsYkjt6gkTT+6AEniPUtX8Te+QIHmF5ErR/gsmFJpHtetLC8z1TRa+EqZO3jyRaABy9qs9zQUXxZ1V0O2QUx7WfWMEwOerInVlvqK09Zj8ORjAv1SsI8+nKpEu6BX0VpJgMX51A5GbecPL/zOVcis4d4bHL+/6E/UvnGbshZrMA== 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)(10201501046)(3231022)(93006095)(93001095)(3002001)(6041248)(20161123560025)(20161123564025)(20161123562025)(20161123555025)(201703131423075)(201702281528075)(201703061421075)(201703061406153)(20161123558100)(6072148)(201708071742011);SRVR:BN3PR07MB2481;BCL:0;PCL:0;RULEID:(100000803101)(100110400095);SRVR:BN3PR07MB2481; X-Forefront-PRVS: 0515208626 X-Forefront-Antispam-Report: SFV:NSPM;SFS:(10009020)(6069001)(366004)(376002)(346002)(199004)(189003)(50226002)(2361001)(68736007)(8676002)(105586002)(2351001)(33646002)(48376002)(305945005)(7736002)(39060400002)(1076002)(106356001)(81156014)(81166006)(6486002)(8936002)(478600001)(6116002)(3846002)(72206003)(4326008)(36756003)(25786009)(54906003)(316002)(50466002)(6506006)(16526018)(6512007)(97736004)(16586007)(2906002)(5660300001)(66066001)(6666003)(2950100002)(47776003)(6916009)(51416003)(52116002)(76176011)(86362001)(53936002)(2004002);DIR:OUT;SFP:1101;SCL:1;SRVR:BN3PR07MB2481;H:localhost.localdomain;FPR:;SPF:None;PTR:InfoNoRecords;A:1;MX:1;LANG:en; X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1;BN3PR07MB2481;23:3lPtGTt+bhmTHmGck64WEEcoVwY+IEbDhPlVqitFH?= =?us-ascii?Q?NHTQwl8QulKJsTlDrsUH/FxtxMs+QuiWt3JcCAZmiGzzfb+ehbOZP7d0kNxz?= =?us-ascii?Q?l6+s+FiqCb3eSRxL4VVlCwvYr4UUEKhpJd1/KxCa+glK+QJiRWOXiecWOxWD?= =?us-ascii?Q?U1bgZ/CUQFDMmJNpfpNPGpIy7NA8KWWyG+Zd5BJiiSqCgn739YxVH/PfEwHD?= =?us-ascii?Q?ecJ4rRPf33JgPk3VzpcrF9D+roM3AV+1iPqyv211EqWM5Uw5AzYRHGRQaqeH?= =?us-ascii?Q?BQgQB/S82IbcM0IrtNX1X5zeNLFQyxfvUOY3LkFGwr8t4xSl5I1YCtsAoi3V?= =?us-ascii?Q?wkPv2vym46jtHd/U34umFvNx1XTvZoKP6GcoFQh8zieaaaKDXIkIcErdT2Qb?= =?us-ascii?Q?dxtPkR+Ll78x1bdjXH9YFJTwCLB2wSldTI83KpnrmcKd/xbbNUs3MG4nVTrA?= =?us-ascii?Q?ln1Ci4+2I56j9vWi+7itJkgENoDzDaAeV5enrH8IfN02RvV6VM9kPUuku7bd?= =?us-ascii?Q?uFQXWqw8u8zk6oMigml2nFAHZvS461prumi8O+yQAopthVPNwxvrWF+sVbsc?= =?us-ascii?Q?BL519hoJVPfwAwEcVdgncVPD5rhCJ3Q0/m4F7dwAl0+Mt7/SjCg2ARGcZG+w?= =?us-ascii?Q?Hc+1OvK4kNCNw834cuOSFYzcRo+AyPPTm3XZt21Jo3+/TwFRpi684rAoc/q7?= =?us-ascii?Q?cr4frZLed329AkpRCx5tqpKhV5r9WrUbeS6SZwzNOvHpnKLMSRZU9IwzbUW8?= =?us-ascii?Q?+QxyGd2caIyqd4FLt4UHrecQSquLTHRAS3dO5ri7SoW+ccSSzAyCBXGsZjhu?= =?us-ascii?Q?DKKCruNFutkXykMvClnW49dmFbFfDoID8qqbsqhrtKKzG1uSVTzIu3X6Pey6?= =?us-ascii?Q?unBSqMZd1ZyPusY9Ib1oNLY/vsxC1eUwsj6Sl/jvJmmu/m4M7dCrttcTbwVn?= =?us-ascii?Q?hDbdtYOCqm9Gh6a/jmJc7aBFDlD8ZluCeytAu++EfYd+wb36m56ETCG5rXoU?= =?us-ascii?Q?iTyYch4dSGiv/u+ZizS7dLbg7+jWC5yjM5AVwItpN7dGixGg93b6MpRny10Y?= =?us-ascii?Q?2ALOcSvHms0fT9xK9OuVrXpPoZnzhfsjkC/zXkQ8+mdSCc8FsNqWAnQZAnQR?= =?us-ascii?Q?J5Ae7mTLJ2rjh9pQppYb7ROnFZ4RNVpH5R2t48cX0dwxzUKmr/5Cw=3D=3D?= X-Microsoft-Exchange-Diagnostics: 1;BN3PR07MB2481;6:po7KPDTklD1DDjjDvl9fDbBclcFkvBa03Fz0SC/Cy2BSoPlvMQIhhWdCUpRZPeGPeu5gSEy34ZVSz7N12lu/xdnm+jyQi0Va5HZLV6uiR/TRlBaiXWXCaXECQD3DBL9hnKo7E6nBh+MUpz8DGNDgAEDISIuC83pxxUC4NqYfmFqM55+twpoVxPR6YsqFCDsIpcgWs74aiavJFEhoMK1r+RFElh3sd6PP46YbiGmllpsTYAtlEnoS5BiZ4deqmuMRazixTt5Q9cTgkkzK30rMMm3292e3bmhQ1ceT9y3B4M8f6nIN6sDbsXXSr/pKKwMf38hYNV7/SD0pHAZAKz1g2+3fCG+qE1D7rhWcr/Lx+r8=;5:aDEQC5ftaGkcTZE092Q/hXaWRiNu5U2NoaGbqTVO0gS2hG0dRIPpcoznULDueZ6oqhUAA81J36K5ORC1sapFmb6p3bwdPuYVAHD2aQ5re6j+33J1n2KO0HGAWfLWovJh5/0oexFFHM+AzfoXoi/8hU2HDIpvOWaNymvA8bSVI6Y=;24:09Orc/DeGheEcnSiVL/QrBxcyDC1RlDCAZZD65m9NMulTK3en8J09YlQdduwnJBavebzlLOZrMUfjxB0sazc2Wk5/vG7vqGl6zLx/M0L/CI=;7:U0JuzCpvTTp509BBhaIUXlYQfsicDvZm5VQqYOH9/7KTaXFPSLWGAcOCp7NYj8KN5F3b8m3nGzZeR5sqMC/TMujlAL9bIIlLavqWKnkK1sDCcv4vt+UCHNkeXlG0x9i4zV//PYsUH3CN6/8RxwHLY3O8Q+Atbbz5f7H56/bDD6eCFuTcpbu2uUgleFtAnGs2KtAOVKpJMYFNB3I9q/UkmVNc8MVE9EHxFWBDAyiWSnWqzt5Le2V8NL6BBK4t4W2K SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: cavium.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 08 Dec 2017 10:35:08.4196 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: e63c759f-b666-4380-ceae-08d53e275bbc X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 711e4ccf-2e9b-4bcf-a551-4094005b6194 X-MS-Exchange-Transport-CrossTenantHeadersStamped: BN3PR07MB2481 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 13480 Lines: 487 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 | 334 ++++++++++++++++++++++++ drivers/net/ethernet/cavium/common/cavium_ptp.h | 78 ++++++ 5 files changed, 426 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..2380e9834007 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 + select 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..f4c738db27fd --- /dev/null +++ b/drivers/net/ethernet/cavium/common/cavium_ptp.c @@ -0,0 +1,334 @@ +/* + * 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(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); + } + + 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..0f6fe2b6e2ca --- /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; +}; + +#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