From 6809b4d8f301e24ba9588868c61cf9d78c84d41c Mon Sep 17 00:00:00 2001
From: AnjanaSuraj <anjana.r@puresoftware.com>
Date: Thu, 7 Apr 2022 11:54:59 +0530
Subject: [PATCH] ptp: ptp_qoriq: add ACPI probe support

Add ACPI support for QorIQ PTP clock so that it can be probed
in both DT and ACPI cases.

Signed-off-by: AnjanaSuraj <anjana.r@puresoftware.com>
Signed-off-by: Camelia Groza <camelia.groza@nxp.com>
---
 drivers/ptp/ptp_qoriq.c       | 85 +++++++++++++++++++++++++++++++----
 include/linux/fsl/ptp_qoriq.h | 13 ++++++
 2 files changed, 89 insertions(+), 9 deletions(-)

diff --git a/drivers/ptp/ptp_qoriq.c b/drivers/ptp/ptp_qoriq.c
index 08f4cf0ad9e3c..c9796c371b819 100644
--- a/drivers/ptp/ptp_qoriq.c
+++ b/drivers/ptp/ptp_qoriq.c
@@ -3,6 +3,7 @@
  * PTP 1588 clock for Freescale QorIQ 1588 timer
  *
  * Copyright (C) 2010 OMICRON electronics GmbH
+ * Copyright (C) 2020 Puresoftware Ltd.
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -16,6 +17,7 @@
 #include <linux/timex.h>
 #include <linux/slab.h>
 #include <linux/clk.h>
+#include <linux/acpi.h>
 
 #include <linux/fsl/ptp_qoriq.h>
 
