From 5d5eef59a48e3b8e0f67c2ab0963d380c7a7399d Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Mon, 2 May 2016 22:05:53 +0300 Subject: [PATCH] can: rcar_can: add enable and standby control pins Add enable and standby can transceiver control pins Signed-off-by: Vladimir Barinov --- .../devicetree/bindings/net/can/rcar_can.txt | 4 ++ drivers/net/can/rcar/rcar_can.c | 58 +++++++++++++++++----- include/linux/can/platform/rcar_can.h | 2 + 3 files changed, 51 insertions(+), 13 deletions(-) diff --git a/Documentation/devicetree/bindings/net/can/rcar_can.txt b/Documentation/devicetree/bindings/net/can/rcar_can.txt index 8d40ab2..9293cf8 100644 --- a/Documentation/devicetree/bindings/net/can/rcar_can.txt +++ b/Documentation/devicetree/bindings/net/can/rcar_can.txt @@ -38,6 +38,7 @@ Optional properties: <0x0> (default) : Peripheral clock (clkp1) <0x1> : Peripheral clock (clkp2) <0x3> : Externally input clock +- gpios: GPIO used for controlling the enable pin and standby pin Example ------- @@ -59,5 +60,8 @@ Board specific .dts file: &can0 { pinctrl-0 = <&can0_pins>; pinctrl-names = "default"; + gpios = <&gpio5 29 GPIO_ACTIVE_HIGH /* enable */ + &gpio5 30 GPIO_ACTIVE_LOW /* standby */ + >; status = "okay"; }; diff --git a/drivers/net/can/rcar/rcar_can.c b/drivers/net/can/rcar/rcar_can.c index 788459f..887ca37 100644 --- a/drivers/net/can/rcar/rcar_can.c +++ b/drivers/net/can/rcar/rcar_can.c @@ -21,6 +21,7 @@ #include #include #include +#include #define RCAR_CAN_DRV_NAME "rcar_can" @@ -94,6 +95,8 @@ struct rcar_can_priv { u32 tx_tail; u8 clock_select; u8 ier; + unsigned int enable_pin; /* transceiver enable */ + unsigned int standby_pin; /* transceiver standby */ }; static const struct can_bittiming_const rcar_can_bittiming_const = { @@ -505,6 +508,10 @@ static int rcar_can_open(struct net_device *ndev) struct rcar_can_priv *priv = netdev_priv(ndev); int err; + /* transceiver normal mode */ + if (gpio_is_valid(priv->standby_pin)) + gpio_set_value(priv->standby_pin, 1); + err = clk_prepare_enable(priv->clk); if (err) { netdev_err(ndev, @@ -581,6 +588,9 @@ static int rcar_can_close(struct net_device *ndev) clk_disable_unprepare(priv->clk); close_candev(ndev); can_led_event(ndev, CAN_LED_EVENT_STOP); + /* transceiver stanby mode */ + if (gpio_is_valid(priv->standby_pin)) + gpio_set_value(priv->standby_pin, 0); return 0; } @@ -743,20 +753,9 @@ static int rcar_can_probe(struct platform_device *pdev) struct resource *mem; void __iomem *addr; u32 clock_select = CLKR_CLKP1; - int err = -ENODEV; + int err = -ENODEV, ret; int irq; - - if (pdev->dev.of_node) { - of_property_read_u32(pdev->dev.of_node, - "renesas,can-clock-select", &clock_select); - } else { - pdata = dev_get_platdata(&pdev->dev); - if (!pdata) { - dev_err(&pdev->dev, "No platform data provided!\n"); - goto fail; - } - clock_select = pdata->clock_select; - } + enum of_gpio_flags enable_flags, standby_flags; irq = platform_get_irq(pdev, 0); if (irq < 0) { @@ -826,6 +825,39 @@ static int rcar_can_probe(struct platform_device *pdev) devm_can_led_init(ndev); + if (pdev->dev.of_node) { + of_property_read_u32(pdev->dev.of_node, + "renesas,can-clock-select", &clock_select); + priv->enable_pin = of_get_gpio_flags(pdev->dev.of_node, 0, &enable_flags); + priv->standby_pin = of_get_gpio_flags(pdev->dev.of_node, 1, &standby_flags); + } else { + pdata = dev_get_platdata(&pdev->dev); + if (!pdata) { + dev_err(&pdev->dev, "No platform data provided!\n"); + goto fail; + } + clock_select = pdata->clock_select; + priv->enable_pin = pdata->enable_pin; + priv->standby_pin = pdata->standby_pin; + } + + if (gpio_is_valid(priv->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, priv->enable_pin, val, "enable"); + if (ret) + dev_info(&pdev->dev, "Failed to request enable pin\n"); + } + + if (gpio_is_valid(priv->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, priv->standby_pin, val, "standby"); + if (ret) + dev_info(&pdev->dev, "Failed to request standby pin\n"); + } + dev_info(&pdev->dev, "device registered (regs @ %p, IRQ%d)\n", priv->regs, ndev->irq); diff --git a/include/linux/can/platform/rcar_can.h b/include/linux/can/platform/rcar_can.h index 0f4a2f3..7ef810d 100644 --- a/include/linux/can/platform/rcar_can.h +++ b/include/linux/can/platform/rcar_can.h @@ -12,6 +12,8 @@ enum CLKR { struct rcar_can_platform_data { enum CLKR clock_select; /* Clock source select */ + unsigned int enable_pin; + unsigned int standby_pin; }; #endif /* !_CAN_PLATFORM_RCAR_CAN_H_ */ -- 1.9.1