diff options
author | Piotr Kwapulinski <piotr.kwapulinski@intel.com> | 2021-07-20 16:23:48 -0700 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2021-07-21 08:53:54 -0700 |
commit | 1050713026a08d605b61f039700b67aab646371f (patch) | |
tree | ba7a1f34ecac3467d4684f1238db4c44aeba8c4f /drivers/net/ethernet/intel/i40e/i40e_main.c | |
parent | ac6627a28dbfb5d96736544a00c3938fa7ea6dfb (diff) |
i40e: add support for PTP external synchronization clock
Add support for external synchronization clock via GPIOs.
1PPS signals are handled via the dedicated 3 GPIOs: SDP3_2,
SDP3_3 and GPIO_4.
Previously it was not possible to use the external PTP
synchronization clock.
All possible HW configurations are supported.
SDP3_2, SDP3_3, GPIO_4
off, off, off
off, in_A, off
off, out_A, off
off, in_B, off
off, out_B, off
in_A, off, off
in_A, in_B, off
in_A, out_B, off
out_A, off, off
out_A, in_B, off
in_B, off, off
in_B, in_A, off
in_B, out_A, off
out_B, off, off
out_B, in_A, off
off, off, in_A
off, out_A, in_A
off, in_B, in_A
off, out_B, in_A
out_A, off, in_A
out_A, in_B, in_A
in_B, off, in_A
in_B, out_A, in_A
out_B, off, in_A
off, off, out_A
off, in_A, out_A
off, in_B, out_A
off, out_B, out_A
in_A, off, out_A
in_A, in_B, out_A
in_A, out_B, out_A
in_B, off, out_A
in_B, in_A, out_A
out_B, off, out_A
out_B, in_A, out_A
off, off, in_B
off, in_A, in_B
off, out_A, in_B
off, out_B, in_B
in_A, off, in_B
in_A, out_B, in_B
out_A, off, in_B
out_B, off, in_B
out_B, in_A, in_B
off, off, out_B
off, in_A, out_B
off, out_A, out_B
off, in_B, out_B
in_A, off, out_B
in_A, in_B, out_B
out_A, off, out_B
out_A, in_B, out_B
in_B, off, out_B
in_B, in_A, out_B
in_B, out_A, out_B
Tested with oscilloscope, 1PPS generator and ts2phc.
Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
Reviewed-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
Signed-off-by: Piotr Kwapulinski <piotr.kwapulinski@intel.com>
Tested-by: Ashish K <ashishx.k@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/intel/i40e/i40e_main.c')
-rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e_main.c | 28 |
1 files changed, 24 insertions, 4 deletions
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 861e59a350bd..53c1fbeee62a 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -4079,10 +4079,13 @@ static irqreturn_t i40e_intr(int irq, void *data) if (icr0 & I40E_PFINT_ICR0_TIMESYNC_MASK) { u32 prttsyn_stat = rd32(hw, I40E_PRTTSYN_STAT_0); - if (prttsyn_stat & I40E_PRTTSYN_STAT_0_TXTIME_MASK) { - icr0 &= ~I40E_PFINT_ICR0_ENA_TIMESYNC_MASK; + if (prttsyn_stat & I40E_PRTTSYN_STAT_0_EVENT0_MASK) + schedule_work(&pf->ptp_extts0_work); + + if (prttsyn_stat & I40E_PRTTSYN_STAT_0_TXTIME_MASK) i40e_ptp_tx_hwtstamp(pf); - } + + icr0 &= ~I40E_PFINT_ICR0_ENA_TIMESYNC_MASK; } /* If a critical error is pending we have no choice but to reset the @@ -15168,6 +15171,22 @@ err_switch_setup: } /** + * i40e_set_subsystem_device_id - set subsystem device id + * @hw: pointer to the hardware info + * + * Set PCI subsystem device id either from a pci_dev structure or + * a specific FW register. + **/ +static inline void i40e_set_subsystem_device_id(struct i40e_hw *hw) +{ + struct pci_dev *pdev = ((struct i40e_pf *)hw->back)->pdev; + + hw->subsystem_device_id = pdev->subsystem_device ? + pdev->subsystem_device : + (ushort)(rd32(hw, I40E_PFPCI_SUBSYSID) & USHRT_MAX); +} + +/** * i40e_probe - Device initialization routine * @pdev: PCI device information struct * @ent: entry in i40e_pci_tbl @@ -15262,7 +15281,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) hw->device_id = pdev->device; pci_read_config_byte(pdev, PCI_REVISION_ID, &hw->revision_id); hw->subsystem_vendor_id = pdev->subsystem_vendor; - hw->subsystem_device_id = pdev->subsystem_device; + i40e_set_subsystem_device_id(hw); hw->bus.device = PCI_SLOT(pdev->devfn); hw->bus.func = PCI_FUNC(pdev->devfn); hw->bus.bus_id = pdev->bus->number; @@ -15442,6 +15461,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (is_valid_ether_addr(hw->mac.port_addr)) pf->hw_features |= I40E_HW_PORT_ID_VALID; + i40e_ptp_alloc_pins(pf); pci_set_drvdata(pdev, pf); pci_save_state(pdev); |