@@ -388,10 +390,20 @@ static int ptp_qoriq_auto_config(struct ptp_qoriq *ptp_qoriq,
 
 	ptp_qoriq->cksel = DEFAULT_CKSEL;
 
-	clk = of_clk_get(node, 0);
-	if (!IS_ERR(clk)) {
-		clk_src = clk_get_rate(clk);
-		clk_put(clk);
+	if (is_of_node(ptp_qoriq->dev->fwnode)) {
+		clk = of_clk_get(node, 0);
+		if (!IS_ERR(clk)) {
+			clk_src = clk_get_rate(clk);
+			clk_put(clk);
+		}
+	} else {
+		/* Fetch clock frq. from DSD property */
+		if (fwnode_property_read_u32(ptp_qoriq->dev->fwnode,
+					     "clock-frequency", &clk_src))
+			dev_err(ptp_qoriq->dev,
+				"%s: failed to read clk for %pOF\n",
+				__func__, ptp_qoriq->dev);
+		return -EINVAL;
 	}
 
 	if (clk_src <= 100000000UL) {
@@ -430,6 +442,49 @@ static int ptp_qoriq_auto_config(struct ptp_qoriq *ptp_qoriq,
 	return 0;
 }
 
+static int ptp_acpi_init(struct ptp_qoriq *ptp_qoriq, void __iomem *base)
+{
+	struct fwnode_handle *ptp_fwnode;
+
+	/* Check for fw node first */
+	ptp_fwnode = ptp_qoriq->dev->fwnode;
+
+	/* Set the properties in case of ACPI/DSDT
+	 * NOTE: None of these properties are present in ACPI tables,
+	 * therefore go for automatic configuration.
+	 */
+	if (fwnode_property_read_u32(ptp_fwnode, "fsl,cksel",
+				     &ptp_qoriq->cksel))
+		ptp_qoriq->cksel = DEFAULT_CKSEL;
+
+	if (fwnode_property_present(ptp_fwnode, "fsl,extts-fifo"))
+		ptp_qoriq->extts_fifo_support = true;
+	else
+		ptp_qoriq->extts_fifo_support = false;
+
+	if (CLK_DSDT_PROPS) {
+		pr_warn("ACPI DSD missing required elements, try auto config\n");
+		if (ptp_qoriq_auto_config(ptp_qoriq, NULL))
+			return -ENODEV;
+	}
+
+	if (fwnode_property_present(ptp_fwnode, "little-endian")) {
+		ptp_qoriq->read = qoriq_read_le;
+		ptp_qoriq->write = qoriq_write_le;
+	} else {
+		ptp_qoriq->read = qoriq_read_be;
+		ptp_qoriq->write = qoriq_write_be;
+	}
+
+	/* memory map with DPAA */
+	ptp_qoriq->regs.ctrl_regs = base + CTRL_REGS_OFFSET;
+	ptp_qoriq->regs.alarm_regs = base + ALARM_REGS_OFFSET;
+	ptp_qoriq->regs.fiper_regs = base + FIPER_REGS_OFFSET;
+	ptp_qoriq->regs.etts_regs = base + ETTS_REGS_OFFSET;
+
+	return 0;
+}
+
 int ptp_qoriq_init(struct ptp_qoriq *ptp_qoriq, void __iomem *base,
 		   const struct ptp_clock_info *caps)
 {
@@ -439,6 +494,13 @@ int ptp_qoriq_init(struct ptp_qoriq *ptp_qoriq, void __iomem *base,
 	unsigned long flags;
 	u32 tmr_ctrl;
 
+	if (is_acpi_node(ptp_qoriq->dev->fwnode)) {
+		if (!ptp_acpi_init(ptp_qoriq, base))
+			goto continue_clk;
+		else
+			return -ENODEV;
+	}
+
 	if (!node)
 		return -ENODEV;
 
@@ -499,6 +561,7 @@ int ptp_qoriq_init(struct ptp_qoriq *ptp_qoriq, void __iomem *base,
 		ptp_qoriq->regs.etts_regs = base + ETTS_REGS_OFFSET;
 	}
 
+continue_clk:
 	spin_lock_init(&ptp_qoriq->lock);
 
 	ktime_get_real_ts64(&now);
@@ -581,11 +644,9 @@ static int ptp_qoriq_probe(struct platform_device *dev)
 		pr_err("no resource\n");
 		goto no_resource;
 	}
-	if (request_resource(&iomem_resource, ptp_qoriq->rsrc)) {
-		pr_err("resource busy\n");
-		goto no_resource;
-	}
-
+	/* Note: Disabling request_resource because DPAA architecture has
+	 * memory overlaps, go for ioremap directly.
+	 */
 	base = ioremap(ptp_qoriq->rsrc->start,
 		       resource_size(ptp_qoriq->rsrc));
 	if (!base) {
@@ -629,10 +690,16 @@ static const struct of_device_id match_table[] = {
 };
 MODULE_DEVICE_TABLE(of, match_table);
 
+static const struct acpi_device_id acpi_ptp_table[] = {
+	{"NXP0027", 0}
+};
+MODULE_DEVICE_TABLE(acpi, acpi_ptp_table);
+
 static struct platform_driver ptp_qoriq_driver = {
 	.driver = {
 		.name		= "ptp_qoriq",
 		.of_match_table	= match_table,
+		.acpi_match_table = ACPI_PTR(acpi_ptp_table),
 	},
 	.probe       = ptp_qoriq_probe,
 	.remove      = ptp_qoriq_remove,
diff --git a/include/linux/fsl/ptp_qoriq.h b/include/linux/fsl/ptp_qoriq.h
index 01acebe37fabc..9188c2e9d3ebb 100644
--- a/include/linux/fsl/ptp_qoriq.h
+++ b/include/linux/fsl/ptp_qoriq.h
@@ -138,6 +138,19 @@ struct ptp_qoriq_registers {
 #define DEFAULT_FIPER2_PERIOD	1000000000
 #define DEFAULT_FIPER3_PERIOD	1000000000
 
+#define CLK_DSDT_PROPS	((fwnode_property_read_u32(ptp_fwnode,		    \
+			 "tclk-period", &ptp_qoriq->tclk_period))	||  \
+			 (fwnode_property_read_u32(ptp_fwnode,		    \
+			 "fsl,tmr-prsc", &ptp_qoriq->tmr_prsc))		||  \
+			 (fwnode_property_read_u32(ptp_fwnode,		    \
+			 "fsl,tmr-add", &ptp_qoriq->tmr_add))		||  \
+			 (fwnode_property_read_u32(ptp_fwnode,		    \
+			 "fsl,tmr-fiper1", &ptp_qoriq->tmr_fiper1))	||  \
+			 (fwnode_property_read_u32(ptp_fwnode,		    \
+			 "fsl,tmr-fiper2", &ptp_qoriq->tmr_fiper1))	||  \
+			 (fwnode_property_read_u32(ptp_fwnode,		    \
+			 "fsl,max-adj", &ptp_qoriq->caps.max_adj)))	    \
+
 struct ptp_qoriq {
 	void __iomem *base;
 	struct ptp_qoriq_registers regs;
-- 
GitLab