[PATCH v2 2/2] net: flexcan: add transceiver switch gpios support
Marc Kleine-Budde
mkl at pengutronix.de
Thu Jun 28 06:31:56 EDT 2012
On 06/28/2012 05:21 AM, Shawn Guo wrote:
> The flexcan driver has function pointer transceiver_switch defined in
> flexcan_platform_data for platform codes to hook up their transceiver
> switch implementation. However this does not cope with device tree
> probe.
>
> It's been observed that platforms mostly use gpios to control the
> switch of flexcan transceiver, like enable and standby. The patch
> adds transceiver switch gpios support into flexcan driver, so that
> platforms booting from device tree can just define properties
> phy-enable-gpios and phy-standby-gpios to have flexcan driver control
> the gpios.
Hmm I'm wondering if transceiver or phy is the correct name here. In
platform_data it's called transceiver_switch.
>
> Signed-off-by: Shawn Guo <shawn.guo at linaro.org>
> ---
> .../devicetree/bindings/net/can/fsl-flexcan.txt | 2 +
> drivers/net/can/flexcan.c | 62 ++++++++++++++++++++
> 2 files changed, 64 insertions(+), 0 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/net/can/fsl-flexcan.txt b/Documentation/devicetree/bindings/net/can/fsl-flexcan.txt
> index 8ff324e..e0dbac7 100644
> --- a/Documentation/devicetree/bindings/net/can/fsl-flexcan.txt
> +++ b/Documentation/devicetree/bindings/net/can/fsl-flexcan.txt
> @@ -15,6 +15,8 @@ Required properties:
> Optional properties:
>
> - clock-frequency : The oscillator frequency driving the flexcan device
> +- phy-enable-gpios : Specify the gpio used to enable phy
> +- phy-standby-gpios : Specify the gpio used to put phy into STANDBY mode
>
> Example:
>
> diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
> index 38c0690..1ce3f9e 100644
> --- a/drivers/net/can/flexcan.c
> +++ b/drivers/net/can/flexcan.c
> @@ -26,6 +26,7 @@
> #include <linux/can/platform/flexcan.h>
> #include <linux/clk.h>
> #include <linux/delay.h>
> +#include <linux/gpio.h>
> #include <linux/if_arp.h>
> #include <linux/if_ether.h>
> #include <linux/interrupt.h>
> @@ -34,6 +35,7 @@
> #include <linux/list.h>
> #include <linux/module.h>
> #include <linux/of.h>
> +#include <linux/of_gpio.h>
> #include <linux/platform_device.h>
> #include <linux/pinctrl/consumer.h>
>
> @@ -180,6 +182,11 @@ struct flexcan_priv {
>
> struct clk *clk;
> struct flexcan_platform_data *pdata;
> +
> + int phy_en_gpio;
> + int phy_stby_gpio;
> + bool phy_en_high;
> + bool phy_stby_high;
> };
>
> static struct can_bittiming_const flexcan_bittiming_const = {
> @@ -224,6 +231,17 @@ static inline void flexcan_write(u32 val, void __iomem *addr)
> */
> static void flexcan_transceiver_switch(const struct flexcan_priv *priv, int on)
> {
> + /*
> + * on == 1: enable phy and exit standby
> + * on == 0: disable phy and enter standby
> + */
> + if (gpio_is_valid(priv->phy_en_gpio))
> + gpio_set_value(priv->phy_en_gpio,
> + priv->phy_en_high ? on : !on);
> + if (gpio_is_valid(priv->phy_stby_gpio))
> + gpio_set_value(priv->phy_stby_gpio,
> + priv->phy_stby_high ? !on : on);
> +
> if (priv->pdata && priv->pdata->transceiver_switch)
> priv->pdata->transceiver_switch(on);
> }
> @@ -933,6 +951,10 @@ static int __devinit flexcan_probe(struct platform_device *pdev)
> resource_size_t mem_size;
> int err, irq;
> u32 clock_freq = 0;
> + int phy_en_gpio = -EINVAL;
> + int phy_stby_gpio = -EINVAL;
> + bool phy_en_high = true;
> + bool phy_stby_high = true;
>
> pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
> if (IS_ERR(pinctrl))
> @@ -940,11 +962,46 @@ static int __devinit flexcan_probe(struct platform_device *pdev)
>
> if (pdev->dev.of_node) {
> const u32 *clock_freq_p;
> + enum of_gpio_flags flags;
>
> clock_freq_p = of_get_property(pdev->dev.of_node,
> "clock-frequency", NULL);
> if (clock_freq_p)
> clock_freq = *clock_freq_p;
> +
> + phy_en_gpio = of_get_named_gpio_flags(pdev->dev.of_node,
> + "phy-enable-gpios",
> + 0, &flags);
> + if (gpio_is_valid(phy_en_gpio)) {
> + if (flags == OF_GPIO_ACTIVE_LOW)
> + phy_en_high = false;
I really like the "flags" solution, much better than a DT property. What
about keeping the term active_low instead of en_high? From my limited
knowledge about electronic I say, that active low is a standard term.
> + err = devm_gpio_request_one(&pdev->dev, phy_en_gpio,
> + GPIOF_DIR_OUT,
> + "phy-enable");
> + if (err) {
> + dev_err(&pdev->dev,
> + "failed to request gpio %d: %d\n",
> + phy_en_gpio, err);
> + goto failed_gpio;
> + }
> + }
> +
> + phy_stby_gpio = of_get_named_gpio_flags(pdev->dev.of_node,
> + "phy-standby-gpios",
> + 0, &flags);
> + if (gpio_is_valid(phy_stby_gpio)) {
> + if (flags == OF_GPIO_ACTIVE_LOW)
> + phy_stby_high = false;
> + err = devm_gpio_request_one(&pdev->dev, phy_stby_gpio,
> + GPIOF_DIR_OUT,
> + "phy-standby");
> + if (err) {
> + dev_err(&pdev->dev,
> + "failed to request gpio %d: %d\n",
> + phy_stby_gpio, err);
> + goto failed_gpio;
> + }
> + }
> }
>
> if (!clock_freq) {
> @@ -997,6 +1054,10 @@ static int __devinit flexcan_probe(struct platform_device *pdev)
> priv->base = base;
> priv->dev = dev;
> priv->clk = clk;
> + priv->phy_en_gpio = phy_en_gpio;
> + priv->phy_en_high = phy_en_high;
> + priv->phy_stby_gpio = phy_stby_gpio;
> + priv->phy_stby_high = phy_stby_high;
> priv->pdata = pdev->dev.platform_data;
>
> netif_napi_add(dev, &priv->napi, flexcan_poll, FLEXCAN_NAPI_WEIGHT);
> @@ -1025,6 +1086,7 @@ static int __devinit flexcan_probe(struct platform_device *pdev)
> if (clk)
> clk_put(clk);
> failed_clock:
> + failed_gpio:
> return err;
> }
>
--
Pengutronix e.K. | Marc Kleine-Budde |
Industrial Linux Solutions | Phone: +49-231-2826-924 |
Vertretung West/Dortmund | Fax: +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de |
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 262 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120628/9b38782a/attachment.sig>
More information about the linux-arm-kernel
mailing list