diff --git a/drivers/net/ethernet/ti/prueth.h b/drivers/net/ethernet/ti/prueth.h
index 3259c84f6f795f8234ed3a8c45d7278abeee6edc..4af2c4cfd3c4c87a87d2b7c6f7a98f000a947842 100644
--- a/drivers/net/ethernet/ti/prueth.h
+++ b/drivers/net/ethernet/ti/prueth.h
@@ -382,6 +382,7 @@ struct prueth_emac {
 	struct sk_buff *ptp_skb[PRUETH_PTP_TS_EVENTS];
 	spinlock_t ptp_skb_lock;	/* serialize access */
 	int emac_ptp_tx_irq;
+	int hsr_ptp_tx_irq;
 	bool ptp_tx_enable;
 };
 
@@ -488,6 +489,8 @@ int emac_rx_packet(struct prueth_emac *emac, u16 *bd_rd_ptr,
 		   const struct prueth_queue_info *rxqueue);
 int emac_add_del_vid(struct prueth_emac *emac,
 		     bool add, __be16 proto, u16 vid);
+irqreturn_t prueth_ptp_tx_irq_handle(int irq, void *dev);
+irqreturn_t prueth_ptp_tx_irq_work(int irq, void *dev);
 
 extern const struct prueth_queue_desc queue_descs[][NUM_QUEUES];
 
diff --git a/drivers/net/ethernet/ti/prueth_core.c b/drivers/net/ethernet/ti/prueth_core.c
index be4d0d23593ef6909ac98d481bd0892da88052dc..51091ea85fc961c16d24beee578b7f3711fc0861 100644
--- a/drivers/net/ethernet/ti/prueth_core.c
+++ b/drivers/net/ethernet/ti/prueth_core.c
@@ -741,13 +741,26 @@ static irqreturn_t emac_rx_hardirq(int irq, void *dev_id)
 
 static u8 prueth_ptp_ts_event_type(struct sk_buff *skb)
 {
-	unsigned int ptp_class = ptp_classify_raw(skb);
-	u8 *msgtype, *data = skb->data, event_type;
-	unsigned int offset = 0;
+	u8 *msgtype, *data, event_type, changed = 0;
+	unsigned int offset = 0, ptp_class;
 	u16 *seqid;
 
-	if (ptp_class == PTP_CLASS_NONE)
-		return PRUETH_PTP_TS_EVENTS;
+	if (eth_hdr(skb)->h_proto == htons(ETH_P_HSR)) {
+		/* This 6-byte shift is just a trick to skip
+		 * the size of a hsr tag so that the same
+		 * pruptp_ts_msgtype can be re-used to parse
+		 * hsr tagged skbs
+		 */
+		skb->data += 6;
+		changed = 6;
+	}
+
+	ptp_class = ptp_classify_raw(skb);
+	data = skb->data;
+	if (ptp_class == PTP_CLASS_NONE) {
+		event_type = PRUETH_PTP_TS_EVENTS;
+		goto exit;
+	}
 
 	if (ptp_class & PTP_CLASS_VLAN)
 		offset += VLAN_HLEN;
@@ -766,8 +779,10 @@ static u8 prueth_ptp_ts_event_type(struct sk_buff *skb)
 		return PRUETH_PTP_TS_EVENTS;
 	}
 
-	if (skb->len + ETH_HLEN < offset + OFF_PTP_SEQUENCE_ID + sizeof(*seqid))
-		return PRUETH_PTP_TS_EVENTS;
+	if (skb->len + ETH_HLEN < offset + OFF_PTP_SEQUENCE_ID + sizeof(*seqid)) {
+		event_type = PRUETH_PTP_TS_EVENTS;
+		goto exit;
+	}
 
 	if (unlikely(ptp_class & PTP_CLASS_V1))
 		msgtype = data + offset + OFF_PTP_CONTROL;
@@ -796,6 +811,9 @@ static u8 prueth_ptp_ts_event_type(struct sk_buff *skb)
 		event_type = PRUETH_PTP_TS_EVENTS;
 	}
 
+exit:
+	skb->data -= changed;
+
 	return event_type;
 }
 
@@ -836,7 +854,7 @@ static int prueth_ptp_tx_ts_enqueue(struct prueth_emac *emac, struct sk_buff *sk
 	return 0;
 }
 
