root/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. config_hw_tstamping
  2. config_sub_second_increment
  3. init_systime
  4. config_addend
  5. adjust_systime
  6. get_systime

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*******************************************************************************
   3   Copyright (C) 2013  Vayavya Labs Pvt Ltd
   4 
   5   This implements all the API for managing HW timestamp & PTP.
   6 
   7 
   8   Author: Rayagond Kokatanur <rayagond@vayavyalabs.com>
   9   Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
  10 *******************************************************************************/
  11 
  12 #include <linux/io.h>
  13 #include <linux/delay.h>
  14 #include "common.h"
  15 #include "stmmac_ptp.h"
  16 
  17 static void config_hw_tstamping(void __iomem *ioaddr, u32 data)
  18 {
  19         writel(data, ioaddr + PTP_TCR);
  20 }
  21 
  22 static void config_sub_second_increment(void __iomem *ioaddr,
  23                 u32 ptp_clock, int gmac4, u32 *ssinc)
  24 {
  25         u32 value = readl(ioaddr + PTP_TCR);
  26         unsigned long data;
  27         u32 reg_value;
  28 
  29         /* For GMAC3.x, 4.x versions, in "fine adjustement mode" set sub-second
  30          * increment to twice the number of nanoseconds of a clock cycle.
  31          * The calculation of the default_addend value by the caller will set it
  32          * to mid-range = 2^31 when the remainder of this division is zero,
  33          * which will make the accumulator overflow once every 2 ptp_clock
  34          * cycles, adding twice the number of nanoseconds of a clock cycle :
  35          * 2000000000ULL / ptp_clock.
  36          */
  37         if (value & PTP_TCR_TSCFUPDT)
  38                 data = (2000000000ULL / ptp_clock);
  39         else
  40                 data = (1000000000ULL / ptp_clock);
  41 
  42         /* 0.465ns accuracy */
  43         if (!(value & PTP_TCR_TSCTRLSSR))
  44                 data = (data * 1000) / 465;
  45 
  46         data &= PTP_SSIR_SSINC_MASK;
  47 
  48         reg_value = data;
  49         if (gmac4)
  50                 reg_value <<= GMAC4_PTP_SSIR_SSINC_SHIFT;
  51 
  52         writel(reg_value, ioaddr + PTP_SSIR);
  53 
  54         if (ssinc)
  55                 *ssinc = data;
  56 }
  57 
  58 static int init_systime(void __iomem *ioaddr, u32 sec, u32 nsec)
  59 {
  60         int limit;
  61         u32 value;
  62 
  63         writel(sec, ioaddr + PTP_STSUR);
  64         writel(nsec, ioaddr + PTP_STNSUR);
  65         /* issue command to initialize the system time value */
  66         value = readl(ioaddr + PTP_TCR);
  67         value |= PTP_TCR_TSINIT;
  68         writel(value, ioaddr + PTP_TCR);
  69 
  70         /* wait for present system time initialize to complete */
  71         limit = 10;
  72         while (limit--) {
  73                 if (!(readl(ioaddr + PTP_TCR) & PTP_TCR_TSINIT))
  74                         break;
  75                 mdelay(10);
  76         }
  77         if (limit < 0)
  78                 return -EBUSY;
  79 
  80         return 0;
  81 }
  82 
  83 static int config_addend(void __iomem *ioaddr, u32 addend)
  84 {
  85         u32 value;
  86         int limit;
  87 
  88         writel(addend, ioaddr + PTP_TAR);
  89         /* issue command to update the addend value */
  90         value = readl(ioaddr + PTP_TCR);
  91         value |= PTP_TCR_TSADDREG;
  92         writel(value, ioaddr + PTP_TCR);
  93 
  94         /* wait for present addend update to complete */
  95         limit = 10;
  96         while (limit--) {
  97                 if (!(readl(ioaddr + PTP_TCR) & PTP_TCR_TSADDREG))
  98                         break;
  99                 mdelay(10);
 100         }
 101         if (limit < 0)
 102                 return -EBUSY;
 103 
 104         return 0;
 105 }
 106 
 107 static int adjust_systime(void __iomem *ioaddr, u32 sec, u32 nsec,
 108                 int add_sub, int gmac4)
 109 {
 110         u32 value;
 111         int limit;
 112 
 113         if (add_sub) {
 114                 /* If the new sec value needs to be subtracted with
 115                  * the system time, then MAC_STSUR reg should be
 116                  * programmed with (2^32 – <new_sec_value>)
 117                  */
 118                 if (gmac4)
 119                         sec = -sec;
 120 
 121                 value = readl(ioaddr + PTP_TCR);
 122                 if (value & PTP_TCR_TSCTRLSSR)
 123                         nsec = (PTP_DIGITAL_ROLLOVER_MODE - nsec);
 124                 else
 125                         nsec = (PTP_BINARY_ROLLOVER_MODE - nsec);
 126         }
 127 
 128         writel(sec, ioaddr + PTP_STSUR);
 129         value = (add_sub << PTP_STNSUR_ADDSUB_SHIFT) | nsec;
 130         writel(value, ioaddr + PTP_STNSUR);
 131 
 132         /* issue command to initialize the system time value */
 133         value = readl(ioaddr + PTP_TCR);
 134         value |= PTP_TCR_TSUPDT;
 135         writel(value, ioaddr + PTP_TCR);
 136 
 137         /* wait for present system time adjust/update to complete */
 138         limit = 10;
 139         while (limit--) {
 140                 if (!(readl(ioaddr + PTP_TCR) & PTP_TCR_TSUPDT))
 141                         break;
 142                 mdelay(10);
 143         }
 144         if (limit < 0)
 145                 return -EBUSY;
 146 
 147         return 0;
 148 }
 149 
 150 static void get_systime(void __iomem *ioaddr, u64 *systime)
 151 {
 152         u64 ns;
 153 
 154         /* Get the TSSS value */
 155         ns = readl(ioaddr + PTP_STNSR);
 156         /* Get the TSS and convert sec time value to nanosecond */
 157         ns += readl(ioaddr + PTP_STSR) * 1000000000ULL;
 158 
 159         if (systime)
 160                 *systime = ns;
 161 }
 162 
 163 const struct stmmac_hwtimestamp stmmac_ptp = {
 164         .config_hw_tstamping = config_hw_tstamping,
 165         .init_systime = init_systime,
 166         .config_sub_second_increment = config_sub_second_increment,
 167         .config_addend = config_addend,
 168         .adjust_systime = adjust_systime,
 169         .get_systime = get_systime,
 170 };

/* [<][>][^][v][top][bottom][index][help] */