RE: [patch v2 net-next] net: phy: micrel: PEROUT support in lan8814

From: Divya.Koppera
Date: Mon Sep 26 2022 - 00:46:59 EST


> -----Original Message-----
> From: Divya Koppera <Divya.Koppera@xxxxxxxxxxxxx>
> Sent: Friday, September 16, 2022 5:48 PM
> To: andrew@xxxxxxx; hkallweit1@xxxxxxxxx; linux@xxxxxxxxxxxxxxx;
> davem@xxxxxxxxxxxxx; edumazet@xxxxxxxxxx; kuba@xxxxxxxxxx;
> pabeni@xxxxxxxxxx; netdev@xxxxxxxxxxxxxxx; linux-
> kernel@xxxxxxxxxxxxxxx; richardcochran@xxxxxxxxx
> Cc: UNGLinuxDriver <UNGLinuxDriver@xxxxxxxxxxxxx>
> Subject: [patch v2 net-next] net: phy: micrel: PEROUT support in lan8814
>
> Support Periodic output from lan8814 gpio
>
> Signed-off-by: Divya Koppera <Divya.Koppera@xxxxxxxxxxxxx>
> ---
> v1 -> v2
> - Adding PTP maintainer
> - Given line space between Macro and function.
> ---
> drivers/net/phy/micrel.c | 408
> ++++++++++++++++++++++++++++++++++++---
> 1 file changed, 384 insertions(+), 24 deletions(-)
>

Gentle ping.

> diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c index
> 7b8c5c8d013e..91e5bf04f652 100644
> --- a/drivers/net/phy/micrel.c
> +++ b/drivers/net/phy/micrel.c
> @@ -243,6 +243,50 @@
> #define PS_TO_REG 200
> #define FIFO_SIZE 8
>
> +#define LAN8814_GPIO_EN1 0x20
> +#define LAN8814_GPIO_EN2 0x21
> +#define LAN8814_GPIO_DIR1 0x22
> +#define LAN8814_GPIO_DIR2 0x23
> +#define LAN8814_GPIO_BUF1 0x24
> +#define LAN8814_GPIO_BUF2 0x25
> +
> +#define LAN8814_GPIO_EN_ADDR(pin) ((pin) > 15 ?
> LAN8814_GPIO_EN1 : LAN8814_GPIO_EN2)
> +#define LAN8814_GPIO_EN_BIT_(pin) BIT(pin)
> +#define LAN8814_GPIO_DIR_ADDR(pin) ((pin) > 15 ?
> LAN8814_GPIO_DIR1 : LAN8814_GPIO_DIR2)
> +#define LAN8814_GPIO_DIR_BIT_(pin) BIT(pin)
> +#define LAN8814_GPIO_BUF_ADDR(pin) ((pin) > 15 ?
> LAN8814_GPIO_BUF1 : LAN8814_GPIO_BUF2)
> +#define LAN8814_GPIO_BUF_BIT_(pin) BIT(pin)
> +
> +#define LAN8814_N_GPIO 24
> +
> +/* The number of periodic outputs is limited by number of
> + * PTP clock event channels
> + */
> +#define LAN8814_PTP_N_PEROUT 2
> +
> +/* LAN8814_TARGET_BUFF: Seconds difference between LTC and target
> register.
> + * Should be more than 1 sec.
> + */
> +#define LAN8814_TARGET_BUFF 3
> +
> +#define LAN8814_PTP_GENERAL_CONFIG 0x0201
> +#define LAN8814_PTP_GENERAL_CONFIG_LTC_EVENT_X_MASK_(channel)
> \
> + ((channel) ? GENMASK(11, 8) : GENMASK(7,
> 4))
> +
> +#define LAN8814_PTP_GENERAL_CONFIG_LTC_EVENT_X_SET_(channel,
> value) \
> + (((value) & 0xF) << (4 + ((channel) << 2)))
> +#define LAN8814_PTP_GENERAL_CONFIG_RELOAD_ADD_X_(channel)
> ((channel) ? BIT(2) : BIT(0))
> +#define LAN8814_PTP_GENERAL_CONFIG_POLARITY_X_(channel)
> ((channel) ? BIT(3) : BIT(1))
> +
> +#define LAN8814_PTP_CLOCK_TARGET_SEC_HI_X(channel)
> ((channel) ? 0x21F : 0x215)
> +#define LAN8814_PTP_CLOCK_TARGET_SEC_LO_X(channel)
> ((channel) ? 0x220 : 0x216)
> +#define LAN8814_PTP_CLOCK_TARGET_NS_HI_X(channel)
> ((channel) ? 0x221 : 0x217)
> +#define LAN8814_PTP_CLOCK_TARGET_NS_LO_X(channel)
> ((channel) ? 0x222 : 0x218)
> +#define LAN8814_PTP_CLOCK_TARGET_RELOAD_SEC_HI_X(channel)
> ((channel) ? 0x223 : 0x219)
> +#define LAN8814_PTP_CLOCK_TARGET_RELOAD_SEC_LO_X(channel)
> ((channel) ? 0x224 : 0x21A)
> +#define LAN8814_PTP_CLOCK_TARGET_RELOAD_NS_HI_X(channel)
> ((channel) ? 0x225 : 0x21B)
> +#define LAN8814_PTP_CLOCK_TARGET_RELOAD_NS_LO_X(channel)
> ((channel) ? 0x226 : 0x21C)
> +
> struct kszphy_hw_stat {
> const char *string;
> u8 reg;
> @@ -267,13 +311,10 @@ struct lan8814_shared_priv {
> struct phy_device *phydev;
> struct ptp_clock *ptp_clock;
> struct ptp_clock_info ptp_clock_info;
> + struct ptp_pin_desc *pin_config;
> + s8 gpio_pin;
>
> - /* Reference counter to how many ports in the package are enabling
> the
> - * timestamping
> - */
> - u8 ref;
> -
> - /* Lock for ptp_clock and ref */
> + /* Lock for ptp_clock and gpio_pin */
> struct mutex shared_lock;
> };
>
> @@ -2091,8 +2132,6 @@ static int lan8814_hwtstamp(struct
> mii_timestamper *mii_ts, struct ifreq *ifr) {
> struct kszphy_ptp_priv *ptp_priv =
> container_of(mii_ts, struct kszphy_ptp_priv,
> mii_ts);
> - struct phy_device *phydev = ptp_priv->phydev;
> - struct lan8814_shared_priv *shared = phydev->shared->priv;
> struct lan8814_ptp_rx_ts *rx_ts, *tmp;
> struct hwtstamp_config config;
> int txcfg = 0, rxcfg = 0;
> @@ -2155,20 +2194,6 @@ static int lan8814_hwtstamp(struct
> mii_timestamper *mii_ts, struct ifreq *ifr)
> else
> lan8814_config_ts_intr(ptp_priv->phydev, false);
>
> - mutex_lock(&shared->shared_lock);
> - if (config.rx_filter != HWTSTAMP_FILTER_NONE)
> - shared->ref++;
> - else
> - shared->ref--;
> -
> - if (shared->ref)
> - lanphy_write_page_reg(ptp_priv->phydev, 4,
> PTP_CMD_CTL,
> - PTP_CMD_CTL_PTP_ENABLE_);
> - else
> - lanphy_write_page_reg(ptp_priv->phydev, 4,
> PTP_CMD_CTL,
> - PTP_CMD_CTL_PTP_DISABLE_);
> - mutex_unlock(&shared->shared_lock);
> -
> /* In case of multiple starts and stops, these needs to be cleared */
> list_for_each_entry_safe(rx_ts, tmp, &ptp_priv->rx_ts_list, list) {
> list_del(&rx_ts->list);
> @@ -2325,6 +2350,293 @@ static int lan8814_ptpci_gettime64(struct
> ptp_clock_info *ptpci,
> return 0;
> }
>
> +static void lan8814_gpio_release(struct lan8814_shared_priv *shared, s8
> +gpio_pin) {
> + struct phy_device *phydev = shared->phydev;
> + int val;
> +
> + /* Disable gpio alternate function, 1: select as gpio, 0: select alt func
> */
> + val = lanphy_read_page_reg(phydev, 4,
> LAN8814_GPIO_EN_ADDR(gpio_pin));
> + val |= LAN8814_GPIO_EN_BIT_(gpio_pin);
> + lanphy_write_page_reg(phydev, 4,
> LAN8814_GPIO_EN_ADDR(gpio_pin), val);
> +
> + val = lanphy_read_page_reg(phydev, 4,
> LAN8814_GPIO_DIR_ADDR(gpio_pin));
> + val &= ~LAN8814_GPIO_DIR_BIT_(gpio_pin);
> + lanphy_write_page_reg(phydev, 4,
> LAN8814_GPIO_DIR_ADDR(gpio_pin),
> +val);
> +
> + val = lanphy_read_page_reg(phydev, 4,
> LAN8814_GPIO_BUF_ADDR(gpio_pin));
> + val &= ~LAN8814_GPIO_BUF_BIT_(gpio_pin);
> + lanphy_write_page_reg(phydev, 4,
> LAN8814_GPIO_BUF_ADDR(gpio_pin),
> +val); }
> +
> +static void lan8814_gpio_init(struct lan8814_shared_priv *shared) {
> + struct phy_device *phydev = shared->phydev;
> +
> + lanphy_write_page_reg(phydev, 4, LAN8814_GPIO_DIR1, 0);
> + lanphy_write_page_reg(phydev, 4, LAN8814_GPIO_DIR2, 0);
> + lanphy_write_page_reg(phydev, 4, LAN8814_GPIO_EN1, 0);
> +
> + /* By default disabling alternate function to GPIO 0 and 1
> + * i.e., 1: select as gpio, 0: select alt func
> + */
> + lanphy_write_page_reg(phydev, 4, LAN8814_GPIO_EN2, 0x3);
> + lanphy_write_page_reg(phydev, 4, LAN8814_GPIO_BUF1, 0);
> + lanphy_write_page_reg(phydev, 4, LAN8814_GPIO_BUF2, 0); }
> +
> +static void lan8814_gpio_config_ptp_out(struct lan8814_shared_priv
> *shared,
> + s8 gpio_pin)
> +{
> + struct phy_device *phydev = shared->phydev;
> + int val;
> +
> + /* Set as gpio output */
> + val = lanphy_read_page_reg(phydev, 4,
> LAN8814_GPIO_DIR_ADDR(gpio_pin));
> + val |= LAN8814_GPIO_DIR_BIT_(gpio_pin);
> + lanphy_write_page_reg(phydev, 4,
> LAN8814_GPIO_DIR_ADDR(gpio_pin),
> +val);
> +
> + /* Enable gpio 0:for alternate function, 1:gpio */
> + val = lanphy_read_page_reg(phydev, 4,
> LAN8814_GPIO_EN_ADDR(gpio_pin));
> + val &= ~LAN8814_GPIO_EN_BIT_(gpio_pin);
> + lanphy_write_page_reg(phydev, 4,
> LAN8814_GPIO_EN_ADDR(gpio_pin), val);
> +
> + /* Set buffer type to push pull */
> + val = lanphy_read_page_reg(phydev, 4,
> LAN8814_GPIO_BUF_ADDR(gpio_pin));
> + val |= LAN8814_GPIO_BUF_BIT_(gpio_pin);
> + lanphy_write_page_reg(phydev, 4,
> LAN8814_GPIO_BUF_ADDR(gpio_pin),
> +val); }
> +
> +static void lan8814_set_clock_target(struct phy_device *phydev, s8
> gpio_pin,
> + s64 start_sec, u32 start_nsec) {
> + if (gpio_pin < 0)
> + return;
> +
> + /* Set the start time */
> + lanphy_write_page_reg(phydev, 4,
> LAN8814_PTP_CLOCK_TARGET_SEC_LO_X(gpio_pin),
> + lower_16_bits(start_sec));
> + lanphy_write_page_reg(phydev, 4,
> LAN8814_PTP_CLOCK_TARGET_SEC_HI_X(gpio_pin),
> + upper_16_bits(start_sec));
> +
> + lanphy_write_page_reg(phydev, 4,
> LAN8814_PTP_CLOCK_TARGET_NS_LO_X(gpio_pin),
> + lower_16_bits(start_nsec));
> + lanphy_write_page_reg(phydev, 4,
> LAN8814_PTP_CLOCK_TARGET_NS_HI_X(gpio_pin),
> + upper_16_bits(start_nsec) & 0x3fff); }
> +
> +static void lan8814_set_clock_reload(struct phy_device *phydev, s8
> gpio_pin,
> + s64 period_sec, u32 period_nsec) {
> + lanphy_write_page_reg(phydev, 4,
> LAN8814_PTP_CLOCK_TARGET_RELOAD_SEC_LO_X(gpio_pin),
> + lower_16_bits(period_sec));
> + lanphy_write_page_reg(phydev, 4,
> LAN8814_PTP_CLOCK_TARGET_RELOAD_SEC_HI_X(gpio_pin),
> + upper_16_bits(period_sec));
> +
> + lanphy_write_page_reg(phydev, 4,
> LAN8814_PTP_CLOCK_TARGET_RELOAD_NS_LO_X(gpio_pin),
> + lower_16_bits(period_nsec));
> + lanphy_write_page_reg(phydev, 4,
> LAN8814_PTP_CLOCK_TARGET_RELOAD_NS_HI_X(gpio_pin),
> + upper_16_bits(period_nsec) & 0x3fff); }
> +
> +static void lan8814_general_event_config(struct phy_device *phydev, s8
> +gpio_pin, int pulse_width) {
> + u16 general_config;
> +
> + general_config = lanphy_read_page_reg(phydev, 4,
> LAN8814_PTP_GENERAL_CONFIG);
> + general_config &=
> ~(LAN8814_PTP_GENERAL_CONFIG_LTC_EVENT_X_MASK_(gpio_pin));
> + general_config |=
> LAN8814_PTP_GENERAL_CONFIG_LTC_EVENT_X_SET_(gpio_pin,
> +
> pulse_width);
> + general_config &=
> ~(LAN8814_PTP_GENERAL_CONFIG_RELOAD_ADD_X_(gpio_pin));
> + general_config |=
> LAN8814_PTP_GENERAL_CONFIG_POLARITY_X_(gpio_pin);
> + lanphy_write_page_reg(phydev, 4,
> LAN8814_PTP_GENERAL_CONFIG,
> +general_config); }
> +
> +static void lan8814_ptp_perout_off(struct lan8814_shared_priv *shared,
> + s8 gpio_pin)
> +{
> + struct phy_device *phydev = shared->phydev;
> + u16 general_config;
> +
> + /* Set target to too far in the future, effectively disabling it */
> + lan8814_set_clock_target(phydev, gpio_pin, 0xFFFFFFFF, 0);
> +
> + general_config = lanphy_read_page_reg(phydev, 4,
> LAN8814_PTP_GENERAL_CONFIG);
> + general_config |=
> LAN8814_PTP_GENERAL_CONFIG_RELOAD_ADD_X_(gpio_pin);
> + lanphy_write_page_reg(phydev, 4,
> LAN8814_PTP_GENERAL_CONFIG,
> +general_config);
> +
> + lan8814_gpio_release(shared, gpio_pin); }
> +
> +#define LAN88XX_PTP_GENERAL_CONFIG_LTC_EVENT_200MS_ 13
> +#define LAN88XX_PTP_GENERAL_CONFIG_LTC_EVENT_100MS_ 12
> +#define LAN88XX_PTP_GENERAL_CONFIG_LTC_EVENT_50MS_ 11
> +#define LAN88XX_PTP_GENERAL_CONFIG_LTC_EVENT_10MS_ 10
> +#define LAN88XX_PTP_GENERAL_CONFIG_LTC_EVENT_5MS_ 9
> +#define LAN88XX_PTP_GENERAL_CONFIG_LTC_EVENT_1MS_ 8
> +#define LAN88XX_PTP_GENERAL_CONFIG_LTC_EVENT_500US_ 7
> +#define LAN88XX_PTP_GENERAL_CONFIG_LTC_EVENT_100US_ 6
> +#define LAN88XX_PTP_GENERAL_CONFIG_LTC_EVENT_50US_ 5
> +#define LAN88XX_PTP_GENERAL_CONFIG_LTC_EVENT_10US_ 4
> +#define LAN88XX_PTP_GENERAL_CONFIG_LTC_EVENT_5US_ 3
> +#define LAN88XX_PTP_GENERAL_CONFIG_LTC_EVENT_1US_ 2
> +#define LAN88XX_PTP_GENERAL_CONFIG_LTC_EVENT_500NS_ 1
> +#define LAN88XX_PTP_GENERAL_CONFIG_LTC_EVENT_100NS_ 0
> +
> +static int lan88xx_get_pulsewidth(struct phy_device *phydev,
> + struct ptp_perout_request
> *perout_request,
> + int *pulse_width)
> +{
> + struct timespec64 ts_period;
> + s64 ts_on_nsec, period_nsec;
> + struct timespec64 ts_on;
> +
> + ts_period.tv_sec = perout_request->period.sec;
> + ts_period.tv_nsec = perout_request->period.nsec;
> +
> + ts_on.tv_sec = perout_request->on.sec;
> + ts_on.tv_nsec = perout_request->on.nsec;
> + ts_on_nsec = timespec64_to_ns(&ts_on);
> + period_nsec = timespec64_to_ns(&ts_period);
> +
> + if (period_nsec < 200) {
> + phydev_warn(phydev, "perout period too small, minimum is
> 200ns\n");
> + return -EOPNOTSUPP;
> + }
> +
> + if (ts_on_nsec >= period_nsec) {
> + phydev_warn(phydev, "pulse width must be smaller than
> period\n");
> + return -EINVAL;
> + }
> +
> + switch (ts_on_nsec) {
> + case 200000000:
> + *pulse_width =
> LAN88XX_PTP_GENERAL_CONFIG_LTC_EVENT_200MS_;
> + break;
> + case 100000000:
> + *pulse_width =
> LAN88XX_PTP_GENERAL_CONFIG_LTC_EVENT_100MS_;
> + break;
> + case 50000000:
> + *pulse_width =
> LAN88XX_PTP_GENERAL_CONFIG_LTC_EVENT_50MS_;
> + break;
> + case 10000000:
> + *pulse_width =
> LAN88XX_PTP_GENERAL_CONFIG_LTC_EVENT_10MS_;
> + break;
> + case 5000000:
> + *pulse_width =
> LAN88XX_PTP_GENERAL_CONFIG_LTC_EVENT_5MS_;
> + break;
> + case 1000000:
> + *pulse_width =
> LAN88XX_PTP_GENERAL_CONFIG_LTC_EVENT_1MS_;
> + break;
> + case 500000:
> + *pulse_width =
> LAN88XX_PTP_GENERAL_CONFIG_LTC_EVENT_500US_;
> + break;
> + case 100000:
> + *pulse_width =
> LAN88XX_PTP_GENERAL_CONFIG_LTC_EVENT_100US_;
> + break;
> + case 50000:
> + *pulse_width =
> LAN88XX_PTP_GENERAL_CONFIG_LTC_EVENT_50US_;
> + break;
> + case 10000:
> + *pulse_width =
> LAN88XX_PTP_GENERAL_CONFIG_LTC_EVENT_10US_;
> + break;
> + case 5000:
> + *pulse_width =
> LAN88XX_PTP_GENERAL_CONFIG_LTC_EVENT_5US_;
> + break;
> + case 1000:
> + *pulse_width =
> LAN88XX_PTP_GENERAL_CONFIG_LTC_EVENT_1US_;
> + break;
> + case 500:
> + *pulse_width =
> LAN88XX_PTP_GENERAL_CONFIG_LTC_EVENT_500NS_;
> + break;
> + case 100:
> + *pulse_width =
> LAN88XX_PTP_GENERAL_CONFIG_LTC_EVENT_100NS_;
> + break;
> + default:
> + phydev_warn(phydev, "Using default pulse width of
> 100ns\n");
> + *pulse_width =
> LAN88XX_PTP_GENERAL_CONFIG_LTC_EVENT_100NS_;
> + break;
> + }
> + return 0;
> +}
> +
> +static int lan8814_ptp_perout(struct lan8814_shared_priv *shared, int on,
> + struct ptp_perout_request *perout_request) {
> + unsigned int perout_ch = perout_request->index;
> + struct phy_device *phydev = shared->phydev;
> + int pulse_width;
> + int ret;
> +
> + /* Reject requests with unsupported flags */
> + if (perout_request->flags & ~PTP_PEROUT_DUTY_CYCLE)
> + return -EOPNOTSUPP;
> +
> + mutex_lock(&shared->shared_lock);
> + shared->gpio_pin = ptp_find_pin(shared->ptp_clock,
> PTP_PF_PEROUT,
> + perout_ch);
> + if (shared->gpio_pin < 0) {
> + mutex_unlock(&shared->shared_lock);
> + return -EBUSY;
> + }
> +
> + if (!on) {
> + lan8814_ptp_perout_off(shared, shared->gpio_pin);
> + shared->gpio_pin = -1;
> + mutex_unlock(&shared->shared_lock);
> + return 0;
> + }
> +
> + ret = lan88xx_get_pulsewidth(phydev, perout_request,
> &pulse_width);
> + if (ret < 0) {
> + shared->gpio_pin = -1;
> + mutex_unlock(&shared->shared_lock);
> + return ret;
> + }
> +
> + /* Configure to pulse every period */
> + lan8814_general_event_config(phydev, shared->gpio_pin,
> pulse_width);
> + lan8814_set_clock_target(phydev, shared->gpio_pin,
> perout_request->start.sec,
> + perout_request->start.nsec);
> + lan8814_set_clock_reload(phydev, shared->gpio_pin,
> perout_request->period.sec,
> + perout_request->period.nsec);
> + lan8814_gpio_config_ptp_out(shared, shared->gpio_pin);
> + mutex_unlock(&shared->shared_lock);
> +
> + return 0;
> +}
> +
> +static int lan8814_ptpci_verify(struct ptp_clock_info *ptp, unsigned int pin,
> + enum ptp_pin_function func, unsigned int
> chan) {
> + if (chan != 0 || (pin != 0 && pin != 1))
> + return -1;
> +
> + switch (func) {
> + case PTP_PF_NONE:
> + case PTP_PF_PEROUT:
> + break;
> + default:
> + return -1;
> + }
> +
> + return 0;
> +}
> +
> +static int lan8814_ptpci_enable(struct ptp_clock_info *ptpci,
> + struct ptp_clock_request *request, int on) {
> + struct lan8814_shared_priv *shared = container_of(ptpci, struct
> lan8814_shared_priv,
> + ptp_clock_info);
> +
> + switch (request->type) {
> + case PTP_CLK_REQ_PEROUT:
> + return lan8814_ptp_perout(shared, on, &request->perout);
> + default:
> + return -EINVAL;
> + }
> +}
> +
> static int lan8814_ptpci_settime64(struct ptp_clock_info *ptpci,
> const struct timespec64 *ts)
> {
> @@ -2333,6 +2645,8 @@ static int lan8814_ptpci_settime64(struct
> ptp_clock_info *ptpci,
> struct phy_device *phydev = shared->phydev;
>
> mutex_lock(&shared->shared_lock);
> + lan8814_set_clock_target(phydev, shared->gpio_pin,
> + ts->tv_sec + LAN8814_TARGET_BUFF, 0);
> lan8814_ptp_clock_set(phydev, ts->tv_sec, ts->tv_nsec);
> mutex_unlock(&shared->shared_lock);
>
> @@ -2342,12 +2656,16 @@ static int lan8814_ptpci_settime64(struct
> ptp_clock_info *ptpci, static void lan8814_ptp_clock_step(struct phy_device
> *phydev,
> s64 time_step_ns)
> {
> + struct lan8814_shared_priv *shared = phydev->shared->priv;
> + int gpio_pin = shared->gpio_pin;
> u32 nano_seconds_step;
> u64 abs_time_step_ns;
> u32 unsigned_seconds;
> u32 nano_seconds;
> u32 remainder;
> s32 seconds;
> + u32 tar_sec;
> + u32 nsec;
>
> if (time_step_ns > 15000000000LL) {
> /* convert to clock set */
> @@ -2359,6 +2677,8 @@ static void lan8814_ptp_clock_step(struct
> phy_device *phydev,
> unsigned_seconds++;
> nano_seconds -= 1000000000;
> }
> + lan8814_set_clock_target(phydev, gpio_pin,
> + unsigned_seconds +
> LAN8814_TARGET_BUFF, 0);
> lan8814_ptp_clock_set(phydev, unsigned_seconds,
> nano_seconds);
> return;
> } else if (time_step_ns < -15000000000LL) { @@ -2374,6 +2694,8 @@
> static void lan8814_ptp_clock_step(struct phy_device *phydev,
> nano_seconds += 1000000000;
> }
> nano_seconds -= nano_seconds_step;
> + lan8814_set_clock_target(phydev, gpio_pin,
> + unsigned_seconds +
> LAN8814_TARGET_BUFF, 0);
> lan8814_ptp_clock_set(phydev, unsigned_seconds,
> nano_seconds);
> return;
> @@ -2428,6 +2750,11 @@ static void lan8814_ptp_clock_step(struct
> phy_device *phydev,
> PTP_LTC_STEP_ADJ_DIR_ |
> adjustment_value_hi);
> seconds -= ((s32)adjustment_value);
> +
> + lan8814_ptp_clock_get(phydev,
> &unsigned_seconds, &nsec);
> + tar_sec = unsigned_seconds - adjustment_value;
> + lan8814_set_clock_target(phydev, gpio_pin,
> + tar_sec +
> LAN8814_TARGET_BUFF, 0);
> } else {
> u32 adjustment_value = (u32)(-seconds);
> u16 adjustment_value_lo, adjustment_value_hi;
> @@ -2443,6 +2770,11 @@ static void lan8814_ptp_clock_step(struct
> phy_device *phydev,
> lanphy_write_page_reg(phydev, 4,
> PTP_LTC_STEP_ADJ_HI,
> adjustment_value_hi);
> seconds += ((s32)adjustment_value);
> +
> + lan8814_ptp_clock_get(phydev,
> &unsigned_seconds, &nsec);
> + tar_sec = unsigned_seconds + adjustment_value;
> + lan8814_set_clock_target(phydev, gpio_pin,
> + tar_sec +
> LAN8814_TARGET_BUFF, 0);
> }
> lanphy_write_page_reg(phydev, 4, PTP_CMD_CTL,
> PTP_CMD_CTL_PTP_LTC_STEP_SEC_);
> @@ -2783,11 +3115,16 @@ static void lan8814_ptp_init(struct phy_device
> *phydev)
> ptp_priv->mii_ts.ts_info = lan8814_ts_info;
>
> phydev->mii_ts = &ptp_priv->mii_ts;
> +
> + /* Enable ptp to run LTC clock for ptp and gpio 1PPS operation */
> + lanphy_write_page_reg(ptp_priv->phydev, 4, PTP_CMD_CTL,
> + PTP_CMD_CTL_PTP_ENABLE_);
> }
>
> static int lan8814_ptp_probe_once(struct phy_device *phydev) {
> struct lan8814_shared_priv *shared = phydev->shared->priv;
> + int i;
>
> if (!IS_ENABLED(CONFIG_PTP_1588_CLOCK) ||
> !IS_ENABLED(CONFIG_NETWORK_PHY_TIMESTAMPING))
> @@ -2796,19 +3133,41 @@ static int lan8814_ptp_probe_once(struct
> phy_device *phydev)
> /* Initialise shared lock for clock*/
> mutex_init(&shared->shared_lock);
>
> + shared->pin_config = devm_kmalloc_array(&phydev->mdio.dev,
> + LAN8814_N_GPIO,
> + sizeof(*shared->pin_config),
> + GFP_KERNEL);
> + if (!shared->pin_config)
> + return -ENOMEM;
> +
> + for (i = 0; i < LAN8814_N_GPIO; i++) {
> + struct ptp_pin_desc *ptp_pin = &shared->pin_config[i];
> +
> + memset(ptp_pin, 0, sizeof(*ptp_pin));
> + snprintf(ptp_pin->name,
> + sizeof(ptp_pin->name), "lan8814_ptp_pin_%02d", i);
> + ptp_pin->index = i;
> + ptp_pin->func = PTP_PF_NONE;
> + }
> +
> + shared->gpio_pin = -1;
> +
> shared->ptp_clock_info.owner = THIS_MODULE;
> snprintf(shared->ptp_clock_info.name, 30, "%s", phydev->drv-
> >name);
> shared->ptp_clock_info.max_adj = 31249999;
> shared->ptp_clock_info.n_alarm = 0;
> shared->ptp_clock_info.n_ext_ts = 0;
> - shared->ptp_clock_info.n_pins = 0;
> + shared->ptp_clock_info.n_pins = LAN8814_N_GPIO;
> shared->ptp_clock_info.pps = 0;
> - shared->ptp_clock_info.pin_config = NULL;
> + shared->ptp_clock_info.pin_config = shared->pin_config;
> + shared->ptp_clock_info.n_per_out = LAN8814_PTP_N_PEROUT;
> shared->ptp_clock_info.adjfine = lan8814_ptpci_adjfine;
> shared->ptp_clock_info.adjtime = lan8814_ptpci_adjtime;
> shared->ptp_clock_info.gettime64 = lan8814_ptpci_gettime64;
> shared->ptp_clock_info.settime64 = lan8814_ptpci_settime64;
> shared->ptp_clock_info.getcrosststamp = NULL;
> + shared->ptp_clock_info.enable = lan8814_ptpci_enable;
> + shared->ptp_clock_info.verify = lan8814_ptpci_verify;
>
> shared->ptp_clock = ptp_clock_register(&shared->ptp_clock_info,
> &phydev->mdio.dev);
> @@ -2829,6 +3188,7 @@ static int lan8814_ptp_probe_once(struct
> phy_device *phydev)
> lanphy_write_page_reg(phydev, 4, PTP_OPERATING_MODE,
> PTP_OPERATING_MODE_STANDALONE_);
>
> + lan8814_gpio_init(shared);
> return 0;
> }
>
> --
> 2.17.1