linux_dsm_epyc7002/drivers/ptp/ptp_idt82p33.h
Min Li 57a10d8c11 ptp: Add a ptp clock driver for IDT 82P33 SMU.
The IDT 82P33 Synchronization Management Unit (SMU) family provides
tools to manage timing references, clock sources and
timing paths for IEEE 1588 / Precision Time Protocol (PTP) and
Synchronous Ethernet (SyncE) based clocks. The device supports up
to three independent timing paths that control: PTP clock synthesis;
SyncE clock generation; and general purpose frequency translation.
The device supports physical layer timing with Digital PLLs (DPLLs)
and it supports packet based timing with Digitally Controlled
Oscillators (DCOs). This patch adds support for ptp clock based on
the device.

Changes since v1:
 - As suggested by Richard Cochran:
   1. Replace _mask_bit_count with the existing hweight8
   2. Prefix all functions with idt82p33
   3. Fix white space issues in Kconfig and Makefile
   4. Remove forward declaration
   5. Use adjfine instead of adjfreq for better resolution

 - As suggested by David Miller:
   1. Replace CHAN_INIT macro with a static function
      idt82p33_channel_init
   2. Employ reverse christmas tree ordering for local
      variables
   3. Fix indentation problem by appropriate number of
      TAB then SPACE character

Signed-off-by: Min Li <min.li.xe@renesas.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2020-02-24 13:08:46 -08:00

172 lines
4.4 KiB
C

