xref: /openbmc/linux/drivers/net/ethernet/ti/cpts.h (revision b78aba49)
168cf027fSGrygorii Strashko /* SPDX-License-Identifier: GPL-2.0+ */
287c0e764SRichard Cochran /*
387c0e764SRichard Cochran  * TI Common Platform Time Sync
487c0e764SRichard Cochran  *
587c0e764SRichard Cochran  * Copyright (C) 2012 Richard Cochran <richardcochran@gmail.com>
687c0e764SRichard Cochran  *
787c0e764SRichard Cochran  */
887c0e764SRichard Cochran #ifndef _TI_CPTS_H_
987c0e764SRichard Cochran #define _TI_CPTS_H_
1087c0e764SRichard Cochran 
118a2c9a5aSGrygorii Strashko #if IS_ENABLED(CONFIG_TI_CPTS)
128a2c9a5aSGrygorii Strashko 
1387c0e764SRichard Cochran #include <linux/clk.h>
1487c0e764SRichard Cochran #include <linux/clkdev.h>
1587c0e764SRichard Cochran #include <linux/clocksource.h>
1687c0e764SRichard Cochran #include <linux/device.h>
1787c0e764SRichard Cochran #include <linux/list.h>
184a88fb95SGrygorii Strashko #include <linux/of.h>
1987c0e764SRichard Cochran #include <linux/ptp_clock_kernel.h>
2087c0e764SRichard Cochran #include <linux/skbuff.h>
21f44f8417SIvan Khoronzhuk #include <linux/ptp_classify.h>
2274d23cc7SRichard Cochran #include <linux/timecounter.h>
2387c0e764SRichard Cochran 
2487c0e764SRichard Cochran struct cpsw_cpts {
2587c0e764SRichard Cochran 	u32 idver;                /* Identification and version */
2687c0e764SRichard Cochran 	u32 control;              /* Time sync control */
27a3047a81SGrygorii Strashko 	u32 rftclk_sel;		  /* Reference Clock Select Register */
2887c0e764SRichard Cochran 	u32 ts_push;              /* Time stamp event push */
2987c0e764SRichard Cochran 	u32 ts_load_val;          /* Time stamp load value */
3087c0e764SRichard Cochran 	u32 ts_load_en;           /* Time stamp load enable */
3187c0e764SRichard Cochran 	u32 res2[2];
3287c0e764SRichard Cochran 	u32 intstat_raw;          /* Time sync interrupt status raw */
3387c0e764SRichard Cochran 	u32 intstat_masked;       /* Time sync interrupt status masked */
3487c0e764SRichard Cochran 	u32 int_enable;           /* Time sync interrupt enable */
3587c0e764SRichard Cochran 	u32 res3;
3687c0e764SRichard Cochran 	u32 event_pop;            /* Event interrupt pop */
3787c0e764SRichard Cochran 	u32 event_low;            /* 32 Bit Event Time Stamp */
3887c0e764SRichard Cochran 	u32 event_high;           /* Event Type Fields */
3987c0e764SRichard Cochran };
4087c0e764SRichard Cochran 
4187c0e764SRichard Cochran /* Bit definitions for the IDVER register */
4287c0e764SRichard Cochran #define TX_IDENT_SHIFT       (16)    /* TX Identification Value */
4387c0e764SRichard Cochran #define TX_IDENT_MASK        (0xffff)
4487c0e764SRichard Cochran #define RTL_VER_SHIFT        (11)    /* RTL Version Value */
4587c0e764SRichard Cochran #define RTL_VER_MASK         (0x1f)
4687c0e764SRichard Cochran #define MAJOR_VER_SHIFT      (8)     /* Major Version Value */
4787c0e764SRichard Cochran #define MAJOR_VER_MASK       (0x7)
4887c0e764SRichard Cochran #define MINOR_VER_SHIFT      (0)     /* Minor Version Value */
4987c0e764SRichard Cochran #define MINOR_VER_MASK       (0xff)
5087c0e764SRichard Cochran 
5187c0e764SRichard Cochran /* Bit definitions for the CONTROL register */
5287c0e764SRichard Cochran #define HW4_TS_PUSH_EN       (1<<11) /* Hardware push 4 enable */
5387c0e764SRichard Cochran #define HW3_TS_PUSH_EN       (1<<10) /* Hardware push 3 enable */
5487c0e764SRichard Cochran #define HW2_TS_PUSH_EN       (1<<9)  /* Hardware push 2 enable */
5587c0e764SRichard Cochran #define HW1_TS_PUSH_EN       (1<<8)  /* Hardware push 1 enable */
5687c0e764SRichard Cochran #define INT_TEST             (1<<1)  /* Interrupt Test */
5787c0e764SRichard Cochran #define CPTS_EN              (1<<0)  /* Time Sync Enable */
5887c0e764SRichard Cochran 
5987c0e764SRichard Cochran /*
6087c0e764SRichard Cochran  * Definitions for the single bit resisters:
6187c0e764SRichard Cochran  * TS_PUSH TS_LOAD_EN  INTSTAT_RAW INTSTAT_MASKED INT_ENABLE EVENT_POP
6287c0e764SRichard Cochran  */
6387c0e764SRichard Cochran #define TS_PUSH             (1<<0)  /* Time stamp event push */
6487c0e764SRichard Cochran #define TS_LOAD_EN          (1<<0)  /* Time Stamp Load */
6587c0e764SRichard Cochran #define TS_PEND_RAW         (1<<0)  /* int read (before enable) */
6687c0e764SRichard Cochran #define TS_PEND             (1<<0)  /* masked interrupt read (after enable) */
6787c0e764SRichard Cochran #define TS_PEND_EN          (1<<0)  /* masked interrupt enable */
6887c0e764SRichard Cochran #define EVENT_POP           (1<<0)  /* writing discards one event */
6987c0e764SRichard Cochran 
7087c0e764SRichard Cochran /* Bit definitions for the EVENT_HIGH register */
7187c0e764SRichard Cochran #define PORT_NUMBER_SHIFT    (24)    /* Indicates Ethernet port or HW pin */
7287c0e764SRichard Cochran #define PORT_NUMBER_MASK     (0x1f)
7387c0e764SRichard Cochran #define EVENT_TYPE_SHIFT     (20)    /* Time sync event type */
7487c0e764SRichard Cochran #define EVENT_TYPE_MASK      (0xf)
7587c0e764SRichard Cochran #define MESSAGE_TYPE_SHIFT   (16)    /* PTP message type */
7687c0e764SRichard Cochran #define MESSAGE_TYPE_MASK    (0xf)
7787c0e764SRichard Cochran #define SEQUENCE_ID_SHIFT    (0)     /* PTP message sequence ID */
7887c0e764SRichard Cochran #define SEQUENCE_ID_MASK     (0xffff)
7987c0e764SRichard Cochran 
8087c0e764SRichard Cochran enum {
8187c0e764SRichard Cochran 	CPTS_EV_PUSH, /* Time Stamp Push Event */
8287c0e764SRichard Cochran 	CPTS_EV_ROLL, /* Time Stamp Rollover Event */
8387c0e764SRichard Cochran 	CPTS_EV_HALF, /* Time Stamp Half Rollover Event */
8487c0e764SRichard Cochran 	CPTS_EV_HW,   /* Hardware Time Stamp Push Event */
8587c0e764SRichard Cochran 	CPTS_EV_RX,   /* Ethernet Receive Event */
8687c0e764SRichard Cochran 	CPTS_EV_TX,   /* Ethernet Transmit Event */
8787c0e764SRichard Cochran };
8887c0e764SRichard Cochran 
8987c0e764SRichard Cochran #define CPTS_FIFO_DEPTH 16
9087c0e764SRichard Cochran #define CPTS_MAX_EVENTS 32
9187c0e764SRichard Cochran 
9287c0e764SRichard Cochran struct cpts_event {
9387c0e764SRichard Cochran 	struct list_head list;
9487c0e764SRichard Cochran 	unsigned long tmo;
9587c0e764SRichard Cochran 	u32 high;
9687c0e764SRichard Cochran 	u32 low;
97e66dccceSGrygorii Strashko 	u64 timestamp;
9887c0e764SRichard Cochran };
9987c0e764SRichard Cochran 
10087c0e764SRichard Cochran struct cpts {
1018a2c9a5aSGrygorii Strashko 	struct device *dev;
10287c0e764SRichard Cochran 	struct cpsw_cpts __iomem *reg;
10387c0e764SRichard Cochran 	int tx_enable;
10487c0e764SRichard Cochran 	int rx_enable;
10587c0e764SRichard Cochran 	struct ptp_clock_info info;
10687c0e764SRichard Cochran 	struct ptp_clock *clock;
107ba107428SGrygorii Strashko 	spinlock_t lock; /* protects fifo/events */
10887c0e764SRichard Cochran 	u32 cc_mult; /* for the nominal frequency */
10987c0e764SRichard Cochran 	struct cyclecounter cc;
11087c0e764SRichard Cochran 	struct timecounter tc;
11187c0e764SRichard Cochran 	int phc_index;
11287c0e764SRichard Cochran 	struct clk *refclk;
11387c0e764SRichard Cochran 	struct list_head events;
11487c0e764SRichard Cochran 	struct list_head pool;
11587c0e764SRichard Cochran 	struct cpts_event pool_data[CPTS_MAX_EVENTS];
11620138cf9SGrygorii Strashko 	unsigned long ov_check_period;
1170d5f54feSGrygorii Strashko 	struct sk_buff_head txq;
118e66dccceSGrygorii Strashko 	u64 cur_timestamp;
1190d6df3e6SGrygorii Strashko 	u32 mult_new;
120ba107428SGrygorii Strashko 	struct mutex ptp_clk_mutex; /* sync PTP interface and worker */
12185624412SGrygorii Strashko 	bool irq_poll;
12285624412SGrygorii Strashko 	struct completion	ts_push_complete;
123b78aba49SGrygorii Strashko 	u32 hw_ts_enable;
12487c0e764SRichard Cochran };
12587c0e764SRichard Cochran 
12695f7f151SJoe Perches void cpts_rx_timestamp(struct cpts *cpts, struct sk_buff *skb);
12795f7f151SJoe Perches void cpts_tx_timestamp(struct cpts *cpts, struct sk_buff *skb);
1288a2c9a5aSGrygorii Strashko int cpts_register(struct cpts *cpts);
129c8395d4eSGrygorii Strashko void cpts_unregister(struct cpts *cpts);
1308a2c9a5aSGrygorii Strashko struct cpts *cpts_create(struct device *dev, void __iomem *regs,
131b78aba49SGrygorii Strashko 			 struct device_node *node, u32 n_ext_ts);
1328a2c9a5aSGrygorii Strashko void cpts_release(struct cpts *cpts);
13385624412SGrygorii Strashko void cpts_misc_interrupt(struct cpts *cpts);
134b63ba58eSGrygorii Strashko 
cpts_can_timestamp(struct cpts * cpts,struct sk_buff * skb)135f44f8417SIvan Khoronzhuk static inline bool cpts_can_timestamp(struct cpts *cpts, struct sk_buff *skb)
136f44f8417SIvan Khoronzhuk {
137f44f8417SIvan Khoronzhuk 	unsigned int class = ptp_classify_raw(skb);
138f44f8417SIvan Khoronzhuk 
139f44f8417SIvan Khoronzhuk 	if (class == PTP_CLASS_NONE)
140f44f8417SIvan Khoronzhuk 		return false;
141f44f8417SIvan Khoronzhuk 
142f44f8417SIvan Khoronzhuk 	return true;
143f44f8417SIvan Khoronzhuk }
144f44f8417SIvan Khoronzhuk 
cpts_set_irqpoll(struct cpts * cpts,bool en)14585624412SGrygorii Strashko static inline void cpts_set_irqpoll(struct cpts *cpts, bool en)
14685624412SGrygorii Strashko {
14785624412SGrygorii Strashko 	cpts->irq_poll = en;
14885624412SGrygorii Strashko }
14985624412SGrygorii Strashko 
15087c0e764SRichard Cochran #else
1518a2c9a5aSGrygorii Strashko struct cpts;
1528a2c9a5aSGrygorii Strashko 
cpts_rx_timestamp(struct cpts * cpts,struct sk_buff * skb)15387c0e764SRichard Cochran static inline void cpts_rx_timestamp(struct cpts *cpts, struct sk_buff *skb)
15487c0e764SRichard Cochran {
15587c0e764SRichard Cochran }
cpts_tx_timestamp(struct cpts * cpts,struct sk_buff * skb)15687c0e764SRichard Cochran static inline void cpts_tx_timestamp(struct cpts *cpts, struct sk_buff *skb)
15787c0e764SRichard Cochran {
15887c0e764SRichard Cochran }
159c8395d4eSGrygorii Strashko 
1608a2c9a5aSGrygorii Strashko static inline
cpts_create(struct device * dev,void __iomem * regs,struct device_node * node,u32 n_ext_ts)1618a2c9a5aSGrygorii Strashko struct cpts *cpts_create(struct device *dev, void __iomem *regs,
162b78aba49SGrygorii Strashko 			 struct device_node *node, u32 n_ext_ts)
1638a2c9a5aSGrygorii Strashko {
1648a2c9a5aSGrygorii Strashko 	return NULL;
1658a2c9a5aSGrygorii Strashko }
1668a2c9a5aSGrygorii Strashko 
cpts_release(struct cpts * cpts)1678a2c9a5aSGrygorii Strashko static inline void cpts_release(struct cpts *cpts)
1688a2c9a5aSGrygorii Strashko {
1698a2c9a5aSGrygorii Strashko }
1708a2c9a5aSGrygorii Strashko 
171c8395d4eSGrygorii Strashko static inline int
cpts_register(struct cpts * cpts)1728a2c9a5aSGrygorii Strashko cpts_register(struct cpts *cpts)
173c8395d4eSGrygorii Strashko {
174c8395d4eSGrygorii Strashko 	return 0;
175c8395d4eSGrygorii Strashko }
176c8395d4eSGrygorii Strashko 
cpts_unregister(struct cpts * cpts)177c8395d4eSGrygorii Strashko static inline void cpts_unregister(struct cpts *cpts)
178c8395d4eSGrygorii Strashko {
179c8395d4eSGrygorii Strashko }
180b63ba58eSGrygorii Strashko 
cpts_can_timestamp(struct cpts * cpts,struct sk_buff * skb)181f44f8417SIvan Khoronzhuk static inline bool cpts_can_timestamp(struct cpts *cpts, struct sk_buff *skb)
182f44f8417SIvan Khoronzhuk {
183f44f8417SIvan Khoronzhuk 	return false;
184f44f8417SIvan Khoronzhuk }
18585624412SGrygorii Strashko 
cpts_misc_interrupt(struct cpts * cpts)18685624412SGrygorii Strashko static inline void cpts_misc_interrupt(struct cpts *cpts)
18785624412SGrygorii Strashko {
18885624412SGrygorii Strashko }
18985624412SGrygorii Strashko 
cpts_set_irqpoll(struct cpts * cpts,bool en)19085624412SGrygorii Strashko static inline void cpts_set_irqpoll(struct cpts *cpts, bool en)
19185624412SGrygorii Strashko {
19285624412SGrygorii Strashko }
19387c0e764SRichard Cochran #endif
19487c0e764SRichard Cochran 
19587c0e764SRichard Cochran 
19687c0e764SRichard Cochran #endif
197