-static irqreturn_t prueth_ptp_tx_irq_handle(int irq, void *dev)
+irqreturn_t prueth_ptp_tx_irq_handle(int irq, void *dev)
 {
 	struct net_device *ndev = (struct net_device *)dev;
 	struct prueth_emac *emac = netdev_priv(ndev);
@@ -874,6 +892,15 @@ static void prueth_ptp_tx_ts_get(struct prueth_emac *emac, u8 event)
 	emac->ptp_skb[event] = NULL;
 	spin_unlock_irqrestore(&emac->ptp_skb_lock, flags);
 	if (!skb) {
+		/* In case of HSR, tx timestamp may be generated by
+		 * cut-through packets such as SYNC, which does not
+		 * have a corresponding queued tx packet. Such a tx
+		 * timestamp is consumed by the rx port when processing
+		 * the rx timestamp.
+		 */
+		if (PRUETH_IS_LRE(emac->prueth))
+			return;
+
 		netdev_err(emac->ndev, "no tx msg %u found waiting for ts\n",
 			   event);
 		return;
@@ -889,7 +916,7 @@ static void prueth_ptp_tx_ts_get(struct prueth_emac *emac, u8 event)
 	dev_consume_skb_any(skb);
 }
 
-static irqreturn_t prueth_ptp_tx_irq_work(int irq, void *dev)
+irqreturn_t prueth_ptp_tx_irq_work(int irq, void *dev)
 {
 	struct prueth_emac *emac = netdev_priv(dev);
 	u32 ts_notify_offs, ts_notify_mask, i;
@@ -1202,6 +1229,7 @@ int emac_rx_packet(struct prueth_emac *emac, u16 *bd_rd_ptr,
 		ptr = nt_dst_addr + PRUETH_ETH_TYPE_OFFSET;
 		type = (*ptr++) << PRUETH_ETH_TYPE_UPPER_SHIFT;
 		type |= *ptr++;
+		eth_hdr(skb)->h_proto = htons(type);
 		if (type == ETH_P_8021Q)
 			offset = 4;
 	}
@@ -2641,6 +2669,12 @@ static int prueth_netdev_init(struct prueth *prueth,
 		dev_err(prueth->dev, "could not get ptp tx irq. Skipping PTP support\n");
 	}
 
+	emac->hsr_ptp_tx_irq = of_irq_get_byname(eth_node, "hsr_ptp_tx");
+	if (emac->hsr_ptp_tx_irq < 0) {
+		emac->hsr_ptp_tx_irq = 0;
+		dev_err(prueth->dev, "could not get hsr ptp tx irq. Skipping PTP support\n");
+	}
+
 	emac->msg_enable = netif_msg_init(debug_level, PRUETH_EMAC_DEBUG);
 	spin_lock_init(&emac->lock);
 	spin_lock_init(&emac->nsp_lock);
diff --git a/drivers/net/ethernet/ti/prueth_lre.c b/drivers/net/ethernet/ti/prueth_lre.c
index 15ab6b9e21416563f7cecc96e6b19d6ad615b9fc..275138c09a93f995e515257994ac6cc711def654 100644
--- a/drivers/net/ethernet/ti/prueth_lre.c
+++ b/drivers/net/ethernet/ti/prueth_lre.c
@@ -858,6 +858,19 @@ int prueth_lre_request_irqs(struct prueth_emac *emac)
 	struct prueth *prueth = emac->prueth;
 	int ret;
 
+	if (emac->hsr_ptp_tx_irq) {
+		ret = request_threaded_irq(emac->hsr_ptp_tx_irq,
+					   prueth_ptp_tx_irq_handle,
+					   prueth_ptp_tx_irq_work,
+					   IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+					   emac->ndev->name, emac->ndev);
+		if (ret) {
+			netdev_err(emac->ndev, "unable to request PTP TX IRQ\n");
+			return ret;
+		}
+
+	}
+
 	/* HSR/PRP. Request irq when first port is initialized */
 	if (prueth->emac_configured)
 		return 0;
@@ -866,17 +879,24 @@ int prueth_lre_request_irqs(struct prueth_emac *emac)
 			  IRQF_TRIGGER_HIGH, "eth_hp_int", prueth->hp);
 	if (ret) {
 		netdev_err(emac->ndev, "unable to request RX HPQ IRQ\n");
-		return ret;
+		goto free_ptp_irq;
 	}
 
 	ret = request_irq(prueth->rx_lpq_irq, prueth_lre_emac_rx_hardirq,
 			  IRQF_TRIGGER_HIGH, "eth_lp_int", prueth->lp);
 	if (ret) {
 		netdev_err(emac->ndev, "unable to request RX LPQ IRQ\n");
-		free_irq(prueth->rx_hpq_irq, prueth->hp);
-		return ret;
+		goto free_rx_hpq_irq;
 	}
 
+	return 0;
+
+free_rx_hpq_irq:
+	free_irq(prueth->rx_hpq_irq, prueth->hp);
+free_ptp_irq:
+	if (emac->hsr_ptp_tx_irq)
+		free_irq(emac->hsr_ptp_tx_irq, emac->ndev);
+
 	return ret;
 }