#include <linux/bitfield.h>
 #include <linux/can/dev.h>
 #include <linux/ethtool.h>
+#include <linux/hrtimer.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/iopoll.h>
 #define TX_EVENT_MM_MASK       GENMASK(31, 24)
 #define TX_EVENT_TXTS_MASK     GENMASK(15, 0)
 
+/* Hrtimer polling interval */
+#define HRTIMER_POLL_INTERVAL_MS               1
+
 /* The ID and DLC registers are adjacent in M_CAN FIFO memory,
  * and we can save a (potentially slow) bus round trip by combining
  * reads and writes to them.
 
        m_can_enable_all_interrupts(cdev);
 
+       if (!dev->irq) {
+               dev_dbg(cdev->dev, "Start hrtimer\n");
+               hrtimer_start(&cdev->hrtimer, ms_to_ktime(HRTIMER_POLL_INTERVAL_MS),
+                             HRTIMER_MODE_REL_PINNED);
+       }
+
        return 0;
 }
 
 {
        struct m_can_classdev *cdev = netdev_priv(dev);
 
+       if (!dev->irq) {
+               dev_dbg(cdev->dev, "Stop hrtimer\n");
+               hrtimer_cancel(&cdev->hrtimer);
+       }
+
        /* disable all interrupts */
        m_can_disable_all_interrupts(cdev);
 
        return NETDEV_TX_OK;
 }
 
+static enum hrtimer_restart hrtimer_callback(struct hrtimer *timer)
+{
+       struct m_can_classdev *cdev = container_of(timer, struct
+                                                  m_can_classdev, hrtimer);
+
+       m_can_isr(0, cdev->net);
+
+       hrtimer_forward_now(timer, ms_to_ktime(HRTIMER_POLL_INTERVAL_MS));
+
+       return HRTIMER_RESTART;
+}
+
 static int m_can_open(struct net_device *dev)
 {
        struct m_can_classdev *cdev = netdev_priv(dev);
                err = request_threaded_irq(dev->irq, NULL, m_can_isr,
                                           IRQF_ONESHOT,
                                           dev->name, dev);
-       } else {
+       } else if (dev->irq) {
                err = request_irq(dev->irq, m_can_isr, IRQF_SHARED, dev->name,
                                  dev);
        }
                        goto clk_disable;
        }
 
+       if (!cdev->net->irq)
+               cdev->hrtimer.function = &hrtimer_callback;
+
        ret = m_can_dev_setup(cdev);
        if (ret)
                goto rx_offload_del;
 
 #include <linux/device.h>
 #include <linux/dma-mapping.h>
 #include <linux/freezer.h>
+#include <linux/hrtimer.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/iopoll.h>
        int is_peripheral;
 
        struct mram_cfg mcfg[MRAM_CFG_NUM];
+
+       struct hrtimer hrtimer;
 };
 
 struct m_can_classdev *m_can_class_allocate_dev(struct device *dev, int sizeof_priv);
 
 //
 // Copyright (C) 2018-19 Texas Instruments Incorporated - http://www.ti.com/
 
+#include <linux/hrtimer.h>
 #include <linux/phy/phy.h>
 #include <linux/platform_device.h>
 
        void __iomem *addr;
        void __iomem *mram_addr;
        struct phy *transceiver;
-       int irq, ret = 0;
+       int irq = 0, ret = 0;
 
        mcan_class = m_can_class_allocate_dev(&pdev->dev,
                                              sizeof(struct m_can_plat_priv));
                goto probe_fail;
 
        addr = devm_platform_ioremap_resource_byname(pdev, "m_can");
-       irq = platform_get_irq_byname(pdev, "int0");
-       if (IS_ERR(addr) || irq < 0) {
-               ret = -EINVAL;
+       if (IS_ERR(addr)) {
+               ret = PTR_ERR(addr);
                goto probe_fail;
        }
 
+       if (device_property_present(mcan_class->dev, "interrupts") ||
+           device_property_present(mcan_class->dev, "interrupt-names")) {
+               irq = platform_get_irq_byname(pdev, "int0");
+               if (irq < 0) {
+                       ret = irq;
+                       goto probe_fail;
+               }
+       } else {
+               dev_dbg(mcan_class->dev, "Polling enabled, initialize hrtimer");
+               hrtimer_init(&mcan_class->hrtimer, CLOCK_MONOTONIC,
+                            HRTIMER_MODE_REL_PINNED);
+       }
+
        /* message ram could be shared */
        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "message_ram");
        if (!res) {