aboutsummaryrefslogtreecommitdiffstats
path: root/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0011-can-rcar_canfd-add-enable-and-standby-control-pins.patch
blob: c35cacc87177fdbe05ddbb092afecf83e540f244 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
From 0f55d888c83aed7ea5a10761edaff52de8dc06a1 Mon Sep 17 00:00:00 2001
From: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
Date: Mon, 30 May 2016 01:51:47 +0300
Subject: [PATCH] can: rcar_canfd: add enable and standby control pins

Add enable and standby can transceiver control pins

Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
---
 .../devicetree/bindings/net/can/rcar_canfd.txt     |  5 +++
 drivers/net/can/rcar/rcar_canfd.c                       | 48 ++++++++++++++++++----
 2 files changed, 44 insertions(+), 9 deletions(-)

diff --git a/Documentation/devicetree/bindings/net/can/rcar_canfd.txt b/Documentation/devicetree/bindings/net/can/rcar_canfd.txt
index 4299bd8..eede77a 100644
--- a/Documentation/devicetree/bindings/net/can/rcar_canfd.txt
+++ b/Documentation/devicetree/bindings/net/can/rcar_canfd.txt
@@ -16,6 +16,7 @@ Required properties:
 - clock-names: 3 clock input name strings: "fck", "canfd", "can_clk".
 - pinctrl-0: pin control group to be used for this controller.
 - pinctrl-names: must be "default".
+- gpios: GPIO used for controlling the enable pin and standby pin
 
 Required child nodes:
 The controller supports two channels and each is represented as a child node.
@@ -49,6 +50,10 @@ SoC common .dtsi file:
 			power-domains = <&cpg>;
 			status = "disabled";
 
+			gpios = <&gpio5 29 GPIO_ACTIVE_HIGH /* enable */
+				 &gpio5 30 GPIO_ACTIVE_LOW /* standby */
+				>;
+
 			channel0 {
 				status = "disabled";
 			};
diff --git a/drivers/net/can/rcar/rcar_canfd.c b/drivers/net/can/rcar/rcar_canfd.c
index 15a14c5..4aa670d 100644
--- a/drivers/net/can/rcar/rcar_canfd.c
+++ b/drivers/net/can/rcar/rcar_canfd.c
@@ -21,6 +21,7 @@
 #include <linux/clk.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/of_gpio.h>
 #include <linux/bitmap.h>
 #include <linux/bitops.h>
 #include <linux/iopoll.h>
@@ -386,6 +387,8 @@ struct rcar_canfd_global {
 	enum rcar_canfd_fcanclk fcan;	/* CANFD or Ext clock */
 	unsigned long channels_mask;	/* Enabled channels mask */
 	bool fdmode;			/* CAN FD or Classical CAN only mode */
+	unsigned int enable_pin;	/* transceiver enable */
+	unsigned int standby_pin;	/* transceiver standby */
 };
 
 /* CAN FD mode nominal rate constants */
@@ -1063,6 +1066,10 @@ static int rcar_canfd_open(struct net_device *ndev)
 	struct rcar_canfd_global *gpriv = priv->gpriv;
 	int err;
 
+	/* transceiver normal mode */
+	if (gpio_is_valid(gpriv->standby_pin))
+		gpio_set_value(gpriv->standby_pin, 1);
+
 	/* Peripheral clock is already enabled in probe */
 	err = clk_prepare_enable(gpriv->can_clk);
 	if (err) {
@@ -1131,6 +1138,9 @@ static int rcar_canfd_close(struct net_device *ndev)
 	clk_disable_unprepare(gpriv->can_clk);
 	close_candev(ndev);
 	can_led_event(ndev, CAN_LED_EVENT_STOP);
+	/* transceiver stanby mode */
+	if (gpio_is_valid(gpriv->standby_pin))
+		gpio_set_value(gpriv->standby_pin, 0);
 	return 0;
 }
 
@@ -1409,8 +1419,9 @@ static int rcar_canfd_probe(struct platform_device *pdev)
 	struct rcar_canfd_global *gpriv;
 	struct device_node *of_child;
 	unsigned long channels_mask = 0;
-	int err, ch_irq, g_irq;
+	int err, ret, ch_irq, g_irq;
 	bool fdmode = true;			/* CAN FD only mode - default */
+	enum of_gpio_flags enable_flags, standby_flags;
 
 	if (of_property_read_bool(pdev->dev.of_node, "renesas,no-can-fd"))
 		fdmode = false;			/* Classical CAN only mode */
@@ -1552,6 +1555,33 @@ static int rcar_canfd_probe(struct platform_device *pdev)
 			goto fail_channel;
 	}
 
+	of_property_read_u32(pdev->dev.of_node,
+			     "renesas,can-clock-select", &clock_select);
+	if (clock_select >= ARRAY_SIZE(clock_names)) {
+		err = -EINVAL;
+		dev_err(&pdev->dev, "invalid CAN clock selected\n");
+		goto fail_dev;
+	}
+	gpriv->enable_pin = of_get_gpio_flags(pdev->dev.of_node, 0, &enable_flags);
+	gpriv->standby_pin = of_get_gpio_flags(pdev->dev.of_node, 1, &standby_flags);
+
+	if (gpio_is_valid(gpriv->enable_pin)) {
+		int val = enable_flags & OF_GPIO_ACTIVE_LOW ?
+			  GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH;
+		ret = devm_gpio_request_one(&pdev->dev, gpriv->enable_pin, val, "enable");
+		if (ret)
+			dev_info(&pdev->dev, "Failed to request enable pin\n");
+	}
+
+	if (gpio_is_valid(gpriv->standby_pin)) {
+		int val = standby_flags & OF_GPIO_ACTIVE_LOW ?
+			  GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH;
+		/* transceiver standby mode */
+		ret = devm_gpio_request_one(&pdev->dev, gpriv->standby_pin, val, "standby");
+		if (ret)
+			dev_info(&pdev->dev, "Failed to request standby pin\n");
+	}
+
 	platform_set_drvdata(pdev, gpriv);
 	dev_info(&pdev->dev, "global operational state (clk %d, fdmode %d)\n",
 		 gpriv->fcan, gpriv->fdmode);
-- 
1.9.1