cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

am65-cpts.c (28492B)


      1// SPDX-License-Identifier: GPL-2.0
      2/* TI K3 AM65x Common Platform Time Sync
      3 *
      4 * Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com
      5 *
      6 */
      7
      8#include <linux/clk.h>
      9#include <linux/clk-provider.h>
     10#include <linux/err.h>
     11#include <linux/if_vlan.h>
     12#include <linux/interrupt.h>
     13#include <linux/module.h>
     14#include <linux/netdevice.h>
     15#include <linux/net_tstamp.h>
     16#include <linux/of.h>
     17#include <linux/of_irq.h>
     18#include <linux/platform_device.h>
     19#include <linux/pm_runtime.h>
     20#include <linux/ptp_classify.h>
     21#include <linux/ptp_clock_kernel.h>
     22
     23#include "am65-cpts.h"
     24
     25struct am65_genf_regs {
     26	u32 comp_lo;	/* Comparison Low Value 0:31 */
     27	u32 comp_hi;	/* Comparison High Value 32:63 */
     28	u32 control;	/* control */
     29	u32 length;	/* Length */
     30	u32 ppm_low;	/* PPM Load Low Value 0:31 */
     31	u32 ppm_hi;	/* PPM Load High Value 32:63 */
     32	u32 ts_nudge;	/* Nudge value */
     33} __aligned(32) __packed;
     34
     35#define AM65_CPTS_GENF_MAX_NUM 9
     36#define AM65_CPTS_ESTF_MAX_NUM 8
     37
     38struct am65_cpts_regs {
     39	u32 idver;		/* Identification and version */
     40	u32 control;		/* Time sync control */
     41	u32 rftclk_sel;		/* Reference Clock Select Register */
     42	u32 ts_push;		/* Time stamp event push */
     43	u32 ts_load_val_lo;	/* Time Stamp Load Low Value 0:31 */
     44	u32 ts_load_en;		/* Time stamp load enable */
     45	u32 ts_comp_lo;		/* Time Stamp Comparison Low Value 0:31 */
     46	u32 ts_comp_length;	/* Time Stamp Comparison Length */
     47	u32 intstat_raw;	/* Time sync interrupt status raw */
     48	u32 intstat_masked;	/* Time sync interrupt status masked */
     49	u32 int_enable;		/* Time sync interrupt enable */
     50	u32 ts_comp_nudge;	/* Time Stamp Comparison Nudge Value */
     51	u32 event_pop;		/* Event interrupt pop */
     52	u32 event_0;		/* Event Time Stamp lo 0:31 */
     53	u32 event_1;		/* Event Type Fields */
     54	u32 event_2;		/* Event Type Fields domain */
     55	u32 event_3;		/* Event Time Stamp hi 32:63 */
     56	u32 ts_load_val_hi;	/* Time Stamp Load High Value 32:63 */
     57	u32 ts_comp_hi;		/* Time Stamp Comparison High Value 32:63 */
     58	u32 ts_add_val;		/* Time Stamp Add value */
     59	u32 ts_ppm_low;		/* Time Stamp PPM Load Low Value 0:31 */
     60	u32 ts_ppm_hi;		/* Time Stamp PPM Load High Value 32:63 */
     61	u32 ts_nudge;		/* Time Stamp Nudge value */
     62	u32 reserv[33];
     63	struct am65_genf_regs genf[AM65_CPTS_GENF_MAX_NUM];
     64	struct am65_genf_regs estf[AM65_CPTS_ESTF_MAX_NUM];
     65};
     66
     67/* CONTROL_REG */
     68#define AM65_CPTS_CONTROL_EN			BIT(0)
     69#define AM65_CPTS_CONTROL_INT_TEST		BIT(1)
     70#define AM65_CPTS_CONTROL_TS_COMP_POLARITY	BIT(2)
     71#define AM65_CPTS_CONTROL_TSTAMP_EN		BIT(3)
     72#define AM65_CPTS_CONTROL_SEQUENCE_EN		BIT(4)
     73#define AM65_CPTS_CONTROL_64MODE		BIT(5)
     74#define AM65_CPTS_CONTROL_TS_COMP_TOG		BIT(6)
     75#define AM65_CPTS_CONTROL_TS_PPM_DIR		BIT(7)
     76#define AM65_CPTS_CONTROL_HW1_TS_PUSH_EN	BIT(8)
     77#define AM65_CPTS_CONTROL_HW2_TS_PUSH_EN	BIT(9)
     78#define AM65_CPTS_CONTROL_HW3_TS_PUSH_EN	BIT(10)
     79#define AM65_CPTS_CONTROL_HW4_TS_PUSH_EN	BIT(11)
     80#define AM65_CPTS_CONTROL_HW5_TS_PUSH_EN	BIT(12)
     81#define AM65_CPTS_CONTROL_HW6_TS_PUSH_EN	BIT(13)
     82#define AM65_CPTS_CONTROL_HW7_TS_PUSH_EN	BIT(14)
     83#define AM65_CPTS_CONTROL_HW8_TS_PUSH_EN	BIT(15)
     84#define AM65_CPTS_CONTROL_HW1_TS_PUSH_OFFSET	(8)
     85
     86#define AM65_CPTS_CONTROL_TX_GENF_CLR_EN	BIT(17)
     87
     88#define AM65_CPTS_CONTROL_TS_SYNC_SEL_MASK	(0xF)
     89#define AM65_CPTS_CONTROL_TS_SYNC_SEL_SHIFT	(28)
     90
     91/* RFTCLK_SEL_REG */
     92#define AM65_CPTS_RFTCLK_SEL_MASK		(0x1F)
     93
     94/* TS_PUSH_REG */
     95#define AM65_CPTS_TS_PUSH			BIT(0)
     96
     97/* TS_LOAD_EN_REG */
     98#define AM65_CPTS_TS_LOAD_EN			BIT(0)
     99
    100/* INTSTAT_RAW_REG */
    101#define AM65_CPTS_INTSTAT_RAW_TS_PEND		BIT(0)
    102
    103/* INTSTAT_MASKED_REG */
    104#define AM65_CPTS_INTSTAT_MASKED_TS_PEND	BIT(0)
    105
    106/* INT_ENABLE_REG */
    107#define AM65_CPTS_INT_ENABLE_TS_PEND_EN		BIT(0)
    108
    109/* TS_COMP_NUDGE_REG */
    110#define AM65_CPTS_TS_COMP_NUDGE_MASK		(0xFF)
    111
    112/* EVENT_POP_REG */
    113#define AM65_CPTS_EVENT_POP			BIT(0)
    114
    115/* EVENT_1_REG */
    116#define AM65_CPTS_EVENT_1_SEQUENCE_ID_MASK	GENMASK(15, 0)
    117
    118#define AM65_CPTS_EVENT_1_MESSAGE_TYPE_MASK	GENMASK(19, 16)
    119#define AM65_CPTS_EVENT_1_MESSAGE_TYPE_SHIFT	(16)
    120
    121#define AM65_CPTS_EVENT_1_EVENT_TYPE_MASK	GENMASK(23, 20)
    122#define AM65_CPTS_EVENT_1_EVENT_TYPE_SHIFT	(20)
    123
    124#define AM65_CPTS_EVENT_1_PORT_NUMBER_MASK	GENMASK(28, 24)
    125#define AM65_CPTS_EVENT_1_PORT_NUMBER_SHIFT	(24)
    126
    127/* EVENT_2_REG */
    128#define AM65_CPTS_EVENT_2_REG_DOMAIN_MASK	(0xFF)
    129#define AM65_CPTS_EVENT_2_REG_DOMAIN_SHIFT	(0)
    130
    131enum {
    132	AM65_CPTS_EV_PUSH,	/* Time Stamp Push Event */
    133	AM65_CPTS_EV_ROLL,	/* Time Stamp Rollover Event */
    134	AM65_CPTS_EV_HALF,	/* Time Stamp Half Rollover Event */
    135	AM65_CPTS_EV_HW,		/* Hardware Time Stamp Push Event */
    136	AM65_CPTS_EV_RX,		/* Ethernet Receive Event */
    137	AM65_CPTS_EV_TX,		/* Ethernet Transmit Event */
    138	AM65_CPTS_EV_TS_COMP,	/* Time Stamp Compare Event */
    139	AM65_CPTS_EV_HOST,	/* Host Transmit Event */
    140};
    141
    142struct am65_cpts_event {
    143	struct list_head list;
    144	unsigned long tmo;
    145	u32 event1;
    146	u32 event2;
    147	u64 timestamp;
    148};
    149
    150#define AM65_CPTS_FIFO_DEPTH		(16)
    151#define AM65_CPTS_MAX_EVENTS		(32)
    152#define AM65_CPTS_EVENT_RX_TX_TIMEOUT	(20) /* ms */
    153#define AM65_CPTS_SKB_TX_WORK_TIMEOUT	1 /* jiffies */
    154#define AM65_CPTS_MIN_PPM		0x400
    155
    156struct am65_cpts {
    157	struct device *dev;
    158	struct am65_cpts_regs __iomem *reg;
    159	struct ptp_clock_info ptp_info;
    160	struct ptp_clock *ptp_clock;
    161	int phc_index;
    162	struct clk_hw *clk_mux_hw;
    163	struct device_node *clk_mux_np;
    164	struct clk *refclk;
    165	u32 refclk_freq;
    166	struct list_head events;
    167	struct list_head pool;
    168	struct am65_cpts_event pool_data[AM65_CPTS_MAX_EVENTS];
    169	spinlock_t lock; /* protects events lists*/
    170	u32 ext_ts_inputs;
    171	u32 genf_num;
    172	u32 ts_add_val;
    173	int irq;
    174	struct mutex ptp_clk_lock; /* PHC access sync */
    175	u64 timestamp;
    176	u32 genf_enable;
    177	u32 hw_ts_enable;
    178	struct sk_buff_head txq;
    179};
    180
    181struct am65_cpts_skb_cb_data {
    182	unsigned long tmo;
    183	u32 skb_mtype_seqid;
    184};
    185
    186#define am65_cpts_write32(c, v, r) writel(v, &(c)->reg->r)
    187#define am65_cpts_read32(c, r) readl(&(c)->reg->r)
    188
    189static void am65_cpts_settime(struct am65_cpts *cpts, u64 start_tstamp)
    190{
    191	u32 val;
    192
    193	val = upper_32_bits(start_tstamp);
    194	am65_cpts_write32(cpts, val, ts_load_val_hi);
    195	val = lower_32_bits(start_tstamp);
    196	am65_cpts_write32(cpts, val, ts_load_val_lo);
    197
    198	am65_cpts_write32(cpts, AM65_CPTS_TS_LOAD_EN, ts_load_en);
    199}
    200
    201static void am65_cpts_set_add_val(struct am65_cpts *cpts)
    202{
    203	/* select coefficient according to the rate */
    204	cpts->ts_add_val = (NSEC_PER_SEC / cpts->refclk_freq - 1) & 0x7;
    205
    206	am65_cpts_write32(cpts, cpts->ts_add_val, ts_add_val);
    207}
    208
    209static void am65_cpts_disable(struct am65_cpts *cpts)
    210{
    211	am65_cpts_write32(cpts, 0, control);
    212	am65_cpts_write32(cpts, 0, int_enable);
    213}
    214
    215static int am65_cpts_event_get_port(struct am65_cpts_event *event)
    216{
    217	return (event->event1 & AM65_CPTS_EVENT_1_PORT_NUMBER_MASK) >>
    218		AM65_CPTS_EVENT_1_PORT_NUMBER_SHIFT;
    219}
    220
    221static int am65_cpts_event_get_type(struct am65_cpts_event *event)
    222{
    223	return (event->event1 & AM65_CPTS_EVENT_1_EVENT_TYPE_MASK) >>
    224		AM65_CPTS_EVENT_1_EVENT_TYPE_SHIFT;
    225}
    226
    227static int am65_cpts_cpts_purge_events(struct am65_cpts *cpts)
    228{
    229	struct list_head *this, *next;
    230	struct am65_cpts_event *event;
    231	int removed = 0;
    232
    233	list_for_each_safe(this, next, &cpts->events) {
    234		event = list_entry(this, struct am65_cpts_event, list);
    235		if (time_after(jiffies, event->tmo)) {
    236			list_del_init(&event->list);
    237			list_add(&event->list, &cpts->pool);
    238			++removed;
    239		}
    240	}
    241
    242	if (removed)
    243		dev_dbg(cpts->dev, "event pool cleaned up %d\n", removed);
    244	return removed ? 0 : -1;
    245}
    246
    247static bool am65_cpts_fifo_pop_event(struct am65_cpts *cpts,
    248				     struct am65_cpts_event *event)
    249{
    250	u32 r = am65_cpts_read32(cpts, intstat_raw);
    251
    252	if (r & AM65_CPTS_INTSTAT_RAW_TS_PEND) {
    253		event->timestamp = am65_cpts_read32(cpts, event_0);
    254		event->event1 = am65_cpts_read32(cpts, event_1);
    255		event->event2 = am65_cpts_read32(cpts, event_2);
    256		event->timestamp |= (u64)am65_cpts_read32(cpts, event_3) << 32;
    257		am65_cpts_write32(cpts, AM65_CPTS_EVENT_POP, event_pop);
    258		return false;
    259	}
    260	return true;
    261}
    262
    263static int am65_cpts_fifo_read(struct am65_cpts *cpts)
    264{
    265	struct ptp_clock_event pevent;
    266	struct am65_cpts_event *event;
    267	bool schedule = false;
    268	int i, type, ret = 0;
    269	unsigned long flags;
    270
    271	spin_lock_irqsave(&cpts->lock, flags);
    272	for (i = 0; i < AM65_CPTS_FIFO_DEPTH; i++) {
    273		event = list_first_entry_or_null(&cpts->pool,
    274						 struct am65_cpts_event, list);
    275
    276		if (!event) {
    277			if (am65_cpts_cpts_purge_events(cpts)) {
    278				dev_err(cpts->dev, "cpts: event pool empty\n");
    279				ret = -1;
    280				goto out;
    281			}
    282			continue;
    283		}
    284
    285		if (am65_cpts_fifo_pop_event(cpts, event))
    286			break;
    287
    288		type = am65_cpts_event_get_type(event);
    289		switch (type) {
    290		case AM65_CPTS_EV_PUSH:
    291			cpts->timestamp = event->timestamp;
    292			dev_dbg(cpts->dev, "AM65_CPTS_EV_PUSH t:%llu\n",
    293				cpts->timestamp);
    294			break;
    295		case AM65_CPTS_EV_RX:
    296		case AM65_CPTS_EV_TX:
    297			event->tmo = jiffies +
    298				msecs_to_jiffies(AM65_CPTS_EVENT_RX_TX_TIMEOUT);
    299
    300			list_del_init(&event->list);
    301			list_add_tail(&event->list, &cpts->events);
    302
    303			dev_dbg(cpts->dev,
    304				"AM65_CPTS_EV_TX e1:%08x e2:%08x t:%lld\n",
    305				event->event1, event->event2,
    306				event->timestamp);
    307			schedule = true;
    308			break;
    309		case AM65_CPTS_EV_HW:
    310			pevent.index = am65_cpts_event_get_port(event) - 1;
    311			pevent.timestamp = event->timestamp;
    312			pevent.type = PTP_CLOCK_EXTTS;
    313			dev_dbg(cpts->dev, "AM65_CPTS_EV_HW p:%d t:%llu\n",
    314				pevent.index, event->timestamp);
    315
    316			ptp_clock_event(cpts->ptp_clock, &pevent);
    317			break;
    318		case AM65_CPTS_EV_HOST:
    319			break;
    320		case AM65_CPTS_EV_ROLL:
    321		case AM65_CPTS_EV_HALF:
    322		case AM65_CPTS_EV_TS_COMP:
    323			dev_dbg(cpts->dev,
    324				"AM65_CPTS_EVT: %d e1:%08x e2:%08x t:%lld\n",
    325				type,
    326				event->event1, event->event2,
    327				event->timestamp);
    328			break;
    329		default:
    330			dev_err(cpts->dev, "cpts: unknown event type\n");
    331			ret = -1;
    332			goto out;
    333		}
    334	}
    335
    336out:
    337	spin_unlock_irqrestore(&cpts->lock, flags);
    338
    339	if (schedule)
    340		ptp_schedule_worker(cpts->ptp_clock, 0);
    341
    342	return ret;
    343}
    344
    345static u64 am65_cpts_gettime(struct am65_cpts *cpts,
    346			     struct ptp_system_timestamp *sts)
    347{
    348	unsigned long flags;
    349	u64 val = 0;
    350
    351	/* temporarily disable cpts interrupt to avoid intentional
    352	 * doubled read. Interrupt can be in-flight - it's Ok.
    353	 */
    354	am65_cpts_write32(cpts, 0, int_enable);
    355
    356	/* use spin_lock_irqsave() here as it has to run very fast */
    357	spin_lock_irqsave(&cpts->lock, flags);
    358	ptp_read_system_prets(sts);
    359	am65_cpts_write32(cpts, AM65_CPTS_TS_PUSH, ts_push);
    360	am65_cpts_read32(cpts, ts_push);
    361	ptp_read_system_postts(sts);
    362	spin_unlock_irqrestore(&cpts->lock, flags);
    363
    364	am65_cpts_fifo_read(cpts);
    365
    366	am65_cpts_write32(cpts, AM65_CPTS_INT_ENABLE_TS_PEND_EN, int_enable);
    367
    368	val = cpts->timestamp;
    369
    370	return val;
    371}
    372
    373static irqreturn_t am65_cpts_interrupt(int irq, void *dev_id)
    374{
    375	struct am65_cpts *cpts = dev_id;
    376
    377	if (am65_cpts_fifo_read(cpts))
    378		dev_dbg(cpts->dev, "cpts: unable to obtain a time stamp\n");
    379
    380	return IRQ_HANDLED;
    381}
    382
    383/* PTP clock operations */
    384static int am65_cpts_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
    385{
    386	struct am65_cpts *cpts = container_of(ptp, struct am65_cpts, ptp_info);
    387	int neg_adj = 0;
    388	u64 adj_period;
    389	u32 val;
    390
    391	if (ppb < 0) {
    392		neg_adj = 1;
    393		ppb = -ppb;
    394	}
    395
    396	/* base freq = 1GHz = 1 000 000 000
    397	 * ppb_norm = ppb * base_freq / clock_freq;
    398	 * ppm_norm = ppb_norm / 1000
    399	 * adj_period = 1 000 000 / ppm_norm
    400	 * adj_period = 1 000 000 000 / ppb_norm
    401	 * adj_period = 1 000 000 000 / (ppb * base_freq / clock_freq)
    402	 * adj_period = (1 000 000 000 * clock_freq) / (ppb * base_freq)
    403	 * adj_period = clock_freq / ppb
    404	 */
    405	adj_period = div_u64(cpts->refclk_freq, ppb);
    406
    407	mutex_lock(&cpts->ptp_clk_lock);
    408
    409	val = am65_cpts_read32(cpts, control);
    410	if (neg_adj)
    411		val |= AM65_CPTS_CONTROL_TS_PPM_DIR;
    412	else
    413		val &= ~AM65_CPTS_CONTROL_TS_PPM_DIR;
    414	am65_cpts_write32(cpts, val, control);
    415
    416	val = upper_32_bits(adj_period) & 0x3FF;
    417	am65_cpts_write32(cpts, val, ts_ppm_hi);
    418	val = lower_32_bits(adj_period);
    419	am65_cpts_write32(cpts, val, ts_ppm_low);
    420
    421	mutex_unlock(&cpts->ptp_clk_lock);
    422
    423	return 0;
    424}
    425
    426static int am65_cpts_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
    427{
    428	struct am65_cpts *cpts = container_of(ptp, struct am65_cpts, ptp_info);
    429	s64 ns;
    430
    431	mutex_lock(&cpts->ptp_clk_lock);
    432	ns = am65_cpts_gettime(cpts, NULL);
    433	ns += delta;
    434	am65_cpts_settime(cpts, ns);
    435	mutex_unlock(&cpts->ptp_clk_lock);
    436
    437	return 0;
    438}
    439
    440static int am65_cpts_ptp_gettimex(struct ptp_clock_info *ptp,
    441				  struct timespec64 *ts,
    442				  struct ptp_system_timestamp *sts)
    443{
    444	struct am65_cpts *cpts = container_of(ptp, struct am65_cpts, ptp_info);
    445	u64 ns;
    446
    447	mutex_lock(&cpts->ptp_clk_lock);
    448	ns = am65_cpts_gettime(cpts, sts);
    449	mutex_unlock(&cpts->ptp_clk_lock);
    450	*ts = ns_to_timespec64(ns);
    451
    452	return 0;
    453}
    454
    455u64 am65_cpts_ns_gettime(struct am65_cpts *cpts)
    456{
    457	u64 ns;
    458
    459	/* reuse ptp_clk_lock as it serialize ts push */
    460	mutex_lock(&cpts->ptp_clk_lock);
    461	ns = am65_cpts_gettime(cpts, NULL);
    462	mutex_unlock(&cpts->ptp_clk_lock);
    463
    464	return ns;
    465}
    466EXPORT_SYMBOL_GPL(am65_cpts_ns_gettime);
    467
    468static int am65_cpts_ptp_settime(struct ptp_clock_info *ptp,
    469				 const struct timespec64 *ts)
    470{
    471	struct am65_cpts *cpts = container_of(ptp, struct am65_cpts, ptp_info);
    472	u64 ns;
    473
    474	ns = timespec64_to_ns(ts);
    475	mutex_lock(&cpts->ptp_clk_lock);
    476	am65_cpts_settime(cpts, ns);
    477	mutex_unlock(&cpts->ptp_clk_lock);
    478
    479	return 0;
    480}
    481
    482static void am65_cpts_extts_enable_hw(struct am65_cpts *cpts, u32 index, int on)
    483{
    484	u32 v;
    485
    486	v = am65_cpts_read32(cpts, control);
    487	if (on) {
    488		v |= BIT(AM65_CPTS_CONTROL_HW1_TS_PUSH_OFFSET + index);
    489		cpts->hw_ts_enable |= BIT(index);
    490	} else {
    491		v &= ~BIT(AM65_CPTS_CONTROL_HW1_TS_PUSH_OFFSET + index);
    492		cpts->hw_ts_enable &= ~BIT(index);
    493	}
    494	am65_cpts_write32(cpts, v, control);
    495}
    496
    497static int am65_cpts_extts_enable(struct am65_cpts *cpts, u32 index, int on)
    498{
    499	if (!!(cpts->hw_ts_enable & BIT(index)) == !!on)
    500		return 0;
    501
    502	mutex_lock(&cpts->ptp_clk_lock);
    503	am65_cpts_extts_enable_hw(cpts, index, on);
    504	mutex_unlock(&cpts->ptp_clk_lock);
    505
    506	dev_dbg(cpts->dev, "%s: ExtTS:%u %s\n",
    507		__func__, index, on ? "enabled" : "disabled");
    508
    509	return 0;
    510}
    511
    512int am65_cpts_estf_enable(struct am65_cpts *cpts, int idx,
    513			  struct am65_cpts_estf_cfg *cfg)
    514{
    515	u64 cycles;
    516	u32 val;
    517
    518	cycles = cfg->ns_period * cpts->refclk_freq;
    519	cycles = DIV_ROUND_UP(cycles, NSEC_PER_SEC);
    520	if (cycles > U32_MAX)
    521		return -EINVAL;
    522
    523	/* according to TRM should be zeroed */
    524	am65_cpts_write32(cpts, 0, estf[idx].length);
    525
    526	val = upper_32_bits(cfg->ns_start);
    527	am65_cpts_write32(cpts, val, estf[idx].comp_hi);
    528	val = lower_32_bits(cfg->ns_start);
    529	am65_cpts_write32(cpts, val, estf[idx].comp_lo);
    530	val = lower_32_bits(cycles);
    531	am65_cpts_write32(cpts, val, estf[idx].length);
    532
    533	dev_dbg(cpts->dev, "%s: ESTF:%u enabled\n", __func__, idx);
    534
    535	return 0;
    536}
    537EXPORT_SYMBOL_GPL(am65_cpts_estf_enable);
    538
    539void am65_cpts_estf_disable(struct am65_cpts *cpts, int idx)
    540{
    541	am65_cpts_write32(cpts, 0, estf[idx].length);
    542
    543	dev_dbg(cpts->dev, "%s: ESTF:%u disabled\n", __func__, idx);
    544}
    545EXPORT_SYMBOL_GPL(am65_cpts_estf_disable);
    546
    547static void am65_cpts_perout_enable_hw(struct am65_cpts *cpts,
    548				       struct ptp_perout_request *req, int on)
    549{
    550	u64 ns_period, ns_start, cycles;
    551	struct timespec64 ts;
    552	u32 val;
    553
    554	if (on) {
    555		ts.tv_sec = req->period.sec;
    556		ts.tv_nsec = req->period.nsec;
    557		ns_period = timespec64_to_ns(&ts);
    558
    559		cycles = (ns_period * cpts->refclk_freq) / NSEC_PER_SEC;
    560
    561		ts.tv_sec = req->start.sec;
    562		ts.tv_nsec = req->start.nsec;
    563		ns_start = timespec64_to_ns(&ts);
    564
    565		val = upper_32_bits(ns_start);
    566		am65_cpts_write32(cpts, val, genf[req->index].comp_hi);
    567		val = lower_32_bits(ns_start);
    568		am65_cpts_write32(cpts, val, genf[req->index].comp_lo);
    569		val = lower_32_bits(cycles);
    570		am65_cpts_write32(cpts, val, genf[req->index].length);
    571
    572		cpts->genf_enable |= BIT(req->index);
    573	} else {
    574		am65_cpts_write32(cpts, 0, genf[req->index].length);
    575
    576		cpts->genf_enable &= ~BIT(req->index);
    577	}
    578}
    579
    580static int am65_cpts_perout_enable(struct am65_cpts *cpts,
    581				   struct ptp_perout_request *req, int on)
    582{
    583	if (!!(cpts->genf_enable & BIT(req->index)) == !!on)
    584		return 0;
    585
    586	mutex_lock(&cpts->ptp_clk_lock);
    587	am65_cpts_perout_enable_hw(cpts, req, on);
    588	mutex_unlock(&cpts->ptp_clk_lock);
    589
    590	dev_dbg(cpts->dev, "%s: GenF:%u %s\n",
    591		__func__, req->index, on ? "enabled" : "disabled");
    592
    593	return 0;
    594}
    595
    596static int am65_cpts_ptp_enable(struct ptp_clock_info *ptp,
    597				struct ptp_clock_request *rq, int on)
    598{
    599	struct am65_cpts *cpts = container_of(ptp, struct am65_cpts, ptp_info);
    600
    601	switch (rq->type) {
    602	case PTP_CLK_REQ_EXTTS:
    603		return am65_cpts_extts_enable(cpts, rq->extts.index, on);
    604	case PTP_CLK_REQ_PEROUT:
    605		return am65_cpts_perout_enable(cpts, &rq->perout, on);
    606	default:
    607		break;
    608	}
    609
    610	return -EOPNOTSUPP;
    611}
    612
    613static long am65_cpts_ts_work(struct ptp_clock_info *ptp);
    614
    615static struct ptp_clock_info am65_ptp_info = {
    616	.owner		= THIS_MODULE,
    617	.name		= "CTPS timer",
    618	.adjfreq	= am65_cpts_ptp_adjfreq,
    619	.adjtime	= am65_cpts_ptp_adjtime,
    620	.gettimex64	= am65_cpts_ptp_gettimex,
    621	.settime64	= am65_cpts_ptp_settime,
    622	.enable		= am65_cpts_ptp_enable,
    623	.do_aux_work	= am65_cpts_ts_work,
    624};
    625
    626static bool am65_cpts_match_tx_ts(struct am65_cpts *cpts,
    627				  struct am65_cpts_event *event)
    628{
    629	struct sk_buff_head txq_list;
    630	struct sk_buff *skb, *tmp;
    631	unsigned long flags;
    632	bool found = false;
    633	u32 mtype_seqid;
    634
    635	mtype_seqid = event->event1 &
    636		      (AM65_CPTS_EVENT_1_MESSAGE_TYPE_MASK |
    637		       AM65_CPTS_EVENT_1_EVENT_TYPE_MASK |
    638		       AM65_CPTS_EVENT_1_SEQUENCE_ID_MASK);
    639
    640	__skb_queue_head_init(&txq_list);
    641
    642	spin_lock_irqsave(&cpts->txq.lock, flags);
    643	skb_queue_splice_init(&cpts->txq, &txq_list);
    644	spin_unlock_irqrestore(&cpts->txq.lock, flags);
    645
    646	/* no need to grab txq.lock as access is always done under cpts->lock */
    647	skb_queue_walk_safe(&txq_list, skb, tmp) {
    648		struct skb_shared_hwtstamps ssh;
    649		struct am65_cpts_skb_cb_data *skb_cb =
    650					(struct am65_cpts_skb_cb_data *)skb->cb;
    651
    652		if (mtype_seqid == skb_cb->skb_mtype_seqid) {
    653			u64 ns = event->timestamp;
    654
    655			memset(&ssh, 0, sizeof(ssh));
    656			ssh.hwtstamp = ns_to_ktime(ns);
    657			skb_tstamp_tx(skb, &ssh);
    658			found = true;
    659			__skb_unlink(skb, &txq_list);
    660			dev_consume_skb_any(skb);
    661			dev_dbg(cpts->dev,
    662				"match tx timestamp mtype_seqid %08x\n",
    663				mtype_seqid);
    664			break;
    665		}
    666
    667		if (time_after(jiffies, skb_cb->tmo)) {
    668			/* timeout any expired skbs over 100 ms */
    669			dev_dbg(cpts->dev,
    670				"expiring tx timestamp mtype_seqid %08x\n",
    671				mtype_seqid);
    672			__skb_unlink(skb, &txq_list);
    673			dev_consume_skb_any(skb);
    674		}
    675	}
    676
    677	spin_lock_irqsave(&cpts->txq.lock, flags);
    678	skb_queue_splice(&txq_list, &cpts->txq);
    679	spin_unlock_irqrestore(&cpts->txq.lock, flags);
    680
    681	return found;
    682}
    683
    684static void am65_cpts_find_ts(struct am65_cpts *cpts)
    685{
    686	struct am65_cpts_event *event;
    687	struct list_head *this, *next;
    688	LIST_HEAD(events_free);
    689	unsigned long flags;
    690	LIST_HEAD(events);
    691
    692	spin_lock_irqsave(&cpts->lock, flags);
    693	list_splice_init(&cpts->events, &events);
    694	spin_unlock_irqrestore(&cpts->lock, flags);
    695
    696	list_for_each_safe(this, next, &events) {
    697		event = list_entry(this, struct am65_cpts_event, list);
    698		if (am65_cpts_match_tx_ts(cpts, event) ||
    699		    time_after(jiffies, event->tmo)) {
    700			list_del_init(&event->list);
    701			list_add(&event->list, &events_free);
    702		}
    703	}
    704
    705	spin_lock_irqsave(&cpts->lock, flags);
    706	list_splice_tail(&events, &cpts->events);
    707	list_splice_tail(&events_free, &cpts->pool);
    708	spin_unlock_irqrestore(&cpts->lock, flags);
    709}
    710
    711static long am65_cpts_ts_work(struct ptp_clock_info *ptp)
    712{
    713	struct am65_cpts *cpts = container_of(ptp, struct am65_cpts, ptp_info);
    714	unsigned long flags;
    715	long delay = -1;
    716
    717	am65_cpts_find_ts(cpts);
    718
    719	spin_lock_irqsave(&cpts->txq.lock, flags);
    720	if (!skb_queue_empty(&cpts->txq))
    721		delay = AM65_CPTS_SKB_TX_WORK_TIMEOUT;
    722	spin_unlock_irqrestore(&cpts->txq.lock, flags);
    723
    724	return delay;
    725}
    726
    727/**
    728 * am65_cpts_rx_enable - enable rx timestamping
    729 * @cpts: cpts handle
    730 * @en: enable
    731 *
    732 * This functions enables rx packets timestamping. The CPTS can timestamp all
    733 * rx packets.
    734 */
    735void am65_cpts_rx_enable(struct am65_cpts *cpts, bool en)
    736{
    737	u32 val;
    738
    739	mutex_lock(&cpts->ptp_clk_lock);
    740	val = am65_cpts_read32(cpts, control);
    741	if (en)
    742		val |= AM65_CPTS_CONTROL_TSTAMP_EN;
    743	else
    744		val &= ~AM65_CPTS_CONTROL_TSTAMP_EN;
    745	am65_cpts_write32(cpts, val, control);
    746	mutex_unlock(&cpts->ptp_clk_lock);
    747}
    748EXPORT_SYMBOL_GPL(am65_cpts_rx_enable);
    749
    750static int am65_skb_get_mtype_seqid(struct sk_buff *skb, u32 *mtype_seqid)
    751{
    752	unsigned int ptp_class = ptp_classify_raw(skb);
    753	struct ptp_header *hdr;
    754	u8 msgtype;
    755	u16 seqid;
    756
    757	if (ptp_class == PTP_CLASS_NONE)
    758		return 0;
    759
    760	hdr = ptp_parse_header(skb, ptp_class);
    761	if (!hdr)
    762		return 0;
    763
    764	msgtype = ptp_get_msgtype(hdr, ptp_class);
    765	seqid	= ntohs(hdr->sequence_id);
    766
    767	*mtype_seqid  = (msgtype << AM65_CPTS_EVENT_1_MESSAGE_TYPE_SHIFT) &
    768			AM65_CPTS_EVENT_1_MESSAGE_TYPE_MASK;
    769	*mtype_seqid |= (seqid & AM65_CPTS_EVENT_1_SEQUENCE_ID_MASK);
    770
    771	return 1;
    772}
    773
    774/**
    775 * am65_cpts_tx_timestamp - save tx packet for timestamping
    776 * @cpts: cpts handle
    777 * @skb: packet
    778 *
    779 * This functions saves tx packet for timestamping if packet can be timestamped.
    780 * The future processing is done in from PTP auxiliary worker.
    781 */
    782void am65_cpts_tx_timestamp(struct am65_cpts *cpts, struct sk_buff *skb)
    783{
    784	struct am65_cpts_skb_cb_data *skb_cb = (void *)skb->cb;
    785
    786	if (!(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS))
    787		return;
    788
    789	/* add frame to queue for processing later.
    790	 * The periodic FIFO check will handle this.
    791	 */
    792	skb_get(skb);
    793	/* get the timestamp for timeouts */
    794	skb_cb->tmo = jiffies + msecs_to_jiffies(100);
    795	skb_queue_tail(&cpts->txq, skb);
    796	ptp_schedule_worker(cpts->ptp_clock, 0);
    797}
    798EXPORT_SYMBOL_GPL(am65_cpts_tx_timestamp);
    799
    800/**
    801 * am65_cpts_prep_tx_timestamp - check and prepare tx packet for timestamping
    802 * @cpts: cpts handle
    803 * @skb: packet
    804 *
    805 * This functions should be called from .xmit().
    806 * It checks if packet can be timestamped, fills internal cpts data
    807 * in skb-cb and marks packet as SKBTX_IN_PROGRESS.
    808 */
    809void am65_cpts_prep_tx_timestamp(struct am65_cpts *cpts, struct sk_buff *skb)
    810{
    811	struct am65_cpts_skb_cb_data *skb_cb = (void *)skb->cb;
    812	int ret;
    813
    814	if (!(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP))
    815		return;
    816
    817	ret = am65_skb_get_mtype_seqid(skb, &skb_cb->skb_mtype_seqid);
    818	if (!ret)
    819		return;
    820	skb_cb->skb_mtype_seqid |= (AM65_CPTS_EV_TX <<
    821				   AM65_CPTS_EVENT_1_EVENT_TYPE_SHIFT);
    822
    823	skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
    824}
    825EXPORT_SYMBOL_GPL(am65_cpts_prep_tx_timestamp);
    826
    827int am65_cpts_phc_index(struct am65_cpts *cpts)
    828{
    829	return cpts->phc_index;
    830}
    831EXPORT_SYMBOL_GPL(am65_cpts_phc_index);
    832
    833static void cpts_free_clk_mux(void *data)
    834{
    835	struct am65_cpts *cpts = data;
    836
    837	of_clk_del_provider(cpts->clk_mux_np);
    838	clk_hw_unregister_mux(cpts->clk_mux_hw);
    839	of_node_put(cpts->clk_mux_np);
    840}
    841
    842static int cpts_of_mux_clk_setup(struct am65_cpts *cpts,
    843				 struct device_node *node)
    844{
    845	unsigned int num_parents;
    846	const char **parent_names;
    847	char *clk_mux_name;
    848	void __iomem *reg;
    849	int ret = -EINVAL;
    850
    851	cpts->clk_mux_np = of_get_child_by_name(node, "refclk-mux");
    852	if (!cpts->clk_mux_np)
    853		return 0;
    854
    855	num_parents = of_clk_get_parent_count(cpts->clk_mux_np);
    856	if (num_parents < 1) {
    857		dev_err(cpts->dev, "mux-clock %pOF must have parents\n",
    858			cpts->clk_mux_np);
    859		goto mux_fail;
    860	}
    861
    862	parent_names = devm_kcalloc(cpts->dev, sizeof(char *), num_parents,
    863				    GFP_KERNEL);
    864	if (!parent_names) {
    865		ret = -ENOMEM;
    866		goto mux_fail;
    867	}
    868
    869	of_clk_parent_fill(cpts->clk_mux_np, parent_names, num_parents);
    870
    871	clk_mux_name = devm_kasprintf(cpts->dev, GFP_KERNEL, "%s.%pOFn",
    872				      dev_name(cpts->dev), cpts->clk_mux_np);
    873	if (!clk_mux_name) {
    874		ret = -ENOMEM;
    875		goto mux_fail;
    876	}
    877
    878	reg = &cpts->reg->rftclk_sel;
    879	/* dev must be NULL to avoid recursive incrementing
    880	 * of module refcnt
    881	 */
    882	cpts->clk_mux_hw = clk_hw_register_mux(NULL, clk_mux_name,
    883					       parent_names, num_parents,
    884					       0, reg, 0, 5, 0, NULL);
    885	if (IS_ERR(cpts->clk_mux_hw)) {
    886		ret = PTR_ERR(cpts->clk_mux_hw);
    887		goto mux_fail;
    888	}
    889
    890	ret = of_clk_add_hw_provider(cpts->clk_mux_np, of_clk_hw_simple_get,
    891				     cpts->clk_mux_hw);
    892	if (ret)
    893		goto clk_hw_register;
    894
    895	ret = devm_add_action_or_reset(cpts->dev, cpts_free_clk_mux, cpts);
    896	if (ret)
    897		dev_err(cpts->dev, "failed to add clkmux reset action %d", ret);
    898
    899	return ret;
    900
    901clk_hw_register:
    902	clk_hw_unregister_mux(cpts->clk_mux_hw);
    903mux_fail:
    904	of_node_put(cpts->clk_mux_np);
    905	return ret;
    906}
    907
    908static int am65_cpts_of_parse(struct am65_cpts *cpts, struct device_node *node)
    909{
    910	u32 prop[2];
    911
    912	if (!of_property_read_u32(node, "ti,cpts-ext-ts-inputs", &prop[0]))
    913		cpts->ext_ts_inputs = prop[0];
    914
    915	if (!of_property_read_u32(node, "ti,cpts-periodic-outputs", &prop[0]))
    916		cpts->genf_num = prop[0];
    917
    918	return cpts_of_mux_clk_setup(cpts, node);
    919}
    920
    921static void am65_cpts_release(void *data)
    922{
    923	struct am65_cpts *cpts = data;
    924
    925	ptp_clock_unregister(cpts->ptp_clock);
    926	am65_cpts_disable(cpts);
    927	clk_disable_unprepare(cpts->refclk);
    928}
    929
    930struct am65_cpts *am65_cpts_create(struct device *dev, void __iomem *regs,
    931				   struct device_node *node)
    932{
    933	struct am65_cpts *cpts;
    934	int ret, i;
    935
    936	cpts = devm_kzalloc(dev, sizeof(*cpts), GFP_KERNEL);
    937	if (!cpts)
    938		return ERR_PTR(-ENOMEM);
    939
    940	cpts->dev = dev;
    941	cpts->reg = (struct am65_cpts_regs __iomem *)regs;
    942
    943	cpts->irq = of_irq_get_byname(node, "cpts");
    944	if (cpts->irq <= 0) {
    945		ret = cpts->irq ?: -ENXIO;
    946		if (ret != -EPROBE_DEFER)
    947			dev_err(dev, "Failed to get IRQ number (err = %d)\n",
    948				ret);
    949		return ERR_PTR(ret);
    950	}
    951
    952	ret = am65_cpts_of_parse(cpts, node);
    953	if (ret)
    954		return ERR_PTR(ret);
    955
    956	mutex_init(&cpts->ptp_clk_lock);
    957	INIT_LIST_HEAD(&cpts->events);
    958	INIT_LIST_HEAD(&cpts->pool);
    959	spin_lock_init(&cpts->lock);
    960	skb_queue_head_init(&cpts->txq);
    961
    962	for (i = 0; i < AM65_CPTS_MAX_EVENTS; i++)
    963		list_add(&cpts->pool_data[i].list, &cpts->pool);
    964
    965	cpts->refclk = devm_get_clk_from_child(dev, node, "cpts");
    966	if (IS_ERR(cpts->refclk)) {
    967		ret = PTR_ERR(cpts->refclk);
    968		if (ret != -EPROBE_DEFER)
    969			dev_err(dev, "Failed to get refclk %d\n", ret);
    970		return ERR_PTR(ret);
    971	}
    972
    973	ret = clk_prepare_enable(cpts->refclk);
    974	if (ret) {
    975		dev_err(dev, "Failed to enable refclk %d\n", ret);
    976		return ERR_PTR(ret);
    977	}
    978
    979	cpts->refclk_freq = clk_get_rate(cpts->refclk);
    980
    981	am65_ptp_info.max_adj = cpts->refclk_freq / AM65_CPTS_MIN_PPM;
    982	cpts->ptp_info = am65_ptp_info;
    983
    984	if (cpts->ext_ts_inputs)
    985		cpts->ptp_info.n_ext_ts = cpts->ext_ts_inputs;
    986	if (cpts->genf_num)
    987		cpts->ptp_info.n_per_out = cpts->genf_num;
    988
    989	am65_cpts_set_add_val(cpts);
    990
    991	am65_cpts_write32(cpts, AM65_CPTS_CONTROL_EN |
    992			  AM65_CPTS_CONTROL_64MODE |
    993			  AM65_CPTS_CONTROL_TX_GENF_CLR_EN,
    994			  control);
    995	am65_cpts_write32(cpts, AM65_CPTS_INT_ENABLE_TS_PEND_EN, int_enable);
    996
    997	/* set time to the current system time */
    998	am65_cpts_settime(cpts, ktime_to_ns(ktime_get_real()));
    999
   1000	cpts->ptp_clock = ptp_clock_register(&cpts->ptp_info, cpts->dev);
   1001	if (IS_ERR_OR_NULL(cpts->ptp_clock)) {
   1002		dev_err(dev, "Failed to register ptp clk %ld\n",
   1003			PTR_ERR(cpts->ptp_clock));
   1004		ret = cpts->ptp_clock ? PTR_ERR(cpts->ptp_clock) : -ENODEV;
   1005		goto refclk_disable;
   1006	}
   1007	cpts->phc_index = ptp_clock_index(cpts->ptp_clock);
   1008
   1009	ret = devm_add_action_or_reset(dev, am65_cpts_release, cpts);
   1010	if (ret) {
   1011		dev_err(dev, "failed to add ptpclk reset action %d", ret);
   1012		return ERR_PTR(ret);
   1013	}
   1014
   1015	ret = devm_request_threaded_irq(dev, cpts->irq, NULL,
   1016					am65_cpts_interrupt,
   1017					IRQF_ONESHOT, dev_name(dev), cpts);
   1018	if (ret < 0) {
   1019		dev_err(cpts->dev, "error attaching irq %d\n", ret);
   1020		return ERR_PTR(ret);
   1021	}
   1022
   1023	dev_info(dev, "CPTS ver 0x%08x, freq:%u, add_val:%u\n",
   1024		 am65_cpts_read32(cpts, idver),
   1025		 cpts->refclk_freq, cpts->ts_add_val);
   1026
   1027	return cpts;
   1028
   1029refclk_disable:
   1030	clk_disable_unprepare(cpts->refclk);
   1031	return ERR_PTR(ret);
   1032}
   1033EXPORT_SYMBOL_GPL(am65_cpts_create);
   1034
   1035static int am65_cpts_probe(struct platform_device *pdev)
   1036{
   1037	struct device_node *node = pdev->dev.of_node;
   1038	struct device *dev = &pdev->dev;
   1039	struct am65_cpts *cpts;
   1040	void __iomem *base;
   1041
   1042	base = devm_platform_ioremap_resource_byname(pdev, "cpts");
   1043	if (IS_ERR(base))
   1044		return PTR_ERR(base);
   1045
   1046	cpts = am65_cpts_create(dev, base, node);
   1047	return PTR_ERR_OR_ZERO(cpts);
   1048}
   1049
   1050static const struct of_device_id am65_cpts_of_match[] = {
   1051	{ .compatible = "ti,am65-cpts", },
   1052	{ .compatible = "ti,j721e-cpts", },
   1053	{},
   1054};
   1055MODULE_DEVICE_TABLE(of, am65_cpts_of_match);
   1056
   1057static struct platform_driver am65_cpts_driver = {
   1058	.probe		= am65_cpts_probe,
   1059	.driver		= {
   1060		.name	= "am65-cpts",
   1061		.of_match_table = am65_cpts_of_match,
   1062	},
   1063};
   1064module_platform_driver(am65_cpts_driver);
   1065
   1066MODULE_LICENSE("GPL v2");
   1067MODULE_AUTHOR("Grygorii Strashko <grygorii.strashko@ti.com>");
   1068MODULE_DESCRIPTION("TI K3 AM65 CPTS driver");