lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Mon, 26 Sep 2022 04:46:35 +0000
From:   <Divya.Koppera@...rochip.com>
To:     <Divya.Koppera@...rochip.com>, <andrew@...n.ch>,
        <hkallweit1@...il.com>, <linux@...linux.org.uk>,
        <davem@...emloft.net>, <edumazet@...gle.com>, <kuba@...nel.org>,
        <pabeni@...hat.com>, <netdev@...r.kernel.org>,
        <linux-kernel@...r.kernel.org>, <richardcochran@...il.com>
CC:     <UNGLinuxDriver@...rochip.com>
Subject: RE: [patch v2 net-next] net: phy: micrel: PEROUT support in lan8814

> -----Original Message-----
> From: Divya Koppera <Divya.Koppera@...rochip.com>
> Sent: Friday, September 16, 2022 5:48 PM
> To: andrew@...n.ch; hkallweit1@...il.com; linux@...linux.org.uk;
> davem@...emloft.net; edumazet@...gle.com; kuba@...nel.org;
> pabeni@...hat.com; netdev@...r.kernel.org; linux-
> kernel@...r.kernel.org; richardcochran@...il.com
> Cc: UNGLinuxDriver <UNGLinuxDriver@...rochip.com>
> 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@...rochip.com>
> ---
> 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

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