* [PATCH v2 net-next] net: phy: mchp: Add 1588 support for LAN8814 Quad PHY
@ 2020-12-14 17:56 Divya Koppera
2020-12-14 19:06 ` Andrew Lunn
` (4 more replies)
0 siblings, 5 replies; 7+ messages in thread
From: Divya Koppera @ 2020-12-14 17:56 UTC (permalink / raw)
To: andrew, hkallweit1, linux, davem, kuba, marex, netdev, linux-kernel
Cc: UNGLinuxDriver
This patch add supports for 1588 Hardware Timestamping support
to LAN8814 Quad Phy. It supports L2 and Ipv4 encapsulations.
Signed-off-by: Divya Koppera<divya.koppera@microchip.com>
---
v1 -> v2
* Fixed warnings
Reported-by: kernel test robot <lkp@intel.com>
---
drivers/net/phy/micrel.c | 1054 +++++++++++++++++++++++++++++++++++++-
1 file changed, 1048 insertions(+), 6 deletions(-)
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index 54e0d75203da..61b637567180 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -27,6 +27,14 @@
#include <linux/of.h>
#include <linux/clk.h>
#include <linux/delay.h>
+#include <linux/ptp_clock_kernel.h>
+#include <linux/ptp_clock.h>
+#include <linux/ptp_classify.h>
+#include <linux/net_tstamp.h>
+#include <linux/netdevice.h>
+#include <linux/if_vlan.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
/* Operation Mode Strap Override */
#define MII_KSZPHY_OMSO 0x16
@@ -53,6 +61,136 @@
#define KSZPHY_INTCS_STATUS (KSZPHY_INTCS_LINK_DOWN_STATUS |\
KSZPHY_INTCS_LINK_UP_STATUS)
+/* Lan8814 general Interrupt control/status reg in GPHY specific block. */
+#define LAN8814_INTC 0x18
+#define LAN8814_INTC_JABBER BIT(7)
+#define LAN8814_INTC_RECEIVE_ERR BIT(6)
+#define LAN8814_INTC_PAGE_RECEIVE BIT(5)
+#define LAN8814_INTC_PARELLEL BIT(4)
+#define LAN8814_INTC_LINK_PARTNER_ACK BIT(3)
+#define LAN8814_INTC_LINK_DOWN BIT(2)
+#define LAN8814_INTC_REMOTE_FAULT BIT(1)
+#define LAN8814_INTC_LINK_UP BIT(0)
+#define LAN8814_INTC_ALL (LAN8814_INTC_LINK_UP |\
+ LAN8814_INTC_LINK_DOWN)
+
+#define LAN8814_INTS 0x1B
+#define LAN8814_INTS_JABBER BIT(7)
+#define LAN8814_INTS_RECEIVE_ERR BIT(6)
+#define LAN8814_INTS_PAGE_RECEIVE BIT(5)
+#define LAN8814_INTS_PARELLEL BIT(4)
+#define LAN8814_INTS_LINK_PARTNER_ACK BIT(3)
+#define LAN8814_INTS_LINK_DOWN BIT(2)
+#define LAN8814_INTS_REMOTE_FAULT BIT(1)
+#define LAN8814_INTS_LINK_UP BIT(0)
+#define LAN8814_INTS_ALL (LAN8814_INTS_LINK_UP |\
+ LAN8814_INTS_LINK_DOWN)
+
+#define LAN8814_PTP_MAX_FREQ_ADJ_IN_PPB (31249999)
+#define LAN8814_PTP_MAX_FINE_ADJ_IN_SCALED_PPM (2047999934)
+
+#define PTP_RX_MOD 0x024F
+#define PTP_RX_RSVD_BYTE_CFG 0x0250
+#define PTP_RX_TIMESTAMP_EN 0x024D
+#define PTP_TX_TIMESTAMP_EN 0x028D
+
+#define PTP_TX_PARSE_L2_ADDR_EN 0x0284
+#define PTP_RX_PARSE_L2_ADDR_EN 0x0244
+#define PTP_FLAG_ISR_ENABLED BIT(2)
+#define PTP_FLAG_PTP_CLOCK_REGISTERED BIT(1)
+
+#define LTC_HARD_RESET 0x023F
+#define LTC_HARD_RESET_ BIT(0)
+
+#define TSU_HARD_RESET 0x02C1
+#define TSU_HARD_RESET_ BIT(0)
+
+#define PTP_CMD_CTL 0x0200
+#define PTP_CMD_CTL_PTP_DISABLE_ BIT(0)
+#define PTP_CMD_CTL_PTP_ENABLE_ BIT(1)
+#define PTP_CMD_CTL_PTP_CLOCK_READ_ BIT(3)
+#define PTP_CMD_CTL_PTP_CLOCK_LOAD_ BIT(4)
+#define PTP_CMD_CTL_PTP_LTC_STEP_SEC_ BIT(5)
+#define PTP_CMD_CTL_PTP_LTC_STEP_NSEC_ BIT(6)
+
+#define PTP_CLOCK_SET_SEC_HI (0x0205)
+#define PTP_CLOCK_SET_SEC_MID (0x0206)
+#define PTP_CLOCK_SET_SEC_LO (0x0207)
+#define PTP_CLOCK_SET_NS_HI (0x0208)
+#define PTP_CLOCK_SET_NS_LO (0x0209)
+#define PTP_CLOCK_SET_SUBNS_LO (0x020B)
+#define PTP_CLOCK_SET_SUBNS_HI (0x020A)
+
+#define PTP_CLOCK_READ_SEC_HI (0x0229)
+#define PTP_CLOCK_READ_SEC_MID (0x022A)
+#define PTP_CLOCK_READ_SEC_LO (0x022B)
+#define PTP_CLOCK_READ_NS_HI (0x022C)
+#define PTP_CLOCK_READ_NS_LO (0x022D)
+#define PTP_CLOCK_READ_SUBNS_HI (0x022E)
+#define PTP_CLOCK_READ_SUBNS_LO (0x022F)
+
+#define PTP_OPERATING_MODE (0x0241)
+#define PTP_OPERATING_MODE_STANDALONE 0x01
+
+#define PTP_TX_MOD (0x028F)
+#define PTP_TX_MOD_TX_PTP_SYNC_TS_INSERT_ BIT(12)
+#define PTP_TX_MOD_BAD_UDPV4_CHKSUM_FORCE_FCS_DIS_ BIT(3)
+
+#define PTP_RX_PARSE_CONFIG (0x0242)
+#define PTP_RX_PARSE_CONFIG_LAYER2_EN_ BIT(0)
+#define PTP_RX_PARSE_CONFIG_IPV4_EN_ BIT(1)
+
+#define PTP_TX_PARSE_CONFIG (0x0282)
+#define PTP_TX_PARSE_CONFIG_LAYER2_EN_ BIT(0)
+#define PTP_TX_PARSE_CONFIG_IPV4_EN_ BIT(1)
+
+#define PTP_CLOCK_RATE_ADJ_HI_ (0x020C)
+#define PTP_CLOCK_RATE_ADJ_LO_ (0x020D)
+#define PTP_CLOCK_RATE_ADJ_DIR_ BIT(15)
+
+#define PTP_LTC_STEP_ADJ_HI (0x0212)
+#define PTP_LTC_STEP_ADJ_LO (0x0213)
+#define PTP_LTC_STEP_ADJ_DIR_ BIT(15)
+
+#define PTP_TX_MSG_HEADER1 (0x0298)
+#define PTP_TX_MSG_HEADER1_MSG_TYPE_ (0x000F)
+#define PTP_TX_MSG_HEADER1_MSG_TYPE_SYNC_ (0x00000000)
+
+#define LAN8814_INTR_CTRL_REG (0x34)
+#define LAN8814_INTR_CTRL_REG_POLARITY BIT(1)
+#define LAN8814_INTR_CTRL_REG_INTR_ENABLE BIT(0)
+
+#define LAN8814_INTR_STS_REG (0x33)
+#define LAN8814_INTR_STS_REG_1588_TSU0 BIT(0)
+
+#define PTP_CAP_INFO (0x022A)
+#define PTP_CAP_INFO_TX_TS_CNT_GET_(reg_val) (((reg_val) & 0x0f00) >> 8)
+
+#define PTP_TX_EGRESS_SEC_HI (0x0296)
+#define PTP_TX_EGRESS_SEC_LO (0x0297)
+#define PTP_TX_EGRESS_NS_HI (0x0294)
+#define PTP_TX_EGRESS_NS_HI_TX_TS_VALID_ BIT(15)
+#define PTP_TX_EGRESS_NS_LO (0x0295)
+#define PTP_TX_MSG_HEADER2 (0x0299)
+
+#define PTP_RX_INGRESS_SEC_HI (0x0256)
+#define PTP_RX_INGRESS_SEC_LO (0x0257)
+#define PTP_RX_INGRESS_NS_HI (0x0254)
+#define PTP_RX_INGRESS_NS_LO (0x0255)
+#define PTP_RX_MSG_HEADER2 (0x0259)
+
+#define PTP_TSU_INT_EN (0x200)
+#define PTP_TSU_INT_EN_PTP_TX_TS_OVRFL_EN BIT(3)
+#define PTP_TSU_INT_EN_PTP_TX_TS_EN BIT(2)
+#define PTP_TSU_INT_EN_PTP_RX_TS_OVRFL_EN BIT(1)
+#define PTP_TSU_INT_EN_PTP_RX_TS_EN BIT(0)
+
+#define PTP_TSU_INT_STS (0x201)
+#define PTP_TSU_INT_STS_PTP_TX_TS_OVRFL_INT BIT(3)
+#define PTP_TSU_INT_STS_PTP_TX_TS_EN BIT(2)
+#define PTP_TSU_INT_STS_PTP_RX_TS_OVRFL_INT BIT(1)
+#define PTP_TSU_INT_STS_PTP_RX_TS_EN BIT(0)
+
/* PHY Control 1 */
#define MII_KSZPHY_CTRL_1 0x1e
@@ -76,6 +214,9 @@
#define MII_KSZPHY_TX_DATA_PAD_SKEW 0x106
#define PS_TO_REG 200
+#define KSZ_EXT_PAGE_ACCESS_CONTROL 0x16
+#define KSZ_EXT_PAGE_ACCESS_ADDRESS_DATA 0x17
+#define OFF_PTP_CONTROL 32 /* PTPv1 only */
struct kszphy_hw_stat {
const char *string;
@@ -96,6 +237,47 @@ struct kszphy_type {
bool has_rmii_ref_clk_sel;
};
+struct lan8814_ptp {
+ int flags;
+ struct ptp_clock *ptp_clock;
+ struct ptp_clock_info ptp_clock_info;
+ struct ptp_pin_desc pin_config[1];
+ enum hwtstamp_tx_types tx_type;
+ enum hwtstamp_rx_filters rx_filter;
+ struct sk_buff_head tx_queue;
+};
+
+struct lan8814_ptphdr {
+ u8 tsmt; /* transportSpecific | messageType */
+ u8 ver; /* reserved0 | versionPTP */
+ __be16 msglen;
+ u8 domain;
+ u8 rsrvd1;
+ __be16 flags;
+ __be64 correction;
+ __be32 rsrvd2;
+ __be64 clk_identity;
+ __be16 src_port_id;
+ __be16 seq_id;
+ u8 ctrl;
+ u8 log_interval;
+} __attribute__((__packed__));
+
+struct lan8814_priv {
+ const struct kszphy_type *type;
+ int led_mode;
+ bool rmii_ref_clk_sel;
+ bool rmii_ref_clk_sel_val;
+ u64 stats[ARRAY_SIZE(kszphy_hw_stats)];
+ struct mii_timestamper mii_ts;
+ struct phy_device *phydev;
+ struct lan8814_ptp ptp;
+ int hwts_tx_en;
+ int hwts_rx_en;
+ int layer;
+ int version;
+};
+
struct kszphy_priv {
const struct kszphy_type *type;
int led_mode;
@@ -135,6 +317,38 @@ static const struct kszphy_type ksz9021_type = {
.interrupt_level_mask = BIT(14),
};
+static void lan8814_ptp_clock_get(struct phy_device *phydev,
+ u32 *seconds, u32 *nano_seconds,
+ u32 *sub_nano_seconds);
+
+static int lan8814_read_page_reg(struct phy_device *phydev,
+ int page, u32 addr)
+{
+ u32 data;
+
+ phy_write(phydev, KSZ_EXT_PAGE_ACCESS_CONTROL, page);
+ phy_write(phydev, KSZ_EXT_PAGE_ACCESS_ADDRESS_DATA, addr);
+ phy_write(phydev, KSZ_EXT_PAGE_ACCESS_CONTROL, (page | 0x4000));
+ data = phy_read(phydev, KSZ_EXT_PAGE_ACCESS_ADDRESS_DATA);
+
+ return data;
+}
+
+static int lan8814_write_page_reg(struct phy_device *phydev,
+ int page, u16 addr, u16 val)
+{
+ phy_write(phydev, KSZ_EXT_PAGE_ACCESS_CONTROL, page);
+ phy_write(phydev, KSZ_EXT_PAGE_ACCESS_ADDRESS_DATA, addr);
+ phy_write(phydev, KSZ_EXT_PAGE_ACCESS_CONTROL, (page | 0x4000));
+ val = phy_write(phydev, KSZ_EXT_PAGE_ACCESS_ADDRESS_DATA, val);
+ if (val != 0) {
+ phydev_err(phydev, "Error: phy_write_mmd has returned error %d\n",
+ val);
+ return val;
+ }
+ return 0;
+}
+
static int kszphy_extended_write(struct phy_device *phydev,
u32 regnum, u16 val)
{
@@ -149,16 +363,196 @@ static int kszphy_extended_read(struct phy_device *phydev,
return phy_read(phydev, MII_KSZPHY_EXTREG_READ);
}
-static int kszphy_ack_interrupt(struct phy_device *phydev)
+static void lan8814_ptp_tx_ts_get(struct phy_device *phydev,
+ u32 *seconds, u32 *nano_seconds,
+ u32 *seq_id);
+
+static struct lan8814_ptphdr *get_ptp_header_l4(struct sk_buff *skb,
+ struct iphdr *iphdr,
+ struct udphdr *udphdr)
+{
+ if (iphdr->version != 4 || iphdr->protocol != IPPROTO_UDP)
+ return NULL;
+
+ return (struct lan8814_ptphdr *)(((unsigned char *)udphdr) + UDP_HLEN);
+}
+
+static struct lan8814_ptphdr *get_ptp_header_tx(struct sk_buff *skb)
+{
+ struct ethhdr *ethhdr = eth_hdr(skb);
+ struct udphdr *udphdr;
+ struct iphdr *iphdr;
+
+ if (ethhdr->h_proto == htons(ETH_P_1588))
+ return (struct lan8814_ptphdr *)(((unsigned char *)ethhdr) +
+ skb_mac_header_len(skb));
+
+ if (ethhdr->h_proto != htons(ETH_P_IP))
+ return NULL;
+
+ iphdr = ip_hdr(skb);
+ udphdr = udp_hdr(skb);
+
+ return get_ptp_header_l4(skb, iphdr, udphdr);
+}
+
+static int get_sig(struct sk_buff *skb, u8 *sig)
+{
+ struct lan8814_ptphdr *ptphdr = get_ptp_header_tx(skb);
+ struct ethhdr *ethhdr = eth_hdr(skb);
+ unsigned int i;
+
+ if (!ptphdr)
+ return -EOPNOTSUPP;
+
+ sig[0] = (__force u16)ptphdr->seq_id >> 8;
+ sig[1] = (__force u16)ptphdr->seq_id & GENMASK(7, 0);
+ sig[2] = ptphdr->domain;
+ sig[3] = ptphdr->tsmt & GENMASK(3, 0);
+
+ memcpy(&sig[4], ethhdr->h_dest, ETH_ALEN);
+
+ /* Fill the last bytes of the signature to reach a 16B signature */
+ for (i = 10; i < 16; i++)
+ sig[i] = ptphdr->tsmt & GENMASK(3, 0);
+
+ return 0;
+}
+
+static void lan8814_dequeue_skb(struct lan8814_ptp *ptp)
+{
+ struct lan8814_priv *priv = container_of(ptp, struct lan8814_priv, ptp);
+ struct phy_device *phydev = priv->phydev;
+ struct skb_shared_hwtstamps shhwtstamps;
+ struct sk_buff *skb;
+ u8 skb_sig[16];
+ int len;
+ u32 reg, cnt;
+ u32 seconds, nsec, seq_id;
+
+ reg = lan8814_read_page_reg(phydev, 5, PTP_CAP_INFO);
+ cnt = PTP_CAP_INFO_TX_TS_CNT_GET_(reg);
+
+ /* FIFO is Empty*/
+ if (cnt == 0)
+ return;
+
+ len = skb_queue_len(&ptp->tx_queue);
+ if (len < 1)
+ return;
+
+ while (len--) {
+ skb = __skb_dequeue(&ptp->tx_queue);
+ if (!skb)
+ return;
+
+ /* Can't get the signature of the packet, won't ever
+ * be able to have one so let's dequeue the packet.
+ */
+ if (get_sig(skb, skb_sig) < 0) {
+ kfree_skb(skb);
+ continue;
+ }
+
+ lan8814_ptp_tx_ts_get(phydev, &seconds, &nsec, &seq_id);
+
+ /* Check if we found the signature we were looking for. */
+ if (memcmp(skb_sig, &seq_id, sizeof(skb_sig))) {
+ memset(&shhwtstamps, 0, sizeof(shhwtstamps));
+ shhwtstamps.hwtstamp = ktime_set(seconds, nsec);
+ skb_complete_tx_timestamp(skb, &shhwtstamps);
+
+ return;
+ }
+
+ /* Valid signature but does not match the one of the
+ * packet in the FIFO right now, reschedule it for later
+ * packets.
+ */
+ __skb_queue_tail(&ptp->tx_queue, skb);
+ }
+}
+
+static void lan8814_get_tx_ts(struct lan8814_ptp *ptp)
{
- /* bit[7..0] int status, which is a read and clear register. */
+ u32 reg;
+ struct lan8814_priv *priv = container_of(ptp, struct lan8814_priv, ptp);
+ struct phy_device *phydev = priv->phydev;
+
+ do {
+ lan8814_dequeue_skb(ptp);
+
+ /* If other timestamps are available in the FIFO, process them. */
+ reg = lan8814_read_page_reg(phydev, 5, PTP_CAP_INFO);
+ } while (PTP_CAP_INFO_TX_TS_CNT_GET_(reg) > 1);
+}
+
+static irqreturn_t lan8814_handle_ptp_interrupt(struct phy_device *phydev)
+{
+ struct lan8814_priv *lan8814 = phydev->priv;
int rc;
- rc = phy_read(phydev, MII_KSZPHY_INTCS);
+ rc = lan8814_read_page_reg(phydev, 5, PTP_TSU_INT_STS);
+
+ if (!(rc & PTP_TSU_INT_STS_PTP_TX_TS_EN))
+ return IRQ_NONE;
+
+ lan8814_get_tx_ts(&lan8814->ptp);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t lan8814_handle_interrupt(struct phy_device *phydev)
+{
+ int irq_status;
+
+ irq_status = lan8814_read_page_reg(phydev, 4, LAN8814_INTR_STS_REG);
+ if (irq_status < 0)
+ return IRQ_NONE;
+
+ if (irq_status & LAN8814_INTR_STS_REG_1588_TSU0)
+ return lan8814_handle_ptp_interrupt(phydev);
+
+ irq_status = phy_read(phydev, LAN8814_INTS);
+ if (irq_status < 0)
+ return IRQ_NONE;
+
+ if (irq_status & LAN8814_INTS_ALL)
+ phy_mac_interrupt(phydev);
+
+ return IRQ_HANDLED;
+}
+
+static int kszphy_ack_interrupt(struct phy_device *phydev)
+{
+ if (phy_read(phydev, MII_KSZPHY_INTCS) < 0)
+ return -1;
+
+ return 0;
+}
- return (rc < 0) ? rc : 0;
+static int lan8814_config_ts_intr(struct phy_device *phydev)
+{
+ return lan8814_write_page_reg(phydev, 5, PTP_TSU_INT_EN, PTP_TSU_INT_EN_PTP_TX_TS_EN |
+ PTP_TSU_INT_EN_PTP_TX_TS_OVRFL_EN);
}
+static int lan8814_config_intr(struct phy_device *phydev)
+{
+ int temp;
+
+ lan8814_write_page_reg(phydev, 4, LAN8814_INTR_CTRL_REG,
+ LAN8814_INTR_CTRL_REG_POLARITY |
+ LAN8814_INTR_CTRL_REG_INTR_ENABLE);
+
+ /* enable / disable interrupts */
+ if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
+ temp = LAN8814_INTC_ALL;
+ else
+ temp = 0;
+
+ return phy_write(phydev, LAN8814_INTC, temp);
+}
static int kszphy_config_intr(struct phy_device *phydev)
{
const struct kszphy_type *type = phydev->drv->driver_data;
@@ -304,7 +698,7 @@ static int kszphy_nand_tree_disable(struct phy_device *phydev)
/* Some config bits need to be set again on resume, handle them here. */
static int kszphy_config_reset(struct phy_device *phydev)
{
- struct kszphy_priv *priv = phydev->priv;
+ struct lan8814_priv *priv = phydev->priv;
int ret;
if (priv->rmii_ref_clk_sel) {
@@ -1124,6 +1518,569 @@ static int kszphy_resume(struct phy_device *phydev)
return 0;
}
+static bool lan8814_ptp_is_enable(struct phy_device *phydev)
+{
+ if (phy_read(phydev, PTP_CMD_CTL) & PTP_CMD_CTL_PTP_ENABLE_)
+ return true;
+
+ return false;
+}
+
+static void lan8814_ptp_rx_ts_get(struct phy_device *phydev,
+ u32 *seconds, u32 *nano_seconds, u32 *seq_id)
+{
+ if (seconds) {
+ (*seconds) = lan8814_read_page_reg(phydev, 5, PTP_RX_INGRESS_SEC_HI);
+ (*seconds) = ((*seconds) << 16) |
+ lan8814_read_page_reg(phydev, 5, PTP_RX_INGRESS_SEC_LO);
+ }
+
+ if (nano_seconds) {
+ (*nano_seconds) = lan8814_read_page_reg(phydev, 5, PTP_RX_INGRESS_NS_HI);
+ (*nano_seconds) = (((*nano_seconds) & 0x3fff) << 16)
+ | lan8814_read_page_reg(phydev, 5, PTP_RX_INGRESS_NS_LO);
+ }
+
+ if (seq_id)
+ (*seq_id) = lan8814_read_page_reg(phydev, 5, PTP_RX_MSG_HEADER2);
+}
+
+static void lan8814_ptp_tx_ts_get(struct phy_device *phydev,
+ u32 *seconds, u32 *nano_seconds, u32 *seq_id)
+{
+ if (seconds) {
+ (*seconds) = lan8814_read_page_reg(phydev, 5, PTP_TX_EGRESS_SEC_HI);
+ (*seconds) = ((*seconds) << 16) |
+ lan8814_read_page_reg(phydev, 5, PTP_TX_EGRESS_SEC_LO);
+ }
+
+ if (nano_seconds) {
+ (*nano_seconds) = lan8814_read_page_reg(phydev, 5, PTP_TX_EGRESS_NS_HI);
+ (*nano_seconds) = (((*nano_seconds) & 0x3fff) << 16) |
+ lan8814_read_page_reg(phydev, 5, PTP_TX_EGRESS_NS_LO);
+ }
+
+ if (seq_id)
+ (*seq_id) = lan8814_read_page_reg(phydev, 5, PTP_TX_MSG_HEADER2);
+}
+
+static int lan8814_ts_info(struct mii_timestamper *mii_ts, struct ethtool_ts_info *info)
+{
+ struct lan8814_priv *ksz9031 = container_of(mii_ts, struct lan8814_priv, mii_ts);
+
+ info->so_timestamping =
+ SOF_TIMESTAMPING_TX_HARDWARE |
+ SOF_TIMESTAMPING_RX_HARDWARE |
+ SOF_TIMESTAMPING_RAW_HARDWARE;
+
+ info->phc_index = ptp_clock_index(ksz9031->ptp.ptp_clock);
+
+ info->tx_types =
+ (1 << HWTSTAMP_TX_OFF) |
+ (1 << HWTSTAMP_TX_ON) |
+ (1 << HWTSTAMP_TX_ONESTEP_SYNC);
+
+ info->rx_filters =
+ (1 << HWTSTAMP_FILTER_NONE) |
+ (1 << HWTSTAMP_FILTER_PTP_V1_L4_EVENT) |
+ (1 << HWTSTAMP_FILTER_PTP_V2_L4_EVENT) |
+ (1 << HWTSTAMP_FILTER_PTP_V2_L2_EVENT) |
+ (1 << HWTSTAMP_FILTER_PTP_V2_EVENT);
+
+ return 0;
+}
+
+static int lan8814_hwtstamp(struct mii_timestamper *mii_ts, struct ifreq *ifr)
+{
+ struct lan8814_priv *lan8814 = container_of(mii_ts, struct lan8814_priv, mii_ts);
+ struct hwtstamp_config config;
+ int txcfg, rxcfg;
+
+ if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
+ return -EFAULT;
+
+ lan8814->hwts_tx_en = config.tx_type;
+
+ lan8814->ptp.rx_filter = config.rx_filter;
+ lan8814->ptp.tx_type = config.tx_type;
+
+ switch (config.rx_filter) {
+ case HWTSTAMP_FILTER_NONE:
+ lan8814->hwts_rx_en = 0;
+ lan8814->layer = 0;
+ lan8814->version = 0;
+ break;
+ case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
+ case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
+ case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
+ lan8814->hwts_rx_en = 1;
+ lan8814->layer = PTP_CLASS_L4;
+ lan8814->version = PTP_CLASS_V2;
+ break;
+ case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
+ case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
+ case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
+ lan8814->hwts_rx_en = 1;
+ lan8814->layer = PTP_CLASS_L2;
+ lan8814->version = PTP_CLASS_V2;
+ break;
+ case HWTSTAMP_FILTER_PTP_V2_EVENT:
+ case HWTSTAMP_FILTER_PTP_V2_SYNC:
+ case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
+ lan8814->hwts_rx_en = 1;
+ lan8814->layer = PTP_CLASS_L4 | PTP_CLASS_L2;
+ lan8814->version = PTP_CLASS_V2;
+ break;
+ default:
+ return -ERANGE;
+ }
+
+ lan8814_write_page_reg(lan8814->phydev, 5, PTP_RX_PARSE_CONFIG, 0);
+ lan8814_write_page_reg(lan8814->phydev, 5, PTP_TX_PARSE_CONFIG, 0);
+
+ if (lan8814->hwts_rx_en && (lan8814->layer & PTP_CLASS_L2))
+ rxcfg = PTP_RX_PARSE_CONFIG_LAYER2_EN_;
+
+ if (lan8814->hwts_tx_en && (lan8814->layer & PTP_CLASS_L2))
+ txcfg = PTP_TX_PARSE_CONFIG_LAYER2_EN_;
+
+ if (lan8814->hwts_rx_en && (lan8814->layer & PTP_CLASS_L4))
+ rxcfg |= PTP_RX_PARSE_CONFIG_IPV4_EN_;
+
+ if (lan8814->hwts_tx_en && (lan8814->layer & PTP_CLASS_L4))
+ txcfg |= PTP_TX_PARSE_CONFIG_IPV4_EN_;
+
+ if (lan8814_ptp_is_enable(lan8814->phydev))
+ lan8814_write_page_reg(lan8814->phydev, 4, PTP_CMD_CTL,
+ PTP_CMD_CTL_PTP_DISABLE_);
+
+ lan8814_write_page_reg(lan8814->phydev, 5, PTP_RX_PARSE_CONFIG, rxcfg);
+ lan8814_write_page_reg(lan8814->phydev, 5, PTP_TX_PARSE_CONFIG, txcfg);
+ lan8814_write_page_reg(lan8814->phydev, 5, PTP_RX_TIMESTAMP_EN, 0x3);
+ lan8814_write_page_reg(lan8814->phydev, 5, PTP_TX_TIMESTAMP_EN, 0x3);
+ lan8814_write_page_reg(lan8814->phydev, 5, PTP_TX_PARSE_L2_ADDR_EN, 0);
+ lan8814_write_page_reg(lan8814->phydev, 5, PTP_RX_PARSE_L2_ADDR_EN, 0);
+
+ lan8814_write_page_reg(lan8814->phydev, 4, PTP_CMD_CTL, PTP_CMD_CTL_PTP_ENABLE_);
+ if (lan8814->hwts_tx_en == HWTSTAMP_TX_ONESTEP_SYNC) {
+ lan8814_write_page_reg(lan8814->phydev, 5, PTP_TX_MOD,
+ PTP_TX_MOD_TX_PTP_SYNC_TS_INSERT_);
+ } else if (lan8814->hwts_tx_en == HWTSTAMP_TX_ON) {
+ /* Enabling 2 step offloading and all option for TS insertion/correction fields */
+ lan8814_write_page_reg(lan8814->phydev, 5, PTP_TX_MOD, 0x800);
+ lan8814_config_ts_intr(lan8814->phydev);
+ }
+
+ return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? -EFAULT : 0;
+}
+
+static bool lan8814_rxtstamp(struct mii_timestamper *mii_ts, struct sk_buff *skb, int type)
+{
+ struct lan8814_priv *ksz9031 = container_of(mii_ts, struct lan8814_priv, mii_ts);
+ struct skb_shared_hwtstamps *shhwtstamps = NULL;
+ u32 seconds, nsec, seq_id;
+
+ if (!ksz9031->hwts_rx_en)
+ return false;
+
+ if (!skb)
+ return false;
+
+ if ((type & ksz9031->version) == 0 || (type & ksz9031->layer) == 0)
+ return false;
+
+ if (ksz9031->ptp.rx_filter == HWTSTAMP_FILTER_NONE ||
+ type == PTP_CLASS_NONE)
+ return false;
+
+ lan8814_ptp_rx_ts_get(ksz9031->phydev, &seconds, &nsec, &seq_id);
+
+ /* Saving timestamp and sending through skbuff */
+ shhwtstamps = skb_hwtstamps(skb);
+ memset(shhwtstamps, 0, sizeof(*shhwtstamps));
+ shhwtstamps->hwtstamp = ktime_set(seconds, nsec);
+
+ netif_rx_ni(skb);
+
+ return true;
+}
+
+static int is_sync(struct sk_buff *skb, int type)
+{
+ u8 *data = skb->data, *msgtype;
+ unsigned int offset = 0;
+
+ if (type & PTP_CLASS_VLAN)
+ offset += VLAN_HLEN;
+
+ switch (type & PTP_CLASS_PMASK) {
+ case PTP_CLASS_IPV4:
+ offset += ETH_HLEN + IPV4_HLEN(data + offset) + UDP_HLEN;
+ break;
+ case PTP_CLASS_IPV6:
+ offset += ETH_HLEN + IP6_HLEN + UDP_HLEN;
+ break;
+ case PTP_CLASS_L2:
+ offset += ETH_HLEN;
+ break;
+ default:
+ return 0;
+ }
+
+ if (type & PTP_CLASS_V1)
+ offset += OFF_PTP_CONTROL;
+
+ if (skb->len < offset + 1)
+ return 0;
+
+ msgtype = data + offset;
+
+ return (*msgtype & 0xf) == 0;
+}
+
+static void lan8814_txtstamp(struct mii_timestamper *mii_ts,
+ struct sk_buff *skb, int type)
+{
+ struct lan8814_priv *kszphy = container_of(mii_ts, struct lan8814_priv, mii_ts);
+
+ switch (kszphy->hwts_tx_en) {
+ case HWTSTAMP_TX_ONESTEP_SYNC:
+ if (is_sync(skb, type)) {
+ kfree_skb(skb);
+ return;
+ }
+ break;
+
+ case HWTSTAMP_TX_ON:
+ skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
+ skb_queue_tail(&kszphy->ptp.tx_queue, skb);
+ break;
+
+ case HWTSTAMP_TX_OFF:
+ default:
+ kfree_skb(skb);
+ break;
+ }
+}
+
+static void lan8814_ptp_clock_set(struct phy_device *phydev,
+ u32 seconds, u32 nano_seconds,
+ u32 sub_nano_seconds)
+{
+ u32 sec_low, sec_high, nsec_low, nsec_high, snsec_low, snsec_high;
+
+ sec_low = seconds & 0xffff;
+ sec_high = ((seconds >> 16) & 0xffff);
+ nsec_low = nano_seconds & 0xffff;
+ nsec_high = ((nano_seconds >> 16) & 0x3fff);
+ snsec_low = sub_nano_seconds & 0xffff;
+ snsec_high = ((sub_nano_seconds >> 16) & 0xffff);
+
+ lan8814_write_page_reg(phydev, 4, PTP_CLOCK_SET_SEC_LO, sec_low);
+ lan8814_write_page_reg(phydev, 4, PTP_CLOCK_SET_SEC_MID, sec_high);
+ lan8814_write_page_reg(phydev, 4, PTP_CLOCK_SET_NS_LO, nsec_low);
+ lan8814_write_page_reg(phydev, 4, PTP_CLOCK_SET_NS_HI, nsec_high);
+ lan8814_write_page_reg(phydev, 4, PTP_CLOCK_SET_SUBNS_LO, snsec_low);
+ lan8814_write_page_reg(phydev, 4, PTP_CLOCK_SET_SUBNS_HI, snsec_high);
+
+ lan8814_write_page_reg(phydev, 4, PTP_CMD_CTL, PTP_CMD_CTL_PTP_CLOCK_LOAD_);
+}
+
+static void lan8814_ptp_clock_get(struct phy_device *phydev,
+ u32 *seconds, u32 *nano_seconds,
+ u32 *sub_nano_seconds)
+{
+ lan8814_write_page_reg(phydev, 4, PTP_CMD_CTL, PTP_CMD_CTL_PTP_CLOCK_READ_);
+
+ if (seconds) {
+ (*seconds) = lan8814_read_page_reg(phydev, 4, PTP_CLOCK_READ_SEC_MID);
+ (*seconds) = ((*seconds) << 16) |
+ lan8814_read_page_reg(phydev, 4, PTP_CLOCK_READ_SEC_LO);
+ }
+
+ if (nano_seconds) {
+ (*nano_seconds) = lan8814_read_page_reg(phydev, 4, PTP_CLOCK_READ_NS_HI);
+ (*nano_seconds) = (((*nano_seconds) & 0x3fff) << 16) |
+ lan8814_read_page_reg(phydev, 4, PTP_CLOCK_READ_NS_LO);
+ }
+
+ if (sub_nano_seconds) {
+ (*sub_nano_seconds) = lan8814_read_page_reg(phydev, 4,
+ PTP_CLOCK_READ_SUBNS_HI);
+ (*sub_nano_seconds) = ((*sub_nano_seconds) << 16) |
+ lan8814_read_page_reg(phydev, 4,
+ PTP_CLOCK_READ_SUBNS_LO);
+ }
+}
+
+static int lan8814_ptpci_gettime64(struct ptp_clock_info *ptpci,
+ struct timespec64 *ts)
+{
+ struct lan8814_ptp *ptp =
+ container_of(ptpci, struct lan8814_ptp, ptp_clock_info);
+ struct lan8814_priv *priv =
+ container_of(ptp, struct lan8814_priv, ptp);
+ struct phy_device *phydev = priv->phydev;
+ u32 nano_seconds = 0;
+ u32 seconds = 0;
+
+ lan8814_ptp_clock_get(phydev, &seconds, &nano_seconds, NULL);
+ ts->tv_sec = seconds;
+ ts->tv_nsec = nano_seconds;
+
+ return 0;
+}
+
+static void lan8814_ptp_clock_step(struct phy_device *phydev,
+ s64 time_step_ns)
+{
+ u32 nano_seconds_step = 0;
+ u64 abs_time_step_ns = 0;
+ u32 unsigned_seconds = 0;
+ u32 nano_seconds = 0;
+ u32 remainder = 0;
+ s32 seconds = 0;
+
+ if (time_step_ns > 15000000000LL) {
+ /* convert to clock set */
+ lan8814_ptp_clock_get(phydev, &unsigned_seconds, &nano_seconds, NULL);
+ unsigned_seconds += div_u64_rem(time_step_ns, 1000000000LL,
+ &remainder);
+ nano_seconds += remainder;
+ if (nano_seconds >= 1000000000) {
+ unsigned_seconds++;
+ nano_seconds -= 1000000000;
+ }
+ lan8814_ptp_clock_set(phydev, unsigned_seconds,
+ nano_seconds, 0);
+ return;
+ } else if (time_step_ns < -15000000000LL) {
+ /* convert to clock set */
+ time_step_ns = -time_step_ns;
+
+ lan8814_ptp_clock_get(phydev, &unsigned_seconds,
+ &nano_seconds, NULL);
+ unsigned_seconds -= div_u64_rem(time_step_ns, 1000000000LL,
+ &remainder);
+ nano_seconds_step = remainder;
+ if (nano_seconds < nano_seconds_step) {
+ unsigned_seconds--;
+ nano_seconds += 1000000000;
+ }
+ nano_seconds -= nano_seconds_step;
+ lan8814_ptp_clock_set(phydev, unsigned_seconds,
+ nano_seconds, 0);
+ return;
+ }
+
+ /* do clock step */
+ if (time_step_ns >= 0) {
+ abs_time_step_ns = (u64)(time_step_ns);
+ seconds = (s32)div_u64_rem(abs_time_step_ns, 1000000000,
+ &remainder);
+ nano_seconds = (u32)remainder;
+ } else {
+ abs_time_step_ns = (u64)(-time_step_ns);
+ seconds = -((s32)div_u64_rem(abs_time_step_ns, 1000000000,
+ &remainder));
+ nano_seconds = (u32)remainder;
+ if (nano_seconds > 0) {
+ /* subtracting nano seconds is not allowed
+ * convert to subtracting from seconds,
+ * and adding to nanoseconds
+ */
+ seconds--;
+ nano_seconds = (1000000000 - nano_seconds);
+ }
+ }
+
+ if (nano_seconds > 0) {
+ /* add 8 ns to cover the likely normal increment */
+ nano_seconds += 8;
+ }
+
+ if (nano_seconds >= 1000000000) {
+ /* carry into seconds */
+ seconds++;
+ nano_seconds -= 1000000000;
+ }
+
+ while (seconds) {
+ if (seconds > 0) {
+ u32 adjustment_value = (u32)seconds;
+ u16 adjustment_value_lo, adjustment_value_hi;
+
+ adjustment_value_lo = adjustment_value & 0xffff;
+ adjustment_value_hi = (adjustment_value >> 16) & 0x3fff;
+
+ if (adjustment_value > 0xF)
+ adjustment_value = 0xF;
+ lan8814_write_page_reg(phydev, 4, PTP_LTC_STEP_ADJ_LO,
+ adjustment_value_lo);
+ lan8814_write_page_reg(phydev, 4, PTP_LTC_STEP_ADJ_HI,
+ PTP_LTC_STEP_ADJ_DIR_ |
+ adjustment_value_hi);
+ seconds -= ((s32)adjustment_value);
+ } else {
+ u32 adjustment_value = (u32)(-seconds);
+ u16 adjustment_value_lo, adjustment_value_hi;
+
+ adjustment_value_lo = adjustment_value & 0xffff;
+ adjustment_value_hi = (adjustment_value >> 16) & 0x3fff;
+ if (adjustment_value > 0xF)
+ adjustment_value = 0xF;
+ lan8814_write_page_reg(phydev, 4, PTP_LTC_STEP_ADJ_LO,
+ adjustment_value_lo);
+ lan8814_write_page_reg(phydev, 4, PTP_LTC_STEP_ADJ_HI,
+ PTP_LTC_STEP_ADJ_DIR_ |
+ adjustment_value_hi);
+ seconds += ((s32)adjustment_value);
+ }
+ lan8814_write_page_reg(phydev, 4, PTP_CMD_CTL,
+ PTP_CMD_CTL_PTP_LTC_STEP_SEC_);
+ }
+ if (nano_seconds) {
+ u16 nano_seconds_lo;
+ u16 nano_seconds_hi;
+
+ nano_seconds_lo = nano_seconds & 0xffff;
+ nano_seconds_hi = (nano_seconds >> 16) & 0x3fff;
+
+ lan8814_write_page_reg(phydev, 4, PTP_LTC_STEP_ADJ_LO,
+ nano_seconds_lo);
+ lan8814_write_page_reg(phydev, 4, PTP_LTC_STEP_ADJ_HI,
+ PTP_LTC_STEP_ADJ_DIR_ |
+ nano_seconds_hi);
+ lan8814_write_page_reg(phydev, 4, PTP_CMD_CTL,
+ PTP_CMD_CTL_PTP_LTC_STEP_NSEC_);
+ }
+}
+
+static int lan8814_ptpci_adjtime(struct ptp_clock_info *ptpci, s64 delta)
+{
+ struct lan8814_ptp *ptp =
+ container_of(ptpci, struct lan8814_ptp, ptp_clock_info);
+ struct lan8814_priv *priv =
+ container_of(ptp, struct lan8814_priv, ptp);
+ struct phy_device *phydev = priv->phydev;
+
+ lan8814_ptp_clock_step(phydev, delta);
+
+ return 0;
+}
+
+static int lan8814_ptpci_adjfreq(struct ptp_clock_info *ptpci, s32 delta_ppb)
+{
+ struct lan8814_ptp *ptp =
+ container_of(ptpci, struct lan8814_ptp, ptp_clock_info);
+ struct lan8814_priv *priv =
+ container_of(ptp, struct lan8814_priv, ptp);
+ struct phy_device *phydev = priv->phydev;
+ u32 kszphy_rate_adj = 0;
+ u16 kszphy_rate_adj_lo = 0, kszphy_rate_adj_hi = 0;
+ bool positive = true;
+ u32 u32_delta = 0;
+ u64 u64_delta = 0;
+
+ if (delta_ppb > 0) {
+ u32_delta = (u32)delta_ppb;
+ positive = true;
+ } else {
+ u32_delta = (u32)(-delta_ppb);
+ positive = false;
+ }
+ u64_delta = (((u64)u32_delta) << 35);
+ kszphy_rate_adj = div_u64(u64_delta, 1000000000);
+
+ kszphy_rate_adj_lo = kszphy_rate_adj & 0xffff;
+ kszphy_rate_adj_hi = (kszphy_rate_adj >> 16) & 0x3fff;
+
+ if (positive)
+ kszphy_rate_adj_hi |= PTP_CLOCK_RATE_ADJ_DIR_;
+
+ lan8814_write_page_reg(phydev, 4, PTP_CLOCK_RATE_ADJ_HI_, kszphy_rate_adj_hi);
+ lan8814_write_page_reg(phydev, 4, PTP_CLOCK_RATE_ADJ_LO_, kszphy_rate_adj_lo);
+
+ return 0;
+}
+
+static int lan8814_ptpci_adjfine(struct ptp_clock_info *ptpci, long scaled_ppm)
+{
+ struct lan8814_ptp *ptp =
+ container_of(ptpci, struct lan8814_ptp, ptp_clock_info);
+ struct lan8814_priv *priv = container_of(ptp, struct lan8814_priv, ptp);
+ struct phy_device *phydev = priv->phydev;
+ u32 kszphy_rate_adj = 0;
+ u16 kszphy_rate_adj_lo = 0, kszphy_rate_adj_hi = 0;
+ bool positive = true;
+ u64 u64_delta = 0;
+
+ if ((scaled_ppm < (-LAN8814_PTP_MAX_FINE_ADJ_IN_SCALED_PPM)) ||
+ scaled_ppm > LAN8814_PTP_MAX_FINE_ADJ_IN_SCALED_PPM) {
+ return -EINVAL;
+ }
+ if (scaled_ppm > 0) {
+ u64_delta = (u64)scaled_ppm;
+ positive = true;
+ } else {
+ u64_delta = (u64)(-scaled_ppm);
+ positive = false;
+ }
+ u64_delta = (u64_delta << 13);
+ kszphy_rate_adj = div_u64(u64_delta, 15625);
+
+ kszphy_rate_adj_lo = kszphy_rate_adj & 0xffff;
+ kszphy_rate_adj_hi = (kszphy_rate_adj >> 16) & 0x3fff;
+
+ if (positive)
+ kszphy_rate_adj_hi |= PTP_CLOCK_RATE_ADJ_DIR_;
+
+ lan8814_write_page_reg(phydev, 4, PTP_CLOCK_RATE_ADJ_HI_, kszphy_rate_adj_hi);
+ lan8814_write_page_reg(phydev, 4, PTP_CLOCK_RATE_ADJ_LO_, kszphy_rate_adj_lo);
+
+ return 0;
+}
+
+static void lan8814_ptp_reset(struct phy_device *phydev)
+{
+ if (lan8814_ptp_is_enable(phydev))
+ lan8814_write_page_reg(phydev, 4, PTP_CMD_CTL, PTP_CMD_CTL_PTP_DISABLE_);
+
+ lan8814_write_page_reg(phydev, 4, LTC_HARD_RESET, LTC_HARD_RESET_);
+ lan8814_write_page_reg(phydev, 5, TSU_HARD_RESET, TSU_HARD_RESET_);
+}
+
+static void lan8814_ptp_enable(struct phy_device *phydev)
+{
+ if (lan8814_ptp_is_enable(phydev))
+ return;
+
+ lan8814_write_page_reg(phydev, 4, PTP_CMD_CTL, PTP_CMD_CTL_PTP_ENABLE_);
+}
+
+static void lan8814_ptp_sync_to_system_clock(struct phy_device *phydev)
+{
+ struct timespec64 ts;
+
+ ktime_get_clocktai_ts64(&ts);
+
+ lan8814_ptp_clock_set(phydev, ts.tv_sec, ts.tv_nsec, 0);
+}
+
+static void lan8814_ptp_init(struct phy_device *phydev)
+{
+ u32 temp;
+
+ lan8814_ptp_reset(phydev);
+ lan8814_ptp_sync_to_system_clock(phydev);
+ temp = lan8814_read_page_reg(phydev, 5, PTP_TX_MOD);
+ temp |= PTP_TX_MOD_BAD_UDPV4_CHKSUM_FORCE_FCS_DIS_;
+ lan8814_write_page_reg(phydev, 5, PTP_TX_MOD, temp);
+ lan8814_write_page_reg(phydev, 4, PTP_OPERATING_MODE,
+ PTP_OPERATING_MODE_STANDALONE);
+ lan8814_ptp_enable(phydev);
+}
+
static int kszphy_probe(struct phy_device *phydev)
{
const struct kszphy_type *type = phydev->drv->driver_data;
@@ -1185,6 +2142,89 @@ static int kszphy_probe(struct phy_device *phydev)
return 0;
}
+static int lan8814_probe(struct phy_device *phydev)
+{
+ struct lan8814_priv *priv;
+ struct clk *clk;
+ const struct kszphy_type *type = phydev->drv->driver_data;
+ const struct device_node *np = phydev->mdio.dev.of_node;
+
+ priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ skb_queue_head_init(&priv->ptp.tx_queue);
+
+ priv->phydev = phydev;
+
+ priv->type = type;
+
+ priv->mii_ts.rxtstamp = lan8814_rxtstamp;
+ priv->mii_ts.txtstamp = lan8814_txtstamp;
+ priv->mii_ts.hwtstamp = lan8814_hwtstamp;
+ priv->mii_ts.ts_info = lan8814_ts_info;
+
+ phydev->mii_ts = &priv->mii_ts;
+
+ phydev->priv = priv;
+
+ lan8814_ptp_init(phydev);
+
+ priv->ptp.flags |= PTP_FLAG_ISR_ENABLED;
+
+ if (!IS_ENABLED(CONFIG_PTP_1588_CLOCK))
+ return 0;
+
+ clk = devm_clk_get(&phydev->mdio.dev, "rmii-ref");
+ /* NOTE: clk may be NULL if building without CONFIG_HAVE_CLK */
+ if (!IS_ERR_OR_NULL(clk)) {
+ unsigned long rate = clk_get_rate(clk);
+ bool rmii_ref_clk_sel_25_mhz;
+
+ priv->rmii_ref_clk_sel = type->has_rmii_ref_clk_sel;
+ rmii_ref_clk_sel_25_mhz = of_property_read_bool(np,
+ "micrel,rmii-reference-clock-select-25-mhz");
+
+ if (rate > 24500000 && rate < 25500000) {
+ priv->rmii_ref_clk_sel_val = rmii_ref_clk_sel_25_mhz;
+ } else if (rate > 49500000 && rate < 50500000) {
+ priv->rmii_ref_clk_sel_val = !rmii_ref_clk_sel_25_mhz;
+ } else {
+ phydev_err(phydev, "Clock rate out of range: %ld\n",
+ rate);
+ return -EINVAL;
+ }
+ }
+
+ priv->ptp.ptp_clock_info.owner = THIS_MODULE;
+ snprintf(priv->ptp.ptp_clock_info.name, 30, "%s",
+ phydev->drv->name);
+ priv->ptp.ptp_clock_info.max_adj = LAN8814_PTP_MAX_FREQ_ADJ_IN_PPB;
+ priv->ptp.ptp_clock_info.n_alarm = 0;
+ priv->ptp.ptp_clock_info.n_ext_ts = 0;
+ priv->ptp.ptp_clock_info.n_per_out = 1;
+ priv->ptp.ptp_clock_info.n_pins = 0;
+ priv->ptp.ptp_clock_info.pps = 0;
+ priv->ptp.ptp_clock_info.pin_config = NULL;
+ priv->ptp.ptp_clock_info.adjfine = lan8814_ptpci_adjfine;
+ priv->ptp.ptp_clock_info.adjfreq = lan8814_ptpci_adjfreq;
+ priv->ptp.ptp_clock_info.adjtime = lan8814_ptpci_adjtime;
+ priv->ptp.ptp_clock_info.gettime64 = lan8814_ptpci_gettime64;
+ priv->ptp.ptp_clock_info.getcrosststamp = NULL;
+
+ priv->ptp.ptp_clock = ptp_clock_register(&priv->ptp.ptp_clock_info,
+ &phydev->mdio.dev);
+
+ if (IS_ERR_OR_NULL(priv->ptp.ptp_clock))
+ phydev_err(phydev, "ptp_clock_register failed %lu\n",
+ PTR_ERR(priv->ptp.ptp_clock));
+
+ priv->ptp.flags |= PTP_FLAG_PTP_CLOCK_REGISTERED;
+ phydev_info(phydev, "successfully registered ptp clock\n");
+
+ return 0;
+}
+
static struct phy_driver ksphy_driver[] = {
{
.phy_id = PHY_ID_KS8737,
@@ -1352,7 +2392,7 @@ static struct phy_driver ksphy_driver[] = {
.phy_id_mask = MICREL_PHY_ID_MASK,
.name = "Microchip INDY Gigabit Quad PHY",
.driver_data = &ksz9021_type,
- .probe = kszphy_probe,
+ .probe = lan8814_probe,
.soft_reset = genphy_soft_reset,
.read_status = ksz9031_read_status,
.get_sset_count = kszphy_get_sset_count,
@@ -1360,6 +2400,8 @@ static struct phy_driver ksphy_driver[] = {
.get_stats = kszphy_get_stats,
.suspend = genphy_suspend,
.resume = kszphy_resume,
+ .config_intr = lan8814_config_intr,
+ .handle_interrupt = lan8814_handle_interrupt,
}, {
.phy_id = PHY_ID_KSZ9131,
.phy_id_mask = MICREL_PHY_ID_MASK,
--
2.17.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v2 net-next] net: phy: mchp: Add 1588 support for LAN8814 Quad PHY
2020-12-14 17:56 [PATCH v2 net-next] net: phy: mchp: Add 1588 support for LAN8814 Quad PHY Divya Koppera
@ 2020-12-14 19:06 ` Andrew Lunn
2020-12-14 19:20 ` Andrew Lunn
` (3 subsequent siblings)
4 siblings, 0 replies; 7+ messages in thread
From: Andrew Lunn @ 2020-12-14 19:06 UTC (permalink / raw)
To: Divya Koppera
Cc: hkallweit1, linux, davem, kuba, marex, netdev, linux-kernel,
UNGLinuxDriver
> +static int lan8814_read_page_reg(struct phy_device *phydev,
> + int page, u32 addr)
> +{
> + u32 data;
> +
> + phy_write(phydev, KSZ_EXT_PAGE_ACCESS_CONTROL, page);
> + phy_write(phydev, KSZ_EXT_PAGE_ACCESS_ADDRESS_DATA, addr);
> + phy_write(phydev, KSZ_EXT_PAGE_ACCESS_CONTROL, (page | 0x4000));
> + data = phy_read(phydev, KSZ_EXT_PAGE_ACCESS_ADDRESS_DATA);
> +
> + return data;
> +}
> +
> +static int lan8814_write_page_reg(struct phy_device *phydev,
> + int page, u16 addr, u16 val)
> +{
> + phy_write(phydev, KSZ_EXT_PAGE_ACCESS_CONTROL, page);
> + phy_write(phydev, KSZ_EXT_PAGE_ACCESS_ADDRESS_DATA, addr);
> + phy_write(phydev, KSZ_EXT_PAGE_ACCESS_CONTROL, (page | 0x4000));
> + val = phy_write(phydev, KSZ_EXT_PAGE_ACCESS_ADDRESS_DATA, val);
> + if (val != 0) {
> + phydev_err(phydev, "Error: phy_write_mmd has returned error %d\n",
> + val);
> + return val;
> + }
> + return 0;
> +}
I think you can just use phy_read_mmd() and phy_write_mmd().
Andrew
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v2 net-next] net: phy: mchp: Add 1588 support for LAN8814 Quad PHY
2020-12-14 17:56 [PATCH v2 net-next] net: phy: mchp: Add 1588 support for LAN8814 Quad PHY Divya Koppera
2020-12-14 19:06 ` Andrew Lunn
@ 2020-12-14 19:20 ` Andrew Lunn
2020-12-14 19:27 ` Andrew Lunn
` (2 subsequent siblings)
4 siblings, 0 replies; 7+ messages in thread
From: Andrew Lunn @ 2020-12-14 19:20 UTC (permalink / raw)
To: Divya Koppera
Cc: hkallweit1, linux, davem, kuba, marex, netdev, linux-kernel,
UNGLinuxDriver
On Mon, Dec 14, 2020 at 11:26:58PM +0530, Divya Koppera wrote:
> This patch add supports for 1588 Hardware Timestamping support
> to LAN8814 Quad Phy. It supports L2 and Ipv4 encapsulations.
Please could you break this patch up a bit. Add support for link
up/down interrupts in one patch. Then add the PTP support, for
example.
Andrew
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v2 net-next] net: phy: mchp: Add 1588 support for LAN8814 Quad PHY
2020-12-14 17:56 [PATCH v2 net-next] net: phy: mchp: Add 1588 support for LAN8814 Quad PHY Divya Koppera
2020-12-14 19:06 ` Andrew Lunn
2020-12-14 19:20 ` Andrew Lunn
@ 2020-12-14 19:27 ` Andrew Lunn
2020-12-14 23:12 ` Jakub Kicinski
2020-12-18 2:42 ` kernel test robot
4 siblings, 0 replies; 7+ messages in thread
From: Andrew Lunn @ 2020-12-14 19:27 UTC (permalink / raw)
To: Divya Koppera
Cc: hkallweit1, linux, davem, kuba, marex, netdev, linux-kernel,
UNGLinuxDriver
> +struct lan8814_priv {
> + const struct kszphy_type *type;
> + int led_mode;
> + bool rmii_ref_clk_sel;
> + bool rmii_ref_clk_sel_val;
> + u64 stats[ARRAY_SIZE(kszphy_hw_stats)];
> + struct mii_timestamper mii_ts;
> + struct phy_device *phydev;
> + struct lan8814_ptp ptp;
> + int hwts_tx_en;
> + int hwts_rx_en;
> + int layer;
> + int version;
> +};
...
> @@ -304,7 +698,7 @@ static int kszphy_nand_tree_disable(struct phy_device *phydev)
> /* Some config bits need to be set again on resume, handle them here. */
> static int kszphy_config_reset(struct phy_device *phydev)
> {
> - struct kszphy_priv *priv = phydev->priv;
> + struct lan8814_priv *priv = phydev->priv;
> int ret;
>
> if (priv->rmii_ref_clk_sel) {
...
> +static int lan8814_probe(struct phy_device *phydev)
> +{
> + struct lan8814_priv *priv;
> + struct clk *clk;
> + const struct kszphy_type *type = phydev->drv->driver_data;
> + const struct device_node *np = phydev->mdio.dev.of_node;
> +
> + priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL);
> + if (!priv)
> + return -ENOMEM;
> static struct phy_driver ksphy_driver[] = {
> {
> .phy_id = PHY_ID_KS8737,
> @@ -1352,7 +2392,7 @@ static struct phy_driver ksphy_driver[] = {
> .phy_id_mask = MICREL_PHY_ID_MASK,
> .name = "Microchip INDY Gigabit Quad PHY",
> .driver_data = &ksz9021_type,
> - .probe = kszphy_probe,
> + .probe = lan8814_probe,
> .soft_reset = genphy_soft_reset,
> .read_status = ksz9031_read_status,
> .get_sset_count = kszphy_get_sset_count,
> @@ -1360,6 +2400,8 @@ static struct phy_driver ksphy_driver[] = {
> .get_stats = kszphy_get_stats,
> .suspend = genphy_suspend,
> .resume = kszphy_resume,
> + .config_intr = lan8814_config_intr,
> + .handle_interrupt = lan8814_handle_interrupt,
> }, {
> .phy_id = PHY_ID_KSZ9131,
> .phy_id_mask = MICREL_PHY_ID_MASK,
If i'm reading this correctly, only PHYs using lan8814_probe() have a
lan8814_priv. All the other phys have a kszphy_priv. Yet in
kszphy_config_reset() you seem to assume it is a lan8814_priv. This is
dangerous.
It would be much better to define a kszphy_ptp_priv structure, and put
a pointer to it in kszphy_priv. Allocate this structure in
lan8814_probe() and leave it NULL otherwise.
Andrew
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v2 net-next] net: phy: mchp: Add 1588 support for LAN8814 Quad PHY
2020-12-14 17:56 [PATCH v2 net-next] net: phy: mchp: Add 1588 support for LAN8814 Quad PHY Divya Koppera
` (2 preceding siblings ...)
2020-12-14 19:27 ` Andrew Lunn
@ 2020-12-14 23:12 ` Jakub Kicinski
2020-12-18 2:42 ` kernel test robot
4 siblings, 0 replies; 7+ messages in thread
From: Jakub Kicinski @ 2020-12-14 23:12 UTC (permalink / raw)
To: Divya Koppera
Cc: andrew, hkallweit1, linux, davem, marex, netdev, linux-kernel,
UNGLinuxDriver
On Mon, 14 Dec 2020 23:26:58 +0530 Divya Koppera wrote:
> This patch add supports for 1588 Hardware Timestamping support
> to LAN8814 Quad Phy. It supports L2 and Ipv4 encapsulations.
>
> Signed-off-by: Divya Koppera<divya.koppera@microchip.com>
> ---
> v1 -> v2
> * Fixed warnings
> Reported-by: kernel test robot <lkp@intel.com>
Still doesn't build here:
In file included from ../arch/x86/include/asm/page_32.h:35,
from ../arch/x86/include/asm/page.h:14,
from ../arch/x86/include/asm/processor.h:19,
from ../arch/x86/include/asm/timex.h:5,
from ../include/linux/timex.h:65,
from ../include/linux/time32.h:13,
from ../include/linux/time.h:73,
from ../include/linux/stat.h:19,
from ../include/linux/module.h:13,
from ../drivers/net/phy/micrel.c:24:
In function ‘memcmp’,
inlined from ‘lan8814_dequeue_skb’ at ../drivers/net/phy/micrel.c:460:7:
../include/linux/string.h:436:4: error: call to ‘__read_overflow2’ declared with attribute error: detected read beyond size of object passed as 2nd parameter
436 | __read_overflow2();
| ^~~~~~~~~~~~~~~~~~
make[4]: *** [drivers/net/phy/micrel.o] Error 1
make[3]: *** [drivers/net/phy] Error 2
make[3]: *** Waiting for unfinished jobs....
make[2]: *** [drivers/net] Error 2
make[2]: *** Waiting for unfinished jobs....
make[1]: *** [drivers] Error 2
make[1]: *** Waiting for unfinished jobs....
make: *** [__sub-make] Error 2
In file included from ../arch/x86/include/asm/page_32.h:35,
from ../arch/x86/include/asm/page.h:14,
from ../arch/x86/include/asm/processor.h:19,
from ../arch/x86/include/asm/timex.h:5,
from ../include/linux/timex.h:65,
from ../include/linux/time32.h:13,
from ../include/linux/time.h:73,
from ../include/linux/stat.h:19,
from ../include/linux/module.h:13,
from ../drivers/net/phy/micrel.c:24:
In function ‘memcmp’,
inlined from ‘lan8814_dequeue_skb’ at ../drivers/net/phy/micrel.c:460:7:
../include/linux/string.h:436:4: error: call to ‘__read_overflow2’ declared with attribute error: detected read beyond size of object passed as 2nd parameter
436 | __read_overflow2();
| ^~~~~~~~~~~~~~~~~~
make[4]: *** [drivers/net/phy/micrel.o] Error 1
make[3]: *** [drivers/net/phy] Error 2
make[3]: *** Waiting for unfinished jobs....
make[2]: *** [drivers/net] Error 2
make[2]: *** Waiting for unfinished jobs....
make[1]: *** [drivers] Error 2
make: *** [__sub-make] Error 2
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v2 net-next] net: phy: mchp: Add 1588 support for LAN8814 Quad PHY
2020-12-14 17:56 [PATCH v2 net-next] net: phy: mchp: Add 1588 support for LAN8814 Quad PHY Divya Koppera
@ 2020-12-18 2:42 ` kernel test robot
2020-12-14 19:20 ` Andrew Lunn
` (3 subsequent siblings)
4 siblings, 0 replies; 7+ messages in thread
From: kernel test robot @ 2020-12-18 2:42 UTC (permalink / raw)
To: Divya Koppera, andrew, hkallweit1, linux, davem, kuba, marex,
netdev, linux-kernel
Cc: kbuild-all, clang-built-linux, UNGLinuxDriver
[-- Attachment #1: Type: text/plain, Size: 8448 bytes --]
Hi Divya,
Thank you for the patch! Perhaps something to improve:
[auto build test WARNING on net-next/master]
url: https://github.com/0day-ci/linux/commits/Divya-Koppera/net-phy-mchp-Add-1588-support-for-LAN8814-Quad-PHY/20201215-020140
base: https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git 13458ffe0a953e17587f172a8e5059c243e6850a
config: powerpc-randconfig-r025-20201217 (attached as .config)
compiler: clang version 12.0.0 (https://github.com/llvm/llvm-project cee1e7d14f4628d6174b33640d502bff3b54ae45)
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# install powerpc cross compiling tool for clang build
# apt-get install binutils-powerpc-linux-gnu
# https://github.com/0day-ci/linux/commit/d92cad561db30d2e4d3e70352b2f715b5c775fe8
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review Divya-Koppera/net-phy-mchp-Add-1588-support-for-LAN8814-Quad-PHY/20201215-020140
git checkout d92cad561db30d2e4d3e70352b2f715b5c775fe8
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=powerpc
If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>
All warnings (new ones prefixed by >>):
>> drivers/net/phy/micrel.c:1641:6: warning: variable 'rxcfg' is used uninitialized whenever 'if' condition is false [-Wsometimes-uninitialized]
if (lan8814->hwts_rx_en && (lan8814->layer & PTP_CLASS_L2))
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/net/phy/micrel.c:1657:66: note: uninitialized use occurs here
lan8814_write_page_reg(lan8814->phydev, 5, PTP_RX_PARSE_CONFIG, rxcfg);
^~~~~
drivers/net/phy/micrel.c:1641:2: note: remove the 'if' if its condition is always true
if (lan8814->hwts_rx_en && (lan8814->layer & PTP_CLASS_L2))
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>> drivers/net/phy/micrel.c:1641:6: warning: variable 'rxcfg' is used uninitialized whenever '&&' condition is false [-Wsometimes-uninitialized]
if (lan8814->hwts_rx_en && (lan8814->layer & PTP_CLASS_L2))
^~~~~~~~~~~~~~~~~~~
drivers/net/phy/micrel.c:1657:66: note: uninitialized use occurs here
lan8814_write_page_reg(lan8814->phydev, 5, PTP_RX_PARSE_CONFIG, rxcfg);
^~~~~
drivers/net/phy/micrel.c:1641:6: note: remove the '&&' if its condition is always true
if (lan8814->hwts_rx_en && (lan8814->layer & PTP_CLASS_L2))
^~~~~~~~~~~~~~~~~~~~~~
drivers/net/phy/micrel.c:1597:18: note: initialize the variable 'rxcfg' to silence this warning
int txcfg, rxcfg;
^
= 0
>> drivers/net/phy/micrel.c:1644:6: warning: variable 'txcfg' is used uninitialized whenever 'if' condition is false [-Wsometimes-uninitialized]
if (lan8814->hwts_tx_en && (lan8814->layer & PTP_CLASS_L2))
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/net/phy/micrel.c:1658:66: note: uninitialized use occurs here
lan8814_write_page_reg(lan8814->phydev, 5, PTP_TX_PARSE_CONFIG, txcfg);
^~~~~
drivers/net/phy/micrel.c:1644:2: note: remove the 'if' if its condition is always true
if (lan8814->hwts_tx_en && (lan8814->layer & PTP_CLASS_L2))
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>> drivers/net/phy/micrel.c:1644:6: warning: variable 'txcfg' is used uninitialized whenever '&&' condition is false [-Wsometimes-uninitialized]
if (lan8814->hwts_tx_en && (lan8814->layer & PTP_CLASS_L2))
^~~~~~~~~~~~~~~~~~~
drivers/net/phy/micrel.c:1658:66: note: uninitialized use occurs here
lan8814_write_page_reg(lan8814->phydev, 5, PTP_TX_PARSE_CONFIG, txcfg);
^~~~~
drivers/net/phy/micrel.c:1644:6: note: remove the '&&' if its condition is always true
if (lan8814->hwts_tx_en && (lan8814->layer & PTP_CLASS_L2))
^~~~~~~~~~~~~~~~~~~~~~
drivers/net/phy/micrel.c:1597:11: note: initialize the variable 'txcfg' to silence this warning
int txcfg, rxcfg;
^
= 0
4 warnings generated.
vim +1641 drivers/net/phy/micrel.c
1592
1593 static int lan8814_hwtstamp(struct mii_timestamper *mii_ts, struct ifreq *ifr)
1594 {
1595 struct lan8814_priv *lan8814 = container_of(mii_ts, struct lan8814_priv, mii_ts);
1596 struct hwtstamp_config config;
1597 int txcfg, rxcfg;
1598
1599 if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
1600 return -EFAULT;
1601
1602 lan8814->hwts_tx_en = config.tx_type;
1603
1604 lan8814->ptp.rx_filter = config.rx_filter;
1605 lan8814->ptp.tx_type = config.tx_type;
1606
1607 switch (config.rx_filter) {
1608 case HWTSTAMP_FILTER_NONE:
1609 lan8814->hwts_rx_en = 0;
1610 lan8814->layer = 0;
1611 lan8814->version = 0;
1612 break;
1613 case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
1614 case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
1615 case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
1616 lan8814->hwts_rx_en = 1;
1617 lan8814->layer = PTP_CLASS_L4;
1618 lan8814->version = PTP_CLASS_V2;
1619 break;
1620 case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
1621 case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
1622 case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
1623 lan8814->hwts_rx_en = 1;
1624 lan8814->layer = PTP_CLASS_L2;
1625 lan8814->version = PTP_CLASS_V2;
1626 break;
1627 case HWTSTAMP_FILTER_PTP_V2_EVENT:
1628 case HWTSTAMP_FILTER_PTP_V2_SYNC:
1629 case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
1630 lan8814->hwts_rx_en = 1;
1631 lan8814->layer = PTP_CLASS_L4 | PTP_CLASS_L2;
1632 lan8814->version = PTP_CLASS_V2;
1633 break;
1634 default:
1635 return -ERANGE;
1636 }
1637
1638 lan8814_write_page_reg(lan8814->phydev, 5, PTP_RX_PARSE_CONFIG, 0);
1639 lan8814_write_page_reg(lan8814->phydev, 5, PTP_TX_PARSE_CONFIG, 0);
1640
> 1641 if (lan8814->hwts_rx_en && (lan8814->layer & PTP_CLASS_L2))
1642 rxcfg = PTP_RX_PARSE_CONFIG_LAYER2_EN_;
1643
> 1644 if (lan8814->hwts_tx_en && (lan8814->layer & PTP_CLASS_L2))
1645 txcfg = PTP_TX_PARSE_CONFIG_LAYER2_EN_;
1646
1647 if (lan8814->hwts_rx_en && (lan8814->layer & PTP_CLASS_L4))
1648 rxcfg |= PTP_RX_PARSE_CONFIG_IPV4_EN_;
1649
1650 if (lan8814->hwts_tx_en && (lan8814->layer & PTP_CLASS_L4))
1651 txcfg |= PTP_TX_PARSE_CONFIG_IPV4_EN_;
1652
1653 if (lan8814_ptp_is_enable(lan8814->phydev))
1654 lan8814_write_page_reg(lan8814->phydev, 4, PTP_CMD_CTL,
1655 PTP_CMD_CTL_PTP_DISABLE_);
1656
1657 lan8814_write_page_reg(lan8814->phydev, 5, PTP_RX_PARSE_CONFIG, rxcfg);
1658 lan8814_write_page_reg(lan8814->phydev, 5, PTP_TX_PARSE_CONFIG, txcfg);
1659 lan8814_write_page_reg(lan8814->phydev, 5, PTP_RX_TIMESTAMP_EN, 0x3);
1660 lan8814_write_page_reg(lan8814->phydev, 5, PTP_TX_TIMESTAMP_EN, 0x3);
1661 lan8814_write_page_reg(lan8814->phydev, 5, PTP_TX_PARSE_L2_ADDR_EN, 0);
1662 lan8814_write_page_reg(lan8814->phydev, 5, PTP_RX_PARSE_L2_ADDR_EN, 0);
1663
1664 lan8814_write_page_reg(lan8814->phydev, 4, PTP_CMD_CTL, PTP_CMD_CTL_PTP_ENABLE_);
1665 if (lan8814->hwts_tx_en == HWTSTAMP_TX_ONESTEP_SYNC) {
1666 lan8814_write_page_reg(lan8814->phydev, 5, PTP_TX_MOD,
1667 PTP_TX_MOD_TX_PTP_SYNC_TS_INSERT_);
1668 } else if (lan8814->hwts_tx_en == HWTSTAMP_TX_ON) {
1669 /* Enabling 2 step offloading and all option for TS insertion/correction fields */
1670 lan8814_write_page_reg(lan8814->phydev, 5, PTP_TX_MOD, 0x800);
1671 lan8814_config_ts_intr(lan8814->phydev);
1672 }
1673
1674 return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? -EFAULT : 0;
1675 }
1676
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 39189 bytes --]
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v2 net-next] net: phy: mchp: Add 1588 support for LAN8814 Quad PHY
@ 2020-12-18 2:42 ` kernel test robot
0 siblings, 0 replies; 7+ messages in thread
From: kernel test robot @ 2020-12-18 2:42 UTC (permalink / raw)
To: kbuild-all
[-- Attachment #1: Type: text/plain, Size: 8615 bytes --]
Hi Divya,
Thank you for the patch! Perhaps something to improve:
[auto build test WARNING on net-next/master]
url: https://github.com/0day-ci/linux/commits/Divya-Koppera/net-phy-mchp-Add-1588-support-for-LAN8814-Quad-PHY/20201215-020140
base: https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git 13458ffe0a953e17587f172a8e5059c243e6850a
config: powerpc-randconfig-r025-20201217 (attached as .config)
compiler: clang version 12.0.0 (https://github.com/llvm/llvm-project cee1e7d14f4628d6174b33640d502bff3b54ae45)
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# install powerpc cross compiling tool for clang build
# apt-get install binutils-powerpc-linux-gnu
# https://github.com/0day-ci/linux/commit/d92cad561db30d2e4d3e70352b2f715b5c775fe8
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review Divya-Koppera/net-phy-mchp-Add-1588-support-for-LAN8814-Quad-PHY/20201215-020140
git checkout d92cad561db30d2e4d3e70352b2f715b5c775fe8
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=powerpc
If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>
All warnings (new ones prefixed by >>):
>> drivers/net/phy/micrel.c:1641:6: warning: variable 'rxcfg' is used uninitialized whenever 'if' condition is false [-Wsometimes-uninitialized]
if (lan8814->hwts_rx_en && (lan8814->layer & PTP_CLASS_L2))
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/net/phy/micrel.c:1657:66: note: uninitialized use occurs here
lan8814_write_page_reg(lan8814->phydev, 5, PTP_RX_PARSE_CONFIG, rxcfg);
^~~~~
drivers/net/phy/micrel.c:1641:2: note: remove the 'if' if its condition is always true
if (lan8814->hwts_rx_en && (lan8814->layer & PTP_CLASS_L2))
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>> drivers/net/phy/micrel.c:1641:6: warning: variable 'rxcfg' is used uninitialized whenever '&&' condition is false [-Wsometimes-uninitialized]
if (lan8814->hwts_rx_en && (lan8814->layer & PTP_CLASS_L2))
^~~~~~~~~~~~~~~~~~~
drivers/net/phy/micrel.c:1657:66: note: uninitialized use occurs here
lan8814_write_page_reg(lan8814->phydev, 5, PTP_RX_PARSE_CONFIG, rxcfg);
^~~~~
drivers/net/phy/micrel.c:1641:6: note: remove the '&&' if its condition is always true
if (lan8814->hwts_rx_en && (lan8814->layer & PTP_CLASS_L2))
^~~~~~~~~~~~~~~~~~~~~~
drivers/net/phy/micrel.c:1597:18: note: initialize the variable 'rxcfg' to silence this warning
int txcfg, rxcfg;
^
= 0
>> drivers/net/phy/micrel.c:1644:6: warning: variable 'txcfg' is used uninitialized whenever 'if' condition is false [-Wsometimes-uninitialized]
if (lan8814->hwts_tx_en && (lan8814->layer & PTP_CLASS_L2))
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/net/phy/micrel.c:1658:66: note: uninitialized use occurs here
lan8814_write_page_reg(lan8814->phydev, 5, PTP_TX_PARSE_CONFIG, txcfg);
^~~~~
drivers/net/phy/micrel.c:1644:2: note: remove the 'if' if its condition is always true
if (lan8814->hwts_tx_en && (lan8814->layer & PTP_CLASS_L2))
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>> drivers/net/phy/micrel.c:1644:6: warning: variable 'txcfg' is used uninitialized whenever '&&' condition is false [-Wsometimes-uninitialized]
if (lan8814->hwts_tx_en && (lan8814->layer & PTP_CLASS_L2))
^~~~~~~~~~~~~~~~~~~
drivers/net/phy/micrel.c:1658:66: note: uninitialized use occurs here
lan8814_write_page_reg(lan8814->phydev, 5, PTP_TX_PARSE_CONFIG, txcfg);
^~~~~
drivers/net/phy/micrel.c:1644:6: note: remove the '&&' if its condition is always true
if (lan8814->hwts_tx_en && (lan8814->layer & PTP_CLASS_L2))
^~~~~~~~~~~~~~~~~~~~~~
drivers/net/phy/micrel.c:1597:11: note: initialize the variable 'txcfg' to silence this warning
int txcfg, rxcfg;
^
= 0
4 warnings generated.
vim +1641 drivers/net/phy/micrel.c
1592
1593 static int lan8814_hwtstamp(struct mii_timestamper *mii_ts, struct ifreq *ifr)
1594 {
1595 struct lan8814_priv *lan8814 = container_of(mii_ts, struct lan8814_priv, mii_ts);
1596 struct hwtstamp_config config;
1597 int txcfg, rxcfg;
1598
1599 if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
1600 return -EFAULT;
1601
1602 lan8814->hwts_tx_en = config.tx_type;
1603
1604 lan8814->ptp.rx_filter = config.rx_filter;
1605 lan8814->ptp.tx_type = config.tx_type;
1606
1607 switch (config.rx_filter) {
1608 case HWTSTAMP_FILTER_NONE:
1609 lan8814->hwts_rx_en = 0;
1610 lan8814->layer = 0;
1611 lan8814->version = 0;
1612 break;
1613 case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
1614 case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
1615 case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
1616 lan8814->hwts_rx_en = 1;
1617 lan8814->layer = PTP_CLASS_L4;
1618 lan8814->version = PTP_CLASS_V2;
1619 break;
1620 case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
1621 case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
1622 case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
1623 lan8814->hwts_rx_en = 1;
1624 lan8814->layer = PTP_CLASS_L2;
1625 lan8814->version = PTP_CLASS_V2;
1626 break;
1627 case HWTSTAMP_FILTER_PTP_V2_EVENT:
1628 case HWTSTAMP_FILTER_PTP_V2_SYNC:
1629 case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
1630 lan8814->hwts_rx_en = 1;
1631 lan8814->layer = PTP_CLASS_L4 | PTP_CLASS_L2;
1632 lan8814->version = PTP_CLASS_V2;
1633 break;
1634 default:
1635 return -ERANGE;
1636 }
1637
1638 lan8814_write_page_reg(lan8814->phydev, 5, PTP_RX_PARSE_CONFIG, 0);
1639 lan8814_write_page_reg(lan8814->phydev, 5, PTP_TX_PARSE_CONFIG, 0);
1640
> 1641 if (lan8814->hwts_rx_en && (lan8814->layer & PTP_CLASS_L2))
1642 rxcfg = PTP_RX_PARSE_CONFIG_LAYER2_EN_;
1643
> 1644 if (lan8814->hwts_tx_en && (lan8814->layer & PTP_CLASS_L2))
1645 txcfg = PTP_TX_PARSE_CONFIG_LAYER2_EN_;
1646
1647 if (lan8814->hwts_rx_en && (lan8814->layer & PTP_CLASS_L4))
1648 rxcfg |= PTP_RX_PARSE_CONFIG_IPV4_EN_;
1649
1650 if (lan8814->hwts_tx_en && (lan8814->layer & PTP_CLASS_L4))
1651 txcfg |= PTP_TX_PARSE_CONFIG_IPV4_EN_;
1652
1653 if (lan8814_ptp_is_enable(lan8814->phydev))
1654 lan8814_write_page_reg(lan8814->phydev, 4, PTP_CMD_CTL,
1655 PTP_CMD_CTL_PTP_DISABLE_);
1656
1657 lan8814_write_page_reg(lan8814->phydev, 5, PTP_RX_PARSE_CONFIG, rxcfg);
1658 lan8814_write_page_reg(lan8814->phydev, 5, PTP_TX_PARSE_CONFIG, txcfg);
1659 lan8814_write_page_reg(lan8814->phydev, 5, PTP_RX_TIMESTAMP_EN, 0x3);
1660 lan8814_write_page_reg(lan8814->phydev, 5, PTP_TX_TIMESTAMP_EN, 0x3);
1661 lan8814_write_page_reg(lan8814->phydev, 5, PTP_TX_PARSE_L2_ADDR_EN, 0);
1662 lan8814_write_page_reg(lan8814->phydev, 5, PTP_RX_PARSE_L2_ADDR_EN, 0);
1663
1664 lan8814_write_page_reg(lan8814->phydev, 4, PTP_CMD_CTL, PTP_CMD_CTL_PTP_ENABLE_);
1665 if (lan8814->hwts_tx_en == HWTSTAMP_TX_ONESTEP_SYNC) {
1666 lan8814_write_page_reg(lan8814->phydev, 5, PTP_TX_MOD,
1667 PTP_TX_MOD_TX_PTP_SYNC_TS_INSERT_);
1668 } else if (lan8814->hwts_tx_en == HWTSTAMP_TX_ON) {
1669 /* Enabling 2 step offloading and all option for TS insertion/correction fields */
1670 lan8814_write_page_reg(lan8814->phydev, 5, PTP_TX_MOD, 0x800);
1671 lan8814_config_ts_intr(lan8814->phydev);
1672 }
1673
1674 return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? -EFAULT : 0;
1675 }
1676
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org
[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 39189 bytes --]
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2020-12-18 2:44 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-12-14 17:56 [PATCH v2 net-next] net: phy: mchp: Add 1588 support for LAN8814 Quad PHY Divya Koppera
2020-12-14 19:06 ` Andrew Lunn
2020-12-14 19:20 ` Andrew Lunn
2020-12-14 19:27 ` Andrew Lunn
2020-12-14 23:12 ` Jakub Kicinski
2020-12-18 2:42 ` kernel test robot
2020-12-18 2:42 ` kernel test robot
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.