2013-02-23 07:29:56 +00:00
/* PTP Hardware Clock (PHC) driver for the Intel 82576 and 82580
2012-03-16 10:55:32 +00:00
*
* Copyright ( C ) 2011 Richard Cochran < richardcochran @ gmail . com >
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
2014-02-25 17:58:57 -08:00
* You should have received a copy of the GNU General Public License along with
* this program ; if not , see < http : //www.gnu.org/licenses/>.
2012-03-16 10:55:32 +00:00
*/
# include <linux/module.h>
# include <linux/device.h>
# include <linux/pci.h>
2012-12-13 07:20:36 +00:00
# include <linux/ptp_classify.h>
2012-03-16 10:55:32 +00:00
# include "igb.h"
# define INCVALUE_MASK 0x7fffffff
# define ISGN 0x80000000
2013-02-23 07:29:56 +00:00
/* The 82580 timesync updates the system timer every 8ns by 8ns,
2012-03-16 10:55:37 +00:00
* and this update value cannot be reprogrammed .
*
2012-03-16 10:55:32 +00:00
* Neither the 82576 nor the 82580 offer registers wide enough to hold
* nanoseconds time values for very long . For the 82580 , SYSTIM always
2015-03-06 20:49:12 -08:00
* counts nanoseconds , but the upper 24 bits are not available . The
2012-03-16 10:55:32 +00:00
* frequency is adjusted by changing the 32 bit fractional nanoseconds
* register , TIMINCA .
*
* For the 82576 , the SYSTIM register time unit is affect by the
* choice of the 24 bit TININCA : IV ( incvalue ) field . Five bits of this
* field are needed to provide the nominal 16 nanosecond period ,
* leaving 19 bits for fractional nanoseconds .
*
2012-03-16 10:55:37 +00:00
* We scale the NIC clock cycle by a large factor so that relatively
* small clock corrections can be added or subtracted at each clock
* tick . The drawbacks of a large factor are a ) that the clock
* register overflows more quickly ( not such a big deal ) and b ) that
* the increment per tick has to fit into 24 bits . As a result we
* need to use a shift of 19 so we can fit a value of 16 into the
* TIMINCA register .
*
2012-03-16 10:55:32 +00:00
*
* SYSTIMH SYSTIML
* + - - - - - - - - - - - - - - + + - - - + - - - + - - - - - - +
* 82576 | 32 | | 8 | 5 | 19 |
* + - - - - - - - - - - - - - - + + - - - + - - - + - - - - - - +
* \ ________ 45 bits _______ / fract
*
* + - - - - - - - - - - + - - - + + - - - - - - - - - - - - - - +
* 82580 | 24 | 8 | | 32 |
* + - - - - - - - - - - + - - - + + - - - - - - - - - - - - - - +
* reserved \ ______ 40 bits _____ /
*
*
* The 45 bit 82576 SYSTIM overflows every
* 2 ^ 45 * 10 ^ - 9 / 3600 = 9.77 hours .
*
* The 40 bit 82580 SYSTIM overflows every
* 2 ^ 40 * 10 ^ - 9 / 60 = 18.3 minutes .
*/
2012-08-10 05:40:44 +00:00
# define IGB_SYSTIM_OVERFLOW_PERIOD (HZ * 60 * 9)
2012-12-13 07:20:34 +00:00
# define IGB_PTP_TX_TIMEOUT (HZ * 15)
2012-08-10 05:40:44 +00:00
# define INCPERIOD_82576 (1 << E1000_TIMINCA_16NS_SHIFT)
# define INCVALUE_82576_MASK ((1 << E1000_TIMINCA_16NS_SHIFT) - 1)
# define INCVALUE_82576 (16 << IGB_82576_TSYNC_SHIFT)
# define IGB_NBITS_82580 40
2012-03-16 10:55:32 +00:00
2014-02-25 17:58:56 -08:00
static void igb_ptp_tx_hwtstamp ( struct igb_adapter * adapter ) ;
2013-02-23 07:29:56 +00:00
/* SYSTIM read access for the 82576 */
2012-08-10 05:40:44 +00:00
static cycle_t igb_ptp_read_82576 ( const struct cyclecounter * cc )
2012-03-16 10:55:32 +00:00
{
struct igb_adapter * igb = container_of ( cc , struct igb_adapter , cc ) ;
struct e1000_hw * hw = & igb - > hw ;
2012-08-10 05:40:44 +00:00
u64 val ;
u32 lo , hi ;
2012-03-16 10:55:32 +00:00
lo = rd32 ( E1000_SYSTIML ) ;
hi = rd32 ( E1000_SYSTIMH ) ;
val = ( ( u64 ) hi ) < < 32 ;
val | = lo ;
return val ;
}
2013-02-23 07:29:56 +00:00
/* SYSTIM read access for the 82580 */
2012-08-10 05:40:44 +00:00
static cycle_t igb_ptp_read_82580 ( const struct cyclecounter * cc )
2012-03-16 10:55:32 +00:00
{
struct igb_adapter * igb = container_of ( cc , struct igb_adapter , cc ) ;
struct e1000_hw * hw = & igb - > hw ;
2013-06-06 01:31:09 +00:00
u32 lo , hi ;
2012-08-10 05:40:44 +00:00
u64 val ;
2012-03-16 10:55:32 +00:00
2013-02-23 07:29:56 +00:00
/* The timestamp latches on lowest register read. For the 82580
2012-03-16 10:55:37 +00:00
* the lowest register is SYSTIMR instead of SYSTIML . However we only
* need to provide nanosecond resolution , so we just ignore it .
*/
2013-06-06 01:31:09 +00:00
rd32 ( E1000_SYSTIMR ) ;
2012-03-16 10:55:32 +00:00
lo = rd32 ( E1000_SYSTIML ) ;
hi = rd32 ( E1000_SYSTIMH ) ;
val = ( ( u64 ) hi ) < < 32 ;
val | = lo ;
return val ;
}
2013-02-23 07:29:56 +00:00
/* SYSTIM read access for I210/I211 */
2015-03-29 23:12:03 +02:00
static void igb_ptp_read_i210 ( struct igb_adapter * adapter ,
struct timespec64 * ts )
2012-08-17 01:30:37 +00:00
{
struct e1000_hw * hw = & adapter - > hw ;
2013-06-06 01:31:09 +00:00
u32 sec , nsec ;
2012-08-17 01:30:37 +00:00
2013-02-23 07:29:56 +00:00
/* The timestamp latches on lowest register read. For I210/I211, the
2012-08-17 01:30:37 +00:00
* lowest register is SYSTIMR . Since we only need to provide nanosecond
* resolution , we can ignore it .
*/
2013-06-06 01:31:09 +00:00
rd32 ( E1000_SYSTIMR ) ;
2012-08-17 01:30:37 +00:00
nsec = rd32 ( E1000_SYSTIML ) ;
sec = rd32 ( E1000_SYSTIMH ) ;
ts - > tv_sec = sec ;
ts - > tv_nsec = nsec ;
}
static void igb_ptp_write_i210 ( struct igb_adapter * adapter ,
2015-03-29 23:12:03 +02:00
const struct timespec64 * ts )
2012-08-17 01:30:37 +00:00
{
struct e1000_hw * hw = & adapter - > hw ;
2013-02-23 07:29:56 +00:00
/* Writing the SYSTIMR register is not necessary as it only provides
2012-08-17 01:30:37 +00:00
* sub - nanosecond resolution .
*/
wr32 ( E1000_SYSTIML , ts - > tv_nsec ) ;
wr32 ( E1000_SYSTIMH , ts - > tv_sec ) ;
}
2012-08-10 05:40:44 +00:00
/**
* igb_ptp_systim_to_hwtstamp - convert system time value to hw timestamp
* @ adapter : board private structure
* @ hwtstamps : timestamp structure to update
* @ systim : unsigned 64 bit system time value .
*
* We need to convert the system time value stored in the RX / TXSTMP registers
* into a hwtstamp which can be used by the upper level timestamping functions .
*
* The ' tmreg_lock ' spinlock is used to protect the consistency of the
* system time value . This is needed because reading the 64 bit time
* value involves reading two ( or three ) 32 bit registers . The first
* read latches the value . Ditto for writing .
*
* In addition , here have extended the system time with an overflow
* counter in software .
* */
static void igb_ptp_systim_to_hwtstamp ( struct igb_adapter * adapter ,
struct skb_shared_hwtstamps * hwtstamps ,
u64 systim )
{
unsigned long flags ;
u64 ns ;
switch ( adapter - > hw . mac . type ) {
2012-08-17 01:30:37 +00:00
case e1000_82576 :
case e1000_82580 :
2013-04-18 22:21:30 +00:00
case e1000_i354 :
2012-08-17 01:30:37 +00:00
case e1000_i350 :
spin_lock_irqsave ( & adapter - > tmreg_lock , flags ) ;
ns = timecounter_cyc2time ( & adapter - > tc , systim ) ;
spin_unlock_irqrestore ( & adapter - > tmreg_lock , flags ) ;
memset ( hwtstamps , 0 , sizeof ( * hwtstamps ) ) ;
hwtstamps - > hwtstamp = ns_to_ktime ( ns ) ;
break ;
2012-08-10 05:40:44 +00:00
case e1000_i210 :
case e1000_i211 :
2012-08-17 01:30:37 +00:00
memset ( hwtstamps , 0 , sizeof ( * hwtstamps ) ) ;
/* Upper 32 bits contain s, lower 32 bits contain ns. */
hwtstamps - > hwtstamp = ktime_set ( systim > > 32 ,
systim & 0xFFFFFFFF ) ;
2012-08-10 05:40:44 +00:00
break ;
default :
2012-08-17 01:30:37 +00:00
break ;
2012-08-10 05:40:44 +00:00
}
}
2013-02-23 07:29:56 +00:00
/* PTP clock operations */
2012-08-10 05:40:44 +00:00
static int igb_ptp_adjfreq_82576 ( struct ptp_clock_info * ptp , s32 ppb )
2012-03-16 10:55:32 +00:00
{
2012-08-10 05:40:44 +00:00
struct igb_adapter * igb = container_of ( ptp , struct igb_adapter ,
ptp_caps ) ;
struct e1000_hw * hw = & igb - > hw ;
int neg_adj = 0 ;
2012-03-16 10:55:32 +00:00
u64 rate ;
u32 incvalue ;
if ( ppb < 0 ) {
neg_adj = 1 ;
ppb = - ppb ;
}
rate = ppb ;
rate < < = 14 ;
rate = div_u64 ( rate , 1953125 ) ;
incvalue = 16 < < IGB_82576_TSYNC_SHIFT ;
if ( neg_adj )
incvalue - = rate ;
else
incvalue + = rate ;
wr32 ( E1000_TIMINCA , INCPERIOD_82576 | ( incvalue & INCVALUE_82576_MASK ) ) ;
return 0 ;
}
2012-08-10 05:40:44 +00:00
static int igb_ptp_adjfreq_82580 ( struct ptp_clock_info * ptp , s32 ppb )
2012-03-16 10:55:32 +00:00
{
2012-08-10 05:40:44 +00:00
struct igb_adapter * igb = container_of ( ptp , struct igb_adapter ,
ptp_caps ) ;
struct e1000_hw * hw = & igb - > hw ;
int neg_adj = 0 ;
2012-03-16 10:55:32 +00:00
u64 rate ;
u32 inca ;
if ( ppb < 0 ) {
neg_adj = 1 ;
ppb = - ppb ;
}
rate = ppb ;
rate < < = 26 ;
rate = div_u64 ( rate , 1953125 ) ;
inca = rate & INCVALUE_MASK ;
if ( neg_adj )
inca | = ISGN ;
wr32 ( E1000_TIMINCA , inca ) ;
return 0 ;
}
2012-08-17 01:30:37 +00:00
static int igb_ptp_adjtime_82576 ( struct ptp_clock_info * ptp , s64 delta )
2012-03-16 10:55:32 +00:00
{
2012-08-10 05:40:44 +00:00
struct igb_adapter * igb = container_of ( ptp , struct igb_adapter ,
ptp_caps ) ;
2012-03-16 10:55:32 +00:00
unsigned long flags ;
spin_lock_irqsave ( & igb - > tmreg_lock , flags ) ;
2014-12-21 19:47:02 +01:00
timecounter_adjtime ( & igb - > tc , delta ) ;
2012-03-16 10:55:32 +00:00
spin_unlock_irqrestore ( & igb - > tmreg_lock , flags ) ;
return 0 ;
}
2012-08-17 01:30:37 +00:00
static int igb_ptp_adjtime_i210 ( struct ptp_clock_info * ptp , s64 delta )
{
struct igb_adapter * igb = container_of ( ptp , struct igb_adapter ,
ptp_caps ) ;
unsigned long flags ;
2015-03-29 23:12:03 +02:00
struct timespec64 now , then = ns_to_timespec64 ( delta ) ;
2012-08-17 01:30:37 +00:00
spin_lock_irqsave ( & igb - > tmreg_lock , flags ) ;
igb_ptp_read_i210 ( igb , & now ) ;
2015-03-29 23:12:03 +02:00
now = timespec64_add ( now , then ) ;
igb_ptp_write_i210 ( igb , ( const struct timespec64 * ) & now ) ;
2012-08-17 01:30:37 +00:00
spin_unlock_irqrestore ( & igb - > tmreg_lock , flags ) ;
return 0 ;
}
static int igb_ptp_gettime_82576 ( struct ptp_clock_info * ptp ,
2015-03-29 23:12:03 +02:00
struct timespec64 * ts )
2012-03-16 10:55:32 +00:00
{
2012-08-10 05:40:44 +00:00
struct igb_adapter * igb = container_of ( ptp , struct igb_adapter ,
ptp_caps ) ;
unsigned long flags ;
2012-03-16 10:55:32 +00:00
u64 ns ;
spin_lock_irqsave ( & igb - > tmreg_lock , flags ) ;
ns = timecounter_read ( & igb - > tc ) ;
spin_unlock_irqrestore ( & igb - > tmreg_lock , flags ) ;
2015-03-31 23:08:12 +02:00
* ts = ns_to_timespec64 ( ns ) ;
2012-03-16 10:55:32 +00:00
return 0 ;
}
2012-08-17 01:30:37 +00:00
static int igb_ptp_gettime_i210 ( struct ptp_clock_info * ptp ,
2015-03-29 23:12:03 +02:00
struct timespec64 * ts )
2012-08-17 01:30:37 +00:00
{
struct igb_adapter * igb = container_of ( ptp , struct igb_adapter ,
ptp_caps ) ;
unsigned long flags ;
spin_lock_irqsave ( & igb - > tmreg_lock , flags ) ;
igb_ptp_read_i210 ( igb , ts ) ;
spin_unlock_irqrestore ( & igb - > tmreg_lock , flags ) ;
return 0 ;
}
static int igb_ptp_settime_82576 ( struct ptp_clock_info * ptp ,
2015-03-29 23:12:03 +02:00
const struct timespec64 * ts )
2012-03-16 10:55:32 +00:00
{
2012-08-10 05:40:44 +00:00
struct igb_adapter * igb = container_of ( ptp , struct igb_adapter ,
ptp_caps ) ;
2012-03-16 10:55:32 +00:00
unsigned long flags ;
2012-08-10 05:40:44 +00:00
u64 ns ;
2012-03-16 10:55:32 +00:00
2015-03-31 23:08:12 +02:00
ns = timespec64_to_ns ( ts ) ;
2012-03-16 10:55:32 +00:00
spin_lock_irqsave ( & igb - > tmreg_lock , flags ) ;
timecounter_init ( & igb - > tc , & igb - > cc , ns ) ;
spin_unlock_irqrestore ( & igb - > tmreg_lock , flags ) ;
return 0 ;
}
2012-08-17 01:30:37 +00:00
static int igb_ptp_settime_i210 ( struct ptp_clock_info * ptp ,
2015-03-29 23:12:03 +02:00
const struct timespec64 * ts )
2012-08-17 01:30:37 +00:00
{
struct igb_adapter * igb = container_of ( ptp , struct igb_adapter ,
ptp_caps ) ;
unsigned long flags ;
spin_lock_irqsave ( & igb - > tmreg_lock , flags ) ;
igb_ptp_write_i210 ( igb , ts ) ;
spin_unlock_irqrestore ( & igb - > tmreg_lock , flags ) ;
return 0 ;
}
2014-11-21 20:51:26 +00:00
static void igb_pin_direction ( int pin , int input , u32 * ctrl , u32 * ctrl_ext )
{
u32 * ptr = pin < 2 ? ctrl : ctrl_ext ;
2015-03-06 03:34:14 +00:00
static const u32 mask [ IGB_N_SDP ] = {
2014-11-21 20:51:26 +00:00
E1000_CTRL_SDP0_DIR ,
E1000_CTRL_SDP1_DIR ,
E1000_CTRL_EXT_SDP2_DIR ,
E1000_CTRL_EXT_SDP3_DIR ,
} ;
if ( input )
* ptr & = ~ mask [ pin ] ;
else
* ptr | = mask [ pin ] ;
}
static void igb_pin_extts ( struct igb_adapter * igb , int chan , int pin )
{
2015-03-06 03:34:14 +00:00
static const u32 aux0_sel_sdp [ IGB_N_SDP ] = {
2014-11-21 20:51:26 +00:00
AUX0_SEL_SDP0 , AUX0_SEL_SDP1 , AUX0_SEL_SDP2 , AUX0_SEL_SDP3 ,
} ;
2015-03-06 03:34:14 +00:00
static const u32 aux1_sel_sdp [ IGB_N_SDP ] = {
2014-11-21 20:51:26 +00:00
AUX1_SEL_SDP0 , AUX1_SEL_SDP1 , AUX1_SEL_SDP2 , AUX1_SEL_SDP3 ,
} ;
2015-03-06 03:34:14 +00:00
static const u32 ts_sdp_en [ IGB_N_SDP ] = {
2014-11-21 20:51:26 +00:00
TS_SDP0_EN , TS_SDP1_EN , TS_SDP2_EN , TS_SDP3_EN ,
} ;
2015-03-06 03:34:14 +00:00
struct e1000_hw * hw = & igb - > hw ;
2014-11-21 20:51:26 +00:00
u32 ctrl , ctrl_ext , tssdp = 0 ;
ctrl = rd32 ( E1000_CTRL ) ;
ctrl_ext = rd32 ( E1000_CTRL_EXT ) ;
tssdp = rd32 ( E1000_TSSDP ) ;
igb_pin_direction ( pin , 1 , & ctrl , & ctrl_ext ) ;
/* Make sure this pin is not enabled as an output. */
tssdp & = ~ ts_sdp_en [ pin ] ;
if ( chan = = 1 ) {
tssdp & = ~ AUX1_SEL_SDP3 ;
tssdp | = aux1_sel_sdp [ pin ] | AUX1_TS_SDP_EN ;
} else {
tssdp & = ~ AUX0_SEL_SDP3 ;
tssdp | = aux0_sel_sdp [ pin ] | AUX0_TS_SDP_EN ;
}
wr32 ( E1000_TSSDP , tssdp ) ;
wr32 ( E1000_CTRL , ctrl ) ;
wr32 ( E1000_CTRL_EXT , ctrl_ext ) ;
}
2015-07-23 14:59:30 -07:00
static void igb_pin_perout ( struct igb_adapter * igb , int chan , int pin , int freq )
2014-11-21 20:51:26 +00:00
{
2015-03-06 03:34:14 +00:00
static const u32 aux0_sel_sdp [ IGB_N_SDP ] = {
2014-11-21 20:51:26 +00:00
AUX0_SEL_SDP0 , AUX0_SEL_SDP1 , AUX0_SEL_SDP2 , AUX0_SEL_SDP3 ,
} ;
2015-03-06 03:34:14 +00:00
static const u32 aux1_sel_sdp [ IGB_N_SDP ] = {
2014-11-21 20:51:26 +00:00
AUX1_SEL_SDP0 , AUX1_SEL_SDP1 , AUX1_SEL_SDP2 , AUX1_SEL_SDP3 ,
} ;
2015-03-06 03:34:14 +00:00
static const u32 ts_sdp_en [ IGB_N_SDP ] = {
2014-11-21 20:51:26 +00:00
TS_SDP0_EN , TS_SDP1_EN , TS_SDP2_EN , TS_SDP3_EN ,
} ;
2015-03-06 03:34:14 +00:00
static const u32 ts_sdp_sel_tt0 [ IGB_N_SDP ] = {
2014-11-21 20:51:26 +00:00
TS_SDP0_SEL_TT0 , TS_SDP1_SEL_TT0 ,
TS_SDP2_SEL_TT0 , TS_SDP3_SEL_TT0 ,
} ;
2015-03-06 03:34:14 +00:00
static const u32 ts_sdp_sel_tt1 [ IGB_N_SDP ] = {
2014-11-21 20:51:26 +00:00
TS_SDP0_SEL_TT1 , TS_SDP1_SEL_TT1 ,
TS_SDP2_SEL_TT1 , TS_SDP3_SEL_TT1 ,
} ;
2015-07-23 14:59:30 -07:00
static const u32 ts_sdp_sel_fc0 [ IGB_N_SDP ] = {
TS_SDP0_SEL_FC0 , TS_SDP1_SEL_FC0 ,
TS_SDP2_SEL_FC0 , TS_SDP3_SEL_FC0 ,
} ;
static const u32 ts_sdp_sel_fc1 [ IGB_N_SDP ] = {
TS_SDP0_SEL_FC1 , TS_SDP1_SEL_FC1 ,
TS_SDP2_SEL_FC1 , TS_SDP3_SEL_FC1 ,
} ;
2015-03-06 03:34:14 +00:00
static const u32 ts_sdp_sel_clr [ IGB_N_SDP ] = {
2014-11-21 20:51:26 +00:00
TS_SDP0_SEL_FC1 , TS_SDP1_SEL_FC1 ,
TS_SDP2_SEL_FC1 , TS_SDP3_SEL_FC1 ,
} ;
2015-03-06 03:34:14 +00:00
struct e1000_hw * hw = & igb - > hw ;
2014-11-21 20:51:26 +00:00
u32 ctrl , ctrl_ext , tssdp = 0 ;
ctrl = rd32 ( E1000_CTRL ) ;
ctrl_ext = rd32 ( E1000_CTRL_EXT ) ;
tssdp = rd32 ( E1000_TSSDP ) ;
igb_pin_direction ( pin , 0 , & ctrl , & ctrl_ext ) ;
/* Make sure this pin is not enabled as an input. */
if ( ( tssdp & AUX0_SEL_SDP3 ) = = aux0_sel_sdp [ pin ] )
tssdp & = ~ AUX0_TS_SDP_EN ;
if ( ( tssdp & AUX1_SEL_SDP3 ) = = aux1_sel_sdp [ pin ] )
tssdp & = ~ AUX1_TS_SDP_EN ;
tssdp & = ~ ts_sdp_sel_clr [ pin ] ;
2015-07-23 14:59:30 -07:00
if ( freq ) {
if ( chan = = 1 )
tssdp | = ts_sdp_sel_fc1 [ pin ] ;
else
tssdp | = ts_sdp_sel_fc0 [ pin ] ;
} else {
if ( chan = = 1 )
tssdp | = ts_sdp_sel_tt1 [ pin ] ;
else
tssdp | = ts_sdp_sel_tt0 [ pin ] ;
}
2014-11-21 20:51:26 +00:00
tssdp | = ts_sdp_en [ pin ] ;
wr32 ( E1000_TSSDP , tssdp ) ;
wr32 ( E1000_CTRL , ctrl ) ;
wr32 ( E1000_CTRL_EXT , ctrl_ext ) ;
}
2014-11-21 20:51:20 +00:00
static int igb_ptp_feature_enable_i210 ( struct ptp_clock_info * ptp ,
struct ptp_clock_request * rq , int on )
{
struct igb_adapter * igb =
container_of ( ptp , struct igb_adapter , ptp_caps ) ;
struct e1000_hw * hw = & igb - > hw ;
2015-07-23 14:59:30 -07:00
u32 tsauxc , tsim , tsauxc_mask , tsim_mask , trgttiml , trgttimh , freqout ;
2014-11-21 20:51:20 +00:00
unsigned long flags ;
2014-11-21 20:51:26 +00:00
struct timespec ts ;
2015-07-23 14:59:30 -07:00
int use_freq = 0 , pin = - 1 ;
2014-11-21 20:51:26 +00:00
s64 ns ;
2014-11-21 20:51:20 +00:00
switch ( rq - > type ) {
2014-11-21 20:51:26 +00:00
case PTP_CLK_REQ_EXTTS :
if ( on ) {
pin = ptp_find_pin ( igb - > ptp_clock , PTP_PF_EXTTS ,
rq - > extts . index ) ;
if ( pin < 0 )
return - EBUSY ;
}
if ( rq - > extts . index = = 1 ) {
tsauxc_mask = TSAUXC_EN_TS1 ;
tsim_mask = TSINTR_AUTT1 ;
} else {
tsauxc_mask = TSAUXC_EN_TS0 ;
tsim_mask = TSINTR_AUTT0 ;
}
spin_lock_irqsave ( & igb - > tmreg_lock , flags ) ;
tsauxc = rd32 ( E1000_TSAUXC ) ;
tsim = rd32 ( E1000_TSIM ) ;
if ( on ) {
igb_pin_extts ( igb , rq - > extts . index , pin ) ;
tsauxc | = tsauxc_mask ;
tsim | = tsim_mask ;
} else {
tsauxc & = ~ tsauxc_mask ;
tsim & = ~ tsim_mask ;
}
wr32 ( E1000_TSAUXC , tsauxc ) ;
wr32 ( E1000_TSIM , tsim ) ;
spin_unlock_irqrestore ( & igb - > tmreg_lock , flags ) ;
return 0 ;
case PTP_CLK_REQ_PEROUT :
if ( on ) {
pin = ptp_find_pin ( igb - > ptp_clock , PTP_PF_PEROUT ,
rq - > perout . index ) ;
if ( pin < 0 )
return - EBUSY ;
}
ts . tv_sec = rq - > perout . period . sec ;
ts . tv_nsec = rq - > perout . period . nsec ;
ns = timespec_to_ns ( & ts ) ;
ns = ns > > 1 ;
2015-07-23 14:59:30 -07:00
if ( on & & ns < = 70000000LL ) {
if ( ns < 8LL )
return - EINVAL ;
use_freq = 1 ;
2014-11-21 20:51:26 +00:00
}
ts = ns_to_timespec ( ns ) ;
if ( rq - > perout . index = = 1 ) {
2015-07-23 14:59:30 -07:00
if ( use_freq ) {
tsauxc_mask = TSAUXC_EN_CLK1 | TSAUXC_ST1 ;
tsim_mask = 0 ;
} else {
tsauxc_mask = TSAUXC_EN_TT1 ;
tsim_mask = TSINTR_TT1 ;
}
2014-11-21 20:51:26 +00:00
trgttiml = E1000_TRGTTIML1 ;
trgttimh = E1000_TRGTTIMH1 ;
2015-07-23 14:59:30 -07:00
freqout = E1000_FREQOUT1 ;
2014-11-21 20:51:26 +00:00
} else {
2015-07-23 14:59:30 -07:00
if ( use_freq ) {
tsauxc_mask = TSAUXC_EN_CLK0 | TSAUXC_ST0 ;
tsim_mask = 0 ;
} else {
tsauxc_mask = TSAUXC_EN_TT0 ;
tsim_mask = TSINTR_TT0 ;
}
2014-11-21 20:51:26 +00:00
trgttiml = E1000_TRGTTIML0 ;
trgttimh = E1000_TRGTTIMH0 ;
2015-07-23 14:59:30 -07:00
freqout = E1000_FREQOUT0 ;
2014-11-21 20:51:26 +00:00
}
spin_lock_irqsave ( & igb - > tmreg_lock , flags ) ;
tsauxc = rd32 ( E1000_TSAUXC ) ;
tsim = rd32 ( E1000_TSIM ) ;
2015-07-23 14:59:30 -07:00
if ( rq - > perout . index = = 1 ) {
tsauxc & = ~ ( TSAUXC_EN_TT1 | TSAUXC_EN_CLK1 | TSAUXC_ST1 ) ;
tsim & = ~ TSINTR_TT1 ;
} else {
tsauxc & = ~ ( TSAUXC_EN_TT0 | TSAUXC_EN_CLK0 | TSAUXC_ST0 ) ;
tsim & = ~ TSINTR_TT0 ;
}
2014-11-21 20:51:26 +00:00
if ( on ) {
int i = rq - > perout . index ;
2015-07-23 14:59:30 -07:00
igb_pin_perout ( igb , i , pin , use_freq ) ;
2014-11-21 20:51:26 +00:00
igb - > perout [ i ] . start . tv_sec = rq - > perout . start . sec ;
igb - > perout [ i ] . start . tv_nsec = rq - > perout . start . nsec ;
igb - > perout [ i ] . period . tv_sec = ts . tv_sec ;
igb - > perout [ i ] . period . tv_nsec = ts . tv_nsec ;
2015-06-11 14:51:30 +02:00
wr32 ( trgttimh , rq - > perout . start . sec ) ;
wr32 ( trgttiml , rq - > perout . start . nsec ) ;
2015-07-23 14:59:30 -07:00
if ( use_freq )
wr32 ( freqout , ns ) ;
2014-11-21 20:51:26 +00:00
tsauxc | = tsauxc_mask ;
tsim | = tsim_mask ;
}
wr32 ( E1000_TSAUXC , tsauxc ) ;
wr32 ( E1000_TSIM , tsim ) ;
spin_unlock_irqrestore ( & igb - > tmreg_lock , flags ) ;
return 0 ;
2014-11-21 20:51:20 +00:00
case PTP_CLK_REQ_PPS :
spin_lock_irqsave ( & igb - > tmreg_lock , flags ) ;
tsim = rd32 ( E1000_TSIM ) ;
if ( on )
tsim | = TSINTR_SYS_WRAP ;
else
tsim & = ~ TSINTR_SYS_WRAP ;
wr32 ( E1000_TSIM , tsim ) ;
spin_unlock_irqrestore ( & igb - > tmreg_lock , flags ) ;
return 0 ;
}
return - EOPNOTSUPP ;
}
2014-05-16 07:21:13 +00:00
static int igb_ptp_feature_enable ( struct ptp_clock_info * ptp ,
struct ptp_clock_request * rq , int on )
2012-03-16 10:55:32 +00:00
{
return - EOPNOTSUPP ;
}
2014-11-21 20:51:26 +00:00
static int igb_ptp_verify_pin ( struct ptp_clock_info * ptp , unsigned int pin ,
enum ptp_pin_function func , unsigned int chan )
{
switch ( func ) {
case PTP_PF_NONE :
case PTP_PF_EXTTS :
case PTP_PF_PEROUT :
break ;
case PTP_PF_PHYSYNC :
return - 1 ;
}
return 0 ;
}
2012-08-18 07:26:33 +00:00
/**
* igb_ptp_tx_work
* @ work : pointer to work struct
*
* This work function polls the TSYNCTXCTL valid bit to determine when a
* timestamp has been taken for the current stored skb .
2013-02-23 07:29:56 +00:00
* */
2014-02-25 17:58:56 -08:00
static void igb_ptp_tx_work ( struct work_struct * work )
2012-08-18 07:26:33 +00:00
{
struct igb_adapter * adapter = container_of ( work , struct igb_adapter ,
ptp_tx_work ) ;
struct e1000_hw * hw = & adapter - > hw ;
u32 tsynctxctl ;
if ( ! adapter - > ptp_tx_skb )
return ;
2012-12-13 07:20:34 +00:00
if ( time_is_before_jiffies ( adapter - > ptp_tx_start +
IGB_PTP_TX_TIMEOUT ) ) {
dev_kfree_skb_any ( adapter - > ptp_tx_skb ) ;
adapter - > ptp_tx_skb = NULL ;
2014-03-15 14:55:32 +00:00
clear_bit_unlock ( __IGB_PTP_TX_IN_PROGRESS , & adapter - > state ) ;
2012-12-13 07:20:34 +00:00
adapter - > tx_hwtstamp_timeouts + + ;
2014-04-02 10:33:22 +00:00
dev_warn ( & adapter - > pdev - > dev , " clearing Tx timestamp hang \n " ) ;
2012-12-13 07:20:34 +00:00
return ;
}
2012-08-18 07:26:33 +00:00
tsynctxctl = rd32 ( E1000_TSYNCTXCTL ) ;
if ( tsynctxctl & E1000_TSYNCTXCTL_VALID )
igb_ptp_tx_hwtstamp ( adapter ) ;
else
/* reschedule to check later */
schedule_work ( & adapter - > ptp_tx_work ) ;
}
2012-08-10 05:40:44 +00:00
static void igb_ptp_overflow_check ( struct work_struct * work )
2012-03-16 10:55:32 +00:00
{
2012-08-10 05:40:44 +00:00
struct igb_adapter * igb =
container_of ( work , struct igb_adapter , ptp_overflow_work . work ) ;
2015-03-29 23:12:03 +02:00
struct timespec64 ts ;
2012-08-10 05:40:44 +00:00
2015-03-29 23:12:03 +02:00
igb - > ptp_caps . gettime64 ( & igb - > ptp_caps , & ts ) ;
2012-08-10 05:40:44 +00:00
2015-03-31 12:01:21 -04:00
pr_debug ( " igb overflow check at %lld.%09lu \n " ,
( long long ) ts . tv_sec , ts . tv_nsec ) ;
2012-08-10 05:40:44 +00:00
schedule_delayed_work ( & igb - > ptp_overflow_work ,
IGB_SYSTIM_OVERFLOW_PERIOD ) ;
2012-03-16 10:55:32 +00:00
}
2012-12-13 07:20:35 +00:00
/**
* igb_ptp_rx_hang - detect error case when Rx timestamp registers latched
* @ adapter : private network adapter structure
*
* This watchdog task is scheduled to detect error case where hardware has
* dropped an Rx packet that was timestamped when the ring is full . The
* particular error is rare but leaves the device in a state unable to timestamp
* any future packets .
2013-02-23 07:29:56 +00:00
* */
2012-12-13 07:20:35 +00:00
void igb_ptp_rx_hang ( struct igb_adapter * adapter )
{
struct e1000_hw * hw = & adapter - > hw ;
u32 tsyncrxctl = rd32 ( E1000_TSYNCRXCTL ) ;
unsigned long rx_event ;
if ( hw - > mac . type ! = e1000_82576 )
return ;
/* If we don't have a valid timestamp in the registers, just update the
* timeout counter and exit
*/
if ( ! ( tsyncrxctl & E1000_TSYNCRXCTL_VALID ) ) {
adapter - > last_rx_ptp_check = jiffies ;
return ;
}
/* Determine the most recent watchdog or rx_timestamp event */
rx_event = adapter - > last_rx_ptp_check ;
2014-04-02 10:33:33 +00:00
if ( time_after ( adapter - > last_rx_timestamp , rx_event ) )
rx_event = adapter - > last_rx_timestamp ;
2012-12-13 07:20:35 +00:00
/* Only need to read the high RXSTMP register to clear the lock */
if ( time_is_before_jiffies ( rx_event + 5 * HZ ) ) {
rd32 ( E1000_RXSTMPH ) ;
adapter - > last_rx_ptp_check = jiffies ;
adapter - > rx_hwtstamp_cleared + + ;
2014-04-02 10:33:22 +00:00
dev_warn ( & adapter - > pdev - > dev , " clearing Rx timestamp hang \n " ) ;
2012-12-13 07:20:35 +00:00
}
}
2012-08-10 05:40:44 +00:00
/**
* igb_ptp_tx_hwtstamp - utility function which checks for TX time stamp
2012-08-18 07:26:33 +00:00
* @ adapter : Board private structure .
2012-08-10 05:40:44 +00:00
*
* If we were asked to do hardware stamping and such a time stamp is
* available , then it must have been for this skb here because we only
* allow only one such packet into the queue .
2013-02-23 07:29:56 +00:00
* */
2014-02-25 17:58:56 -08:00
static void igb_ptp_tx_hwtstamp ( struct igb_adapter * adapter )
2012-03-16 10:55:32 +00:00
{
2012-08-10 05:40:44 +00:00
struct e1000_hw * hw = & adapter - > hw ;
struct skb_shared_hwtstamps shhwtstamps ;
u64 regval ;
2012-03-16 10:55:32 +00:00
2012-08-10 05:40:44 +00:00
regval = rd32 ( E1000_TXSTMPL ) ;
regval | = ( u64 ) rd32 ( E1000_TXSTMPH ) < < 32 ;
2012-03-16 10:55:32 +00:00
2012-08-10 05:40:44 +00:00
igb_ptp_systim_to_hwtstamp ( adapter , & shhwtstamps , regval ) ;
2012-08-18 07:26:33 +00:00
skb_tstamp_tx ( adapter - > ptp_tx_skb , & shhwtstamps ) ;
dev_kfree_skb_any ( adapter - > ptp_tx_skb ) ;
adapter - > ptp_tx_skb = NULL ;
2014-03-15 14:55:32 +00:00
clear_bit_unlock ( __IGB_PTP_TX_IN_PROGRESS , & adapter - > state ) ;
2012-08-10 05:40:44 +00:00
}
2012-09-25 05:14:55 +00:00
/**
* igb_ptp_rx_pktstamp - retrieve Rx per packet timestamp
* @ q_vector : Pointer to interrupt specific structure
* @ va : Pointer to address containing Rx buffer
* @ skb : Buffer containing timestamp and packet
*
* This function is meant to retrieve a timestamp from the first buffer of an
* incoming frame . The value is stored in little endian format starting on
* byte 8.
2013-02-23 07:29:56 +00:00
* */
2012-09-25 05:14:55 +00:00
void igb_ptp_rx_pktstamp ( struct igb_q_vector * q_vector ,
unsigned char * va ,
struct sk_buff * skb )
{
2012-10-23 00:01:04 +00:00
__le64 * regval = ( __le64 * ) va ;
2012-09-25 05:14:55 +00:00
2013-02-23 07:29:56 +00:00
/* The timestamp is recorded in little endian format.
2012-09-25 05:14:55 +00:00
* DWORD : 0 1 2 3
* Field : Reserved Reserved SYSTIML SYSTIMH
*/
igb_ptp_systim_to_hwtstamp ( q_vector - > adapter , skb_hwtstamps ( skb ) ,
le64_to_cpu ( regval [ 1 ] ) ) ;
}
/**
* igb_ptp_rx_rgtstamp - retrieve Rx timestamp stored in register
* @ q_vector : Pointer to interrupt specific structure
* @ skb : Buffer containing timestamp and packet
*
* This function is meant to retrieve a timestamp from the internal registers
* of the adapter and store it in the skb .
2013-02-23 07:29:56 +00:00
* */
2012-09-25 05:14:55 +00:00
void igb_ptp_rx_rgtstamp ( struct igb_q_vector * q_vector ,
2012-08-10 05:40:44 +00:00
struct sk_buff * skb )
{
struct igb_adapter * adapter = q_vector - > adapter ;
struct e1000_hw * hw = & adapter - > hw ;
u64 regval ;
2013-02-23 07:29:56 +00:00
/* If this bit is set, then the RX registers contain the time stamp. No
2012-08-10 05:40:44 +00:00
* other packet will be time stamped until we read these registers , so
* read the registers to make them available again . Because only one
* packet can be time stamped at a time , we know that the register
* values must belong to this one here and therefore we don ' t need to
* compare any of the additional attributes stored for it .
*
* If nothing went wrong , then it should have a shared tx_flags that we
* can turn into a skb_shared_hwtstamps .
*/
2012-09-25 05:14:55 +00:00
if ( ! ( rd32 ( E1000_TSYNCRXCTL ) & E1000_TSYNCRXCTL_VALID ) )
return ;
regval = rd32 ( E1000_RXSTMPL ) ;
regval | = ( u64 ) rd32 ( E1000_RXSTMPH ) < < 32 ;
2012-08-10 05:40:44 +00:00
igb_ptp_systim_to_hwtstamp ( adapter , skb_hwtstamps ( skb ) , regval ) ;
2014-04-02 10:33:33 +00:00
/* Update the last_rx_timestamp timer in order to enable watchdog check
* for error case of latched timestamp on a dropped packet .
*/
adapter - > last_rx_timestamp = jiffies ;
2012-08-10 05:40:44 +00:00
}
/**
2014-01-11 07:20:06 +00:00
* igb_ptp_get_ts_config - get hardware time stamping config
* @ netdev :
* @ ifreq :
*
* Get the hwtstamp_config settings to return to the user . Rather than attempt
* to deconstruct the settings from the registers , just return a shadow copy
* of the last known settings .
* */
int igb_ptp_get_ts_config ( struct net_device * netdev , struct ifreq * ifr )
{
struct igb_adapter * adapter = netdev_priv ( netdev ) ;
struct hwtstamp_config * config = & adapter - > tstamp_config ;
return copy_to_user ( ifr - > ifr_data , config , sizeof ( * config ) ) ?
- EFAULT : 0 ;
}
2014-06-05 07:25:10 +00:00
2014-01-11 07:20:06 +00:00
/**
2014-06-05 07:25:10 +00:00
* igb_ptp_set_timestamp_mode - setup hardware for timestamping
* @ adapter : networking device structure
* @ config : hwtstamp configuration
2012-08-10 05:40:44 +00:00
*
* Outgoing time stamping can be enabled and disabled . Play nice and
* disable it when requested , although it shouldn ' t case any overhead
* when no packet needs it . At most one packet in the queue may be
* marked for time stamping , otherwise it would be impossible to tell
* for sure to which packet the hardware time stamp belongs .
*
* Incoming time stamping has to be configured via the hardware
* filters . Not all combinations are supported , in particular event
* type has to be specified . Matching the kind of event packet is
* not supported , with the exception of " all V2 events regardless of
* level 2 or 4 " .
2014-06-05 07:25:10 +00:00
*/
static int igb_ptp_set_timestamp_mode ( struct igb_adapter * adapter ,
struct hwtstamp_config * config )
2012-08-10 05:40:44 +00:00
{
struct e1000_hw * hw = & adapter - > hw ;
u32 tsync_tx_ctl = E1000_TSYNCTXCTL_ENABLED ;
u32 tsync_rx_ctl = E1000_TSYNCRXCTL_ENABLED ;
u32 tsync_rx_cfg = 0 ;
bool is_l4 = false ;
bool is_l2 = false ;
u32 regval ;
/* reserved for future extensions */
2014-01-11 07:20:06 +00:00
if ( config - > flags )
2012-08-10 05:40:44 +00:00
return - EINVAL ;
2014-01-11 07:20:06 +00:00
switch ( config - > tx_type ) {
2012-08-10 05:40:44 +00:00
case HWTSTAMP_TX_OFF :
tsync_tx_ctl = 0 ;
case HWTSTAMP_TX_ON :
break ;
default :
return - ERANGE ;
}
2014-01-11 07:20:06 +00:00
switch ( config - > rx_filter ) {
2012-08-10 05:40:44 +00:00
case HWTSTAMP_FILTER_NONE :
tsync_rx_ctl = 0 ;
break ;
case HWTSTAMP_FILTER_PTP_V1_L4_SYNC :
tsync_rx_ctl | = E1000_TSYNCRXCTL_TYPE_L4_V1 ;
tsync_rx_cfg = E1000_TSYNCRXCFG_PTP_V1_SYNC_MESSAGE ;
is_l4 = true ;
break ;
case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ :
tsync_rx_ctl | = E1000_TSYNCRXCTL_TYPE_L4_V1 ;
tsync_rx_cfg = E1000_TSYNCRXCFG_PTP_V1_DELAY_REQ_MESSAGE ;
is_l4 = true ;
break ;
2012-11-08 08:38:57 +00:00
case HWTSTAMP_FILTER_PTP_V2_EVENT :
case HWTSTAMP_FILTER_PTP_V2_L2_EVENT :
case HWTSTAMP_FILTER_PTP_V2_L4_EVENT :
case HWTSTAMP_FILTER_PTP_V2_SYNC :
2012-08-10 05:40:44 +00:00
case HWTSTAMP_FILTER_PTP_V2_L2_SYNC :
case HWTSTAMP_FILTER_PTP_V2_L4_SYNC :
2012-11-08 08:38:57 +00:00
case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ :
2012-08-10 05:40:44 +00:00
case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ :
case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ :
tsync_rx_ctl | = E1000_TSYNCRXCTL_TYPE_EVENT_V2 ;
2014-01-11 07:20:06 +00:00
config - > rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT ;
2012-08-10 05:40:44 +00:00
is_l2 = true ;
is_l4 = true ;
break ;
2012-11-08 08:38:57 +00:00
case HWTSTAMP_FILTER_PTP_V1_L4_EVENT :
case HWTSTAMP_FILTER_ALL :
/* 82576 cannot timestamp all packets, which it needs to do to
* support both V1 Sync and Delay_Req messages
*/
if ( hw - > mac . type ! = e1000_82576 ) {
tsync_rx_ctl | = E1000_TSYNCRXCTL_TYPE_ALL ;
2014-01-11 07:20:06 +00:00
config - > rx_filter = HWTSTAMP_FILTER_ALL ;
2012-11-08 08:38:57 +00:00
break ;
}
/* fall through */
2012-08-10 05:40:44 +00:00
default :
2014-01-11 07:20:06 +00:00
config - > rx_filter = HWTSTAMP_FILTER_NONE ;
2012-08-10 05:40:44 +00:00
return - ERANGE ;
}
if ( hw - > mac . type = = e1000_82575 ) {
if ( tsync_rx_ctl | tsync_tx_ctl )
return - EINVAL ;
return 0 ;
}
2013-02-23 07:29:56 +00:00
/* Per-packet timestamping only works if all packets are
2012-08-10 05:40:44 +00:00
* timestamped , so enable timestamping in all packets as
2013-02-23 07:29:56 +00:00
* long as one Rx filter was configured .
2012-08-10 05:40:44 +00:00
*/
if ( ( hw - > mac . type > = e1000_82580 ) & & tsync_rx_ctl ) {
tsync_rx_ctl = E1000_TSYNCRXCTL_ENABLED ;
tsync_rx_ctl | = E1000_TSYNCRXCTL_TYPE_ALL ;
2014-01-11 07:20:06 +00:00
config - > rx_filter = HWTSTAMP_FILTER_ALL ;
2012-11-08 08:38:57 +00:00
is_l2 = true ;
is_l4 = true ;
2012-08-17 01:30:37 +00:00
if ( ( hw - > mac . type = = e1000_i210 ) | |
( hw - > mac . type = = e1000_i211 ) ) {
regval = rd32 ( E1000_RXPBS ) ;
regval | = E1000_RXPBS_CFG_TS_EN ;
wr32 ( E1000_RXPBS , regval ) ;
}
2012-08-10 05:40:44 +00:00
}
/* enable/disable TX */
regval = rd32 ( E1000_TSYNCTXCTL ) ;
regval & = ~ E1000_TSYNCTXCTL_ENABLED ;
regval | = tsync_tx_ctl ;
wr32 ( E1000_TSYNCTXCTL , regval ) ;
/* enable/disable RX */
regval = rd32 ( E1000_TSYNCRXCTL ) ;
regval & = ~ ( E1000_TSYNCRXCTL_ENABLED | E1000_TSYNCRXCTL_TYPE_MASK ) ;
regval | = tsync_rx_ctl ;
wr32 ( E1000_TSYNCRXCTL , regval ) ;
/* define which PTP packets are time stamped */
wr32 ( E1000_TSYNCRXCFG , tsync_rx_cfg ) ;
/* define ethertype filter for timestamped packets */
if ( is_l2 )
wr32 ( E1000_ETQF ( 3 ) ,
( E1000_ETQF_FILTER_ENABLE | /* enable filter */
E1000_ETQF_1588 | /* enable timestamping */
ETH_P_1588 ) ) ; /* 1588 eth protocol type */
else
wr32 ( E1000_ETQF ( 3 ) , 0 ) ;
/* L4 Queue Filter[3]: filter by destination port and protocol */
if ( is_l4 ) {
u32 ftqf = ( IPPROTO_UDP /* UDP */
| E1000_FTQF_VF_BP /* VF not compared */
| E1000_FTQF_1588_TIME_STAMP /* Enable Timestamping */
| E1000_FTQF_MASK ) ; /* mask all inputs */
ftqf & = ~ E1000_FTQF_MASK_PROTO_BP ; /* enable protocol check */
2012-12-13 07:20:36 +00:00
wr32 ( E1000_IMIR ( 3 ) , htons ( PTP_EV_PORT ) ) ;
2012-08-10 05:40:44 +00:00
wr32 ( E1000_IMIREXT ( 3 ) ,
( E1000_IMIREXT_SIZE_BP | E1000_IMIREXT_CTRL_BP ) ) ;
if ( hw - > mac . type = = e1000_82576 ) {
/* enable source port check */
2012-12-13 07:20:36 +00:00
wr32 ( E1000_SPQF ( 3 ) , htons ( PTP_EV_PORT ) ) ;
2012-08-10 05:40:44 +00:00
ftqf & = ~ E1000_FTQF_MASK_SOURCE_PORT_BP ;
}
wr32 ( E1000_FTQF ( 3 ) , ftqf ) ;
} else {
wr32 ( E1000_FTQF ( 3 ) , E1000_FTQF_MASK ) ;
}
wrfl ( ) ;
/* clear TX/RX time stamp registers, just to be sure */
2012-08-17 01:30:37 +00:00
regval = rd32 ( E1000_TXSTMPL ) ;
2012-08-10 05:40:44 +00:00
regval = rd32 ( E1000_TXSTMPH ) ;
2012-08-17 01:30:37 +00:00
regval = rd32 ( E1000_RXSTMPL ) ;
2012-08-10 05:40:44 +00:00
regval = rd32 ( E1000_RXSTMPH ) ;
2014-06-05 07:25:10 +00:00
return 0 ;
}
/**
* igb_ptp_set_ts_config - set hardware time stamping config
* @ netdev :
* @ ifreq :
*
* */
int igb_ptp_set_ts_config ( struct net_device * netdev , struct ifreq * ifr )
{
struct igb_adapter * adapter = netdev_priv ( netdev ) ;
struct hwtstamp_config config ;
int err ;
if ( copy_from_user ( & config , ifr - > ifr_data , sizeof ( config ) ) )
return - EFAULT ;
err = igb_ptp_set_timestamp_mode ( adapter , & config ) ;
if ( err )
return err ;
/* save these settings for future reference */
memcpy ( & adapter - > tstamp_config , & config ,
sizeof ( adapter - > tstamp_config ) ) ;
return copy_to_user ( ifr - > ifr_data , & config , sizeof ( config ) ) ?
2012-08-10 05:40:44 +00:00
- EFAULT : 0 ;
2012-03-16 10:55:32 +00:00
}
void igb_ptp_init ( struct igb_adapter * adapter )
{
struct e1000_hw * hw = & adapter - > hw ;
2012-08-10 05:40:46 +00:00
struct net_device * netdev = adapter - > netdev ;
2014-11-21 20:51:26 +00:00
int i ;
2012-03-16 10:55:32 +00:00
switch ( hw - > mac . type ) {
2012-08-17 01:30:37 +00:00
case e1000_82576 :
snprintf ( adapter - > ptp_caps . name , 16 , " %pm " , netdev - > dev_addr ) ;
adapter - > ptp_caps . owner = THIS_MODULE ;
2013-03-20 09:06:34 +00:00
adapter - > ptp_caps . max_adj = 999999881 ;
2012-08-17 01:30:37 +00:00
adapter - > ptp_caps . n_ext_ts = 0 ;
adapter - > ptp_caps . pps = 0 ;
adapter - > ptp_caps . adjfreq = igb_ptp_adjfreq_82576 ;
adapter - > ptp_caps . adjtime = igb_ptp_adjtime_82576 ;
2015-03-29 23:12:03 +02:00
adapter - > ptp_caps . gettime64 = igb_ptp_gettime_82576 ;
adapter - > ptp_caps . settime64 = igb_ptp_settime_82576 ;
2014-05-16 07:21:13 +00:00
adapter - > ptp_caps . enable = igb_ptp_feature_enable ;
2012-08-17 01:30:37 +00:00
adapter - > cc . read = igb_ptp_read_82576 ;
2015-01-02 20:22:06 +01:00
adapter - > cc . mask = CYCLECOUNTER_MASK ( 64 ) ;
2012-08-17 01:30:37 +00:00
adapter - > cc . mult = 1 ;
adapter - > cc . shift = IGB_82576_TSYNC_SHIFT ;
/* Dial the nominal frequency. */
wr32 ( E1000_TIMINCA , INCPERIOD_82576 | INCVALUE_82576 ) ;
break ;
2012-03-16 10:55:32 +00:00
case e1000_82580 :
2013-04-18 22:21:30 +00:00
case e1000_i354 :
2012-08-17 01:30:37 +00:00
case e1000_i350 :
2012-08-10 05:40:46 +00:00
snprintf ( adapter - > ptp_caps . name , 16 , " %pm " , netdev - > dev_addr ) ;
2012-08-10 05:40:44 +00:00
adapter - > ptp_caps . owner = THIS_MODULE ;
adapter - > ptp_caps . max_adj = 62499999 ;
adapter - > ptp_caps . n_ext_ts = 0 ;
adapter - > ptp_caps . pps = 0 ;
adapter - > ptp_caps . adjfreq = igb_ptp_adjfreq_82580 ;
2012-08-17 01:30:37 +00:00
adapter - > ptp_caps . adjtime = igb_ptp_adjtime_82576 ;
2015-03-29 23:12:03 +02:00
adapter - > ptp_caps . gettime64 = igb_ptp_gettime_82576 ;
adapter - > ptp_caps . settime64 = igb_ptp_settime_82576 ;
2014-05-16 07:21:13 +00:00
adapter - > ptp_caps . enable = igb_ptp_feature_enable ;
2012-08-10 05:40:44 +00:00
adapter - > cc . read = igb_ptp_read_82580 ;
2015-01-02 20:22:06 +01:00
adapter - > cc . mask = CYCLECOUNTER_MASK ( IGB_NBITS_82580 ) ;
2012-08-10 05:40:44 +00:00
adapter - > cc . mult = 1 ;
adapter - > cc . shift = 0 ;
2012-03-16 10:55:32 +00:00
/* Enable the timer functions by clearing bit 31. */
wr32 ( E1000_TSAUXC , 0x0 ) ;
break ;
2012-08-17 01:30:37 +00:00
case e1000_i210 :
case e1000_i211 :
2014-11-21 20:51:26 +00:00
for ( i = 0 ; i < IGB_N_SDP ; i + + ) {
struct ptp_pin_desc * ppd = & adapter - > sdp_config [ i ] ;
snprintf ( ppd - > name , sizeof ( ppd - > name ) , " SDP%d " , i ) ;
ppd - > index = i ;
ppd - > func = PTP_PF_NONE ;
}
2012-08-10 05:40:46 +00:00
snprintf ( adapter - > ptp_caps . name , 16 , " %pm " , netdev - > dev_addr ) ;
2012-08-10 05:40:44 +00:00
adapter - > ptp_caps . owner = THIS_MODULE ;
2012-08-17 01:30:37 +00:00
adapter - > ptp_caps . max_adj = 62499999 ;
2014-11-21 20:51:26 +00:00
adapter - > ptp_caps . n_ext_ts = IGB_N_EXTTS ;
adapter - > ptp_caps . n_per_out = IGB_N_PEROUT ;
adapter - > ptp_caps . n_pins = IGB_N_SDP ;
2014-11-21 20:51:20 +00:00
adapter - > ptp_caps . pps = 1 ;
2014-11-21 20:51:26 +00:00
adapter - > ptp_caps . pin_config = adapter - > sdp_config ;
2012-08-17 01:30:37 +00:00
adapter - > ptp_caps . adjfreq = igb_ptp_adjfreq_82580 ;
adapter - > ptp_caps . adjtime = igb_ptp_adjtime_i210 ;
2015-03-29 23:12:03 +02:00
adapter - > ptp_caps . gettime64 = igb_ptp_gettime_i210 ;
adapter - > ptp_caps . settime64 = igb_ptp_settime_i210 ;
2014-11-21 20:51:20 +00:00
adapter - > ptp_caps . enable = igb_ptp_feature_enable_i210 ;
2014-11-21 20:51:26 +00:00
adapter - > ptp_caps . verify = igb_ptp_verify_pin ;
2012-08-17 01:30:37 +00:00
/* Enable the timer functions by clearing bit 31. */
wr32 ( E1000_TSAUXC , 0x0 ) ;
2012-03-16 10:55:32 +00:00
break ;
default :
adapter - > ptp_clock = NULL ;
return ;
}
wrfl ( ) ;
2012-08-17 01:30:37 +00:00
spin_lock_init ( & adapter - > tmreg_lock ) ;
INIT_WORK ( & adapter - > ptp_tx_work , igb_ptp_tx_work ) ;
2012-03-16 10:55:32 +00:00
2012-08-17 01:30:37 +00:00
/* Initialize the clock and overflow work for devices that need it. */
if ( ( hw - > mac . type = = e1000_i210 ) | | ( hw - > mac . type = = e1000_i211 ) ) {
2015-03-29 23:12:03 +02:00
struct timespec64 ts = ktime_to_timespec64 ( ktime_get_real ( ) ) ;
2012-03-16 10:55:32 +00:00
2012-08-17 01:30:37 +00:00
igb_ptp_settime_i210 ( & adapter - > ptp_caps , & ts ) ;
} else {
timecounter_init ( & adapter - > tc , & adapter - > cc ,
ktime_to_ns ( ktime_get_real ( ) ) ) ;
2012-03-16 10:55:32 +00:00
2012-08-17 01:30:37 +00:00
INIT_DELAYED_WORK ( & adapter - > ptp_overflow_work ,
igb_ptp_overflow_check ) ;
2012-08-18 07:26:33 +00:00
2012-08-17 01:30:37 +00:00
schedule_delayed_work ( & adapter - > ptp_overflow_work ,
IGB_SYSTIM_OVERFLOW_PERIOD ) ;
}
2012-03-16 10:55:32 +00:00
2012-08-18 07:26:33 +00:00
/* Initialize the time sync interrupts for devices that support it. */
if ( hw - > mac . type > = e1000_82580 ) {
2014-03-11 06:15:37 +00:00
wr32 ( E1000_TSIM , TSYNC_INTERRUPTS ) ;
2012-08-18 07:26:33 +00:00
wr32 ( E1000_IMS , E1000_IMS_TS ) ;
}
2014-06-05 07:25:10 +00:00
adapter - > tstamp_config . rx_filter = HWTSTAMP_FILTER_NONE ;
adapter - > tstamp_config . tx_type = HWTSTAMP_TX_OFF ;
2012-09-22 07:02:03 +00:00
adapter - > ptp_clock = ptp_clock_register ( & adapter - > ptp_caps ,
& adapter - > pdev - > dev ) ;
2012-03-16 10:55:32 +00:00
if ( IS_ERR ( adapter - > ptp_clock ) ) {
adapter - > ptp_clock = NULL ;
dev_err ( & adapter - > pdev - > dev , " ptp_clock_register failed \n " ) ;
2012-08-18 07:26:33 +00:00
} else {
2012-03-16 10:55:32 +00:00
dev_info ( & adapter - > pdev - > dev , " added PHC on %s \n " ,
adapter - > netdev - > name ) ;
2012-08-18 07:26:33 +00:00
adapter - > flags | = IGB_FLAG_PTP ;
}
2012-03-16 10:55:32 +00:00
}
2012-08-10 05:40:44 +00:00
/**
* igb_ptp_stop - Disable PTP device and stop the overflow check .
* @ adapter : Board private structure .
*
* This function stops the PTP support and cancels the delayed work .
* */
void igb_ptp_stop ( struct igb_adapter * adapter )
2012-03-16 10:55:32 +00:00
{
2012-05-16 01:46:00 +00:00
switch ( adapter - > hw . mac . type ) {
case e1000_82576 :
2012-08-18 07:26:33 +00:00
case e1000_82580 :
2013-04-18 22:21:30 +00:00
case e1000_i354 :
2012-08-18 07:26:33 +00:00
case e1000_i350 :
2012-08-10 05:40:44 +00:00
cancel_delayed_work_sync ( & adapter - > ptp_overflow_work ) ;
2012-05-16 01:46:00 +00:00
break ;
2012-08-18 07:26:33 +00:00
case e1000_i210 :
case e1000_i211 :
/* No delayed work to cancel. */
break ;
2012-05-16 01:46:00 +00:00
default :
return ;
}
2012-03-16 10:55:32 +00:00
2012-08-18 07:26:33 +00:00
cancel_work_sync ( & adapter - > ptp_tx_work ) ;
2012-12-13 07:20:37 +00:00
if ( adapter - > ptp_tx_skb ) {
dev_kfree_skb_any ( adapter - > ptp_tx_skb ) ;
adapter - > ptp_tx_skb = NULL ;
2014-03-15 14:55:32 +00:00
clear_bit_unlock ( __IGB_PTP_TX_IN_PROGRESS , & adapter - > state ) ;
2012-12-13 07:20:37 +00:00
}
2012-08-18 07:26:33 +00:00
2012-03-16 10:55:32 +00:00
if ( adapter - > ptp_clock ) {
ptp_clock_unregister ( adapter - > ptp_clock ) ;
dev_info ( & adapter - > pdev - > dev , " removed PHC on %s \n " ,
adapter - > netdev - > name ) ;
2012-08-18 07:26:33 +00:00
adapter - > flags & = ~ IGB_FLAG_PTP ;
2012-03-16 10:55:32 +00:00
}
}
2012-08-18 07:26:33 +00:00
/**
* igb_ptp_reset - Re - enable the adapter for PTP following a reset .
* @ adapter : Board private structure .
*
* This function handles the reset work required to re - enable the PTP device .
* */
void igb_ptp_reset ( struct igb_adapter * adapter )
{
struct e1000_hw * hw = & adapter - > hw ;
2014-11-21 20:51:15 +00:00
unsigned long flags ;
2012-08-18 07:26:33 +00:00
if ( ! ( adapter - > flags & IGB_FLAG_PTP ) )
return ;
2014-01-11 07:20:06 +00:00
/* reset the tstamp_config */
2014-06-05 07:25:10 +00:00
igb_ptp_set_timestamp_mode ( adapter , & adapter - > tstamp_config ) ;
2014-01-11 07:20:06 +00:00
2014-11-21 20:51:15 +00:00
spin_lock_irqsave ( & adapter - > tmreg_lock , flags ) ;
2012-08-18 07:26:33 +00:00
switch ( adapter - > hw . mac . type ) {
case e1000_82576 :
/* Dial the nominal frequency. */
wr32 ( E1000_TIMINCA , INCPERIOD_82576 | INCVALUE_82576 ) ;
break ;
case e1000_82580 :
2013-04-18 22:21:30 +00:00
case e1000_i354 :
2012-08-18 07:26:33 +00:00
case e1000_i350 :
case e1000_i210 :
case e1000_i211 :
wr32 ( E1000_TSAUXC , 0x0 ) ;
2014-11-21 20:51:26 +00:00
wr32 ( E1000_TSSDP , 0x0 ) ;
2014-03-11 06:15:37 +00:00
wr32 ( E1000_TSIM , TSYNC_INTERRUPTS ) ;
2012-08-18 07:26:33 +00:00
wr32 ( E1000_IMS , E1000_IMS_TS ) ;
break ;
default :
/* No work to do. */
2014-11-21 20:51:15 +00:00
goto out ;
2012-08-18 07:26:33 +00:00
}
2012-08-17 01:30:37 +00:00
/* Re-initialize the timer. */
if ( ( hw - > mac . type = = e1000_i210 ) | | ( hw - > mac . type = = e1000_i211 ) ) {
2015-03-29 23:12:03 +02:00
struct timespec64 ts = ktime_to_timespec64 ( ktime_get_real ( ) ) ;
2012-08-17 01:30:37 +00:00
2014-11-21 20:51:15 +00:00
igb_ptp_write_i210 ( adapter , & ts ) ;
2012-08-17 01:30:37 +00:00
} else {
timecounter_init ( & adapter - > tc , & adapter - > cc ,
ktime_to_ns ( ktime_get_real ( ) ) ) ;
}
2014-11-21 20:51:15 +00:00
out :
spin_unlock_irqrestore ( & adapter - > tmreg_lock , flags ) ;
2012-08-18 07:26:33 +00:00
}