// SPDX-License-Identifier: GPL-2.0
/* Copyright(c) 2013 - 2018 Intel Corporation. */
#include "i40e.h"
#include <linux/ptp_classify.h>
#include <linux/posix-clock.h>
/* The XL710 timesync is very much like Intel's 82599 design when it comes to
* the fundamental clock design. However, the clock operations are much simpler
* in the XL710 because the device supports a full 64 bits of nanoseconds.
* Because the field is so wide, we can forgo the cycle counter and just
* operate with the nanosecond field directly without fear of overflow.
*
* Much like the 82599, the update period is dependent upon the link speed:
* At 40Gb, 25Gb, or no link, the period is 1.6ns.
* At 10Gb or 5Gb link, the period is multiplied by 2. (3.2ns)
* At 1Gb link, the period is multiplied by 20. (32ns)
* 1588 functionality is not supported at 100Mbps.
*/
#define I40E_PTP_40GB_INCVAL 0x0199999999ULL
#define I40E_PTP_10GB_INCVAL_MULT 2
#define I40E_PTP_5GB_INCVAL_MULT 2
#define I40E_PTP_1GB_INCVAL_MULT 20
#define I40E_ISGN 0x80000000
#define I40E_PRTTSYN_CTL1_TSYNTYPE_V1 BIT(I40E_PRTTSYN_CTL1_TSYNTYPE_SHIFT)
#define I40E_PRTTSYN_CTL1_TSYNTYPE_V2 (2 << \
I40E_PRTTSYN_CTL1_TSYNTYPE_SHIFT)
#define I40E_SUBDEV_ID_25G_PTP_PIN 0xB
enum i40e_ptp_pin {
SDP3_2 = 0,
SDP3_3,
GPIO_4
};
enum i40e_can_set_pins {
CANT_DO_PINS = -1,
CAN_SET_PINS,
CAN_DO_PINS
};
static struct ptp_pin_desc sdp_desc[] = {
/* name idx func chan */
{"SDP3_2", SDP3_2, PTP_PF_NONE, 0},
{"SDP3_3", SDP3_3, PTP_PF_NONE, 1},
{"GPIO_4", GPIO_4, PTP_PF_NONE, 1},
};
enum i40e_ptp_gpio_pin_state {
end = -2,
invalid,
off,
in_A,
in_B,
out_A,
out_B,
};
static const char * const i40e_ptp_gpio_pin_state2str[] = {
"off", "in_A", "in_B", "out_A", "out_B"
};
enum i40e_ptp_led_pin_state {
led_end = -2,
low = 0,
high,
};
struct i40e_ptp_pins_settings {
enum i40e_ptp_gpio_pin_state sdp3_2;
enum i40e_ptp_gpio_pin_state sdp3_3;
enum i40e_ptp_gpio_pin_state gpio_4;
enum i40e_ptp_led_pin_state led2_0;
enum i40e_ptp_led_pin_state led2_1;
enum i40e_ptp_led_pin_state led3_0;
enum i40e_ptp_led_pin_state led3_1;
};
static const struct i40e_ptp_pins_settings
i40e_ptp_pin_led_allowed_states[] = {
{off, off, off, high, high, high, high},
{off, in_A, off, high, high, high, low},
{off, out_A, off, high, low, high, high},
{off, in_B, off, high, high, high, low},
{off, out_B, off, high, low, high, high},
{in_A, off, off, high, high, high, low},
{in_A, in_B, off, high, high, high, low},
{in_A, out_B, off, high, low, high, high},
{out_A, off, off, high, low, high, high},
{out_A, in_B, off, high, low, high, high},
{in_B, off, off, high, high, high, low},
{in_B, in_A, off, high, high, high, low},
{in_B, out_A, off, high, low, high, high},
{out_B, off, off, high, low, high, high},
{out_B, in_A, off, high, low, high, high},
{off, off, in_A, high, high, low, high},
{off, out_A, in_A, high, low, low, high},
{off, in_B, in_A, high, high, low, low},
{off, out_B, in_A, high, low, low, high},
{out_A, off, in_A, high, low, low, high},
{out_A, in_B, in_A, high, low, low, high},
{in_B, off, in_A, high, high, low, low},
{in_B, out_A, in_A, high, low, low, high},
{out_B, off, in_A, high, low, low, high},
{off, off, out_A, low, high, high, high},
{off, in_A, out_A, low, high, high, low},
{off, in_B, out_A, low, high, high, low},
{off, out_B, out_A, low, low, high, high},
{in_A, off, out_A, low, high, high, low},
{in_A, in_B, out_A, low, high, high, low},
{in_A, out_B, out_A, low, low, high, high},
{in_B, off, out_A, low, high, high, low},
{in_B, in_A, out_A, low, high, high, low},
{out_B, off, out_A, low, low, high, high},
{out_B, in_A, out_A, low, low, high, high},
{off, off, in_B, high, high, low, high},
{off, in_A, in_B, high, high, low, low},
{off, out_A, in_B, high, low, low, high},
{off, out_B, in_B, high, low, low, high},
{in_A, off, in_B, high, high, low, low},
{in_A, out_B, in_B, high, low, low, high},
{out_A, off, in_B, high, low, low, high},
{out_B, off, in_B, high, low, low, high},
{out_B, in_A, in_B, high, low, low, high},
{off, off, out_B, low, high, high, high},
{off, in_A, out_B, low, high, high, low},
{off, out_A, out_B, low, low, high, high},
{off, in_B, out_B, low, high, high, low},
{in_A, off, out_B, low, high, high, low},
{in_A, in_B, out_B, low, high, high, low},
{out_A, off, out_B, low, low, high, high},
{out_A, in_B, out_B, low, low, high, high},
{in_B, off, out_B, low, high, high, low},
{in_B, in_A, out_B, low, high, high, low},
{in_B, out_A, out_B, low, low, high, high},
{end, end, end, led_end, led_end, led_end, led_end}
};
static int i40e_ptp_set_pins(struct i40e_pf *pf,
struct i40e_ptp_pins_settings *pins);
/**
* i40e_ptp_extts0_work - workqueue task function
* @work: workqueue task structure
*
* Service for PTP external clock event
**/
static void i40e_ptp_extts0_work(struct work_stru
|