From 0f55d888c83aed7ea5a10761edaff52de8dc06a1 Mon Sep 17 00:00:00 2001 From: Vladimir Barinov 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 --- .../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 #include #include +#include #include #include #include @@ -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