Received: by 2002:ac0:a5a7:0:0:0:0:0 with SMTP id m36-v6csp657495imm; Wed, 1 Aug 2018 03:09:43 -0700 (PDT) X-Google-Smtp-Source: AAOMgpdFEElexxE/gGTdtqxGr978jbP+EKHrGspN1GvSRE/AZtx7t8pnd2Kn6DACayOx14vCd8hC X-Received: by 2002:a65:5bc4:: with SMTP id o4-v6mr23724481pgr.448.1533118183854; Wed, 01 Aug 2018 03:09:43 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1533118183; cv=none; d=google.com; s=arc-20160816; b=YfwRPsqnIw07HJXjR9qPfgWJBnrfKoL/NVcSPyON1lligCGf6XA0wRCy6gVEvJpLOf v8Q1F2vZ6a6mI0kKpW3IPs//tex1XFU2XaEC4M9io/XnhjpxJM7+1f5uJVvVoALpwXBh NRqf28cwXrWsSWWpM6jfJMYPnioTQBdj0halT0eDo/ppxKLxwY1blI8FveaOEwBETC/c DI6H3vUSimbKqtIpwGiU6Z3g2zhMHua8KhpUNiPx75OPG/g+rdceMzYSmzuayGeT6YuN goLuSoXH82Ec1Q6cXdSvCZ6YUh+SH8hwJr3s33PWTWeE76+F3a/1Bj8N6emWZXg4w37H TP5A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:arc-authentication-results; bh=J3tD4scs546NuEisvkKGL68XT7zSE1KNiIQiPef60+A=; b=Dyn70bsyY709twfquzZwKPfpGugnT9b9JZmShjwQHP01uwqjygyoDmbcEJDKEM1QYR 63c+Uy3g0AAfPumYlUnQ7BrzfkK33pVsRLPaqQwnl8Bh9ixaHIxuKLqBbZ7G0W620wfG 2IPWledXv1fCp/vuaTlQtJdP5gqSimFMZ03SdGzrywTsGSvJgeT+FaJANaDjJgQnOwkD IondWFIT/FtGYbcq38NvXVvzobiXDu3hOg6wRmfpmXAHtkw7iuO+KrXqWEn5RhbbBp5+ VH55SlTLjC447KiLRQJcfYB7A8rzXqGccWAVzB8CRd95x7CsmRutVOT4C523Z3PMIWb2 7CgQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=nxp.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id l9-v6si14124948pfe.11.2018.08.01.03.09.29; Wed, 01 Aug 2018 03:09:43 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=nxp.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2389292AbeHALxg (ORCPT + 99 others); Wed, 1 Aug 2018 07:53:36 -0400 Received: from inva021.nxp.com ([92.121.34.21]:53006 "EHLO inva021.nxp.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2388984AbeHALxf (ORCPT ); Wed, 1 Aug 2018 07:53:35 -0400 Received: from inva021.nxp.com (localhost [127.0.0.1]) by inva021.eu-rdc02.nxp.com (Postfix) with ESMTP id 7888B200030; Wed, 1 Aug 2018 12:08:32 +0200 (CEST) Received: from invc005.ap-rdc01.nxp.com (invc005.ap-rdc01.nxp.com [165.114.16.14]) by inva021.eu-rdc02.nxp.com (Postfix) with ESMTP id 5FF832000E0; Wed, 1 Aug 2018 12:08:27 +0200 (CEST) Received: from titan.ap.freescale.net (TITAN.ap.freescale.net [10.192.208.233]) by invc005.ap-rdc01.nxp.com (Postfix) with ESMTP id F3ECF402E5; Wed, 1 Aug 2018 18:08:20 +0800 (SGT) From: Yangbo Lu To: netdev@vger.kernel.org, madalin.bucur@nxp.com, Richard Cochran , Rob Herring , Shawn Guo , "David S . Miller" Cc: devicetree@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Yangbo Lu Subject: [v2, 3/3] ptp_qoriq: support automatic configuration for ptp timer Date: Wed, 1 Aug 2018 18:05:54 +0800 Message-Id: <20180801100554.36634-3-yangbo.lu@nxp.com> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20180801100554.36634-1-yangbo.lu@nxp.com> References: <20180801100554.36634-1-yangbo.lu@nxp.com> X-Virus-Scanned: ClamAV using ClamSMTP Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org This patch is to support automatic configuration for ptp timer. If required ptp dts properties are not provided, driver could try to calculate a set of default configurations to initialize the ptp timer. This makes the driver work for many boards which don't have the required ptp dts properties in current kernel. Also the users could set dts properties by themselves according to their requirement. Signed-off-by: Yangbo Lu --- Changes for v2: - Dropped module_param. --- drivers/ptp/ptp_qoriq.c | 111 +++++++++++++++++++++++++++++++++++++++- include/linux/fsl/ptp_qoriq.h | 6 ++- 2 files changed, 113 insertions(+), 4 deletions(-) diff --git a/drivers/ptp/ptp_qoriq.c b/drivers/ptp/ptp_qoriq.c index a14c317..095c185 100644 --- a/drivers/ptp/ptp_qoriq.c +++ b/drivers/ptp/ptp_qoriq.c @@ -29,6 +29,7 @@ #include #include #include +#include #include @@ -317,6 +318,105 @@ static int ptp_qoriq_enable(struct ptp_clock_info *ptp, .enable = ptp_qoriq_enable, }; +/** + * qoriq_ptp_nominal_freq - calculate nominal frequency according to + * reference clock frequency + * + * @clk_src: reference clock frequency + * + * The nominal frequency is the desired clock frequency. + * It should be less than the reference clock frequency. + * It should be a factor of 1000MHz. + * + * Return the nominal frequency + */ +static u32 qoriq_ptp_nominal_freq(u32 clk_src) +{ + u32 remainder = 0; + + clk_src /= 1000000; + remainder = clk_src % 100; + if (remainder) { + clk_src -= remainder; + clk_src += 100; + } + + do { + clk_src -= 100; + + } while (1000 % clk_src); + + return clk_src * 1000000; +} + +/** + * qoriq_ptp_auto_config - calculate a set of default configurations + * + * @qoriq_ptp: pointer to qoriq_ptp + * @node: pointer to device_node + * + * If below dts properties are not provided, this function will be + * called to calculate a set of default configurations for them. + * "fsl,tclk-period" + * "fsl,tmr-prsc" + * "fsl,tmr-add" + * "fsl,tmr-fiper1" + * "fsl,tmr-fiper2" + * "fsl,max-adj" + * + * Return 0 if success + */ +static int qoriq_ptp_auto_config(struct qoriq_ptp *qoriq_ptp, + struct device_node *node) +{ + struct clk *clk; + u64 freq_comp; + u64 max_adj; + u32 nominal_freq; + u32 clk_src = 0; + + qoriq_ptp->cksel = DEFAULT_CKSEL; + + clk = of_clk_get(node, 0); + if (!IS_ERR(clk)) { + clk_src = clk_get_rate(clk); + clk_put(clk); + } + + if (clk_src <= 100000000UL) { + pr_err("error reference clock value, or lower than 100MHz\n"); + return -EINVAL; + } + + nominal_freq = qoriq_ptp_nominal_freq(clk_src); + if (!nominal_freq) + return -EINVAL; + + qoriq_ptp->tclk_period = 1000000000UL / nominal_freq; + qoriq_ptp->tmr_prsc = DEFAULT_TMR_PRSC; + + /* Calculate initial frequency compensation value for TMR_ADD register. + * freq_comp = ceil(2^32 / freq_ratio) + * freq_ratio = reference_clock_freq / nominal_freq + */ + freq_comp = ((u64)1 << 32) * nominal_freq; + if (do_div(freq_comp, clk_src)) + freq_comp++; + + qoriq_ptp->tmr_add = freq_comp; + qoriq_ptp->tmr_fiper1 = DEFAULT_FIPER1_PERIOD - qoriq_ptp->tclk_period; + qoriq_ptp->tmr_fiper2 = DEFAULT_FIPER2_PERIOD - qoriq_ptp->tclk_period; + + /* max_adj = 1000000000 * (freq_ratio - 1.0) - 1 + * freq_ratio = reference_clock_freq / nominal_freq + */ + max_adj = 1000000000ULL * (clk_src - nominal_freq); + max_adj = max_adj / nominal_freq - 1; + qoriq_ptp->caps.max_adj = max_adj; + + return 0; +} + static int qoriq_ptp_probe(struct platform_device *dev) { struct device_node *node = dev->dev.of_node; @@ -332,7 +432,7 @@ static int qoriq_ptp_probe(struct platform_device *dev) if (!qoriq_ptp) goto no_memory; - err = -ENODEV; + err = -EINVAL; qoriq_ptp->caps = ptp_qoriq_caps; @@ -351,10 +451,14 @@ static int qoriq_ptp_probe(struct platform_device *dev) "fsl,tmr-fiper2", &qoriq_ptp->tmr_fiper2) || of_property_read_u32(node, "fsl,max-adj", &qoriq_ptp->caps.max_adj)) { - pr_err("device tree node missing required elements\n"); - goto no_node; + pr_warn("device tree node missing required elements, try automatic configuration\n"); + + if (qoriq_ptp_auto_config(qoriq_ptp, node)) + goto no_config; } + err = -ENODEV; + qoriq_ptp->irq = platform_get_irq(dev, 0); if (qoriq_ptp->irq < 0) { @@ -436,6 +540,7 @@ static int qoriq_ptp_probe(struct platform_device *dev) release_resource(qoriq_ptp->rsrc); no_resource: free_irq(qoriq_ptp->irq, qoriq_ptp); +no_config: no_node: kfree(qoriq_ptp); no_memory: diff --git a/include/linux/fsl/ptp_qoriq.h b/include/linux/fsl/ptp_qoriq.h index dc3dac4..c1f003a 100644 --- a/include/linux/fsl/ptp_qoriq.h +++ b/include/linux/fsl/ptp_qoriq.h @@ -127,9 +127,13 @@ struct qoriq_ptp_registers { #define DRIVER "ptp_qoriq" -#define DEFAULT_CKSEL 1 #define N_EXT_TS 2 +#define DEFAULT_CKSEL 1 +#define DEFAULT_TMR_PRSC 2 +#define DEFAULT_FIPER1_PERIOD 1000000000 +#define DEFAULT_FIPER2_PERIOD 100000 + struct qoriq_ptp { void __iomem *base; struct qoriq_ptp_registers regs; -- 1.7.1