blob: 0f3059ae1fffa79e4344901304ef0bb409ed4290 [file] [log] [blame]
Vincent Cheng3a6ba7d2019-10-31 23:20:07 -04001/* SPDX-License-Identifier: GPL-2.0+ */
2/*
3 * PTP hardware clock driver for the IDT ClockMatrix(TM) family of timing and
4 * synchronization devices.
5 *
6 * Copyright (C) 2019 Integrated Device Technology, Inc., a Renesas Company.
7 */
8#ifndef PTP_IDTCLOCKMATRIX_H
9#define PTP_IDTCLOCKMATRIX_H
10
11#include <linux/ktime.h>
Min Li930dfa52021-09-24 15:01:32 -040012#include <linux/mfd/idt8a340_reg.h>
13#include <linux/regmap.h>
Vincent Cheng3a6ba7d2019-10-31 23:20:07 -040014
15#define FW_FILENAME "idtcm.bin"
Min Li7ea5fda2020-07-28 16:00:30 -040016#define MAX_TOD (4)
17#define MAX_PLL (8)
Vincent Cheng3a6ba7d2019-10-31 23:20:07 -040018
Vincent Cheng425d2b12020-05-01 23:35:38 -040019#define MAX_ABS_WRITE_PHASE_PICOSECONDS (107374182350LL)
20
Min Li7ea5fda2020-07-28 16:00:30 -040021#define TOD_MASK_ADDR (0xFFA5)
22#define DEFAULT_TOD_MASK (0x04)
Vincent Cheng3a6ba7d2019-10-31 23:20:07 -040023
24#define SET_U16_LSB(orig, val8) (orig = (0xff00 & (orig)) | (val8))
25#define SET_U16_MSB(orig, val8) (orig = (0x00ff & (orig)) | (val8 << 8))
26
Min Li7ea5fda2020-07-28 16:00:30 -040027#define TOD0_PTP_PLL_ADDR (0xFFA8)
28#define TOD1_PTP_PLL_ADDR (0xFFA9)
29#define TOD2_PTP_PLL_ADDR (0xFFAA)
30#define TOD3_PTP_PLL_ADDR (0xFFAB)
31
32#define TOD0_OUT_ALIGN_MASK_ADDR (0xFFB0)
33#define TOD1_OUT_ALIGN_MASK_ADDR (0xFFB2)
34#define TOD2_OUT_ALIGN_MASK_ADDR (0xFFB4)
35#define TOD3_OUT_ALIGN_MASK_ADDR (0xFFB6)
Vincent Cheng3a6ba7d2019-10-31 23:20:07 -040036
37#define DEFAULT_OUTPUT_MASK_PLL0 (0x003)
38#define DEFAULT_OUTPUT_MASK_PLL1 (0x00c)
39#define DEFAULT_OUTPUT_MASK_PLL2 (0x030)
40#define DEFAULT_OUTPUT_MASK_PLL3 (0x0c0)
41
Min Li7ea5fda2020-07-28 16:00:30 -040042#define DEFAULT_TOD0_PTP_PLL (0)
43#define DEFAULT_TOD1_PTP_PLL (1)
44#define DEFAULT_TOD2_PTP_PLL (2)
45#define DEFAULT_TOD3_PTP_PLL (3)
46
Min Lida948232020-12-08 10:41:57 -050047#define PHASE_PULL_IN_THRESHOLD_NS_DEPRECATED (150000)
48#define PHASE_PULL_IN_THRESHOLD_NS (15000)
49#define TOD_WRITE_OVERHEAD_COUNT_MAX (2)
50#define TOD_BYTE_COUNT (11)
Min Li7ea5fda2020-07-28 16:00:30 -040051
Vincent Cheng797d3182021-02-17 00:42:12 -050052#define LOCK_TIMEOUT_MS (2000)
53#define LOCK_POLL_INTERVAL_MS (10)
54
Min Li251f4fe2020-12-08 10:41:54 -050055#define PEROUT_ENABLE_OUTPUT_MASK (0xdeadbeef)
Min Li7ea5fda2020-07-28 16:00:30 -040056
Min Li251f4fe2020-12-08 10:41:54 -050057#define IDTCM_MAX_WRITE_COUNT (512)
58
Min Lida9facf2021-09-13 16:12:34 -040059#define PHASE_PULL_IN_MAX_PPB (144000)
60#define PHASE_PULL_IN_MIN_THRESHOLD_NS (2)
61
Min Li794c3df2021-09-13 16:12:33 -040062/*
63 * Return register address based on passed in firmware version
64 */
65#define IDTCM_FW_REG(FW, VER, REG) (((FW) < (VER)) ? (REG) : (REG##_##VER))
Min Li930dfa52021-09-24 15:01:32 -040066enum fw_version {
67 V_DEFAULT = 0,
68 V487 = 1,
69 V520 = 2,
70};
Min Li957ff422020-08-18 10:41:22 -040071
Min Lida9facf2021-09-13 16:12:34 -040072/* PTP PLL Mode */
73enum ptp_pll_mode {
74 PTP_PLL_MODE_MIN = 0,
75 PTP_PLL_MODE_WRITE_FREQUENCY = PTP_PLL_MODE_MIN,
76 PTP_PLL_MODE_WRITE_PHASE,
77 PTP_PLL_MODE_UNSUPPORTED,
78 PTP_PLL_MODE_MAX = PTP_PLL_MODE_UNSUPPORTED,
79};
80
Vincent Cheng3a6ba7d2019-10-31 23:20:07 -040081struct idtcm;
82
83struct idtcm_channel {
84 struct ptp_clock_info caps;
85 struct ptp_clock *ptp_clock;
86 struct idtcm *idtcm;
87 u16 dpll_phase;
88 u16 dpll_freq;
89 u16 dpll_n;
90 u16 dpll_ctrl_n;
91 u16 dpll_phase_pull_in;
92 u16 tod_read_primary;
93 u16 tod_write;
94 u16 tod_n;
95 u16 hw_dpll_n;
Min Li794c3df2021-09-13 16:12:33 -040096 u8 sync_src;
Min Lida9facf2021-09-13 16:12:34 -040097 enum ptp_pll_mode mode;
98 int (*configure_write_frequency)(struct idtcm_channel *channel);
99 int (*configure_write_phase)(struct idtcm_channel *channel);
100 int (*do_phase_pull_in)(struct idtcm_channel *channel,
101 s32 offset_ns, u32 max_ffo_ppb);
102 s32 current_freq_scaled_ppm;
103 bool phase_pull_in;
Min Li930dfa52021-09-24 15:01:32 -0400104 u32 dco_delay;
105 /* last input trigger for extts */
106 u8 refn;
Min Li7ea5fda2020-07-28 16:00:30 -0400107 u8 pll;
Vincent Cheng3a6ba7d2019-10-31 23:20:07 -0400108 u16 output_mask;
Vincent Cheng3a6ba7d2019-10-31 23:20:07 -0400109};
110
111struct idtcm {
Min Li7ea5fda2020-07-28 16:00:30 -0400112 struct idtcm_channel channel[MAX_TOD];
Min Li930dfa52021-09-24 15:01:32 -0400113 struct device *dev;
Min Li7ea5fda2020-07-28 16:00:30 -0400114 u8 tod_mask;
115 char version[16];
Min Li794c3df2021-09-13 16:12:33 -0400116 enum fw_version fw_ver;
Min Li930dfa52021-09-24 15:01:32 -0400117 /* Polls for external time stamps */
118 u8 extts_mask;
119 struct delayed_work extts_work;
120 /* Remember the ptp channel to report extts */
121 struct idtcm_channel *event_channel[MAX_TOD];
122 /* Mutex to protect operations from being interrupted */
123 struct mutex *lock;
124 struct device *mfd;
125 struct regmap *regmap;
Vincent Cheng3a6ba7d2019-10-31 23:20:07 -0400126 /* Overhead calculation for adjtime */
127 u8 calculate_overhead_flag;
128 s64 tod_write_overhead_ns;
129 ktime_t start_time;
Vincent Cheng3a6ba7d2019-10-31 23:20:07 -0400130};
131
132struct idtcm_fwrc {
133 u8 hiaddr;
134 u8 loaddr;
135 u8 value;
136 u8 reserved;
137} __packed;
138
139#endif /* PTP_IDTCLOCKMATRIX_H */