From nobody Mon Sep 15 07:38:24 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4C728C54EBE for ; Mon, 16 Jan 2023 08:56:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232478AbjAPI4k (ORCPT ); Mon, 16 Jan 2023 03:56:40 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59948 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232271AbjAPI4C (ORCPT ); Mon, 16 Jan 2023 03:56:02 -0500 Received: from fllv0016.ext.ti.com (fllv0016.ext.ti.com [198.47.19.142]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9F85413528; Mon, 16 Jan 2023 00:56:00 -0800 (PST) Received: from fllv0035.itg.ti.com ([10.64.41.0]) by fllv0016.ext.ti.com (8.15.2/8.15.2) with ESMTP id 30G8tn7n064498; Mon, 16 Jan 2023 02:55:49 -0600 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1673859349; bh=9/dGcXdSQTYQZcts0DoejUhZKSatGGyFed0YM1Fc9UI=; h=From:To:CC:Subject:Date:In-Reply-To:References; b=d7mPrNH1U5tmY3yVHLCx52l6bV/U2lFOSqbfP7XQIn7kEqYVa8HU9ZG3vkSpcEBwg a4/Ts4xKErGHDDUMwbHqAC8twse3fulrktlRF+xaWbmRpmIGj39ak9tCLzL0xrIRu4 uRUFZ90mdMHX6glcKpeNJM6TT0cIR+zUkofzPcA0= Received: from DLEE115.ent.ti.com (dlee115.ent.ti.com [157.170.170.26]) by fllv0035.itg.ti.com (8.15.2/8.15.2) with ESMTPS id 30G8tnJ3049655 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL); Mon, 16 Jan 2023 02:55:49 -0600 Received: from DLEE114.ent.ti.com (157.170.170.25) by DLEE115.ent.ti.com (157.170.170.26) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.2507.16; Mon, 16 Jan 2023 02:55:49 -0600 Received: from lelv0327.itg.ti.com (10.180.67.183) by DLEE114.ent.ti.com (157.170.170.25) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.2507.16 via Frontend Transport; Mon, 16 Jan 2023 02:55:49 -0600 Received: from uda0492258.dhcp.ti.com (ileaxei01-snat.itg.ti.com [10.180.69.5]) by lelv0327.itg.ti.com (8.15.2/8.15.2) with ESMTP id 30G8tZwJ040368; Mon, 16 Jan 2023 02:55:45 -0600 From: Siddharth Vadapalli To: , , , , , , , , , CC: , , , , , Subject: [PATCH net-next v2 2/3] net: ethernet: ti: am65-cpts: add pps support Date: Mon, 16 Jan 2023 14:25:33 +0530 Message-ID: <20230116085534.440820-3-s-vadapalli@ti.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230116085534.440820-1-s-vadapalli@ti.com> References: <20230116085534.440820-1-s-vadapalli@ti.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-EXCLAIMER-MD-CONFIG: e1e8a2fd-e40a-4ac6-ac9b-f7e9cc9ee180 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Grygorii Strashko CPTS doesn't have HW support for PPS ("pulse per second=E2=80=9D) signal generation, but it can be modeled by using Time Sync Router and routing GenFx (periodic signal generator) output to CPTS_HWy_TS_PUSH (hardware time stamp) input, and configuring GenFx to generate 1sec pulses. +------------------------+ | CPTS | | | +--->CPTS_HW4_PUSH GENFx+---+ | | | | | +------------------------+ | | | +--------------------------------+ Add corresponding support to am65-cpts driver. The DT property "ti,pps" has to be used to enable PPS support and configure pair [CPTS_HWy_TS_PUSH, GenFx]. Once enabled, PPS can be tested using ppstest tool: # ./ppstest /dev/pps0 Signed-off-by: Grygorii Strashko Signed-off-by: Siddharth Vadapalli Reviewed-by: Roger Quadros --- drivers/net/ethernet/ti/am65-cpts.c | 96 +++++++++++++++++++++++++++-- 1 file changed, 91 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/ti/am65-cpts.c b/drivers/net/ethernet/ti/= am65-cpts.c index 9535396b28cd..c405af266b41 100644 --- a/drivers/net/ethernet/ti/am65-cpts.c +++ b/drivers/net/ethernet/ti/am65-cpts.c @@ -176,6 +176,10 @@ struct am65_cpts { u32 genf_enable; u32 hw_ts_enable; struct sk_buff_head txq; + bool pps_enabled; + bool pps_present; + u32 pps_hw_ts_idx; + u32 pps_genf_idx; /* context save/restore */ u64 sr_cpts_ns; u64 sr_ktime_ns; @@ -319,8 +323,15 @@ static int am65_cpts_fifo_read(struct am65_cpts *cpts) case AM65_CPTS_EV_HW: pevent.index =3D am65_cpts_event_get_port(event) - 1; pevent.timestamp =3D event->timestamp; - pevent.type =3D PTP_CLOCK_EXTTS; - dev_dbg(cpts->dev, "AM65_CPTS_EV_HW p:%d t:%llu\n", + if (cpts->pps_enabled && pevent.index =3D=3D cpts->pps_hw_ts_idx) { + pevent.type =3D PTP_CLOCK_PPSUSR; + pevent.pps_times.ts_real =3D ns_to_timespec64(pevent.timestamp); + } else { + pevent.type =3D PTP_CLOCK_EXTTS; + } + dev_dbg(cpts->dev, "AM65_CPTS_EV_HW:%s p:%d t:%llu\n", + pevent.type =3D=3D PTP_CLOCK_EXTTS ? + "extts" : "pps", pevent.index, event->timestamp); =20 ptp_clock_event(cpts->ptp_clock, &pevent); @@ -507,7 +518,13 @@ static void am65_cpts_extts_enable_hw(struct am65_cpts= *cpts, u32 index, int on) =20 static int am65_cpts_extts_enable(struct am65_cpts *cpts, u32 index, int o= n) { - if (!!(cpts->hw_ts_enable & BIT(index)) =3D=3D !!on) + if (index >=3D cpts->ptp_info.n_ext_ts) + return -ENXIO; + + if (cpts->pps_present && index =3D=3D cpts->pps_hw_ts_idx) + return -EINVAL; + + if (((cpts->hw_ts_enable & BIT(index)) >> index) =3D=3D on) return 0; =20 mutex_lock(&cpts->ptp_clk_lock); @@ -591,6 +608,12 @@ static void am65_cpts_perout_enable_hw(struct am65_cpt= s *cpts, static int am65_cpts_perout_enable(struct am65_cpts *cpts, struct ptp_perout_request *req, int on) { + if (req->index >=3D cpts->ptp_info.n_per_out) + return -ENXIO; + + if (cpts->pps_present && req->index =3D=3D cpts->pps_genf_idx) + return -EINVAL; + if (!!(cpts->genf_enable & BIT(req->index)) =3D=3D !!on) return 0; =20 @@ -604,6 +627,48 @@ static int am65_cpts_perout_enable(struct am65_cpts *c= pts, return 0; } =20 +static int am65_cpts_pps_enable(struct am65_cpts *cpts, int on) +{ + int ret =3D 0; + struct timespec64 ts; + struct ptp_clock_request rq; + u64 ns; + + if (!cpts->pps_present) + return -EINVAL; + + if (cpts->pps_enabled =3D=3D !!on) + return 0; + + mutex_lock(&cpts->ptp_clk_lock); + + if (on) { + am65_cpts_extts_enable_hw(cpts, cpts->pps_hw_ts_idx, on); + + ns =3D am65_cpts_gettime(cpts, NULL); + ts =3D ns_to_timespec64(ns); + rq.perout.period.sec =3D 1; + rq.perout.period.nsec =3D 0; + rq.perout.start.sec =3D ts.tv_sec + 2; + rq.perout.start.nsec =3D 0; + rq.perout.index =3D cpts->pps_genf_idx; + + am65_cpts_perout_enable_hw(cpts, &rq.perout, on); + cpts->pps_enabled =3D true; + } else { + rq.perout.index =3D cpts->pps_genf_idx; + am65_cpts_perout_enable_hw(cpts, &rq.perout, on); + am65_cpts_extts_enable_hw(cpts, cpts->pps_hw_ts_idx, on); + cpts->pps_enabled =3D false; + } + + mutex_unlock(&cpts->ptp_clk_lock); + + dev_dbg(cpts->dev, "%s: pps: %s\n", + __func__, on ? "enabled" : "disabled"); + return ret; +} + static int am65_cpts_ptp_enable(struct ptp_clock_info *ptp, struct ptp_clock_request *rq, int on) { @@ -614,6 +679,8 @@ static int am65_cpts_ptp_enable(struct ptp_clock_info *= ptp, return am65_cpts_extts_enable(cpts, rq->extts.index, on); case PTP_CLK_REQ_PEROUT: return am65_cpts_perout_enable(cpts, &rq->perout, on); + case PTP_CLK_REQ_PPS: + return am65_cpts_pps_enable(cpts, on); default: break; } @@ -926,6 +993,23 @@ static int am65_cpts_of_parse(struct am65_cpts *cpts, = struct device_node *node) if (!of_property_read_u32(node, "ti,cpts-periodic-outputs", &prop[0])) cpts->genf_num =3D prop[0]; =20 + if (!of_property_read_u32_array(node, "ti,pps", prop, 2)) { + cpts->pps_present =3D true; + + if (prop[0] > 7) { + dev_err(cpts->dev, "invalid HWx_TS_PUSH index: %u provided\n", prop[0]); + cpts->pps_present =3D false; + } + if (prop[1] > 1) { + dev_err(cpts->dev, "invalid GENFy index: %u provided\n", prop[1]); + cpts->pps_present =3D false; + } + if (cpts->pps_present) { + cpts->pps_hw_ts_idx =3D prop[0]; + cpts->pps_genf_idx =3D prop[1]; + } + } + return cpts_of_mux_clk_setup(cpts, node); } =20 @@ -993,6 +1077,8 @@ struct am65_cpts *am65_cpts_create(struct device *dev,= void __iomem *regs, cpts->ptp_info.n_ext_ts =3D cpts->ext_ts_inputs; if (cpts->genf_num) cpts->ptp_info.n_per_out =3D cpts->genf_num; + if (cpts->pps_present) + cpts->ptp_info.pps =3D 1; =20 am65_cpts_set_add_val(cpts); =20 @@ -1028,9 +1114,9 @@ struct am65_cpts *am65_cpts_create(struct device *dev= , void __iomem *regs, return ERR_PTR(ret); } =20 - dev_info(dev, "CPTS ver 0x%08x, freq:%u, add_val:%u\n", + dev_info(dev, "CPTS ver 0x%08x, freq:%u, add_val:%u pps:%d\n", am65_cpts_read32(cpts, idver), - cpts->refclk_freq, cpts->ts_add_val); + cpts->refclk_freq, cpts->ts_add_val, cpts->pps_present); =20 return cpts; =20 --=20 2.25.1