From: Przemyslaw Korba
Add control for E825 input pins: phy clock recovery and clock 1588.
E825 does not provide control over platform level DPLL but it
provides control over PHY clock recovery, and PTP/timestamp driven
inputs for platform level DPLL.
Introduce a software controlled layer of abstraction to:
- create a DPLL of type EEC for E825c,
- create recovered clock pin for each PF, and control them through
writing to registers,
- create pin to control clock 1588 for PF0, and control it through
writing to registers.
Reviewed-by: Milena Olech
Co-developed-by: Grzegorz Nitka
Signed-off-by: Grzegorz Nitka
Signed-off-by: Przemyslaw Korba
---
v4:
- rebased
- fix docstring for ice_dpll_cfg_synce_ethdiv_e825c (removed 'divider'
argument)
v3:
- rebased
- removed netdev reference in 1588 pin initialization
- improved error path in ice_dpll_init_pins
v2:
- rebased, addressed comments from v1 (kdoc updated, removed unrelated
code changes, fixed undefined 'ret' code in error patchs, use feature
flag instead of MAC type chacking)
- use ptp.ptp_port to create pins indexes instead of PF ID
- removed CLK_OUT/output pins definitions as unused
- removed redundant dpll_netdev_pin_set call on 1588 pin
- removed checkpatch warning about SET_PIN_STATE macro (parenthesis
added)
---
drivers/net/ethernet/intel/ice/ice_dpll.c | 863 ++--
drivers/net/ethernet/intel/ice/ice_dpll.h | 26 +-
drivers/net/ethernet/intel/ice/ice_lib.c| 3 +
drivers/net/ethernet/intel/ice/ice_ptp_hw.c | 35 +-
drivers/net/ethernet/intel/ice/ice_ptp_hw.h | 2 +
drivers/net/ethernet/intel/ice/ice_tspll.h | 7 +
drivers/net/ethernet/intel/ice/ice_type.h | 6 +
7 files changed, 879 insertions(+), 63 deletions(-)
diff --git a/drivers/net/ethernet/intel/ice/ice_dpll.c
b/drivers/net/ethernet/intel/ice/ice_dpll.c
index 53b54e395a2e..e0ba78d7e17e 100644
--- a/drivers/net/ethernet/intel/ice/ice_dpll.c
+++ b/drivers/net/ethernet/intel/ice/ice_dpll.c
@@ -9,6 +9,7 @@
#define ICE_CGU_STATE_ACQ_ERR_THRESHOLD50
#define ICE_DPLL_PIN_IDX_INVALID 0xff
#define ICE_DPLL_RCLK_NUM_PER_PF 1
+#define ICE_DPLL_PIN_1588_NUM 1
#define ICE_DPLL_PIN_ESYNC_PULSE_HIGH_PERCENT 25
#define ICE_DPLL_PIN_GEN_RCLK_FREQ 1953125
#define ICE_DPLL_PIN_PRIO_OUTPUT 0xff
@@ -74,6 +75,7 @@ static const char * const pin_type_name[] = {
static const char * const ice_dpll_sw_pin_sma[] = { "SMA1", "SMA2" };
static const char * const ice_dpll_sw_pin_ufl[] = { "U.FL1", "U.FL2" };
+static const char ice_dpll_pin_1588[] = "pin_1588";
static const struct dpll_pin_frequency ice_esync_range[] = {
DPLL_PIN_FREQUENCY_RANGE(0, DPLL_PIN_FREQUENCY_1_HZ),
@@ -528,6 +530,117 @@ ice_dpll_pin_disable(struct ice_hw *hw, struct
ice_dpll_pin *pin,
return ret;
}
+/**
+ * ice_dpll_rclk_update_e825c - updates the state of rclk pin on e825c device
+ * @pf: private board struct
+ * @pin: pointer to a pin
+ *
+ * Update struct holding pin states info, states are separate for each parent
+ *
+ * Context: Called under pf->dplls.lock
+ * Return:
+ * * 0 - OK
+ * * negative - error
+ */
+static int ice_dpll_rclk_update_e825c(struct ice_pf *pf,
+ struct ice_dpll_pin *pin)
+{
+ u8 rclk_bits;
+ int err;
+ u32 reg;
+
+ if (pf->dplls.rclk.num_parents > ICE_SYNCE_CLK_NUM)
+ return -EINVAL;
+
+ err = ice_read_cgu_reg(&pf->hw, ICE_CGU_R10, ®);
+ if (err)
+ return err;
+ rclk_bits = FIELD_GET(ICE_CGU_R10_SYNCE_S_REF_CLK, reg);
+ SET_PIN_STATE(pin, ICE_SYNCE_CLK0, rclk_bits ==
+(pf->ptp.port.port_num + ICE_CGU_BYPASS_MUX_OFFSET_E825C));
+
+ err = ice_read_cgu_reg(&pf->hw, ICE_CGU_R11, ®);
+ if (err)
+ return err;
+ rclk_bits = FIELD_GET(ICE_CGU_R11_SYNCE_S_BYP_CLK, reg);
+ SET_PIN_STATE(pin, ICE_SYNCE_CLK1, rclk_bits ==
+(pf->ptp.port.port_num + ICE_CGU_BYPASS_MUX_OFFSET_E825C));
+ return 0;
+}
+
+/**
+ * ice_dpll_rclk_update - updates the state of rclk pin on a device
+ * @pf: private board struct
+ * @pin: pointer to a pin
+ * @port_num: port number
+ *
+ * Update struct holding pin states info, states are separate for each parent
+ *
+ * Context: Called under pf->dplls.lock
+ * Return:
+ * * 0 - OK
+ * * negative - error
+ */
+static int ice_dpll_rclk_update(struct ice_pf *pf, struct ice_dpll_pin *pin,
+ u8 port_num)
+{
+ int ret;
+
+ for (u8 parent = 0; parent < pf->dplls.rclk.num_parents; parent++) {
+ ret = ice_aq_get_phy_rec_clk_out(&pf->hw, &parent, &port_num,
+&pin->flags[parent], NULL);
+ if (ret)
+ return ret;
+ SET_PIN_STATE(pin, parent,
+ ICE_AQC_GET_PHY_REC_CLK_OUT_OUT_EN &
+