/* SPDX-License-Identifier: GPL-2.0+ */
/*
* PTP hardware clock driver for the IDT 82P33XXX family of clocks.
*
* Copyright (C) 2019 Integrated Device Technology, Inc., a Renesas Company.
*/
#ifndef PTP_IDT82P33_H
#define PTP_IDT82P33_H
#include <linux/ktime.h>
#include <linux/workqueue.h>
/* Register Map - AN888_SMUforIEEE_SynchEther_82P33xxx_RevH.pdf */
#define PAGE_NUM (8)
#define _ADDR(page, offset) (((page) << 0x7) | ((offset) & 0x7f))
#define _PAGE(addr) (((addr) >> 0x7) & 0x7)
#define _OFFSET(addr) ((addr) & 0x7f)
#define DPLL1_TOD_CNFG 0x134
#define DPLL2_TOD_CNFG 0x1B4
#define DPLL1_TOD_STS 0x10B
#define DPLL2_TOD_STS 0x18B
#define DPLL1_TOD_TRIGGER 0x115
#define DPLL2_TOD_TRIGGER 0x195
#define DPLL1_OPERATING_MODE_CNFG 0x120
#define DPLL2_OPERATING_MODE_CNFG 0x1A0
#define DPLL1_HOLDOVER_FREQ_CNFG 0x12C
#define DPLL2_HOLDOVER_FREQ_CNFG 0x1AC
#define DPLL1_PHASE_OFFSET_CNFG 0x143
#define DPLL2_PHASE_OFFSET_CNFG 0x1C3
#define DPLL1_SYNC_EDGE_CNFG 0X140
#define DPLL2_SYNC_EDGE_CNFG 0X1C0
#define DPLL1_INPUT_MODE_CNFG 0X116
#define DPLL2_INPUT_MODE_CNFG 0X196
#define OUT_MUX_CNFG(outn) _ADDR(0x6, (0xC * (outn)))
#define PAGE_ADDR 0x7F
/* Register Map end */
/* Register definitions - AN888_SMUforIEEE_SynchEther_82P33xxx_RevH.pdf*/
#define TOD_TRIGGER(wr_trig, rd_trig) ((wr_trig & 0xf) << 4 | (rd_trig & 0xf))
#define SYNC_TOD BIT(1)
#define PH_OFFSET_EN BIT(7)
#define SQUELCH_ENABLE BIT(5)
/* Bit definitions for the DPLL_MODE register */
#define PLL_MODE_SHIFT (0)
#define PLL_MODE_MASK (0x1F)
enum pll_mode {
PLL_MODE_MIN = 0,
PLL_MODE_AUTOMATIC = PLL_MODE_MIN,
PLL_MODE_FORCE_FREERUN = 1,
PLL_MODE_FORCE_HOLDOVER = 2,
PLL_MODE_FORCE_LOCKED = 4,
PLL_MODE_FORCE_PRE_LOCKED2 = 5,
PLL_MODE_FORCE_PRE_LOCKED = 6,
PLL_MODE_FORCE_LOST_PHASE = 7,
PLL_MODE_DCO = 10,
PLL_MODE_WPH = 18,
PLL_MODE_MAX = PLL_MODE_WPH,
};
enum hw_tod_trig_sel {
HW_TOD_TRIG_SEL_MIN = 0,
HW_TOD_TRIG_SEL_NO_WRITE = HW_TOD_TRIG_SEL_MIN,
HW_TOD_TRIG_SEL_SYNC_SEL = 1,
HW_TOD_TRIG_SEL_IN12 = 2,
HW_TOD_TRIG_SEL_IN13 = 3,
HW_TOD_TRIG_SEL_IN14 = 4,
HW_TOD_TRIG_SEL_TOD_PPS = 5,
HW_TOD_TRIG_SEL_TIMER_INTERVAL = 6,
HW_TOD_TRIG_SEL_MSB_PHASE_OFFSET_CNFG = 7,
HW_TOD_TRIG_SEL_MSB_HOLDOVER_FREQ_CNFG = 8,
HW_TOD_WR_TRIG_SEL_MSB_TOD_CNFG = 9,
HW_TOD_RD_TRIG_SEL_LSB_TOD_STS = HW_TOD_WR_TRIG_SEL_MSB_TOD_CNFG,
WR_TRIG_SEL_MAX = HW_TOD_WR_TRIG_SEL_MSB_TOD_CNFG,
};
/* Register bit definitions end */
#define FW_FILENAME "idt82p33xxx.bin"
#define MAX_PHC_PLL (2)
#define TOD_BYTE_COUNT (10)
#define MAX_MEASURMENT_COUNT (5)
#define SNAP_THRESHOLD_NS (150000)
#define SYNC_TOD_TIMEOUT_SEC (5)
#define PLLMASK_ADDR_HI 0xFF
#define PLLMASK_ADDR_LO 0xA5
#define PLL0_OUTMASK_ADDR_HI 0xFF
#define PLL0_OUTMASK_ADDR_LO 0xB0
#define PLL1_OUTMASK_ADDR_HI 0xFF
#define PLL1_OUTMASK_ADDR_LO 0xB2
#define PLL2_OUTMASK_ADDR_HI 0xFF
#define PLL2_OUTMASK_ADDR_LO 0xB4
#define PLL3_OUTMASK_ADDR_HI 0xFF
#define PLL3_OUTMASK_ADDR_LO 0xB6
#define DEFAULT_PLL_MASK (0x01)
#define DEFAULT_OUTPUT_MASK_PLL0 (0xc0)
#define DEFAULT_OUTPUT_MASK_PLL1 DEFAULT_OUTPUT_MASK_PLL0
/* PTP Hardware Clock interface */
struct idt82p33_channel {
struct ptp_clock_info caps;
struct ptp_clock *ptp_clock;
struct idt82p33 *idt82p33;
enum pll_mode pll_mode;
/* task to turn off SYNC_TOD bit after pps sync */
struct delayed_work sync_tod_work;
bool sync_tod_on;
s32 current_freq_ppb;
u8 output_mask;
u16 dpll_tod_cnfg;
u16 dpll_tod_trigger;
u16 dpll_tod_sts;
u16 dpll_mode_cnfg;
u16 dpll_freq_cnfg;
u16 dpll_phase_cnfg;
u16 dpll_sync_cnfg;
u16 dpll_input_mode_cnfg;
};
struct idt82p33 {
struct idt82p33_channel channel[MAX_PHC_PLL];
struct i2c_client *client;
u8 page_offset;
u8 pll_mask;
ktime_t start_time;
int calculate_overhead_flag;
s64 tod_write_overhead_ns;
/* Protects I2C read/modify/write registers from concurrent access */
struct mutex reg_lock;
};
/* firmware interface */
struct idt82p33_fwrc {
u8 hiaddr;
u8 loaddr;
u8 value;
u8 reserved;
} __packed;
/**
* @brief Maximum absolute value for write phase offset in femtoseconds
*/
#define WRITE_PHASE_OFFSET_LIMIT (20000052084ll)
/** @brief Phase offset resolution
*
* DPLL phase offset = 10^15 fs / ( System Clock * 2^13)
* = 10^15 fs / ( 1638400000 * 2^23)
* = 74.5058059692382 fs
*/
#define IDT_T0DPLL_PHASE_RESOL 74506
#endif /* PTP_IDT82P33_H */