diff mbox series

[RFC,3/3] ptp_ocp: implement DPLL ops

Message ID 20220622000651.27299-4-vfedorenko@novek.ru (mailing list archive)
State Superseded
Delegated to: Netdev Maintainers
Headers show
Series Create common DPLL/clock configuration API | expand

Checks

Context Check Description
netdev/tree_selection success Guessed tree name to be net-next
netdev/fixes_present success Fixes tag not required for -next series
netdev/subject_prefix success Link
netdev/cover_letter success Series has a cover letter
netdev/patch_count success Link
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit fail Errors and warnings before: 0 this patch: 17
netdev/cc_maintainers fail 2 maintainers not CCed: richardcochran@gmail.com jonathan.lemon@gmail.com
netdev/build_clang fail Errors and warnings before: 0 this patch: 25
netdev/module_param success Was 0 now: 0
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn fail Errors and warnings before: 0 this patch: 32
netdev/checkpatch warning CHECK: Please don't use multiple blank lines WARNING: line length of 90 exceeds 80 columns
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0

Commit Message

Vadim Fedorenko June 22, 2022, 12:06 a.m. UTC
From: Vadim Fedorenko <vadfed@fb.com>

Implement DPLL operations in ptp_ocp driver.

Signed-off-by: Vadim Fedorenko <vadfed@fb.com>
---
 drivers/ptp/Kconfig   |  1 +
 drivers/ptp/ptp_ocp.c | 85 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 86 insertions(+)
diff mbox series

Patch

diff --git a/drivers/ptp/Kconfig b/drivers/ptp/Kconfig
index 458218f88c5e..f74846ebc177 100644
--- a/drivers/ptp/Kconfig
+++ b/drivers/ptp/Kconfig
@@ -176,6 +176,7 @@  config PTP_1588_CLOCK_OCP
 	depends on !S390
 	depends on COMMON_CLK
 	select NET_DEVLINK
+	select DPLL
 	help
 	  This driver adds support for an OpenCompute time card.
 
diff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c
index e59ea2173aac..b7bdb210514d 100644
--- a/drivers/ptp/ptp_ocp.c
+++ b/drivers/ptp/ptp_ocp.c
@@ -21,6 +21,7 @@ 
 #include <linux/mtd/mtd.h>
 #include <linux/nvmem-consumer.h>
 #include <linux/crc16.h>
+#include <uapi/linux/dpll.h>
 
 #define PCI_VENDOR_ID_FACEBOOK			0x1d9b
 #define PCI_DEVICE_ID_FACEBOOK_TIMECARD		0x0400
@@ -336,6 +337,7 @@  struct ptp_ocp {
 	struct ptp_ocp_signal	signal[4];
 	struct ptp_ocp_sma_connector sma[4];
 	const struct ocp_sma_op *sma_op;
+	struct dpll_device *dpll;
 };
 
 #define OCP_REQ_TIMESTAMP	BIT(0)
@@ -3713,6 +3715,81 @@  ptp_ocp_detach(struct ptp_ocp *bp)
 	device_unregister(&bp->dev);
 }
 
+static int ptp_ocp_dpll_get_status(struct dpll_device *dpll)
+{
+	struct ptp_ocp *bp = (struct ptp_ocp *)dpll->priv;
+	int sync;
+
+	sync = ioread32(&bp->reg->status) & OCP_STATUS_IN_SYNC;
+	return sync;
+}
+
+static int ptp_ocp_dpll_get_lock_status(struct dpll_device *dpll)
+{
+	struct ptp_ocp *bp = (struct ptp_ocp *)dpll->priv;
+	int sync;
+
+	sync = ioread32(&bp->reg->status) & OCP_STATUS_IN_SYNC;
+	return sync;
+}
+
+static int ptp_ocp_dpll_get_source_type(struct dpll_device *dpll, int sma)
+{
+	struct ptp_ocp *bp = (struct ptp_ocp *)dpll->priv;
+	int ret;
+
+	if (bp->sma[sma].mode != SMA_MODE_IN)
+		return -1;
+
+	switch (ptp_ocp_sma_get(bp, sma)) {
+	case 0:
+		ret = DPLL_TYPE_EXT_10MHZ;
+		break;
+	case 1:
+	case 2:
+		ret = DPLL_TYPE_EXT_1PPS;
+		break;
+	default:
+		ret = DPLL_TYPE_INT_OSCILLATOR;
+	}
+
+	return ret;
+}
+
+
+static int ptp_ocp_dpll_get_output_type(struct dpll_device *dpll, int sma)
+{
+	struct ptp_ocp *bp = (struct ptp_ocp *)dpll->priv;
+	int ret;
+
+	if (bp->sma[sma].mode != SMA_MODE_IN)
+		return -1;
+
+	switch (ptp_ocp_sma_get(bp, sma)) {
+	case 0:
+		ret = DPLL_TYPE_EXT_10MHZ;
+		break;
+	case 1:
+	case 2:
+		ret = DPLL_TYPE_INT_OSCILLATOR;
+	case 4:
+	case 8:
+		ret = DPLL_TYPE_GNSS;
+		break;
+	default:
+		ret = DPLL_TYPE_INT_OSCILLATOR;
+	}
+
+	return ret;
+}
+
+static struct dpll_device_ops ptp_ocp_dpll_ops {
+	.get_status			= ptp_ocp_dpll_get_status;
+	.get_lock_status	= ptp_ocp_dpll_get_lock_status;
+	.get_source_type	= ptp_ocp_dpll_get_source_type;
+	.get_output_type	= ptp_ocp_dpll_get_output_type;
+};
+
 static int
 ptp_ocp_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
@@ -3768,6 +3845,14 @@  ptp_ocp_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
 	ptp_ocp_info(bp);
 	devlink_register(devlink);
+
+	bp->dpll = dpll_device_alloc(&dpll_ops, ARRAY_SIZE(bp->sma), ARRAY_SIZE(bp->sma));
+	if (!bp->dpll) {
+		dev_err(&pdev->dev, "dpll_device_alloc failed\n");
+		return 0;
+	}
+	dpll_device_register(bp->dpll);
+
 	return 0;
 
 out: