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
|