From patchwork Thu Jan 26 13:33:44 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandru Tachici X-Patchwork-Id: 48655 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:eb09:0:0:0:0:0 with SMTP id s9csp276217wrn; Thu, 26 Jan 2023 05:44:46 -0800 (PST) X-Google-Smtp-Source: AMrXdXvOhvMSTQI2SBkL6o7U84JfFZFo3VBv4pte6Ex1r7MLsFEGgQcMRYt+5X/DNoXLrn8aeYM1 X-Received: by 2002:a05:6402:28c6:b0:498:f2d:f52e with SMTP id ef6-20020a05640228c600b004980f2df52emr38682193edb.21.1674740686462; Thu, 26 Jan 2023 05:44:46 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1674740686; cv=none; d=google.com; s=arc-20160816; b=QRx3Xl2y0l8NI3B9a/YugZ5yfgYINBozWA37tyMMIOYycrBIrvWZ+rGu78IqOFHLv/ 7CVhJie4zydw35Oz+4m3IPmUDf0jrxCGG8gac+rKf02Ovb9BSdjCA1+PUTymXKJEHmqP YSe6kHSDIcCvbv8Q3xCgzqVBjppiLCeCyEwm5+cDbBIH5zEUnw9lbUEqQbQqazEfdD13 g7DqYfl8XyLVfKGEP8lLCe3X6IR1yH+WxppB4My3Wjiu3IKBy0iXaHUfRjLLPl5CpjJ4 33Aw3fkmpt8/xEg+e5z7Tz1R/IuoU2gETOZ/c3TKn3FlOC8yoNQ6w7Giv34QnRk+71rW 2drg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from; bh=TqY7HjXVK53UnHwCKx0MBFOuJWCsza6dDXlACwN0xmA=; b=kPYt/h0+LTY9L1Z27ViLulqiyxyCIfYGM78Bs1CupnjNORt0HjxqBfpgiGUwhvJPzb GINKR2AfleWWVmX7JuoS32USWcaRbjdaAvGA4A6CY+IWdhXJIq8nHTxElpThwERvgTN+ Ch8H0V81ygQ7cJkAayRZqtcNHLomXhq23zmNb0liYkJoDil9OA9UOfZYWolv/VN1KK3U hWEk8D6xtYwK4o12roAVSwUtSBylkdijlQeL7aJUMS4ZKAlB8VKW6cy7bsRYMbSo23lM cZiDDTtB0hEHl7FoIDAmweuXudIMHhLDVa0od5QeO2w++4v0i3oZd2BsnLP3te39hVY8 VFjw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=analog.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id j9-20020a05640211c900b004a090c40aecsi1851910edw.411.2023.01.26.05.44.22; Thu, 26 Jan 2023 05:44:46 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=analog.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237090AbjAZNeh (ORCPT + 99 others); Thu, 26 Jan 2023 08:34:37 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45330 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237019AbjAZNeY (ORCPT ); Thu, 26 Jan 2023 08:34:24 -0500 Received: from mx0a-00128a01.pphosted.com (mx0a-00128a01.pphosted.com [148.163.135.77]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5922430C5; Thu, 26 Jan 2023 05:34:22 -0800 (PST) Received: from pps.filterd (m0167089.ppops.net [127.0.0.1]) by mx0a-00128a01.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 30QAPk9m013285; Thu, 26 Jan 2023 08:34:12 -0500 Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-00128a01.pphosted.com (PPS) with ESMTPS id 3n8dua5kse-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 26 Jan 2023 08:34:11 -0500 Received: from m0167089.ppops.net (m0167089.ppops.net [127.0.0.1]) by pps.reinject (8.17.1.5/8.17.1.5) with ESMTP id 30QDXseW008536; Thu, 26 Jan 2023 08:34:11 -0500 Received: from nwd2mta4.analog.com ([137.71.173.58]) by mx0a-00128a01.pphosted.com (PPS) with ESMTPS id 3n8dua5ks3-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 26 Jan 2023 08:34:11 -0500 Received: from ASHBMBX9.ad.analog.com (ASHBMBX9.ad.analog.com [10.64.17.10]) by nwd2mta4.analog.com (8.14.7/8.14.7) with ESMTP id 30QDYAv7014249 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Thu, 26 Jan 2023 08:34:10 -0500 Received: from ASHBCASHYB5.ad.analog.com (10.64.17.133) by ASHBMBX9.ad.analog.com (10.64.17.10) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.14; Thu, 26 Jan 2023 08:34:09 -0500 Received: from ASHBMBX8.ad.analog.com (10.64.17.5) by ASHBCASHYB5.ad.analog.com (10.64.17.133) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.14; Thu, 26 Jan 2023 08:34:09 -0500 Received: from zeus.spd.analog.com (10.66.68.11) by ashbmbx8.ad.analog.com (10.64.17.5) with Microsoft SMTP Server id 15.2.986.14 via Frontend Transport; Thu, 26 Jan 2023 08:34:08 -0500 Received: from tachici-Precision-5530.ad.analog.com ([10.48.65.156]) by zeus.spd.analog.com (8.15.1/8.15.1) with ESMTP id 30QDXoao000628; Thu, 26 Jan 2023 08:34:03 -0500 From: Alexandru Tachici To: CC: , , , , , , , , , , , Subject: [net-next v2 1/3] net: ethernet: adi: adin1110: add PTP clock support Date: Thu, 26 Jan 2023 15:33:44 +0200 Message-ID: <20230126133346.61097-2-alexandru.tachici@analog.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230126133346.61097-1-alexandru.tachici@analog.com> References: <20230126133346.61097-1-alexandru.tachici@analog.com> MIME-Version: 1.0 X-ADIRuleOP-NewSCL: Rule Triggered X-Proofpoint-GUID: MI7ReFCP1apN4LLGvIOLDX2oKSNXLIOm X-Proofpoint-ORIG-GUID: RRrf6ecTGbRQ1CK3Sb-zGJVWQiHhYr3X X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.219,Aquarius:18.0.930,Hydra:6.0.562,FMLib:17.11.122.1 definitions=2023-01-26_05,2023-01-25_01,2022-06-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 lowpriorityscore=0 suspectscore=0 impostorscore=0 bulkscore=0 malwarescore=0 phishscore=0 mlxscore=0 spamscore=0 adultscore=0 clxscore=1015 mlxlogscore=999 priorityscore=1501 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2212070000 definitions=main-2301260131 X-Spam-Status: No, score=-2.6 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1756092889968665808?= X-GMAIL-MSGID: =?utf-8?q?1756092889968665808?= Add control for the PHC inside the ADIN1110/2111. Device contains a syntonized counter driven by a 120 MHz clock with 8 ns resolution. Time is stored on two registers: a 32bit seconds register and a 32bit nanoseconds register. For adjusting the clock timing, device uses an addend register. Can generate an output signal on the TS_TIMER pin. For reading the timestamp the current tiem is saved by setting the TS_CAPT pin via gpio in order to snapshot both seconds and nanoseconds in different registers that the live ones. Signed-off-by: Alexandru Tachici --- drivers/net/ethernet/adi/adin1110.c | 398 ++++++++++++++++++++++++++++ 1 file changed, 398 insertions(+) diff --git a/drivers/net/ethernet/adi/adin1110.c b/drivers/net/ethernet/adi/adin1110.c index 0805f249fff2..1b0caec847b9 100644 --- a/drivers/net/ethernet/adi/adin1110.c +++ b/drivers/net/ethernet/adi/adin1110.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -15,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -22,7 +24,9 @@ #include #include #include +#include #include +#include #include @@ -35,6 +39,8 @@ #define ADIN1110_CONFIG1 0x04 #define ADIN1110_CONFIG1_SYNC BIT(15) +#define ADIN1110_CONFIG1_FTSE BIT(7) +#define ADIN1110_CONFIG1_FTSS BIT(6) #define ADIN1110_CONFIG2 0x06 #define ADIN2111_P2_FWD_UNK2HOST BIT(12) @@ -78,6 +84,20 @@ #define ADIN1110_MAC_ADDR_MASK_UPR 0x70 #define ADIN1110_MAC_ADDR_MASK_LWR 0x71 +#define ADIN1110_MAC_TS_ADDEND 0x80 +#define ADIN1110_MAC_TS_SEC_CNT 0x82 +#define ADIN1110_MAC_TS_NS_CNT 0x83 +#define ADIN1110_MAC_TS_CFG 0x84 +#define ADIN1110_MAC_TS_CFG_EN BIT(0) +#define ADIN1110_MAC_TS_CFG_CLR BIT(1) +#define ADIN1110_MAC_TS_CFG_TIMER_STOP BIT(3) +#define ADIN1110_MAC_TS_CFG_CAPT_CNT BIT(4) +#define ADIN1110_MAC_TS_TIMER_HI 0x85 +#define ADIN1110_MAC_TS_TIMER_LO 0x86 +#define ADIN1110_MAC_TS_TIMER_START 0x88 +#define ADIN1110_MAC_TS_CAPT0 0x89 +#define ADIN1110_MAC_TS_CAPT1 0x8A + #define ADIN1110_RX_FSIZE 0x90 #define ADIN1110_RX 0x91 @@ -90,6 +110,19 @@ #define ADIN1110_MDIO_OP_WR 0x1 #define ADIN1110_MDIO_OP_RD 0x3 +/* ADIN2111 PHY PINMUX Controls */ +#define ADIN2111_PINMUX_CFG1 0x8C56 +#define ADIN2111_PINMUX_CFG1_DIGIO_TSCAPT GENMASK(5, 4) + +#define ADIN2111_PINMUX_CFG1_TSCAPT_TEST_1 BIT(5) +#define ADIN2111_PINMUX_CFG1_NOT_ASSIGNED GENMASK(5, 4) + +/* ADIN2111 PHY LEDs Controls */ +#define ADIN2111_LED_CNTRL 0x8C82 +#define ADIN2111_LED_CNTRL_LED0_FUNCTION GENMASK(4, 0) + +#define ADIN2111_LED_CNTRL_TS_TIMER 0x17 + #define ADIN1110_CD BIT(7) #define ADIN1110_WRITE BIT(5) @@ -114,6 +147,11 @@ #define ADIN_MAC_P2_ADDR_SLOT 3 #define ADIN_MAC_FDB_ADDR_SLOT 4 +#define ADIN_MAC_MAX_PTP_PINS 2 +#define ADIN_MAC_MAX_TS_SLOTS 3 + +#define adin1110_ptp_to_priv(x) container_of(x, struct adin1110_priv, ptp) + DECLARE_CRC8_TABLE(adin1110_crc_table); enum adin1110_chips_id { @@ -150,6 +188,11 @@ struct adin1110_port_priv { struct adin1110_priv { struct mutex lock; /* protect spi */ spinlock_t state_lock; /* protect RX mode */ + bool ts_rx_append; + struct ptp_clock_info ptp; + struct ptp_clock *ptp_clock; + struct gpio_desc *ts_capt; + struct ptp_pin_desc ptp_pins[ADIN_MAC_MAX_PTP_PINS]; struct mii_bus *mii_bus; struct spi_device *spidev; bool append_crc; @@ -1640,6 +1683,355 @@ static int adin1110_probe_netdevs(struct adin1110_priv *priv) return 0; } +/* ADIN1110 has a syntonized counter driven by an internal 120 MHz clock, a 64-bit + * counter in which the lower 32 bits represent nanoseconds with 1 LSB = 1 ns. + * Frequency is adjusted by modifying the addend register. + */ +static int adin1110_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm) +{ + struct adin1110_priv *priv = adin1110_ptp_to_priv(ptp); + u32 val; + int ret; + + mutex_lock(&priv->lock); + + ret = adin1110_read_reg(priv, ADIN1110_MAC_TS_ADDEND, &val); + if (ret < 0) + goto out; + + val = adjust_by_scaled_ppm(val, scaled_ppm); + ret = adin1110_write_reg(priv, ADIN1110_MAC_TS_ADDEND, val); +out: + mutex_unlock(&priv->lock); + return ret; +} + +static int adin1110_ptp_read_ts_capt(struct adin1110_priv *priv, + struct timespec64 *ts, + struct ptp_system_timestamp *sts, + struct ktime_timestamps *snap) +{ + u32 val; + int ret; + + mutex_lock(&priv->lock); + + if (sts) + ptp_read_system_prets(sts); + + if (snap) { + snap->mono = ktime_get_mono_fast_ns(); + snap->real = ktime_get_real_fast_ns(); + } + + gpiod_set_value(priv->ts_capt, 1); + fsleep(1); + gpiod_set_value(priv->ts_capt, 0); + + ret = adin1110_read_reg(priv, ADIN1110_MAC_TS_CAPT0, &val); + if (ret < 0) + goto out; + /* No TS captured when nsecs == 0 */ + if (!val) { + ret = -EINVAL; + goto out; + } + + ts->tv_nsec = val; + + ret = adin1110_read_reg(priv, ADIN1110_MAC_TS_CAPT1, &val); + if (ret < 0) + goto out; + if (sts) + ptp_read_system_postts(sts); + + ts->tv_sec = val; +out: + mutex_unlock(&priv->lock); + + return ret; +} + +static int adin1110_ptp_settime64(struct ptp_clock_info *ptp, + const struct timespec64 *ts) +{ + struct adin1110_priv *priv = adin1110_ptp_to_priv(ptp); + u32 addend; + int ret; + + mutex_lock(&priv->lock); + + ret = adin1110_read_reg(priv, ADIN1110_MAC_TS_ADDEND, &addend); + if (ret < 0) + goto out; + + ret = adin1110_write_reg(priv, ADIN1110_MAC_TS_ADDEND, 0); + if (ret < 0) + goto out; + + ret = adin1110_write_reg(priv, ADIN1110_MAC_TS_NS_CNT, + ALIGN(ts->tv_nsec, 16)); + if (ret < 0) + goto out; + + ret = adin1110_write_reg(priv, ADIN1110_MAC_TS_SEC_CNT, + ts->tv_sec); + if (ret < 0) + goto out; + + ret = adin1110_write_reg(priv, ADIN1110_MAC_TS_ADDEND, addend); +out: + mutex_unlock(&priv->lock); + + return ret; +} + +static int adin1110_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) +{ + struct adin1110_priv *priv = adin1110_ptp_to_priv(ptp); + struct timespec64 ts; + u64 dev_time; + int ret; + + ret = adin1110_ptp_read_ts_capt(priv, &ts, NULL, NULL); + if (ret < 0) + return ret; + + dev_time = timespec64_to_ns(&ts); + dev_time += delta; + + ts = ns_to_timespec64(dev_time); + + return adin1110_ptp_settime64(ptp, &ts); +} + +static int adin1110_ptp_gettimex64(struct ptp_clock_info *ptp, + struct timespec64 *ts, + struct ptp_system_timestamp *sts) +{ + struct adin1110_priv *priv = adin1110_ptp_to_priv(ptp); + + return adin1110_ptp_read_ts_capt(priv, ts, sts, NULL); +} + +static int adin1110_ptp_getcrosststamp(struct ptp_clock_info *ptp, + struct system_device_crosststamp *cts) +{ + struct adin1110_priv *priv = adin1110_ptp_to_priv(ptp); + struct ktime_timestamps snap; + struct timespec64 ts; + int ret; + + ret = adin1110_ptp_read_ts_capt(priv, &ts, NULL, &snap); + if (ret < 0) + return ret; + + cts->device = timespec64_to_ktime(ts); + cts->sys_realtime = snap.real; + cts->sys_monoraw = snap.mono; + + return 0; +} + +static int adin2111_enable_ts_timer(struct adin1110_priv *priv, int on) +{ + struct phy_device *phydev = priv->ports[0]->phydev; + int ret; + + mutex_lock(&phydev->lock); + + ret = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, + ADIN2111_LED_CNTRL, + ADIN2111_LED_CNTRL_LED0_FUNCTION); + if (ret < 0) + goto out; + + ret = phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, + ADIN2111_LED_CNTRL, + on ? ADIN2111_LED_CNTRL_TS_TIMER : 0); +out: + mutex_unlock(&phydev->lock); + return ret; +} + +static int adin1110_enable_perout(struct adin1110_priv *priv, + struct ptp_perout_request perout, + int on) +{ + u32 on_nsec; + u32 phase; + u32 mask; + int ret; + + if (priv->cfg->id == ADIN2111_MAC) { + ret = adin2111_enable_ts_timer(priv, on); + if (ret < 0) + return ret; + } + + mutex_lock(&priv->lock); + + ret = adin1110_set_bits(priv, ADIN1110_MAC_TS_CFG, + ADIN1110_MAC_TS_CFG_CLR, + ADIN1110_MAC_TS_CFG_CLR); + if (ret < 0) + goto out; + + if (perout.flags & PTP_PEROUT_DUTY_CYCLE) + on_nsec = perout.on.nsec; + else + on_nsec = perout.period.nsec / 2; + + ret = adin1110_write_reg(priv, ADIN1110_MAC_TS_TIMER_HI, + ALIGN(on_nsec, 16)); + if (ret < 0) + goto out; + + ret = adin1110_write_reg(priv, ADIN1110_MAC_TS_TIMER_LO, + ALIGN((perout.period.nsec - on_nsec), 16)); + if (ret < 0) + goto out; + + if (perout.flags & PTP_PEROUT_PHASE) + phase = ALIGN(perout.phase.nsec, 16); + else + phase = 0; + + /* TS_TIMER_START reg must be written to a value >= 16 because of how + * the syntonized counter was implemented. + */ + if (phase < 16) + phase = 16; + + if (on) { + ret = adin1110_write_reg(priv, ADIN1110_MAC_TS_TIMER_START, + phase); + if (ret < 0) + goto out; + } + + mask = ADIN1110_MAC_TS_CFG_EN | ADIN1110_MAC_TS_CFG_TIMER_STOP; + ret = adin1110_set_bits(priv, ADIN1110_MAC_TS_CFG, mask, + on ? ADIN1110_MAC_TS_CFG_EN : ADIN1110_MAC_TS_CFG_TIMER_STOP); + if (ret < 0) + goto out; + + ret = adin1110_set_bits(priv, ADIN1110_CONFIG1, ADIN1110_CONFIG1_SYNC, + ADIN1110_CONFIG1_SYNC); +out: + mutex_unlock(&priv->lock); + return ret; +} + +static int adin2111_enable_extts(struct adin1110_priv *priv, int on) +{ + struct phy_device *phydev = priv->ports[0]->phydev; + u32 val; + int ret; + + mutex_lock(&phydev->lock); + + ret = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, ADIN2111_PINMUX_CFG1, + ADIN2111_PINMUX_CFG1_DIGIO_TSCAPT); + if (ret < 0) + goto out; + + val = on ? ADIN2111_PINMUX_CFG1_TSCAPT_TEST_1 : ADIN2111_PINMUX_CFG1_NOT_ASSIGNED; + ret = phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, + ADIN2111_PINMUX_CFG1_DIGIO_TSCAPT, val); +out: + mutex_unlock(&phydev->lock); + return ret; +} + +static int adin1110_enable_extts(struct adin1110_priv *priv, + struct ptp_extts_request extts, + int on) +{ + int ret; + + if (extts.index >= priv->ptp.n_ext_ts) + return -EINVAL; + + if (priv->cfg->id == ADIN2111_MAC) { + ret = adin2111_enable_extts(priv, on); + if (ret < 0) + return ret; + } + + mutex_lock(&priv->lock); + ret = adin1110_set_bits(priv, ADIN1110_MAC_TS_CFG, + ADIN1110_MAC_TS_CFG_EN, + on ? ADIN1110_MAC_TS_CFG_EN : 0); + if (ret < 0) + goto out; + + ret = adin1110_set_bits(priv, ADIN1110_CONFIG1, + ADIN1110_CONFIG1_SYNC, + ADIN1110_CONFIG1_SYNC); +out: + mutex_unlock(&priv->lock); + return ret; +} + +static int adin1110_ptp_enable(struct ptp_clock_info *ptp, + struct ptp_clock_request *request, int on) +{ + struct adin1110_priv *priv = adin1110_ptp_to_priv(ptp); + + switch (request->type) { + case PTP_CLK_REQ_EXTTS: + return adin1110_enable_extts(priv, request->extts, on); + case PTP_CLK_REQ_PEROUT: + return adin1110_enable_perout(priv, request->perout, on); + case PTP_CLK_REQ_PPS: + default: + return -EOPNOTSUPP; + } +} + +static int adin1110_setup_ptp(struct adin1110_priv *priv) +{ + priv->ts_capt = devm_gpiod_get_optional(&priv->spidev->dev, "ts-capt", + GPIOD_OUT_LOW); + if (!priv->ts_capt) + return 0; + + snprintf(priv->ptp_pins[0].name, 64, "%s-%u-ptp-per-out", + priv->cfg->name, priv->spidev->chip_select); + priv->ptp_pins[0].index = 0; + priv->ptp_pins[0].func = PTP_PF_PEROUT; + priv->ptp_pins[0].chan = 0; + + snprintf(priv->ptp_pins[1].name, 64, "%s-%u-ptp-ext-ts", + priv->cfg->name, priv->spidev->chip_select); + priv->ptp_pins[1].index = 1; + priv->ptp_pins[1].func = PTP_PF_EXTTS; + priv->ptp_pins[1].chan = 0; + + priv->ptp.owner = THIS_MODULE; + snprintf(priv->ptp.name, PTP_CLOCK_NAME_LEN, "%s-%u-ptp", + priv->cfg->name, priv->spidev->chip_select); + + priv->ptp.max_adj = 512000; + priv->ptp.n_ext_ts = 1; + priv->ptp.n_per_out = 1; + priv->ptp.n_pins = ADIN_MAC_MAX_PTP_PINS; + priv->ptp.pin_config = priv->ptp_pins; + priv->ptp.adjfine = adin1110_ptp_adjfine; + priv->ptp.adjtime = adin1110_ptp_adjtime; + priv->ptp.gettimex64 = adin1110_ptp_gettimex64; + priv->ptp.getcrosststamp = adin1110_ptp_getcrosststamp; + priv->ptp.settime64 = adin1110_ptp_settime64; + priv->ptp.enable = adin1110_ptp_enable; + + priv->ptp_clock = ptp_clock_register(&priv->ptp, &priv->spidev->dev); + if (IS_ERR(priv->ptp_clock)) + return PTR_ERR(priv->ptp_clock); + + return 0; +} + static int adin1110_probe(struct spi_device *spi) { const struct spi_device_id *dev_id = spi_get_device_id(spi); @@ -1680,6 +2072,12 @@ static int adin1110_probe(struct spi_device *spi) return ret; } + ret = adin1110_setup_ptp(priv); + if (ret < 0) { + dev_err(dev, "Could not register PTP clock %d\n", ret); + return ret; + } + return adin1110_probe_netdevs(priv); }