linux/drivers/net/ethernet/freescale/fec_ptp.c
<<
>>
Prefs
   1/*
   2 * Fast Ethernet Controller (ENET) PTP driver for MX6x.
   3 *
   4 * Copyright (C) 2012 Freescale Semiconductor, Inc.
   5 *
   6 * This program is free software; you can redistribute it and/or modify it
   7 * under the terms and conditions of the GNU General Public License,
   8 * version 2, as published by the Free Software Foundation.
   9 *
  10 * This program is distributed in the hope it will be useful, but WITHOUT
  11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  13 * more details.
  14 *
  15 * You should have received a copy of the GNU General Public License along with
  16 * this program; if not, write to the Free Software Foundation, Inc.,
  17 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
  18 */
  19
  20#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  21
  22#include <linux/module.h>
  23#include <linux/kernel.h>
  24#include <linux/string.h>
  25#include <linux/ptrace.h>
  26#include <linux/errno.h>
  27#include <linux/ioport.h>
  28#include <linux/slab.h>
  29#include <linux/interrupt.h>
  30#include <linux/pci.h>
  31#include <linux/init.h>
  32#include <linux/delay.h>
  33#include <linux/netdevice.h>
  34#include <linux/etherdevice.h>
  35#include <linux/skbuff.h>
  36#include <linux/spinlock.h>
  37#include <linux/workqueue.h>
  38#include <linux/bitops.h>
  39#include <linux/io.h>
  40#include <linux/irq.h>
  41#include <linux/clk.h>
  42#include <linux/platform_device.h>
  43#include <linux/phy.h>
  44#include <linux/fec.h>
  45#include <linux/of.h>
  46#include <linux/of_device.h>
  47#include <linux/of_gpio.h>
  48#include <linux/of_net.h>
  49
  50#include "fec.h"
  51
  52/* FEC 1588 register bits */
  53#define FEC_T_CTRL_SLAVE                0x00002000
  54#define FEC_T_CTRL_CAPTURE              0x00000800
  55#define FEC_T_CTRL_RESTART              0x00000200
  56#define FEC_T_CTRL_PERIOD_RST           0x00000030
  57#define FEC_T_CTRL_PERIOD_EN            0x00000010
  58#define FEC_T_CTRL_ENABLE               0x00000001
  59
  60#define FEC_T_INC_MASK                  0x0000007f
  61#define FEC_T_INC_OFFSET                0
  62#define FEC_T_INC_CORR_MASK             0x00007f00
  63#define FEC_T_INC_CORR_OFFSET           8
  64
  65#define FEC_ATIME_CTRL          0x400
  66#define FEC_ATIME               0x404
  67#define FEC_ATIME_EVT_OFFSET    0x408
  68#define FEC_ATIME_EVT_PERIOD    0x40c
  69#define FEC_ATIME_CORR          0x410
  70#define FEC_ATIME_INC           0x414
  71#define FEC_TS_TIMESTAMP        0x418
  72
  73#define FEC_CC_MULT     (1 << 31)
  74/**
  75 * fec_ptp_read - read raw cycle counter (to be used by time counter)
  76 * @cc: the cyclecounter structure
  77 *
  78 * this function reads the cyclecounter registers and is called by the
  79 * cyclecounter structure used to construct a ns counter from the
  80 * arbitrary fixed point registers
  81 */
  82static cycle_t fec_ptp_read(const struct cyclecounter *cc)
  83{
  84        struct fec_enet_private *fep =
  85                container_of(cc, struct fec_enet_private, cc);
  86        u32 tempval;
  87
  88        tempval = readl(fep->hwp + FEC_ATIME_CTRL);
  89        tempval |= FEC_T_CTRL_CAPTURE;
  90        writel(tempval, fep->hwp + FEC_ATIME_CTRL);
  91
  92        return readl(fep->hwp + FEC_ATIME);
  93}
  94
  95/**
  96 * fec_ptp_start_cyclecounter - create the cycle counter from hw
  97 * @ndev: network device
  98 *
  99 * this function initializes the timecounter and cyclecounter
 100 * structures for use in generated a ns counter from the arbitrary
 101 * fixed point cycles registers in the hardware.
 102 */
 103void fec_ptp_start_cyclecounter(struct net_device *ndev)
 104{
 105        struct fec_enet_private *fep = netdev_priv(ndev);
 106        unsigned long flags;
 107        int inc;
 108
 109        inc = 1000000000 / fep->cycle_speed;
 110
 111        /* grab the ptp lock */
 112        spin_lock_irqsave(&fep->tmreg_lock, flags);
 113
 114        /* 1ns counter */
 115        writel(inc << FEC_T_INC_OFFSET, fep->hwp + FEC_ATIME_INC);
 116
 117        /* use free running count */
 118        writel(0, fep->hwp + FEC_ATIME_EVT_PERIOD);
 119
 120        writel(FEC_T_CTRL_ENABLE, fep->hwp + FEC_ATIME_CTRL);
 121
 122        memset(&fep->cc, 0, sizeof(fep->cc));
 123        fep->cc.read = fec_ptp_read;
 124        fep->cc.mask = CLOCKSOURCE_MASK(32);
 125        fep->cc.shift = 31;
 126        fep->cc.mult = FEC_CC_MULT;
 127
 128        /* reset the ns time counter */
 129        timecounter_init(&fep->tc, &fep->cc, ktime_to_ns(ktime_get_real()));
 130
 131        spin_unlock_irqrestore(&fep->tmreg_lock, flags);
 132}
 133
 134/**
 135 * fec_ptp_adjfreq - adjust ptp cycle frequency
 136 * @ptp: the ptp clock structure
 137 * @ppb: parts per billion adjustment from base
 138 *
 139 * Adjust the frequency of the ptp cycle counter by the
 140 * indicated ppb from the base frequency.
 141 *
 142 * Because ENET hardware frequency adjust is complex,
 143 * using software method to do that.
 144 */
 145static int fec_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
 146{
 147        u64 diff;
 148        unsigned long flags;
 149        int neg_adj = 0;
 150        u32 mult = FEC_CC_MULT;
 151
 152        struct fec_enet_private *fep =
 153            container_of(ptp, struct fec_enet_private, ptp_caps);
 154
 155        if (ppb < 0) {
 156                ppb = -ppb;
 157                neg_adj = 1;
 158        }
 159
 160        diff = mult;
 161        diff *= ppb;
 162        diff = div_u64(diff, 1000000000ULL);
 163
 164        spin_lock_irqsave(&fep->tmreg_lock, flags);
 165        /*
 166         * dummy read to set cycle_last in tc to now.
 167         * So use adjusted mult to calculate when next call
 168         * timercounter_read.
 169         */
 170        timecounter_read(&fep->tc);
 171
 172        fep->cc.mult = neg_adj ? mult - diff : mult + diff;
 173
 174        spin_unlock_irqrestore(&fep->tmreg_lock, flags);
 175
 176        return 0;
 177}
 178
 179/**
 180 * fec_ptp_adjtime
 181 * @ptp: the ptp clock structure
 182 * @delta: offset to adjust the cycle counter by
 183 *
 184 * adjust the timer by resetting the timecounter structure.
 185 */
 186static int fec_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
 187{
 188        struct fec_enet_private *fep =
 189            container_of(ptp, struct fec_enet_private, ptp_caps);
 190        unsigned long flags;
 191        u64 now;
 192
 193        spin_lock_irqsave(&fep->tmreg_lock, flags);
 194
 195        now = timecounter_read(&fep->tc);
 196        now += delta;
 197
 198        /* reset the timecounter */
 199        timecounter_init(&fep->tc, &fep->cc, now);
 200
 201        spin_unlock_irqrestore(&fep->tmreg_lock, flags);
 202
 203        return 0;
 204}
 205
 206/**
 207 * fec_ptp_gettime
 208 * @ptp: the ptp clock structure
 209 * @ts: timespec structure to hold the current time value
 210 *
 211 * read the timecounter and return the correct value on ns,
 212 * after converting it into a struct timespec.
 213 */
 214static int fec_ptp_gettime(struct ptp_clock_info *ptp, struct timespec *ts)
 215{
 216        struct fec_enet_private *adapter =
 217            container_of(ptp, struct fec_enet_private, ptp_caps);
 218        u64 ns;
 219        u32 remainder;
 220        unsigned long flags;
 221
 222        spin_lock_irqsave(&adapter->tmreg_lock, flags);
 223        ns = timecounter_read(&adapter->tc);
 224        spin_unlock_irqrestore(&adapter->tmreg_lock, flags);
 225
 226        ts->tv_sec = div_u64_rem(ns, 1000000000ULL, &remainder);
 227        ts->tv_nsec = remainder;
 228
 229        return 0;
 230}
 231
 232/**
 233 * fec_ptp_settime
 234 * @ptp: the ptp clock structure
 235 * @ts: the timespec containing the new time for the cycle counter
 236 *
 237 * reset the timecounter to use a new base value instead of the kernel
 238 * wall timer value.
 239 */
 240static int fec_ptp_settime(struct ptp_clock_info *ptp,
 241                           const struct timespec *ts)
 242{
 243        struct fec_enet_private *fep =
 244            container_of(ptp, struct fec_enet_private, ptp_caps);
 245
 246        u64 ns;
 247        unsigned long flags;
 248
 249        ns = ts->tv_sec * 1000000000ULL;
 250        ns += ts->tv_nsec;
 251
 252        spin_lock_irqsave(&fep->tmreg_lock, flags);
 253        timecounter_init(&fep->tc, &fep->cc, ns);
 254        spin_unlock_irqrestore(&fep->tmreg_lock, flags);
 255        return 0;
 256}
 257
 258/**
 259 * fec_ptp_enable
 260 * @ptp: the ptp clock structure
 261 * @rq: the requested feature to change
 262 * @on: whether to enable or disable the feature
 263 *
 264 */
 265static int fec_ptp_enable(struct ptp_clock_info *ptp,
 266                          struct ptp_clock_request *rq, int on)
 267{
 268        return -EOPNOTSUPP;
 269}
 270
 271/**
 272 * fec_ptp_hwtstamp_ioctl - control hardware time stamping
 273 * @ndev: pointer to net_device
 274 * @ifreq: ioctl data
 275 * @cmd: particular ioctl requested
 276 */
 277int fec_ptp_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd)
 278{
 279        struct fec_enet_private *fep = netdev_priv(ndev);
 280
 281        struct hwtstamp_config config;
 282
 283        if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
 284                return -EFAULT;
 285
 286        /* reserved for future extensions */
 287        if (config.flags)
 288                return -EINVAL;
 289
 290        switch (config.tx_type) {
 291        case HWTSTAMP_TX_OFF:
 292                fep->hwts_tx_en = 0;
 293                break;
 294        case HWTSTAMP_TX_ON:
 295                fep->hwts_tx_en = 1;
 296                break;
 297        default:
 298                return -ERANGE;
 299        }
 300
 301        switch (config.rx_filter) {
 302        case HWTSTAMP_FILTER_NONE:
 303                if (fep->hwts_rx_en)
 304                        fep->hwts_rx_en = 0;
 305                config.rx_filter = HWTSTAMP_FILTER_NONE;
 306                break;
 307
 308        default:
 309                /*
 310                 * register RXMTRL must be set in order to do V1 packets,
 311                 * therefore it is not possible to time stamp both V1 Sync and
 312                 * Delay_Req messages and hardware does not support
 313                 * timestamping all packets => return error
 314                 */
 315                fep->hwts_rx_en = 1;
 316                config.rx_filter = HWTSTAMP_FILTER_ALL;
 317                break;
 318        }
 319
 320        return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ?
 321            -EFAULT : 0;
 322}
 323
 324/**
 325 * fec_time_keep - call timecounter_read every second to avoid timer overrun
 326 *                 because ENET just support 32bit counter, will timeout in 4s
 327 */
 328static void fec_time_keep(unsigned long _data)
 329{
 330        struct fec_enet_private *fep = (struct fec_enet_private *)_data;
 331        u64 ns;
 332        unsigned long flags;
 333
 334        spin_lock_irqsave(&fep->tmreg_lock, flags);
 335        ns = timecounter_read(&fep->tc);
 336        spin_unlock_irqrestore(&fep->tmreg_lock, flags);
 337
 338        mod_timer(&fep->time_keep, jiffies + HZ);
 339}
 340
 341/**
 342 * fec_ptp_init
 343 * @ndev: The FEC network adapter
 344 *
 345 * This function performs the required steps for enabling ptp
 346 * support. If ptp support has already been loaded it simply calls the
 347 * cyclecounter init routine and exits.
 348 */
 349
 350void fec_ptp_init(struct net_device *ndev, struct platform_device *pdev)
 351{
 352        struct fec_enet_private *fep = netdev_priv(ndev);
 353
 354        fep->ptp_caps.owner = THIS_MODULE;
 355        snprintf(fep->ptp_caps.name, 16, "fec ptp");
 356
 357        fep->ptp_caps.max_adj = 250000000;
 358        fep->ptp_caps.n_alarm = 0;
 359        fep->ptp_caps.n_ext_ts = 0;
 360        fep->ptp_caps.n_per_out = 0;
 361        fep->ptp_caps.pps = 0;
 362        fep->ptp_caps.adjfreq = fec_ptp_adjfreq;
 363        fep->ptp_caps.adjtime = fec_ptp_adjtime;
 364        fep->ptp_caps.gettime = fec_ptp_gettime;
 365        fep->ptp_caps.settime = fec_ptp_settime;
 366        fep->ptp_caps.enable = fec_ptp_enable;
 367
 368        fep->cycle_speed = clk_get_rate(fep->clk_ptp);
 369
 370        spin_lock_init(&fep->tmreg_lock);
 371
 372        fec_ptp_start_cyclecounter(ndev);
 373
 374        init_timer(&fep->time_keep);
 375        fep->time_keep.data = (unsigned long)fep;
 376        fep->time_keep.function = fec_time_keep;
 377        fep->time_keep.expires = jiffies + HZ;
 378        add_timer(&fep->time_keep);
 379
 380        fep->ptp_clock = ptp_clock_register(&fep->ptp_caps, &pdev->dev);
 381        if (IS_ERR(fep->ptp_clock)) {
 382                fep->ptp_clock = NULL;
 383                pr_err("ptp_clock_register failed\n");
 384        }
 385}
 386