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