xref: /linux/drivers/ptp/ptp_clockmatrix.h (revision d0034a7a4ac7fae708146ac0059b9c47a1543f0d)
13a6ba7dcSVincent Cheng /* SPDX-License-Identifier: GPL-2.0+ */
23a6ba7dcSVincent Cheng /*
33a6ba7dcSVincent Cheng  * PTP hardware clock driver for the IDT ClockMatrix(TM) family of timing and
43a6ba7dcSVincent Cheng  * synchronization devices.
53a6ba7dcSVincent Cheng  *
63a6ba7dcSVincent Cheng  * Copyright (C) 2019 Integrated Device Technology, Inc., a Renesas Company.
73a6ba7dcSVincent Cheng  */
83a6ba7dcSVincent Cheng #ifndef PTP_IDTCLOCKMATRIX_H
93a6ba7dcSVincent Cheng #define PTP_IDTCLOCKMATRIX_H
103a6ba7dcSVincent Cheng 
113a6ba7dcSVincent Cheng #include <linux/ktime.h>
123a6ba7dcSVincent Cheng 
133a6ba7dcSVincent Cheng #include "idt8a340_reg.h"
143a6ba7dcSVincent Cheng 
153a6ba7dcSVincent Cheng #define FW_FILENAME	"idtcm.bin"
167ea5fda2SMin Li #define MAX_TOD		(4)
177ea5fda2SMin Li #define MAX_PLL		(8)
183a6ba7dcSVincent Cheng 
19425d2b1cSVincent Cheng #define MAX_ABS_WRITE_PHASE_PICOSECONDS (107374182350LL)
20425d2b1cSVincent Cheng 
217ea5fda2SMin Li #define TOD_MASK_ADDR		(0xFFA5)
227ea5fda2SMin Li #define DEFAULT_TOD_MASK	(0x04)
233a6ba7dcSVincent Cheng 
243a6ba7dcSVincent Cheng #define SET_U16_LSB(orig, val8) (orig = (0xff00 & (orig)) | (val8))
253a6ba7dcSVincent Cheng #define SET_U16_MSB(orig, val8) (orig = (0x00ff & (orig)) | (val8 << 8))
263a6ba7dcSVincent Cheng 
277ea5fda2SMin Li #define TOD0_PTP_PLL_ADDR		(0xFFA8)
287ea5fda2SMin Li #define TOD1_PTP_PLL_ADDR		(0xFFA9)
297ea5fda2SMin Li #define TOD2_PTP_PLL_ADDR		(0xFFAA)
307ea5fda2SMin Li #define TOD3_PTP_PLL_ADDR		(0xFFAB)
317ea5fda2SMin Li 
327ea5fda2SMin Li #define TOD0_OUT_ALIGN_MASK_ADDR	(0xFFB0)
337ea5fda2SMin Li #define TOD1_OUT_ALIGN_MASK_ADDR	(0xFFB2)
347ea5fda2SMin Li #define TOD2_OUT_ALIGN_MASK_ADDR	(0xFFB4)
357ea5fda2SMin Li #define TOD3_OUT_ALIGN_MASK_ADDR	(0xFFB6)
363a6ba7dcSVincent Cheng 
373a6ba7dcSVincent Cheng #define DEFAULT_OUTPUT_MASK_PLL0	(0x003)
383a6ba7dcSVincent Cheng #define DEFAULT_OUTPUT_MASK_PLL1	(0x00c)
393a6ba7dcSVincent Cheng #define DEFAULT_OUTPUT_MASK_PLL2	(0x030)
403a6ba7dcSVincent Cheng #define DEFAULT_OUTPUT_MASK_PLL3	(0x0c0)
413a6ba7dcSVincent Cheng 
427ea5fda2SMin Li #define DEFAULT_TOD0_PTP_PLL		(0)
437ea5fda2SMin Li #define DEFAULT_TOD1_PTP_PLL		(1)
447ea5fda2SMin Li #define DEFAULT_TOD2_PTP_PLL		(2)
457ea5fda2SMin Li #define DEFAULT_TOD3_PTP_PLL		(3)
467ea5fda2SMin Li 
473a6ba7dcSVincent Cheng #define POST_SM_RESET_DELAY_MS			(3000)
48da948233SMin Li #define PHASE_PULL_IN_THRESHOLD_NS_DEPRECATED	(150000)
49da948233SMin Li #define PHASE_PULL_IN_THRESHOLD_NS		(15000)
507ea5fda2SMin Li #define TOD_WRITE_OVERHEAD_COUNT_MAX		(2)
513a6ba7dcSVincent Cheng #define TOD_BYTE_COUNT				(11)
527ea5fda2SMin Li 
53*797d3186SVincent Cheng #define LOCK_TIMEOUT_MS			(2000)
54*797d3186SVincent Cheng #define LOCK_POLL_INTERVAL_MS		(10)
55*797d3186SVincent Cheng 
567ea5fda2SMin Li #define PEROUT_ENABLE_OUTPUT_MASK	(0xdeadbeef)
577ea5fda2SMin Li 
58957ff427SMin Li #define IDTCM_MAX_WRITE_COUNT		(512)
59251f4fe2SMin Li 
60251f4fe2SMin Li #define FULL_FW_CFG_BYTES		(SCRATCH - GPIO_USER_CONTROL)
61251f4fe2SMin Li #define FULL_FW_CFG_SKIPPED_BYTES	(((SCRATCH >> 7) \
62251f4fe2SMin Li 					  - (GPIO_USER_CONTROL >> 7)) \
63251f4fe2SMin Li 					 * 4) /* 4 bytes skipped every 0x80 */
64957ff427SMin Li 
653a6ba7dcSVincent Cheng /* Values of DPLL_N.DPLL_MODE.PLL_MODE */
663a6ba7dcSVincent Cheng enum pll_mode {
673a6ba7dcSVincent Cheng 	PLL_MODE_MIN = 0,
683a6ba7dcSVincent Cheng 	PLL_MODE_NORMAL = PLL_MODE_MIN,
693a6ba7dcSVincent Cheng 	PLL_MODE_WRITE_PHASE = 1,
703a6ba7dcSVincent Cheng 	PLL_MODE_WRITE_FREQUENCY = 2,
713a6ba7dcSVincent Cheng 	PLL_MODE_GPIO_INC_DEC = 3,
723a6ba7dcSVincent Cheng 	PLL_MODE_SYNTHESIS = 4,
733a6ba7dcSVincent Cheng 	PLL_MODE_PHASE_MEASUREMENT = 5,
747ea5fda2SMin Li 	PLL_MODE_DISABLED = 6,
757ea5fda2SMin Li 	PLL_MODE_MAX = PLL_MODE_DISABLED,
763a6ba7dcSVincent Cheng };
773a6ba7dcSVincent Cheng 
783a6ba7dcSVincent Cheng enum hw_tod_write_trig_sel {
793a6ba7dcSVincent Cheng 	HW_TOD_WR_TRIG_SEL_MIN = 0,
803a6ba7dcSVincent Cheng 	HW_TOD_WR_TRIG_SEL_MSB = HW_TOD_WR_TRIG_SEL_MIN,
813a6ba7dcSVincent Cheng 	HW_TOD_WR_TRIG_SEL_RESERVED = 1,
823a6ba7dcSVincent Cheng 	HW_TOD_WR_TRIG_SEL_TOD_PPS = 2,
833a6ba7dcSVincent Cheng 	HW_TOD_WR_TRIG_SEL_IRIGB_PPS = 3,
843a6ba7dcSVincent Cheng 	HW_TOD_WR_TRIG_SEL_PWM_PPS = 4,
853a6ba7dcSVincent Cheng 	HW_TOD_WR_TRIG_SEL_GPIO = 5,
863a6ba7dcSVincent Cheng 	HW_TOD_WR_TRIG_SEL_FOD_SYNC = 6,
873a6ba7dcSVincent Cheng 	WR_TRIG_SEL_MAX = HW_TOD_WR_TRIG_SEL_FOD_SYNC,
883a6ba7dcSVincent Cheng };
893a6ba7dcSVincent Cheng 
907ea5fda2SMin Li /* 4.8.7 only */
917ea5fda2SMin Li enum scsr_tod_write_trig_sel {
927ea5fda2SMin Li 	SCSR_TOD_WR_TRIG_SEL_DISABLE = 0,
937ea5fda2SMin Li 	SCSR_TOD_WR_TRIG_SEL_IMMEDIATE = 1,
947ea5fda2SMin Li 	SCSR_TOD_WR_TRIG_SEL_REFCLK = 2,
957ea5fda2SMin Li 	SCSR_TOD_WR_TRIG_SEL_PWMPPS = 3,
967ea5fda2SMin Li 	SCSR_TOD_WR_TRIG_SEL_TODPPS = 4,
977ea5fda2SMin Li 	SCSR_TOD_WR_TRIG_SEL_SYNCFOD = 5,
987ea5fda2SMin Li 	SCSR_TOD_WR_TRIG_SEL_GPIO = 6,
997ea5fda2SMin Li 	SCSR_TOD_WR_TRIG_SEL_MAX = SCSR_TOD_WR_TRIG_SEL_GPIO,
1007ea5fda2SMin Li };
1017ea5fda2SMin Li 
1027ea5fda2SMin Li /* 4.8.7 only */
1037ea5fda2SMin Li enum scsr_tod_write_type_sel {
1047ea5fda2SMin Li 	SCSR_TOD_WR_TYPE_SEL_ABSOLUTE = 0,
1057ea5fda2SMin Li 	SCSR_TOD_WR_TYPE_SEL_DELTA_PLUS = 1,
1067ea5fda2SMin Li 	SCSR_TOD_WR_TYPE_SEL_DELTA_MINUS = 2,
1077ea5fda2SMin Li 	SCSR_TOD_WR_TYPE_SEL_MAX = SCSR_TOD_WR_TYPE_SEL_DELTA_MINUS,
1087ea5fda2SMin Li };
1097ea5fda2SMin Li 
110*797d3186SVincent Cheng /* Values STATUS.DPLL_SYS_STATUS.DPLL_SYS_STATE */
111*797d3186SVincent Cheng enum dpll_state {
112*797d3186SVincent Cheng 	DPLL_STATE_MIN = 0,
113*797d3186SVincent Cheng 	DPLL_STATE_FREERUN = DPLL_STATE_MIN,
114*797d3186SVincent Cheng 	DPLL_STATE_LOCKACQ = 1,
115*797d3186SVincent Cheng 	DPLL_STATE_LOCKREC = 2,
116*797d3186SVincent Cheng 	DPLL_STATE_LOCKED = 3,
117*797d3186SVincent Cheng 	DPLL_STATE_HOLDOVER = 4,
118*797d3186SVincent Cheng 	DPLL_STATE_OPEN_LOOP = 5,
119*797d3186SVincent Cheng 	DPLL_STATE_MAX = DPLL_STATE_OPEN_LOOP,
120*797d3186SVincent Cheng };
121*797d3186SVincent Cheng 
1223a6ba7dcSVincent Cheng struct idtcm;
1233a6ba7dcSVincent Cheng 
1243a6ba7dcSVincent Cheng struct idtcm_channel {
1253a6ba7dcSVincent Cheng 	struct ptp_clock_info	caps;
1263a6ba7dcSVincent Cheng 	struct ptp_clock	*ptp_clock;
1273a6ba7dcSVincent Cheng 	struct idtcm		*idtcm;
1283a6ba7dcSVincent Cheng 	u16			dpll_phase;
1293a6ba7dcSVincent Cheng 	u16			dpll_freq;
1303a6ba7dcSVincent Cheng 	u16			dpll_n;
1313a6ba7dcSVincent Cheng 	u16			dpll_ctrl_n;
1323a6ba7dcSVincent Cheng 	u16			dpll_phase_pull_in;
1333a6ba7dcSVincent Cheng 	u16			tod_read_primary;
1343a6ba7dcSVincent Cheng 	u16			tod_write;
1353a6ba7dcSVincent Cheng 	u16			tod_n;
1363a6ba7dcSVincent Cheng 	u16			hw_dpll_n;
1373a6ba7dcSVincent Cheng 	enum pll_mode		pll_mode;
1387ea5fda2SMin Li 	u8			pll;
1393a6ba7dcSVincent Cheng 	u16			output_mask;
1403a6ba7dcSVincent Cheng };
1413a6ba7dcSVincent Cheng 
1423a6ba7dcSVincent Cheng struct idtcm {
1437ea5fda2SMin Li 	struct idtcm_channel	channel[MAX_TOD];
1443a6ba7dcSVincent Cheng 	struct i2c_client	*client;
1453a6ba7dcSVincent Cheng 	u8			page_offset;
1467ea5fda2SMin Li 	u8			tod_mask;
1477ea5fda2SMin Li 	char			version[16];
148da948233SMin Li 	u8			deprecated;
1493a6ba7dcSVincent Cheng 
1503a6ba7dcSVincent Cheng 	/* Overhead calculation for adjtime */
1513a6ba7dcSVincent Cheng 	u8			calculate_overhead_flag;
1523a6ba7dcSVincent Cheng 	s64			tod_write_overhead_ns;
1533a6ba7dcSVincent Cheng 	ktime_t			start_time;
1543a6ba7dcSVincent Cheng 
1553a6ba7dcSVincent Cheng 	/* Protects I2C read/modify/write registers from concurrent access */
1563a6ba7dcSVincent Cheng 	struct mutex		reg_lock;
1573a6ba7dcSVincent Cheng };
1583a6ba7dcSVincent Cheng 
1593a6ba7dcSVincent Cheng struct idtcm_fwrc {
1603a6ba7dcSVincent Cheng 	u8 hiaddr;
1613a6ba7dcSVincent Cheng 	u8 loaddr;
1623a6ba7dcSVincent Cheng 	u8 value;
1633a6ba7dcSVincent Cheng 	u8 reserved;
1643a6ba7dcSVincent Cheng } __packed;
1653a6ba7dcSVincent Cheng 
1663a6ba7dcSVincent Cheng #endif /* PTP_IDTCLOCKMATRIX_H */
167