Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752361AbdLFNbv (ORCPT ); Wed, 6 Dec 2017 08:31:51 -0500 Received: from mail-sn1nam02on0074.outbound.protection.outlook.com ([104.47.36.74]:25088 "EHLO NAM02-SN1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1751937AbdLFNbj (ORCPT ); Wed, 6 Dec 2017 08:31:39 -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 Subject: [PATCH net-next v3 1/2] net: add support for Cavium PTP coprocessor Date: Wed, 6 Dec 2017 16:30:57 +0300 Message-Id: <20171206133100.26436-2-aleksey.makarov@cavium.com> X-Mailer: git-send-email 2.15.1 In-Reply-To: <20171206133100.26436-1-aleksey.makarov@cavium.com> References: <20171206133100.26436-1-aleksey.makarov@cavium.com> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [46.242.8.171] X-ClientProxiedBy: HE1P191CA0021.EURP191.PROD.OUTLOOK.COM (10.172.132.159) To BN3PR07MB2482.namprd07.prod.outlook.com (10.167.4.23) X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 887e4fa1-9e18-4567-3465-08d53cadad42 X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:(4534020)(4602075)(4627115)(201703031133081)(201702281549075)(5600026)(4604075)(2017052603286);SRVR:BN3PR07MB2482; X-Microsoft-Exchange-Diagnostics: 1;BN3PR07MB2482;3:jkGVBHvOsH11YSdPLiVb0KE4Kb07XXVPUOcLTQOrKKJ1wCpnpsSJ62Qw8QmaEpFeLv4QZMCbrEy0g0oZ3Rf9XTnMgObdQjy+QlNkGkdtRmEGKjSNddvKWg8qigHq/Nm9UDa1jRcU9CgJ2h8RvIBLXc2aDCmWCy6e2eH0ImWJ8nRnxf60XtVL19mbWRswNKn52GihVpGuQS2eAVfy1Qo/c28Cr8NSNCPikb451RAqbGXbqk6+CD2bIUC+/Z+Cn1Jp;25:QUgWiAu5U6pcnj5NOYgCnvSOCNm4ZhBkB6p7DLxKIK3nIxZoXZaXK+Ku+wQ5ATO6LRH262BXRRrqAbwly6XOXgoMbXxLZ/PRNUlJY1UM8TGID34Lm6ehm5E2tGwqVm8XnL5pXrRfdjgMoRXr+rNPirhOO+h66heAE4FljBj4Y+0j4rAPCyhv9lRcLHkq+IOQmoum95v31IIw7rbq55+89dI+4bGhlS6l7MJX2G+S9fF7Rois59W/AJaFgfiR5azQ67bPge19G7wS5t9LC0TcQ1LoA2yyIoNkytXggSbD9ZVyo8i7EHNmngf/BFIMLQa7nS+JnlWzkUe0yB6iv7GTIg==;31:L7TYvBANsMkp+hLHJgsKHuRD7eXgZnE6DKKdAUmVX63yiiUx7lE3mdL1qzM/zg6RhmKUrcztJur4GBz2EPriqEoaGi1G2TvTunRW6s2KH3XLvKRWUHhLUB5a+EkVBxRZBicpL9ckhZV9W0+Kiq/eQQXQssQrOOY19UQTLarHIRIIIBk5a/0bN2LABZEdaCpRBUUk3g12tvVqYgfiD7aDBJxx6nSzZSBT9+RQes0ThNk= X-MS-TrafficTypeDiagnostic: BN3PR07MB2482: X-Microsoft-Exchange-Diagnostics: 1;BN3PR07MB2482;20:AwJ71F3aJyaYzguaLOe/EMgkbJb5dVs/L/vgA+JUGytO4dMBeCNpYBUR1Fbaq9ahqLuWQHEKgvv0LtJVOVOTO8Tg/wPOyg8PaaNfFbFn3HH6QYFd8Su06dlCMZ6Blq5ycx9mS+RHDxBcTpQPPDQ3gbs6hPCctLlTAfKkPKNEQ5hhsLtkaSeyDm+4IetA/f6B/MPmPywm95cbbCs5xqoiAHOI07B9NH1Xmr6m8S9DxUqinaMip7yLvcthn19eHORQxUPZBhq4EyY+vsfH2gU+OZwTMuBaUuRGZ20CvMZzTvl620Hd/cAFhxqXDAvNcG7Ox5qkFoBuWnhVW906hxnsHVXXQBv7+nJvG/uZw3Cx7remAENULI1ga/k6iY75RANN9EXA5xTWfgEqXB5oZYevcseWwMZgWPP669MWRnAlbIm6NHoGcn0v60xpsPROAs5lfTQnwB3+8TfELJv6esFo4i9TOoBElt20B0GuQYGuZsOk7SOgPSLmYEMa3LLcmyzR;4:0ry5uf3gFvdOlq6eyByL20e/mvv0ZX7u8TX7/h0P5CasycMuxNukYytpEhbQrud8B42lNBMNicTzn41PnG45pgJaLqTiW65fvnAwN1uuepEHS5qpmecVoNM53f1TY7YdkhgnA46UaeRN4Tc02KaLz7m9B6ZLdLR9S8rVD5lVUWN3RiXo6BpQi0PMuV8Gue6s4Xzvf40x/qoA6SJ5sUUsdPYSToK/I7VCeSzCS24D2Kipb8wenZJkgW7Y4wijZkt3S0CUOSZOac9oooWJST7Yzg== X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(6040450)(2401047)(8121501046)(5005006)(93006095)(93001095)(10201501046)(3231022)(3002001)(6041248)(201703131423075)(201702281528075)(201703061421075)(201703061406153)(20161123564025)(20161123562025)(20161123558100)(20161123560025)(20161123555025)(6072148)(201708071742011);SRVR:BN3PR07MB2482;BCL:0;PCL:0;RULEID:(100000803101)(100110400095);SRVR:BN3PR07MB2482; X-Forefront-PRVS: 05134F8B4F X-Forefront-Antispam-Report: SFV:NSPM;SFS:(10009020)(6069001)(376002)(346002)(366004)(189003)(199004)(25786009)(6666003)(50226002)(305945005)(2950100002)(6916009)(3846002)(8936002)(7736002)(478600001)(72206003)(68736007)(8676002)(81166006)(81156014)(54906003)(86362001)(36756003)(2906002)(6116002)(33646002)(1076002)(575784001)(6486002)(16526018)(6512007)(107886003)(51416003)(52116002)(76176011)(6506006)(106356001)(2361001)(53936002)(316002)(16586007)(105586002)(2351001)(5660300001)(48376002)(101416001)(97736004)(50466002)(4326008)(66066001)(47776003)(2004002);DIR:OUT;SFP:1101;SCL:1;SRVR:BN3PR07MB2482;H:localhost.localdomain;FPR:;SPF:None;PTR:InfoNoRecords;MX:1;A:1;LANG:en; X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1;BN3PR07MB2482;23:oHmINRQiE2Jxx2COwHgx4lTbLBYsdtUINuU8dicD5?= =?us-ascii?Q?GPzk4nmOIpDAhdnLcVl6YMzylZbLS3PaXcuYGlvz2lYVv6GmkTW0UflmsCwl?= =?us-ascii?Q?iUaW4R2NSuWC/CcUTBAqiBT8GZc6u4peQojE1lMsq46zQS3n0Ry9/VgkJ6h9?= =?us-ascii?Q?UqHizz/ltqqdpb3cx1aykX0zT6/nnygOscUbdU7bvKxB7vMEUpwEg25EDJzP?= =?us-ascii?Q?+czKzfCqRmuaenyDeq4QRl3b6f38QgWqHtMNfAhoPEfR0KMJdAkvcAaGh6jy?= =?us-ascii?Q?MHMsH69ZlYmmLpcVGSwzs8cYNOTvciXs6Kmq2uuhUvBeA2B36TPA50YFVFNT?= =?us-ascii?Q?tpSXJ+B++UHkqAzPOEKPokigYTB+p8wdJRjx+7+9C8i1uZ9CUC5ymrxkS1fo?= =?us-ascii?Q?jtAICkgcpddY1nTFeLri0X7TIwHgo1YC3Z8JY7Wg7L9TZ8eGIFDjL9Q85IOs?= =?us-ascii?Q?8fpcYSb0RPfSGprm0nGNOE9iJH1YgsnRNzOOstcESIVzNe92MQIkE6/x15xE?= =?us-ascii?Q?B2Iad2jVKK8mPaFtheUtJCXKoU8pdgXKef6/MyIpdpcMhSWl1OAsZi5xc2lr?= =?us-ascii?Q?8SHEuo2B+qy9Z/gbp1RWefWRKdi/WOncbJstdSSzoXesBGedXsv8bDes/qEK?= =?us-ascii?Q?wG5ssIRj8knhjRVf41gOBRILM/sXgdhzN+URzX2ndaYfJeqczOhTTGpBtmLT?= =?us-ascii?Q?MZFXhjiEIAJe0mj8QtMXzs6a3dEh2lMQyKnrYMWTLOIso+jWD49fGNzV7I3I?= =?us-ascii?Q?naGgF5vnUyFAeG6GZr7PNUBGccdwrYyKs6SpJkgWJ+zCLKiZDqIW0FTC1VfI?= =?us-ascii?Q?DCBRJQoQqeDgKyy00+hV3NR6ySlLPnmoN+o8n4fT4OGbHNN9YPKnTKGffxqj?= =?us-ascii?Q?prZ/WtSM5tRy1fPxFDPzs72x4s7Fr1XNMEd88JWQEunjqu7vCTQ/sVA9S6Eo?= =?us-ascii?Q?J6+hZRLrQ5UrRUYg+ehasm95z/KZy1zeuCDwfLUpivEgm/k4Kd5p8YalhIDd?= =?us-ascii?Q?dVubQUUYwnG4DTx4HfzDrhBc805ZRX3btdkJdIbYwe7qg2xPqKSXC5ykE9a4?= =?us-ascii?Q?6VnX0L+DBNiuygvEuGiNZqi78JtGJn2LMaKwnKZc26h3P8Jw1RCJE0FmXsU3?= =?us-ascii?Q?Ay2GTTqcCeSrNOyCwuVIO3hYUL7O0v0d36JLx/EOhkFmA2XS8K6QNQrE4gRo?= =?us-ascii?Q?URwedM9miI3/I9V5Lw07HBz6V1mqcpcq4X8?= X-Microsoft-Exchange-Diagnostics: 1;BN3PR07MB2482;6:gP+SHvD6dYS2bSz/FhA9kzQnXvwSHlKUTzDhR+2QVfccarX88fuA67gwrzw+2sb7qcqi1XzVyVmmDph5YCaVCBXP8vwFFk2/wRkXMogADVtL6mi7Kt27pliKIL7DyFeQMYD2VewZF/C76MMmaveVrY2Bc3YChlxtpXcq0IkbppUhFtnzCXb3jPeUftQIWDWTSULwe0WLftF3y5+IxsAUVoHWcuVyHPnBC7X1CyRb7efkP7sdMWzxoaafMGdkkoS3XjaTCo+YA3Kh7BrtqLtL08ZzPLSKWFBHZLsuNKx6srN3TEPa/tBGleKDniddHkRR6vKyNuOXDZylR0KAHlaZGXZzxSJrhXAfrPzC0Vhj8Ds=;5:TYS/9ceshIVzNqsrxi2YLoAqx8lUGU6+grONjDJ7DbOs4Ht6YmslrwjnRMYAc8ILcDEquz5lTpnevuXGsri+wJezkDMaDNja/i69ndILARYhH4DX5vL4FRZsNbeOJ/RgkPW6Ay+jK8SFNn314rLwfKIfBzSYMqKJT35Z6RiPWmQ=;24:g081d38mM3GPePG7CpVMQ8SwGZThdSUbwFsc4m7aaN+RBR+ZY0RGQ48P60cf4CgUW6331nGWgO55+/5htkQPt0qUDms1MUgH/aJPLpD1+ao=;7:S8dCa/ud2tnksEIlb1u7OyHmRoZ4xQsCrQrKji+4BYFX7uFrBH+90qx58Or8CFGFDhlDxyNnNF91fwVlW3Sytyvlm9rRWXLK3rpL16J2uTGlZMtU2aFXWhltx9B+F6n1IaaQ4X0VAgGpKy0YmMzw7Cqik1UjksrQrSronCKuP0VHuL0zZNrXoLOmjcTFyYNYtrMF5hbBM9PsarMc3O3NEKtt1dwoCNs9ujgPHw/qZY4xH9wGLpzELynNbGXkRil7 SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: cavium.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 06 Dec 2017 13:31:34.8625 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 887e4fa1-9e18-4567-3465-08d53cadad42 X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 711e4ccf-2e9b-4bcf-a551-4094005b6194 X-MS-Exchange-Transport-CrossTenantHeadersStamped: BN3PR07MB2482 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 13495 Lines: 488 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 | 334 ++++++++++++++++++++++++ drivers/net/ethernet/cavium/common/cavium_ptp.h | 78 ++++++ 5 files changed, 427 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..fabe0ffcc2d4 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..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..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 -- 2.15.1