summaryrefslogtreecommitdiff
path: root/drivers/net/can/m_can/m_can_platform.c
diff options
context:
space:
mode:
authorJudith Mendez <jm@ti.com>2023-05-30 17:48:20 -0500
committerHiago De Franco <hiago.franco@toradex.com>2023-06-16 18:24:42 +0200
commiteebf5918e7c7e39eeec8779b9572edf736f19451 (patch)
tree0ddacec5a901a81ccbd048bf748a153ae4e9ee18 /drivers/net/can/m_can/m_can_platform.c
parent12a61f35933af8326d8267335d425b159eef71f1 (diff)
can: m_can: Add hrtimer to generate software interrupt
Introduce timer polling method to MCAN since some SoCs may not have M_CAN interrupt routed to A53 Linux and do not have interrupt property in device tree M_CAN node. On AM62x SoC, MCANs on MCU domain do not have hardware interrupt routed to A53 Linux, instead they will use timer polling method. Add an hrtimer to MCAN class device. Each MCAN will have its own hrtimer instantiated if there is no hardware interrupt found in device tree M_CAN node. The timer will generate a software interrupt every 1 ms. In hrtimer callback, we check if there is a transaction pending by reading a register, then process by calling the isr if there is. Upstream-Status: Submitted [https://lore.kernel.org/all/20230530224820.303619-3-jm@ti.com/] Signed-off-by: Judith Mendez <jm@ti.com>
Diffstat (limited to 'drivers/net/can/m_can/m_can_platform.c')
-rw-r--r--drivers/net/can/m_can/m_can_platform.c23
1 files changed, 20 insertions, 3 deletions
diff --git a/drivers/net/can/m_can/m_can_platform.c b/drivers/net/can/m_can/m_can_platform.c
index 45910fb5145c..ab8e056e2ee7 100644
--- a/drivers/net/can/m_can/m_can_platform.c
+++ b/drivers/net/can/m_can/m_can_platform.c
@@ -7,6 +7,7 @@
#include <linux/platform_device.h>
#include <linux/phy/phy.h>
+#include <linux/hrtimer.h>
#include "m_can.h"
@@ -82,11 +83,27 @@ static int m_can_plat_probe(struct platform_device *pdev)
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "m_can");
addr = devm_ioremap_resource(&pdev->dev, res);
- 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 == -EPROBE_DEFER) {
+ ret = -EPROBE_DEFER;
+ goto probe_fail;
+ }
+ if (irq < 0) {
+ ret = -EINVAL;
+ goto probe_fail;
+ }
+ } else {
+ irq = 0;
+ 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");