162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0+ */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * PTP hardware clock driver for the IDT ClockMatrix(TM) family of timing and
462306a36Sopenharmony_ci * synchronization devices.
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * Copyright (C) 2019 Integrated Device Technology, Inc., a Renesas Company.
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci#ifndef PTP_IDTCLOCKMATRIX_H
962306a36Sopenharmony_ci#define PTP_IDTCLOCKMATRIX_H
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#include <linux/ktime.h>
1262306a36Sopenharmony_ci#include <linux/mfd/idt8a340_reg.h>
1362306a36Sopenharmony_ci#include <linux/ptp_clock.h>
1462306a36Sopenharmony_ci#include <linux/regmap.h>
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci#define FW_FILENAME	"idtcm.bin"
1762306a36Sopenharmony_ci#define MAX_TOD		(4)
1862306a36Sopenharmony_ci#define MAX_PLL		(8)
1962306a36Sopenharmony_ci#define MAX_REF_CLK	(16)
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci#define MAX_ABS_WRITE_PHASE_NANOSECONDS (107374182L)
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci#define TOD_MASK_ADDR		(0xFFA5)
2462306a36Sopenharmony_ci#define DEFAULT_TOD_MASK	(0x04)
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci#define SET_U16_LSB(orig, val8) (orig = (0xff00 & (orig)) | (val8))
2762306a36Sopenharmony_ci#define SET_U16_MSB(orig, val8) (orig = (0x00ff & (orig)) | (val8 << 8))
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci#define TOD0_PTP_PLL_ADDR		(0xFFA8)
3062306a36Sopenharmony_ci#define TOD1_PTP_PLL_ADDR		(0xFFA9)
3162306a36Sopenharmony_ci#define TOD2_PTP_PLL_ADDR		(0xFFAA)
3262306a36Sopenharmony_ci#define TOD3_PTP_PLL_ADDR		(0xFFAB)
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci#define TOD0_OUT_ALIGN_MASK_ADDR	(0xFFB0)
3562306a36Sopenharmony_ci#define TOD1_OUT_ALIGN_MASK_ADDR	(0xFFB2)
3662306a36Sopenharmony_ci#define TOD2_OUT_ALIGN_MASK_ADDR	(0xFFB4)
3762306a36Sopenharmony_ci#define TOD3_OUT_ALIGN_MASK_ADDR	(0xFFB6)
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci#define DEFAULT_OUTPUT_MASK_PLL0	(0x003)
4062306a36Sopenharmony_ci#define DEFAULT_OUTPUT_MASK_PLL1	(0x00c)
4162306a36Sopenharmony_ci#define DEFAULT_OUTPUT_MASK_PLL2	(0x030)
4262306a36Sopenharmony_ci#define DEFAULT_OUTPUT_MASK_PLL3	(0x0c0)
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci#define DEFAULT_TOD0_PTP_PLL		(0)
4562306a36Sopenharmony_ci#define DEFAULT_TOD1_PTP_PLL		(1)
4662306a36Sopenharmony_ci#define DEFAULT_TOD2_PTP_PLL		(2)
4762306a36Sopenharmony_ci#define DEFAULT_TOD3_PTP_PLL		(3)
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci#define PHASE_PULL_IN_THRESHOLD_NS_DEPRECATED	(150000)
5062306a36Sopenharmony_ci#define PHASE_PULL_IN_THRESHOLD_NS		(15000)
5162306a36Sopenharmony_ci#define TOD_WRITE_OVERHEAD_COUNT_MAX		(2)
5262306a36Sopenharmony_ci#define TOD_BYTE_COUNT				(11)
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci#define LOCK_TIMEOUT_MS			(2000)
5562306a36Sopenharmony_ci#define LOCK_POLL_INTERVAL_MS		(10)
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci#define IDTCM_MAX_WRITE_COUNT		(512)
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci#define PHASE_PULL_IN_MAX_PPB		(144000)
6062306a36Sopenharmony_ci#define PHASE_PULL_IN_MIN_THRESHOLD_NS	(2)
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci/*
6362306a36Sopenharmony_ci * Return register address based on passed in firmware version
6462306a36Sopenharmony_ci */
6562306a36Sopenharmony_ci#define IDTCM_FW_REG(FW, VER, REG)	(((FW) < (VER)) ? (REG) : (REG##_##VER))
6662306a36Sopenharmony_cienum fw_version {
6762306a36Sopenharmony_ci	V_DEFAULT = 0,
6862306a36Sopenharmony_ci	V487 = 1,
6962306a36Sopenharmony_ci	V520 = 2,
7062306a36Sopenharmony_ci};
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci/* PTP PLL Mode */
7362306a36Sopenharmony_cienum ptp_pll_mode {
7462306a36Sopenharmony_ci	PTP_PLL_MODE_MIN = 0,
7562306a36Sopenharmony_ci	PTP_PLL_MODE_WRITE_FREQUENCY = PTP_PLL_MODE_MIN,
7662306a36Sopenharmony_ci	PTP_PLL_MODE_WRITE_PHASE,
7762306a36Sopenharmony_ci	PTP_PLL_MODE_UNSUPPORTED,
7862306a36Sopenharmony_ci	PTP_PLL_MODE_MAX = PTP_PLL_MODE_UNSUPPORTED,
7962306a36Sopenharmony_ci};
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_cistruct idtcm;
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_cistruct idtcm_channel {
8462306a36Sopenharmony_ci	struct ptp_clock_info	caps;
8562306a36Sopenharmony_ci	struct ptp_clock	*ptp_clock;
8662306a36Sopenharmony_ci	struct idtcm		*idtcm;
8762306a36Sopenharmony_ci	u16			dpll_phase;
8862306a36Sopenharmony_ci	u16			dpll_freq;
8962306a36Sopenharmony_ci	u16			dpll_n;
9062306a36Sopenharmony_ci	u16			dpll_ctrl_n;
9162306a36Sopenharmony_ci	u16			dpll_phase_pull_in;
9262306a36Sopenharmony_ci	u16			tod_read_primary;
9362306a36Sopenharmony_ci	u16			tod_read_secondary;
9462306a36Sopenharmony_ci	u16			tod_write;
9562306a36Sopenharmony_ci	u16			tod_n;
9662306a36Sopenharmony_ci	u16			hw_dpll_n;
9762306a36Sopenharmony_ci	u8			sync_src;
9862306a36Sopenharmony_ci	enum ptp_pll_mode	mode;
9962306a36Sopenharmony_ci	int			(*configure_write_frequency)(struct idtcm_channel *channel);
10062306a36Sopenharmony_ci	int			(*configure_write_phase)(struct idtcm_channel *channel);
10162306a36Sopenharmony_ci	int			(*do_phase_pull_in)(struct idtcm_channel *channel,
10262306a36Sopenharmony_ci						    s32 offset_ns, u32 max_ffo_ppb);
10362306a36Sopenharmony_ci	s32			current_freq_scaled_ppm;
10462306a36Sopenharmony_ci	bool			phase_pull_in;
10562306a36Sopenharmony_ci	u32			dco_delay;
10662306a36Sopenharmony_ci	/* last input trigger for extts */
10762306a36Sopenharmony_ci	u8			refn;
10862306a36Sopenharmony_ci	u8			pll;
10962306a36Sopenharmony_ci	u8			tod;
11062306a36Sopenharmony_ci	u16			output_mask;
11162306a36Sopenharmony_ci};
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_cistruct idtcm {
11462306a36Sopenharmony_ci	struct idtcm_channel	channel[MAX_TOD];
11562306a36Sopenharmony_ci	struct device		*dev;
11662306a36Sopenharmony_ci	u8			tod_mask;
11762306a36Sopenharmony_ci	char			version[16];
11862306a36Sopenharmony_ci	enum fw_version		fw_ver;
11962306a36Sopenharmony_ci	/* Polls for external time stamps */
12062306a36Sopenharmony_ci	u8			extts_mask;
12162306a36Sopenharmony_ci	bool			extts_single_shot;
12262306a36Sopenharmony_ci	struct delayed_work	extts_work;
12362306a36Sopenharmony_ci	/* Remember the ptp channel to report extts */
12462306a36Sopenharmony_ci	struct idtcm_channel	*event_channel[MAX_TOD];
12562306a36Sopenharmony_ci	/* Mutex to protect operations from being interrupted */
12662306a36Sopenharmony_ci	struct mutex		*lock;
12762306a36Sopenharmony_ci	struct device		*mfd;
12862306a36Sopenharmony_ci	struct regmap		*regmap;
12962306a36Sopenharmony_ci	/* Overhead calculation for adjtime */
13062306a36Sopenharmony_ci	u8			calculate_overhead_flag;
13162306a36Sopenharmony_ci	s64			tod_write_overhead_ns;
13262306a36Sopenharmony_ci	ktime_t			start_time;
13362306a36Sopenharmony_ci};
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_cistruct idtcm_fwrc {
13662306a36Sopenharmony_ci	u8 hiaddr;
13762306a36Sopenharmony_ci	u8 loaddr;
13862306a36Sopenharmony_ci	u8 value;
13962306a36Sopenharmony_ci	u8 reserved;
14062306a36Sopenharmony_ci} __packed;
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_ci#endif /* PTP_IDTCLOCKMATRIX_H */
143