Commit 9c477032 authored by Dmitry Bezrukov's avatar Dmitry Bezrukov Committed by David S. Miller

net: aquantia: add support for PIN funcs

Depending on FW configuration we can manage from 0 to 3 PINs for periodic output
and from 0 to 1 ext ts PIN for getting TS for external event.

Ext TS PIN functionality is implemented via periodic timestamps polling
directly from PHY, because right now there is now way to receive the
PIN trigger interrupt from phy.

The polling interval is 15 milliseconds.
Co-developed-by: default avatarEgor Pomozov <epomozov@marvell.com>
Signed-off-by: default avatarEgor Pomozov <epomozov@marvell.com>
Co-developed-by: default avatarPavel Belous <pavel.belous@aquantia.com>
Signed-off-by: default avatarPavel Belous <pavel.belous@aquantia.com>
Signed-off-by: default avatarDmitry Bezrukov <dmitry.bezrukov@aquantia.com>
Signed-off-by: default avatarIgor Russkikh <igor.russkikh@aquantia.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent dbcd6806
......@@ -259,6 +259,16 @@ struct aq_hw_ops {
int (*hw_set_sys_clock)(struct aq_hw_s *self, u64 time, u64 ts);
int (*hw_ts_to_sys_clock)(struct aq_hw_s *self, u64 ts, u64 *time);
int (*hw_gpio_pulse)(struct aq_hw_s *self, u32 index, u64 start,
u32 period);
int (*hw_extts_gpio_enable)(struct aq_hw_s *self, u32 index,
u32 enable);
int (*hw_get_sync_ts)(struct aq_hw_s *self, u64 *ts);
u16 (*rx_extract_ts)(struct aq_hw_s *self, u8 *p, unsigned int len,
u64 *timestamp);
......
......@@ -152,6 +152,7 @@ static int aq_nic_update_link_status(struct aq_nic_s *self)
aq_ptp_clock_init(self);
aq_ptp_tm_offset_set(self,
self->aq_hw->aq_link_status.mbps);
aq_ptp_link_change(self);
}
/* Driver has to update flow control settings on RX block
......
......@@ -52,4 +52,6 @@ u16 aq_ptp_extract_ts(struct aq_nic_s *aq_nic, struct sk_buff *skb, u8 *p,
struct ptp_clock *aq_ptp_get_ptp_clock(struct aq_ptp_s *aq_ptp);
int aq_ptp_link_change(struct aq_nic_s *aq_nic);
#endif /* AQ_PTP_H */
......@@ -10,6 +10,7 @@
#include "../aq_hw_utils.h"
#include "../aq_ring.h"
#include "../aq_nic.h"
#include "../aq_phy.h"
#include "hw_atl_b0.h"
#include "hw_atl_utils.h"
#include "hw_atl_llh.h"
......@@ -1151,6 +1152,12 @@ static int hw_atl_b0_set_sys_clock(struct aq_hw_s *self, u64 time, u64 ts)
return hw_atl_b0_adj_sys_clock(self, delta);
}
int hw_atl_b0_ts_to_sys_clock(struct aq_hw_s *self, u64 ts, u64 *time)
{
*time = self->ptp_clk_offset + ts;
return 0;
}
static int hw_atl_b0_adj_clock_freq(struct aq_hw_s *self, s32 ppb)
{
struct hw_fw_request_iface fwreq;
......@@ -1173,6 +1180,57 @@ static int hw_atl_b0_adj_clock_freq(struct aq_hw_s *self, s32 ppb)
return self->aq_fw_ops->send_fw_request(self, &fwreq, size);
}
static int hw_atl_b0_gpio_pulse(struct aq_hw_s *self, u32 index,
u64 start, u32 period)
{
struct hw_fw_request_iface fwreq;
size_t size;
memset(&fwreq, 0, sizeof(fwreq));
fwreq.msg_id = HW_AQ_FW_REQUEST_PTP_GPIO_CTRL;
fwreq.ptp_gpio_ctrl.index = index;
fwreq.ptp_gpio_ctrl.period = period;
/* Apply time offset */
fwreq.ptp_gpio_ctrl.start = start - self->ptp_clk_offset;
size = sizeof(fwreq.msg_id) + sizeof(fwreq.ptp_gpio_ctrl);
return self->aq_fw_ops->send_fw_request(self, &fwreq, size);
}
static int hw_atl_b0_extts_gpio_enable(struct aq_hw_s *self, u32 index,
u32 enable)
{
/* Enable/disable Sync1588 GPIO Timestamping */
aq_phy_write_reg(self, MDIO_MMD_PCS, 0xc611, enable ? 0x71 : 0);
return 0;
}
static int hw_atl_b0_get_sync_ts(struct aq_hw_s *self, u64 *ts)
{
u64 sec_l;
u64 sec_h;
u64 nsec_l;
u64 nsec_h;
if (!ts)
return -1;
/* PTP external GPIO clock seconds count 15:0 */
sec_l = aq_phy_read_reg(self, MDIO_MMD_PCS, 0xc914);
/* PTP external GPIO clock seconds count 31:16 */
sec_h = aq_phy_read_reg(self, MDIO_MMD_PCS, 0xc915);
/* PTP external GPIO clock nanoseconds count 15:0 */
nsec_l = aq_phy_read_reg(self, MDIO_MMD_PCS, 0xc916);
/* PTP external GPIO clock nanoseconds count 31:16 */
nsec_h = aq_phy_read_reg(self, MDIO_MMD_PCS, 0xc917);
*ts = (nsec_h << 16) + nsec_l + ((sec_h << 16) + sec_l) * NSEC_PER_SEC;
return 0;
}
static u16 hw_atl_b0_rx_extract_ts(struct aq_hw_s *self, u8 *p,
unsigned int len, u64 *timestamp)
{
......@@ -1416,8 +1474,11 @@ const struct aq_hw_ops hw_atl_ops_b0 = {
.hw_get_ptp_ts = hw_atl_b0_get_ptp_ts,
.hw_adj_sys_clock = hw_atl_b0_adj_sys_clock,
.hw_set_sys_clock = hw_atl_b0_set_sys_clock,
.hw_ts_to_sys_clock = hw_atl_b0_ts_to_sys_clock,
.hw_adj_clock_freq = hw_atl_b0_adj_clock_freq,
.hw_gpio_pulse = hw_atl_b0_gpio_pulse,
.hw_extts_gpio_enable = hw_atl_b0_extts_gpio_enable,
.hw_get_sync_ts = hw_atl_b0_get_sync_ts,
.rx_extract_ts = hw_atl_b0_rx_extract_ts,
.extract_hwts = hw_atl_b0_extract_hwts,
.hw_set_offload = hw_atl_b0_hw_offload_set,
......
......@@ -288,6 +288,12 @@ struct __packed offload_info {
};
/* Mailbox FW Request interface */
struct __packed hw_fw_request_ptp_gpio_ctrl {
u32 index;
u32 period;
u64 start;
};
struct __packed hw_fw_request_ptp_adj_freq {
u32 ns_mac;
u32 fns_mac;
......@@ -303,6 +309,7 @@ struct __packed hw_fw_request_ptp_adj_clock {
int sign;
};
#define HW_AQ_FW_REQUEST_PTP_GPIO_CTRL 0x11
#define HW_AQ_FW_REQUEST_PTP_ADJ_FREQ 0x12
#define HW_AQ_FW_REQUEST_PTP_ADJ_CLOCK 0x13
......@@ -310,6 +317,7 @@ struct __packed hw_fw_request_iface {
u32 msg_id;
union {
/* PTP FW Request */
struct hw_fw_request_ptp_gpio_ctrl ptp_gpio_ctrl;
struct hw_fw_request_ptp_adj_freq ptp_adj_freq;
struct hw_fw_request_ptp_adj_clock ptp_adj_clock;
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment