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