linux/drivers/net/ethernet/ti/am65-cpts.c
<<
>>
Prefs
   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");
1069