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

From: Divya Koppera
Date: Fri Sep 16 2022 - 08:18:25 EST


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(-)

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