From nobody Fri Apr 3 03:48:31 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 58C83C6FA8B for ; Fri, 16 Sep 2022 11:20:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230517AbiIPLUy (ORCPT ); Fri, 16 Sep 2022 07:20:54 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46374 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230172AbiIPLUw (ORCPT ); Fri, 16 Sep 2022 07:20:52 -0400 Received: from esa.microchip.iphmx.com (esa.microchip.iphmx.com [68.232.153.233]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B8F6D659F4; Fri, 16 Sep 2022 04:20:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=microchip.com; i=@microchip.com; q=dns/txt; s=mchp; t=1663327251; x=1694863251; h=from:to:cc:subject:date:message-id:mime-version; bh=8l4RriQD/hwVHdbftRRsu89aSeMB6zhFaUrHxy3UrpY=; b=yLMFpH882bISfGi5i55GNMxbKpxIKbNyiOi3z0FHHdzGO7aALLgISyAU pRvHN18H4R8pY+7YhFmW1pRh4ypPb/N7G+4wHusXK+WABfXve38oLeVF/ sPQxjOwq2LOestT0DVwP+WhPhsF8tKsbKcfFycepT+/xV32BZ6oo/cBdg NZzLPUdmKSTbzl+G7SPl2s0dgcm+3aFgKuP7/NDt2wxmlSI/of3DaSR3j Ixb6s+WHMPdU6x15TpVKJdZum1sXZq3Oy8Jnj5HFVX7jxh2VGt8pW1GkV JtNBpsycjR+bSoSNtD2l/vJ2n2DBJEsTha61CHtIlb/oGBVqz5ait3KRQ g==; X-IronPort-AV: E=Sophos;i="5.93,320,1654585200"; d="scan'208";a="180674086" Received: from unknown (HELO email.microchip.com) ([170.129.1.10]) by esa5.microchip.iphmx.com with ESMTP/TLS/AES256-SHA256; 16 Sep 2022 04:20:50 -0700 Received: from chn-vm-ex04.mchp-main.com (10.10.85.152) by chn-vm-ex03.mchp-main.com (10.10.85.151) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.12; Fri, 16 Sep 2022 04:20:50 -0700 Received: from training-HP-280-G1-MT-PC.microchip.com (10.10.115.15) by chn-vm-ex04.mchp-main.com (10.10.85.152) with Microsoft SMTP Server id 15.1.2507.12 via Frontend Transport; Fri, 16 Sep 2022 04:20:46 -0700 From: Divya Koppera To: , , , , , , , , CC: Subject: [patch net-next] net: phy: micrel: PEROUT support in lan8814 Date: Fri, 16 Sep 2022 16:50:42 +0530 Message-ID: <20220916112042.16501-1-Divya.Koppera@microchip.com> X-Mailer: git-send-email 2.17.1 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Support Periodic output from lan8814 gpio Signed-off-by: Divya Koppera --- drivers/net/phy/micrel.c | 407 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 383 insertions(+), 24 deletions(-) diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c index 7b8c5c8d013e..1f2eaceaef16 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 =20 +#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 : LAN88= 14_GPIO_DIR2) +#define LAN8814_GPIO_DIR_BIT_(pin) BIT(pin) +#define LAN8814_GPIO_BUF_ADDR(pin) ((pin) > 15 ? LAN8814_GPIO_BUF1 : LAN88= 14_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 : 0= x215) +#define LAN8814_PTP_CLOCK_TARGET_SEC_LO_X(channel) ((channel) ? 0x220 : 0= x216) +#define LAN8814_PTP_CLOCK_TARGET_NS_HI_X(channel) ((channel) ? 0x221 : 0x= 217) +#define LAN8814_PTP_CLOCK_TARGET_NS_LO_X(channel) ((channel) ? 0x222 : 0x= 218) +#define LAN8814_PTP_CLOCK_TARGET_RELOAD_SEC_HI_X(channel) ((channel) ? 0x2= 23 : 0x219) +#define LAN8814_PTP_CLOCK_TARGET_RELOAD_SEC_LO_X(channel) ((channel) ? 0x2= 24 : 0x21A) +#define LAN8814_PTP_CLOCK_TARGET_RELOAD_NS_HI_X(channel) ((channel) ? 0x22= 5 : 0x21B) +#define LAN8814_PTP_CLOCK_TARGET_RELOAD_NS_LO_X(channel) ((channel) ? 0x22= 6 : 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; =20 - /* 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; }; =20 @@ -2091,8 +2132,6 @@ static int lan8814_hwtstamp(struct mii_timestamper *m= ii_ts, struct ifreq *ifr) { struct kszphy_ptp_priv *ptp_priv =3D container_of(mii_ts, struct kszphy_ptp_priv, mii_ts); - struct phy_device *phydev =3D ptp_priv->phydev; - struct lan8814_shared_priv *shared =3D phydev->shared->priv; struct lan8814_ptp_rx_ts *rx_ts, *tmp; struct hwtstamp_config config; int txcfg =3D 0, rxcfg =3D 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); =20 - mutex_lock(&shared->shared_lock); - if (config.rx_filter !=3D 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,292 @@ static int lan8814_ptpci_gettime64(struct ptp_clock= _info *ptpci, return 0; } =20 +static void lan8814_gpio_release(struct lan8814_shared_priv *shared, s8 gp= io_pin) +{ + struct phy_device *phydev =3D shared->phydev; + int val; + + /* Disable gpio alternate function, 1: select as gpio, 0: select alt func= */ + val =3D lanphy_read_page_reg(phydev, 4, LAN8814_GPIO_EN_ADDR(gpio_pin)); + val |=3D LAN8814_GPIO_EN_BIT_(gpio_pin); + lanphy_write_page_reg(phydev, 4, LAN8814_GPIO_EN_ADDR(gpio_pin), val); + + val =3D lanphy_read_page_reg(phydev, 4, LAN8814_GPIO_DIR_ADDR(gpio_pin)); + val &=3D ~LAN8814_GPIO_DIR_BIT_(gpio_pin); + lanphy_write_page_reg(phydev, 4, LAN8814_GPIO_DIR_ADDR(gpio_pin), val); + + val =3D lanphy_read_page_reg(phydev, 4, LAN8814_GPIO_BUF_ADDR(gpio_pin)); + val &=3D ~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 =3D 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 =3D shared->phydev; + int val; + + /* Set as gpio output */ + val =3D lanphy_read_page_reg(phydev, 4, LAN8814_GPIO_DIR_ADDR(gpio_pin)); + val |=3D 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 =3D lanphy_read_page_reg(phydev, 4, LAN8814_GPIO_EN_ADDR(gpio_pin)); + val &=3D ~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 =3D lanphy_read_page_reg(phydev, 4, LAN8814_GPIO_BUF_ADDR(gpio_pin)); + val |=3D 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_pi= n, + 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_p= in), + lower_16_bits(start_sec)); + lanphy_write_page_reg(phydev, 4, LAN8814_PTP_CLOCK_TARGET_SEC_HI_X(gpio_p= in), + upper_16_bits(start_sec)); + + lanphy_write_page_reg(phydev, 4, LAN8814_PTP_CLOCK_TARGET_NS_LO_X(gpio_pi= n), + lower_16_bits(start_nsec)); + lanphy_write_page_reg(phydev, 4, LAN8814_PTP_CLOCK_TARGET_NS_HI_X(gpio_pi= n), + upper_16_bits(start_nsec) & 0x3fff); +} + +static void lan8814_set_clock_reload(struct phy_device *phydev, s8 gpio_pi= n, + 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 gpi= o_pin, int pulse_width) +{ + u16 general_config; + + general_config =3D lanphy_read_page_reg(phydev, 4, LAN8814_PTP_GENERAL_CO= NFIG); + general_config &=3D ~(LAN8814_PTP_GENERAL_CONFIG_LTC_EVENT_X_MASK_(gpio_p= in)); + general_config |=3D LAN8814_PTP_GENERAL_CONFIG_LTC_EVENT_X_SET_(gpio_pin, + pulse_width); + general_config &=3D ~(LAN8814_PTP_GENERAL_CONFIG_RELOAD_ADD_X_(gpio_pin)); + general_config |=3D LAN8814_PTP_GENERAL_CONFIG_POLARITY_X_(gpio_pin); + lanphy_write_page_reg(phydev, 4, LAN8814_PTP_GENERAL_CONFIG, general_conf= ig); +} + +static void lan8814_ptp_perout_off(struct lan8814_shared_priv *shared, + s8 gpio_pin) +{ + struct phy_device *phydev =3D 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 =3D lanphy_read_page_reg(phydev, 4, LAN8814_PTP_GENERAL_CO= NFIG); + general_config |=3D LAN8814_PTP_GENERAL_CONFIG_RELOAD_ADD_X_(gpio_pin); + lanphy_write_page_reg(phydev, 4, LAN8814_PTP_GENERAL_CONFIG, general_conf= ig); + + 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 =3D perout_request->period.sec; + ts_period.tv_nsec =3D perout_request->period.nsec; + + ts_on.tv_sec =3D perout_request->on.sec; + ts_on.tv_nsec =3D perout_request->on.nsec; + ts_on_nsec =3D timespec64_to_ns(&ts_on); + period_nsec =3D 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 >=3D period_nsec) { + phydev_warn(phydev, "pulse width must be smaller than period\n"); + return -EINVAL; + } + + switch (ts_on_nsec) { + case 200000000: + *pulse_width =3D LAN88XX_PTP_GENERAL_CONFIG_LTC_EVENT_200MS_; + break; + case 100000000: + *pulse_width =3D LAN88XX_PTP_GENERAL_CONFIG_LTC_EVENT_100MS_; + break; + case 50000000: + *pulse_width =3D LAN88XX_PTP_GENERAL_CONFIG_LTC_EVENT_50MS_; + break; + case 10000000: + *pulse_width =3D LAN88XX_PTP_GENERAL_CONFIG_LTC_EVENT_10MS_; + break; + case 5000000: + *pulse_width =3D LAN88XX_PTP_GENERAL_CONFIG_LTC_EVENT_5MS_; + break; + case 1000000: + *pulse_width =3D LAN88XX_PTP_GENERAL_CONFIG_LTC_EVENT_1MS_; + break; + case 500000: + *pulse_width =3D LAN88XX_PTP_GENERAL_CONFIG_LTC_EVENT_500US_; + break; + case 100000: + *pulse_width =3D LAN88XX_PTP_GENERAL_CONFIG_LTC_EVENT_100US_; + break; + case 50000: + *pulse_width =3D LAN88XX_PTP_GENERAL_CONFIG_LTC_EVENT_50US_; + break; + case 10000: + *pulse_width =3D LAN88XX_PTP_GENERAL_CONFIG_LTC_EVENT_10US_; + break; + case 5000: + *pulse_width =3D LAN88XX_PTP_GENERAL_CONFIG_LTC_EVENT_5US_; + break; + case 1000: + *pulse_width =3D LAN88XX_PTP_GENERAL_CONFIG_LTC_EVENT_1US_; + break; + case 500: + *pulse_width =3D LAN88XX_PTP_GENERAL_CONFIG_LTC_EVENT_500NS_; + break; + case 100: + *pulse_width =3D LAN88XX_PTP_GENERAL_CONFIG_LTC_EVENT_100NS_; + break; + default: + phydev_warn(phydev, "Using default pulse width of 100ns\n"); + *pulse_width =3D 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 =3D perout_request->index; + struct phy_device *phydev =3D 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 =3D 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 =3D -1; + mutex_unlock(&shared->shared_lock); + return 0; + } + + ret =3D lan88xx_get_pulsewidth(phydev, perout_request, &pulse_width); + if (ret < 0) { + shared->gpio_pin =3D -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 p= in, + enum ptp_pin_function func, unsigned int chan) +{ + if (chan !=3D 0 || (pin !=3D 0 && pin !=3D 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 =3D 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 +2644,8 @@ static int lan8814_ptpci_settime64(struct ptp_clock_i= nfo *ptpci, struct phy_device *phydev =3D shared->phydev; =20 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); =20 @@ -2342,12 +2655,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 =3D phydev->shared->priv; + int gpio_pin =3D 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; =20 if (time_step_ns > 15000000000LL) { /* convert to clock set */ @@ -2359,6 +2676,8 @@ static void lan8814_ptp_clock_step(struct phy_device = *phydev, unsigned_seconds++; nano_seconds -=3D 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 +2693,8 @@ static void lan8814_ptp_clock_step(struct phy_device = *phydev, nano_seconds +=3D 1000000000; } nano_seconds -=3D 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 +2749,11 @@ static void lan8814_ptp_clock_step(struct phy_device= *phydev, PTP_LTC_STEP_ADJ_DIR_ | adjustment_value_hi); seconds -=3D ((s32)adjustment_value); + + lan8814_ptp_clock_get(phydev, &unsigned_seconds, &nsec); + tar_sec =3D unsigned_seconds - adjustment_value; + lan8814_set_clock_target(phydev, gpio_pin, + tar_sec + LAN8814_TARGET_BUFF, 0); } else { u32 adjustment_value =3D (u32)(-seconds); u16 adjustment_value_lo, adjustment_value_hi; @@ -2443,6 +2769,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 +=3D ((s32)adjustment_value); + + lan8814_ptp_clock_get(phydev, &unsigned_seconds, &nsec); + tar_sec =3D 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 +3114,16 @@ static void lan8814_ptp_init(struct phy_device *phy= dev) ptp_priv->mii_ts.ts_info =3D lan8814_ts_info; =20 phydev->mii_ts =3D &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_); } =20 static int lan8814_ptp_probe_once(struct phy_device *phydev) { struct lan8814_shared_priv *shared =3D phydev->shared->priv; + int i; =20 if (!IS_ENABLED(CONFIG_PTP_1588_CLOCK) || !IS_ENABLED(CONFIG_NETWORK_PHY_TIMESTAMPING)) @@ -2796,19 +3132,41 @@ static int lan8814_ptp_probe_once(struct phy_device= *phydev) /* Initialise shared lock for clock*/ mutex_init(&shared->shared_lock); =20 + shared->pin_config =3D devm_kmalloc_array(&phydev->mdio.dev, + LAN8814_N_GPIO, + sizeof(*shared->pin_config), + GFP_KERNEL); + if (!shared->pin_config) + return -ENOMEM; + + for (i =3D 0; i < LAN8814_N_GPIO; i++) { + struct ptp_pin_desc *ptp_pin =3D &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 =3D i; + ptp_pin->func =3D PTP_PF_NONE; + } + + shared->gpio_pin =3D -1; + shared->ptp_clock_info.owner =3D THIS_MODULE; snprintf(shared->ptp_clock_info.name, 30, "%s", phydev->drv->name); shared->ptp_clock_info.max_adj =3D 31249999; shared->ptp_clock_info.n_alarm =3D 0; shared->ptp_clock_info.n_ext_ts =3D 0; - shared->ptp_clock_info.n_pins =3D 0; + shared->ptp_clock_info.n_pins =3D LAN8814_N_GPIO; shared->ptp_clock_info.pps =3D 0; - shared->ptp_clock_info.pin_config =3D NULL; + shared->ptp_clock_info.pin_config =3D shared->pin_config; + shared->ptp_clock_info.n_per_out =3D LAN8814_PTP_N_PEROUT; shared->ptp_clock_info.adjfine =3D lan8814_ptpci_adjfine; shared->ptp_clock_info.adjtime =3D lan8814_ptpci_adjtime; shared->ptp_clock_info.gettime64 =3D lan8814_ptpci_gettime64; shared->ptp_clock_info.settime64 =3D lan8814_ptpci_settime64; shared->ptp_clock_info.getcrosststamp =3D NULL; + shared->ptp_clock_info.enable =3D lan8814_ptpci_enable; + shared->ptp_clock_info.verify =3D lan8814_ptpci_verify; =20 shared->ptp_clock =3D ptp_clock_register(&shared->ptp_clock_info, &phydev->mdio.dev); @@ -2829,6 +3187,7 @@ static int lan8814_ptp_probe_once(struct phy_device *= phydev) lanphy_write_page_reg(phydev, 4, PTP_OPERATING_MODE, PTP_OPERATING_MODE_STANDALONE_); =20 + lan8814_gpio_init(shared); return 0; } =20 --=20 2.17.1