Received: by 2002:a05:6358:53a8:b0:117:f937:c515 with SMTP id z40csp5145783rwe; Tue, 18 Apr 2023 02:44:29 -0700 (PDT) X-Google-Smtp-Source: AKy350YsQBYs9GjIztJy8ZftX1qUVKu2beMdgGPRmCzBv45NReUEvRsGDXtLYCSeI5PNNnLS3Ene X-Received: by 2002:a17:90b:28d:b0:247:90ea:1a7f with SMTP id az13-20020a17090b028d00b0024790ea1a7fmr1306735pjb.37.1681811069077; Tue, 18 Apr 2023 02:44:29 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1681811069; cv=none; d=google.com; s=arc-20160816; b=jPrW4WTBvFmG1mptsb6oeVtcxeHhQOFyUUkFbfeoZWAaY6aRF1TSuY+SGyk0e+rp0Y r2j6u99d+jmcMkCvEpS8DBp25FMy+7Po2l5ol1uyK2wQBQdpv4tp/RE+y3YqECzbcFDy PLKBMFtwP9nKAVfPagmav8J73Q6EV5iV+4/HMwK5MBW5syiiuApLD7B/OF5xQCPksoac 5yAfUdVcqyBrQtWhMiTp1nfMWeQ/fEp041Dfp+4JJcjVybZJOTYTdXcBWPR35sEh4J9X 2aCUMggMiIcIvQ4DZx60wp1iRU4oZz6CC+7JeU3uGXd6I537Zac6l/3XjheuRxHtn+TG zI2A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:in-reply-to:content-disposition:mime-version :references:message-id:subject:cc:to:from:date:dkim-signature; bh=+y3yi/JhxDXJmnNrfnP1AQLX1EnlQEPnmNu8Hni09gg=; b=U8l/0+08FiFfREQ+ACkOQorAE097rLdHMBpXBD1Hp9rsaRiNit4wjUc107UtfVenCc uZPdpQgvS4bntLGhjlXpGXLtTNf2KfsY9dzCZUcJtvEtBv1bOnJ5q8ivWs1IJjW47H2E fZfNac/SnO47CUOga3LBj0wAwCGj0caIqKPa81woFIecm57HfHFBOCfwGUokzneZmDHV e/EdVpqeuAQIxBHzI5tUCbCemTBlRLunWloUS5jbOLs3IA5USdQRkuYCsT/EIZva3s28 I56xT1ETZhCCfnvUx2LOavAlpLxxAAG06jWo/T2c3ZlW27re10iaEDI5kxkOn2sy1WOY GfLA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@microchip.com header.s=mchp header.b=EiGXodQ6; 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=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=microchip.com Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id i23-20020a17090acf9700b0024742f4da6csi10264356pju.183.2023.04.18.02.44.15; Tue, 18 Apr 2023 02:44:29 -0700 (PDT) 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; dkim=pass header.i=@microchip.com header.s=mchp header.b=EiGXodQ6; 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=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=microchip.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231310AbjDRJh5 (ORCPT + 99 others); Tue, 18 Apr 2023 05:37:57 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40456 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231158AbjDRJhz (ORCPT ); Tue, 18 Apr 2023 05:37:55 -0400 Received: from esa.microchip.iphmx.com (esa.microchip.iphmx.com [68.232.154.123]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4934C1701; Tue, 18 Apr 2023 02:37:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=microchip.com; i=@microchip.com; q=dns/txt; s=mchp; t=1681810672; x=1713346672; h=date:from:to:cc:subject:message-id:references: mime-version:in-reply-to; bh=zBdjqaBdLvU7OEQpgU6QfXXHLq3MaNCTuYuVYxz499Q=; b=EiGXodQ6iG+amaMkaQ1kdGo/PdtzrmniokIPpDF5lm05P6GkSYr+Dvcs /9K4fsZumi3yNMsjQlZT05zYw24ijazx9XhWIrqIu4KVp3v9ridNOn898 +mQKsOi37Te/5wr/o2h5O+exLhOH/I6BdkiBoqRJUFapjzQO0kBmlazAT 7qwc0vN7O7PRJAUxec1rmjUZd2W6IkFHfTBgRam85os7EFjmk6uaiM1W2 7s9herB8kzl7ST0t2BY3gUwc1ONRmQfyIpxzC8C3eX5Y+a4dYz1y1qqff Fqax2iKzkld6HUqUf29/W8IqgEleXjAEDzmF5H/CaFoHe9HTe903iQIAh w==; X-IronPort-AV: E=Sophos;i="5.99,206,1677567600"; d="scan'208";a="210969932" Received: from unknown (HELO email.microchip.com) ([170.129.1.10]) by esa2.microchip.iphmx.com with ESMTP/TLS/AES256-SHA256; 18 Apr 2023 02:37:51 -0700 Received: from chn-vm-ex03.mchp-main.com (10.10.85.151) by chn-vm-ex02.mchp-main.com (10.10.85.144) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.21; Tue, 18 Apr 2023 02:37:48 -0700 Received: from localhost (10.10.115.15) by chn-vm-ex03.mchp-main.com (10.10.85.151) with Microsoft SMTP Server id 15.1.2507.21 via Frontend Transport; Tue, 18 Apr 2023 02:37:48 -0700 Date: Tue, 18 Apr 2023 11:37:47 +0200 From: Horatiu Vultur To: Shmuel Hazan CC: Russell King , Marcin Wojtas , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Richard Cochran , , Subject: Re: [PATCH v2 2/3] net: mvpp2: tai: add extts support Message-ID: <20230418093747.jxxvoizofd6cgk6v@soft-dev3-1> References: <20230417170741.1714310-1-shmuel.h@siklu.com> <20230417170741.1714310-3-shmuel.h@siklu.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Disposition: inline In-Reply-To: <20230417170741.1714310-3-shmuel.h@siklu.com> X-Spam-Status: No, score=-4.4 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_MED, RCVD_IN_MSPIKE_H2,SPF_HELO_PASS,SPF_PASS,T_SCC_BODY_TEXT_LINE, URIBL_BLOCKED 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 The 04/17/2023 20:07, Shmuel Hazan wrote: > > This commit add support for capturing a timestamp in which the PTP_PULSE > pin, received a signal. > > This feature is needed in order to synchronize multiple clocks in the > same board, using tools like ts2phc from the linuxptp project. > > On the Armada 8040, this is the only way to do so as a result of > multiple erattas with the PTP_PULSE_IN interface that was designed to > synchronize the TAI on an external PPS signal (the errattas are > FE-6856276, FE-7382160 from document MV-S501388-00). > > This patch introduces a pinctrl configuration "extts" that will be > selected once the user had enabled extts, and then will be returned back > to the "default" pinctrl config once it has been disabled. Additionally > these configurations will be also used in any case that the user asks us > to perform any action that involves "triggerering" the TAI subsystem, in > order to avoid a case where the external trigger would trigger with the > wrong action. > > This pinctrl mess is needed due to the fact that there is no way for us > to distinguish betwee an external trigger (e.g. from the PTP_PULSE_IN > pin) or an internal one, triggered by the registers. > > This feature has been tested on an Aramda > 8040 based board, with linuxptp 3.1.1's ts2phc. It looks good to me, just one more questions bellow. Reviewed-by: Horatiu Vultur > > Signed-off-by: Shmuel Hazan > --- > .../net/ethernet/marvell/mvpp2/mvpp2_tai.c | 304 ++++++++++++++++-- > 1 file changed, 273 insertions(+), 31 deletions(-) > > diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_tai.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_tai.c > index 2e3d43b1bac1..ff57075c6ebc 100644 > --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_tai.c > +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_tai.c > @@ -3,8 +3,11 @@ > * Marvell PP2.2 TAI support > * > * Note: > - * Do NOT use the event capture support. > - * Do Not even set the MPP muxes to allow PTP_EVENT_REQ to be used. > + * In order to use the event capture support, please see the example > + * in marvell,pp2.yaml. > + * Do not manually (e.g. without pinctrl-1, as described in > + * marvell,pp2.yaml) set the MPP muxes to allow PTP_EVENT_REQ to be > + * used. > * It will disrupt the operation of this driver, and there is nothing > * that this driver can do to prevent that. Even using PTP_EVENT_REQ > * as an output will be seen as a trigger input, which can't be masked. > @@ -33,6 +36,8 @@ > * Consequently, we support none of these. > */ > #include > +#include > +#include > #include > #include > > @@ -53,6 +58,10 @@ > #define TCSR_CAPTURE_1_VALID BIT(1) > #define TCSR_CAPTURE_0_VALID BIT(0) > > +#define MVPP2_PINCTRL_EXTTS_STATE "extts" > +#define MAX_PINS 1 > +#define EXTTS_PERIOD_MS 95 How have you come with this 95 value? > + > struct mvpp2_tai { > struct ptp_clock_info caps; > struct ptp_clock *ptp_clock; > @@ -61,7 +70,12 @@ struct mvpp2_tai { > u64 period; // nanosecond period in 32.32 fixed point > /* This timestamp is updated every two seconds */ > struct timespec64 stamp; > + struct pinctrl *extts_pinctrl; > + struct pinctrl_state *default_pinctrl_state; > + struct pinctrl_state *extts_pinctrl_state; > + struct ptp_pin_desc pin_config[MAX_PINS]; > u16 poll_worker_refcount; > + bool extts_enabled:1; > }; > > static void mvpp2_tai_modify(void __iomem *reg, u32 mask, u32 set) > @@ -73,6 +87,38 @@ static void mvpp2_tai_modify(void __iomem *reg, u32 mask, u32 set) > writel(val, reg); > } > > +/* mvpp2_tai_{pause,resume}_external_trigger are used as guards > + * to mask external triggers where it is undesirable. For example, > + * in case that the action is "increment", we may want to perform it > + * once; however, we may trigger it once internally and once from > + * an external pulse, which will cause an issue. > + * In order to work around this issue, we need perform the following sequence: > + * 1. call mvpp2_tai_pause_external_trigger > + * 2. save the current trigger operation. > + * 3. update the trigger operation. > + * 4. perform an internal trigger. > + * 5. restore the previous trigger operation. > + * 6. call mvpp2_tai_restore_external_trigger. > + */ > +static int mvpp2_tai_pause_external_trigger(struct mvpp2_tai *tai) > +{ > + if (tai->extts_enabled && tai->extts_pinctrl && > + tai->extts_pinctrl_state) > + return pinctrl_select_state(tai->extts_pinctrl, > + tai->default_pinctrl_state); > + > + return 0; > +} > + > +static int mvpp2_tai_resume_external_trigger(struct mvpp2_tai *tai) > +{ > + if (tai->extts_enabled && tai->extts_pinctrl && > + tai->extts_pinctrl_state) > + return pinctrl_select_state(tai->extts_pinctrl, > + tai->extts_pinctrl_state); > + return 0; > +} > + > static void mvpp2_tai_write(u32 val, void __iomem *reg) > { > writel_relaxed(val & 0xffff, reg); > @@ -102,6 +148,28 @@ static void mvpp22_tai_read_ts(struct timespec64 *ts, void __iomem *base) > readl_relaxed(base + 24); > } > > +static int mvpp22_tai_try_read_ts(struct timespec64 *ts, void __iomem *base) > +{ > + long tcsr = readl(base + MVPP22_TAI_TCSR); > + /* If both captures are not valid, return EBUSY */ > + int ret = -EBUSY; > + > + if (tcsr & TCSR_CAPTURE_1_VALID) { > + mvpp22_tai_read_ts(ts, base + MVPP22_TAI_TCV1_SEC_HIGH); > + ret = 0; > + } > + > + /* If both capture 1 and capture 0 are valid, use capture 0 > + * but also read and clear capture 1. > + */ > + if (tcsr & TCSR_CAPTURE_0_VALID) { > + mvpp22_tai_read_ts(ts, base + MVPP22_TAI_TCV0_SEC_HIGH); > + ret = 0; > + } > + > + return ret; > +} > + > static void mvpp2_tai_write_tlv(const struct timespec64 *ts, u32 frac, > void __iomem *base) > { > @@ -114,16 +182,30 @@ static void mvpp2_tai_write_tlv(const struct timespec64 *ts, u32 frac, > mvpp2_tai_write(frac, base + MVPP22_TAI_TLV_FRAC_LOW); > } > > -static void mvpp2_tai_op(u32 op, void __iomem *base) > +static int mvpp2_tai_op(u32 op, void __iomem *base, struct mvpp2_tai *tai) > { > + u32 reg_val; > + int ret; > + > + reg_val = mvpp2_tai_read(base + MVPP22_TAI_TCFCR0); > /* Trigger the operation. Note that an external unmaskable > * event on PTP_EVENT_REQ will also trigger this action. > + * therefore, pause possible (known) external triggers. > */ > + ret = mvpp2_tai_pause_external_trigger(tai); > + if (ret) > + goto out; > + > mvpp2_tai_modify(base + MVPP22_TAI_TCFCR0, > TCFCR0_TCF_MASK | TCFCR0_TCF_TRIGGER, > op | TCFCR0_TCF_TRIGGER); > - mvpp2_tai_modify(base + MVPP22_TAI_TCFCR0, TCFCR0_TCF_MASK, > - TCFCR0_TCF_NOP); > + mvpp2_tai_modify(base + MVPP22_TAI_TCFCR0, > + TCFCR0_TCF_MASK | TCFCR0_TCF_TRIGGER, reg_val); > + > + mvpp2_tai_resume_external_trigger(tai); > + > +out: > + return ret; > } > > /* The adjustment has a range of +0.5ns to -0.5ns in 2^32 steps, so has units > @@ -170,6 +252,7 @@ static int mvpp22_tai_adjfine(struct ptp_clock_info *ptp, long scaled_ppm) > bool neg_adj; > s32 frac; > u64 val; > + int ret; > > neg_adj = scaled_ppm < 0; > if (neg_adj) > @@ -197,10 +280,10 @@ static int mvpp22_tai_adjfine(struct ptp_clock_info *ptp, long scaled_ppm) > spin_lock_irqsave(&tai->lock, flags); > mvpp2_tai_write(frac >> 16, base + MVPP22_TAI_TLV_FRAC_HIGH); > mvpp2_tai_write(frac, base + MVPP22_TAI_TLV_FRAC_LOW); > - mvpp2_tai_op(TCFCR0_TCF_FREQUPDATE, base); > + ret = mvpp2_tai_op(TCFCR0_TCF_FREQUPDATE, base, tai); > spin_unlock_irqrestore(&tai->lock, flags); > > - return 0; > + return ret; > } > > static int mvpp22_tai_adjtime(struct ptp_clock_info *ptp, s64 delta) > @@ -210,6 +293,7 @@ static int mvpp22_tai_adjtime(struct ptp_clock_info *ptp, s64 delta) > unsigned long flags; > void __iomem *base; > u32 tcf; > + int ret; > > /* We can't deal with S64_MIN */ > if (delta == S64_MIN) > @@ -227,10 +311,10 @@ static int mvpp22_tai_adjtime(struct ptp_clock_info *ptp, s64 delta) > base = tai->base; > spin_lock_irqsave(&tai->lock, flags); > mvpp2_tai_write_tlv(&ts, 0, base); > - mvpp2_tai_op(tcf, base); > + ret = mvpp2_tai_op(tcf, base, tai); > spin_unlock_irqrestore(&tai->lock, flags); > > - return 0; > + return ret; > } > > static int mvpp22_tai_gettimex64(struct ptp_clock_info *ptp, > @@ -240,35 +324,34 @@ static int mvpp22_tai_gettimex64(struct ptp_clock_info *ptp, > struct mvpp2_tai *tai = ptp_to_tai(ptp); > unsigned long flags; > void __iomem *base; > - u32 tcsr; > + u32 reg_val; > int ret; > > base = tai->base; > spin_lock_irqsave(&tai->lock, flags); > /* XXX: the only way to read the PTP time is for the CPU to trigger > * an event. However, there is no way to distinguish between the CPU > - * triggered event, and an external event on PTP_EVENT_REQ. So this > - * is incompatible with external use of PTP_EVENT_REQ. > + * triggered event, and an external event on PTP_EVENT_REQ. As a result > + * we are pausing here external triggers by switching the pinctrl state > + * to the default state (if applicable). > */ > + ret = mvpp2_tai_pause_external_trigger(tai); > + if (ret) > + goto unlock_out; > + > + reg_val = mvpp2_tai_read(base + MVPP22_TAI_TCFCR0); > ptp_read_system_prets(sts); > mvpp2_tai_modify(base + MVPP22_TAI_TCFCR0, > TCFCR0_TCF_MASK | TCFCR0_TCF_TRIGGER, > TCFCR0_TCF_CAPTURE | TCFCR0_TCF_TRIGGER); > ptp_read_system_postts(sts); > - mvpp2_tai_modify(base + MVPP22_TAI_TCFCR0, TCFCR0_TCF_MASK, > - TCFCR0_TCF_NOP); > + mvpp2_tai_modify(base + MVPP22_TAI_TCFCR0, > + TCFCR0_TCF_MASK | TCFCR0_TCF_TRIGGER, reg_val); > > - tcsr = readl(base + MVPP22_TAI_TCSR); > - if (tcsr & TCSR_CAPTURE_1_VALID) { > - mvpp22_tai_read_ts(ts, base + MVPP22_TAI_TCV1_SEC_HIGH); > - ret = 0; > - } else if (tcsr & TCSR_CAPTURE_0_VALID) { > - mvpp22_tai_read_ts(ts, base + MVPP22_TAI_TCV0_SEC_HIGH); > - ret = 0; > - } else { > - /* We don't seem to have a reading... */ > - ret = -EBUSY; > - } > + ret = mvpp22_tai_try_read_ts(ts, base); > + mvpp2_tai_resume_external_trigger(tai); > + > +unlock_out: > spin_unlock_irqrestore(&tai->lock, flags); > > return ret; > @@ -280,32 +363,71 @@ static int mvpp22_tai_settime64(struct ptp_clock_info *ptp, > struct mvpp2_tai *tai = ptp_to_tai(ptp); > unsigned long flags; > void __iomem *base; > + u32 reg_val; > + int ret; > > base = tai->base; > spin_lock_irqsave(&tai->lock, flags); > mvpp2_tai_write_tlv(ts, 0, base); > > + ret = mvpp2_tai_pause_external_trigger(tai); > + if (ret) > + goto unlock_out; > + > /* Trigger an update to load the value from the TLV registers > * into the TOD counter. Note that an external unmaskable event on > * PTP_EVENT_REQ will also trigger this action. > */ > + reg_val = mvpp2_tai_read(base + MVPP22_TAI_TCFCR0); > mvpp2_tai_modify(base + MVPP22_TAI_TCFCR0, > - TCFCR0_PHASE_UPDATE_ENABLE | > - TCFCR0_TCF_MASK | TCFCR0_TCF_TRIGGER, > + TCFCR0_PHASE_UPDATE_ENABLE | TCFCR0_TCF_MASK | > + TCFCR0_TCF_TRIGGER, > TCFCR0_TCF_UPDATE | TCFCR0_TCF_TRIGGER); > - mvpp2_tai_modify(base + MVPP22_TAI_TCFCR0, TCFCR0_TCF_MASK, > - TCFCR0_TCF_NOP); > + mvpp2_tai_modify(base + MVPP22_TAI_TCFCR0, > + TCFCR0_PHASE_UPDATE_ENABLE | TCFCR0_TCF_MASK | > + TCFCR0_TCF_TRIGGER, > + reg_val); > + > + mvpp2_tai_resume_external_trigger(tai); > + > +unlock_out: > spin_unlock_irqrestore(&tai->lock, flags); > > - return 0; > + return ret; > +} > + > +static void do_aux_work_extts(struct mvpp2_tai *tai) > +{ > + unsigned long flags; > + int ret; > + > + spin_lock_irqsave(&tai->lock, flags); > + > + ret = mvpp22_tai_try_read_ts(&tai->stamp, tai->base); > + /* We are not managed to read a TS, try again later */ > + if (!ret) { > + struct ptp_clock_event event; > + > + /* Triggered - save timestamp */ > + event.type = PTP_CLOCK_EXTTS; > + event.index = 0; /* We only have one channel */ > + event.timestamp = timespec64_to_ns(&tai->stamp); > + ptp_clock_event(tai->ptp_clock, &event); > + } > + > + spin_unlock_irqrestore(&tai->lock, flags); > } > > static long mvpp22_tai_aux_work(struct ptp_clock_info *ptp) > { > struct mvpp2_tai *tai = ptp_to_tai(ptp); > > - mvpp22_tai_gettimex64(ptp, &tai->stamp, NULL); > + if (tai->extts_enabled) { > + do_aux_work_extts(tai); > + return msecs_to_jiffies(EXTTS_PERIOD_MS); > + } > > + mvpp22_tai_gettimex64(ptp, &tai->stamp, NULL); > return msecs_to_jiffies(2000); > } > > @@ -404,6 +526,94 @@ void mvpp22_tai_stop(struct mvpp2_tai *tai) > spin_unlock_irqrestore(&tai->lock, flags); > } > > +static void mvpp22_tai_capture_enable(struct mvpp2_tai *tai, bool enable) > +{ > + mvpp2_tai_modify(tai->base + MVPP22_TAI_TCFCR0, TCFCR0_TCF_MASK, > + enable ? TCFCR0_TCF_CAPTURE : TCFCR0_TCF_NOP); > +} > + > +static int mvpp22_tai_req_extts_enable(struct mvpp2_tai *tai, > + struct ptp_clock_request *rq, int on) > +{ > + u8 index = rq->extts.index; > + int ret = 0; > + > + if (!tai->extts_pinctrl) > + return -EINVAL; > + > + /* Reject requests with unsupported flags */ > + if (rq->extts.flags & ~(PTP_ENABLE_FEATURE | PTP_RISING_EDGE | > + PTP_FALLING_EDGE | PTP_STRICT_FLAGS)) > + return -EOPNOTSUPP; > + > + /* Reject requests to enable time stamping on falling edge */ > + if ((rq->extts.flags & PTP_ENABLE_FEATURE) && > + (rq->extts.flags & PTP_FALLING_EDGE)) > + return -EOPNOTSUPP; > + > + if (index >= MAX_PINS) > + return -EINVAL; > + > + if (on) > + ret = pinctrl_select_state(tai->extts_pinctrl, > + tai->extts_pinctrl_state); > + else > + ret = pinctrl_select_state(tai->extts_pinctrl, > + tai->default_pinctrl_state); > + if (ret) > + goto out; > + > + tai->extts_enabled = on != 0; > + mvpp22_tai_capture_enable(tai, tai->extts_enabled); > + > + /* We need to enable the poll worker in order for events to be polled */ > + if (on) > + mvpp22_tai_start_unlocked(tai); > + else > + mvpp22_tai_stop_unlocked(tai); > + > +out: > + return ret; > +} > + > +static int mvpp22_tai_enable(struct ptp_clock_info *ptp, > + struct ptp_clock_request *rq, int on) > +{ > + struct mvpp2_tai *tai = ptp_to_tai(ptp); > + int err = -EOPNOTSUPP; > + unsigned long flags; > + > + spin_lock_irqsave(&tai->lock, flags); > + > + switch (rq->type) { > + case PTP_CLK_REQ_EXTTS: > + err = mvpp22_tai_req_extts_enable(tai, rq, on); > + break; > + default: > + break; > + } > + > + spin_unlock_irqrestore(&tai->lock, flags); > + return err; > +} > + > +static int mvpp22_tai_verify_pin(struct ptp_clock_info *ptp, unsigned int pin, > + enum ptp_pin_function func, unsigned int chan) > +{ > + if (chan != 0) > + return -1; > + > + switch (func) { > + case PTP_PF_NONE: > + case PTP_PF_EXTTS: > + break; > + case PTP_PF_PEROUT: > + case PTP_PF_PHYSYNC: > + return -1; > + } > + return 0; > +} > + > static void mvpp22_tai_remove(void *priv) > { > struct mvpp2_tai *tai = priv; > @@ -423,6 +633,24 @@ int mvpp22_tai_probe(struct device *dev, struct mvpp2 *priv) > > spin_lock_init(&tai->lock); > > + tai->extts_pinctrl = devm_pinctrl_get_select_default(dev); > + if (!IS_ERR(tai->extts_pinctrl)) { > + tai->default_pinctrl_state = pinctrl_lookup_state > + (tai->extts_pinctrl, PINCTRL_STATE_DEFAULT); > + tai->extts_pinctrl_state = pinctrl_lookup_state > + (tai->extts_pinctrl, MVPP2_PINCTRL_EXTTS_STATE); > + > + if (IS_ERR(tai->default_pinctrl_state) || > + IS_ERR(tai->extts_pinctrl_state)) { > + pinctrl_put(tai->extts_pinctrl); > + tai->extts_pinctrl = NULL; > + tai->default_pinctrl_state = NULL; > + tai->extts_pinctrl_state = NULL; > + } > + } else { > + tai->extts_pinctrl = NULL; > + } > + > tai->base = priv->iface_base; > > /* The step size consists of three registers - a 16-bit nanosecond step > @@ -458,12 +686,26 @@ int mvpp22_tai_probe(struct device *dev, struct mvpp2 *priv) > > tai->caps.owner = THIS_MODULE; > strscpy(tai->caps.name, "Marvell PP2.2", sizeof(tai->caps.name)); > + tai->caps.n_ext_ts = MAX_PINS; > + tai->caps.n_pins = MAX_PINS; > tai->caps.max_adj = mvpp22_calc_max_adj(tai); > tai->caps.adjfine = mvpp22_tai_adjfine; > tai->caps.adjtime = mvpp22_tai_adjtime; > tai->caps.gettimex64 = mvpp22_tai_gettimex64; > tai->caps.settime64 = mvpp22_tai_settime64; > tai->caps.do_aux_work = mvpp22_tai_aux_work; > + tai->caps.enable = mvpp22_tai_enable; > + tai->caps.verify = mvpp22_tai_verify_pin; > + tai->caps.pin_config = tai->pin_config; > + > + for (int i = 0; i < tai->caps.n_pins; ++i) { > + struct ptp_pin_desc *ppd = &tai->caps.pin_config[i]; > + > + snprintf(ppd->name, sizeof(ppd->name), "PTP_PULSE_IN%d", i); > + ppd->index = i; > + ppd->func = PTP_PF_NONE; > + ppd->chan = 0; > + } > > ret = devm_add_action(dev, mvpp22_tai_remove, tai); > if (ret) > -- > 2.40.0 > -- /Horatiu