11
11
#define ICE_DPLL_RCLK_NUM_PER_PF 1
12
12
#define ICE_DPLL_PIN_ESYNC_PULSE_HIGH_PERCENT 25
13
13
#define ICE_DPLL_PIN_GEN_RCLK_FREQ 1953125
14
+ #define ICE_DPLL_INPUT_REF_NUM 10
15
+ #define ICE_DPLL_PHASE_OFFSET_PERIOD 2
14
16
15
17
/**
16
18
* enum ice_dpll_pin_type - enumerate ice pin types:
@@ -587,6 +589,63 @@ static int ice_dpll_mode_get(const struct dpll_device *dpll, void *dpll_priv,
587
589
return 0 ;
588
590
}
589
591
592
+ /**
593
+ * ice_dpll_features_set - set dpll's features
594
+ * @dpll: registered dpll pointer
595
+ * @dpll_priv: private data pointer passed on dpll registration
596
+ * @features: mask of features to be set
597
+ * @extack: error reporting
598
+ *
599
+ * Dpll subsystem callback. Enable/disable features of dpll.
600
+ *
601
+ * Context: Acquires and releases pf->dplls.lock
602
+ * Return: 0 - success
603
+ */
604
+ static int ice_dpll_features_set (const struct dpll_device * dpll ,
605
+ void * dpll_priv , u32 features ,
606
+ struct netlink_ext_ack * extack )
607
+ {
608
+ struct ice_dpll * d = dpll_priv ;
609
+ struct ice_pf * pf = d -> pf ;
610
+
611
+ mutex_lock (& pf -> dplls .lock );
612
+ if (features & DPLL_FEATURES_ALL_INPUTS_PHASE_OFFSET_MONITOR )
613
+ d -> phase_offset_monitor_period = ICE_DPLL_PHASE_OFFSET_PERIOD ;
614
+ else
615
+ d -> phase_offset_monitor_period = 0 ;
616
+ mutex_unlock (& pf -> dplls .lock );
617
+
618
+ return 0 ;
619
+ }
620
+
621
+ /**
622
+ * ice_dpll_features_get - get dpll's features
623
+ * @dpll: registered dpll pointer
624
+ * @dpll_priv: private data pointer passed on dpll registration
625
+ * @features: on success holds currently enabled features of dpll
626
+ * @extack: error reporting
627
+ *
628
+ * Dpll subsystem callback. Provides currently enabled features of dpll.
629
+ *
630
+ * Context: Acquires and releases pf->dplls.lock
631
+ * Return: 0 - success
632
+ */
633
+ static int ice_dpll_features_get (const struct dpll_device * dpll ,
634
+ void * dpll_priv , u32 * features ,
635
+ struct netlink_ext_ack * extack )
636
+ {
637
+ struct ice_dpll * d = dpll_priv ;
638
+ struct ice_pf * pf = d -> pf ;
639
+
640
+ mutex_lock (& pf -> dplls .lock );
641
+ * features = 0 ;
642
+ if (d -> phase_offset_monitor_period )
643
+ * features |= DPLL_FEATURES_ALL_INPUTS_PHASE_OFFSET_MONITOR ;
644
+ mutex_unlock (& pf -> dplls .lock );
645
+
646
+ return 0 ;
647
+ }
648
+
590
649
/**
591
650
* ice_dpll_pin_state_set - set pin's state on dpll
592
651
* @pin: pointer to a pin
@@ -1093,12 +1152,15 @@ ice_dpll_phase_offset_get(const struct dpll_pin *pin, void *pin_priv,
1093
1152
const struct dpll_device * dpll , void * dpll_priv ,
1094
1153
s64 * phase_offset , struct netlink_ext_ack * extack )
1095
1154
{
1155
+ struct ice_dpll_pin * p = pin_priv ;
1096
1156
struct ice_dpll * d = dpll_priv ;
1097
1157
struct ice_pf * pf = d -> pf ;
1098
1158
1099
1159
mutex_lock (& pf -> dplls .lock );
1100
1160
if (d -> active_input == pin )
1101
1161
* phase_offset = d -> phase_offset * ICE_DPLL_PHASE_OFFSET_FACTOR ;
1162
+ else if (d -> phase_offset_monitor_period )
1163
+ * phase_offset = p -> phase_offset * ICE_DPLL_PHASE_OFFSET_FACTOR ;
1102
1164
else
1103
1165
* phase_offset = 0 ;
1104
1166
mutex_unlock (& pf -> dplls .lock );
@@ -1457,6 +1519,8 @@ static const struct dpll_pin_ops ice_dpll_output_ops = {
1457
1519
static const struct dpll_device_ops ice_dpll_ops = {
1458
1520
.lock_status_get = ice_dpll_lock_status_get ,
1459
1521
.mode_get = ice_dpll_mode_get ,
1522
+ .features_set = ice_dpll_features_set ,
1523
+ .features_get = ice_dpll_features_get ,
1460
1524
};
1461
1525
1462
1526
/**
@@ -1503,6 +1567,110 @@ static void ice_dpll_notify_changes(struct ice_dpll *d)
1503
1567
}
1504
1568
}
1505
1569
1570
+ /**
1571
+ * ice_dpll_is_pps_phase_monitor - check if dpll capable of phase offset monitor
1572
+ * @pf: pf private structure
1573
+ *
1574
+ * Check if firmware is capable of supporting admin command to provide
1575
+ * phase offset monitoring on all the input pins on PPS dpll.
1576
+ *
1577
+ * Returns:
1578
+ * * true - PPS dpll phase offset monitoring is supported
1579
+ * * false - PPS dpll phase offset monitoring is not supported
1580
+ */
1581
+ static bool ice_dpll_is_pps_phase_monitor (struct ice_pf * pf )
1582
+ {
1583
+ struct ice_cgu_input_measure meas [ICE_DPLL_INPUT_REF_NUM ];
1584
+ int ret = ice_aq_get_cgu_input_pin_measure (& pf -> hw , DPLL_TYPE_PPS , meas ,
1585
+ ARRAY_SIZE (meas ));
1586
+
1587
+ if (ret && pf -> hw .adminq .sq_last_status == ICE_AQ_RC_ESRCH )
1588
+ return false;
1589
+
1590
+ return true;
1591
+ }
1592
+
1593
+ /**
1594
+ * ice_dpll_pins_notify_mask - notify dpll subsystem about bulk pin changes
1595
+ * @pins: array of ice_dpll_pin pointers registered within dpll subsystem
1596
+ * @pin_num: number of pins
1597
+ * @phase_offset_ntf_mask: bitmask of pin indexes to notify
1598
+ *
1599
+ * Iterate over array of pins and call dpll subsystem pin notify if
1600
+ * corresponding pin index within bitmask is set.
1601
+ *
1602
+ * Context: Must be called while pf->dplls.lock is released.
1603
+ */
1604
+ static void ice_dpll_pins_notify_mask (struct ice_dpll_pin * pins ,
1605
+ u8 pin_num ,
1606
+ u32 phase_offset_ntf_mask )
1607
+ {
1608
+ int i = 0 ;
1609
+
1610
+ for (i = 0 ; i < pin_num ; i ++ )
1611
+ if (phase_offset_ntf_mask & (1 << i ))
1612
+ dpll_pin_change_ntf (pins [i ].pin );
1613
+ }
1614
+
1615
+ /**
1616
+ * ice_dpll_pps_update_phase_offsets - update phase offset measurements
1617
+ * @pf: pf private structure
1618
+ * @phase_offset_pins_updated: returns mask of updated input pin indexes
1619
+ *
1620
+ * Read phase offset measurements for PPS dpll device and store values in
1621
+ * input pins array. On success phase_offset_pins_updated - fills bitmask of
1622
+ * updated input pin indexes, pins shall be notified.
1623
+ *
1624
+ * Context: Shall be called with pf->dplls.lock being locked.
1625
+ * Returns:
1626
+ * * 0 - success or no data available
1627
+ * * negative - AQ failure
1628
+ */
1629
+ static int ice_dpll_pps_update_phase_offsets (struct ice_pf * pf ,
1630
+ u32 * phase_offset_pins_updated )
1631
+ {
1632
+ struct ice_cgu_input_measure meas [ICE_DPLL_INPUT_REF_NUM ];
1633
+ struct ice_dpll_pin * p ;
1634
+ s64 phase_offset , tmp ;
1635
+ int i , j , ret ;
1636
+
1637
+ * phase_offset_pins_updated = 0 ;
1638
+ ret = ice_aq_get_cgu_input_pin_measure (& pf -> hw , DPLL_TYPE_PPS , meas ,
1639
+ ARRAY_SIZE (meas ));
1640
+ if (ret && pf -> hw .adminq .sq_last_status == ICE_AQ_RC_EAGAIN ) {
1641
+ return 0 ;
1642
+ } else if (ret ) {
1643
+ dev_err (ice_pf_to_dev (pf ),
1644
+ "failed to get input pin measurements dpll=%d, ret=%d %s\n" ,
1645
+ DPLL_TYPE_PPS , ret ,
1646
+ ice_aq_str (pf -> hw .adminq .sq_last_status ));
1647
+ return ret ;
1648
+ }
1649
+ for (i = 0 ; i < pf -> dplls .num_inputs ; i ++ ) {
1650
+ p = & pf -> dplls .inputs [i ];
1651
+ phase_offset = 0 ;
1652
+ for (j = 0 ; j < ICE_CGU_INPUT_PHASE_OFFSET_BYTES ; j ++ ) {
1653
+ tmp = meas [i ].phase_offset [j ];
1654
+ #ifdef __LITTLE_ENDIAN
1655
+ phase_offset += tmp << 8 * j ;
1656
+ #else
1657
+ phase_offset += tmp << 8 *
1658
+ (ICE_CGU_INPUT_PHASE_OFFSET_BYTES - 1 - j );
1659
+ #endif
1660
+ }
1661
+ phase_offset = sign_extend64 (phase_offset , 47 );
1662
+ if (p -> phase_offset != phase_offset ) {
1663
+ dev_dbg (ice_pf_to_dev (pf ),
1664
+ "phase offset changed for pin:%d old:%llx, new:%llx\n" ,
1665
+ p -> idx , p -> phase_offset , phase_offset );
1666
+ p -> phase_offset = phase_offset ;
1667
+ * phase_offset_pins_updated |= (1 << i );
1668
+ }
1669
+ }
1670
+
1671
+ return 0 ;
1672
+ }
1673
+
1506
1674
/**
1507
1675
* ice_dpll_update_state - update dpll state
1508
1676
* @pf: pf private structure
@@ -1589,14 +1757,19 @@ static void ice_dpll_periodic_work(struct kthread_work *work)
1589
1757
struct ice_pf * pf = container_of (d , struct ice_pf , dplls );
1590
1758
struct ice_dpll * de = & pf -> dplls .eec ;
1591
1759
struct ice_dpll * dp = & pf -> dplls .pps ;
1760
+ u32 phase_offset_ntf = 0 ;
1592
1761
int ret = 0 ;
1593
1762
1594
1763
if (ice_is_reset_in_progress (pf -> state ))
1595
1764
goto resched ;
1596
1765
mutex_lock (& pf -> dplls .lock );
1766
+ d -> periodic_counter ++ ;
1597
1767
ret = ice_dpll_update_state (pf , de , false);
1598
1768
if (!ret )
1599
1769
ret = ice_dpll_update_state (pf , dp , false);
1770
+ if (!ret && dp -> phase_offset_monitor_period &&
1771
+ d -> periodic_counter % dp -> phase_offset_monitor_period == 0 )
1772
+ ret = ice_dpll_pps_update_phase_offsets (pf , & phase_offset_ntf );
1600
1773
if (ret ) {
1601
1774
d -> cgu_state_acq_err_num ++ ;
1602
1775
/* stop rescheduling this worker */
@@ -1611,6 +1784,9 @@ static void ice_dpll_periodic_work(struct kthread_work *work)
1611
1784
mutex_unlock (& pf -> dplls .lock );
1612
1785
ice_dpll_notify_changes (de );
1613
1786
ice_dpll_notify_changes (dp );
1787
+ if (phase_offset_ntf )
1788
+ ice_dpll_pins_notify_mask (d -> inputs , d -> num_inputs ,
1789
+ phase_offset_ntf );
1614
1790
1615
1791
resched :
1616
1792
/* Run twice a second or reschedule if update failed */
@@ -1987,6 +2163,7 @@ ice_dpll_deinit_dpll(struct ice_pf *pf, struct ice_dpll *d, bool cgu)
1987
2163
* @d: dpll to be initialized
1988
2164
* @cgu: if cgu is present and controlled by this NIC
1989
2165
* @type: type of dpll being initialized
2166
+ * @caps: bitmap of capabilities of dpll
1990
2167
*
1991
2168
* Allocate dpll instance for this board in dpll subsystem, if cgu is controlled
1992
2169
* by this NIC, register dpll with the callback ops.
@@ -1997,7 +2174,7 @@ ice_dpll_deinit_dpll(struct ice_pf *pf, struct ice_dpll *d, bool cgu)
1997
2174
*/
1998
2175
static int
1999
2176
ice_dpll_init_dpll (struct ice_pf * pf , struct ice_dpll * d , bool cgu ,
2000
- enum dpll_type type )
2177
+ enum dpll_type type , u32 caps )
2001
2178
{
2002
2179
u64 clock_id = pf -> dplls .clock_id ;
2003
2180
int ret ;
@@ -2012,7 +2189,8 @@ ice_dpll_init_dpll(struct ice_pf *pf, struct ice_dpll *d, bool cgu,
2012
2189
d -> pf = pf ;
2013
2190
if (cgu ) {
2014
2191
ice_dpll_update_state (pf , d , true);
2015
- ret = dpll_device_register (d -> dpll , type , 0 , & ice_dpll_ops , d );
2192
+ ret = dpll_device_register (d -> dpll , type , caps , & ice_dpll_ops ,
2193
+ d );
2016
2194
if (ret ) {
2017
2195
dpll_device_put (d -> dpll );
2018
2196
return ret ;
@@ -2426,10 +2604,12 @@ void ice_dpll_init(struct ice_pf *pf)
2426
2604
err = ice_dpll_init_info (pf , cgu );
2427
2605
if (err )
2428
2606
goto err_exit ;
2429
- err = ice_dpll_init_dpll (pf , & pf -> dplls .eec , cgu , DPLL_TYPE_EEC );
2607
+ err = ice_dpll_init_dpll (pf , & pf -> dplls .eec , cgu , DPLL_TYPE_EEC , 0 );
2430
2608
if (err )
2431
2609
goto deinit_info ;
2432
- err = ice_dpll_init_dpll (pf , & pf -> dplls .pps , cgu , DPLL_TYPE_PPS );
2610
+ err = ice_dpll_init_dpll (pf , & pf -> dplls .pps , cgu , DPLL_TYPE_PPS ,
2611
+ !ice_dpll_is_pps_phase_monitor (pf ) ? 0 :
2612
+ DPLL_FEATURES_ALL_INPUTS_PHASE_OFFSET_MONITOR );
2433
2613
if (err )
2434
2614
goto deinit_eec ;
2435
2615
err = ice_dpll_init_pins (pf , cgu );
0 commit comments