Add GPIO support using the gpiod APIs for controlling the IrDA
transceiver modes (FIR vs SIR), power and range.

Signed-off-by: Russell King <rmk+ker...@armlinux.org.uk>
---
 drivers/net/irda/sa1100_ir.c | 58 ++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 56 insertions(+), 2 deletions(-)

diff --git a/drivers/net/irda/sa1100_ir.c b/drivers/net/irda/sa1100_ir.c
index 7bc9c2955d4b..25c63c9ff33c 100644
--- a/drivers/net/irda/sa1100_ir.c
+++ b/drivers/net/irda/sa1100_ir.c
@@ -23,6 +23,7 @@
 #include <linux/types.h>
 #include <linux/init.h>
 #include <linux/errno.h>
+#include <linux/gpio/consumer.h>
 #include <linux/netdevice.h>
 #include <linux/slab.h>
 #include <linux/rtnetlink.h>
@@ -72,6 +73,10 @@ struct sa1100_irda {
 
        int (*tx_start)(struct sk_buff *, struct net_device *, struct 
sa1100_irda *);
        irqreturn_t (*irq)(struct net_device *, struct sa1100_irda *);
+
+       struct gpio_desc        *fsel_gpio;
+       struct gpio_desc        *pwr_gpio;
+       struct gpio_desc        *md_gpio[2];
 };
 
 static int sa1100_irda_set_speed(struct sa1100_irda *, int);
@@ -574,6 +579,8 @@ static int sa1100_irda_set_speed(struct sa1100_irda *si, 
int speed)
 
                if (si->pdata->set_speed)
                        si->pdata->set_speed(si->dev, speed);
+               if (si->fsel_gpio)
+                       gpiod_set_value(si->fsel_gpio, 0);
 
                si->speed = speed;
                si->tx_start = sa1100_irda_sir_tx_start;
@@ -600,6 +607,8 @@ static int sa1100_irda_set_speed(struct sa1100_irda *si, 
int speed)
 
                if (si->pdata->set_speed)
                        si->pdata->set_speed(si->dev, speed);
+               if (si->fsel_gpio)
+                       gpiod_set_value(si->fsel_gpio, 1);
 
                sa1100_irda_rx_alloc(si);
                sa1100_irda_rx_dma_start(si);
@@ -629,9 +638,19 @@ static int
 __sa1100_irda_set_power(struct sa1100_irda *si, unsigned int state)
 {
        int ret = 0;
-       if (si->pdata->set_power)
+       if (si->pdata->set_power) {
                ret = si->pdata->set_power(si->dev, state);
-       return ret;
+       } else if (si->pwr_gpio) {
+               gpiod_set_value_cansleep(si->pwr_gpio, state);
+       } else if (si->md_gpio[0] && si->md_gpio[1]) {
+               int vals[2];
+
+               vals[0] = state < 2;
+               vals[1] = state == 1 || state == 2;
+
+               gpiod_set_array_value_cansleep(2, si->md_gpio, vals);
+       }
+       return 0;
 }
 
 static inline int
@@ -914,6 +933,21 @@ static const struct net_device_ops sa1100_irda_netdev_ops 
= {
        .ndo_do_ioctl           = sa1100_irda_ioctl,
 };
 
+static int sa1100_irda_get_gpio(struct device *dev, struct gpio_desc **descp,
+       const char *name, enum gpiod_flags flags)
+{
+       struct gpio_desc *desc = devm_gpiod_get_optional(dev, name, flags);
+
+       if (IS_ERR(desc)) {
+               int err = PTR_ERR(desc);
+               dev_err(dev, "unable to get %s gpio: %d\n", name, err);
+               return err;
+       }
+
+       *descp = desc;
+       return 0;
+}
+
 static int sa1100_irda_probe(struct platform_device *pdev)
 {
        struct net_device *dev;
@@ -950,6 +984,26 @@ static int sa1100_irda_probe(struct platform_device *pdev)
        si->dev = &pdev->dev;
        si->pdata = pdev->dev.platform_data;
 
+       err = sa1100_irda_get_gpio(&pdev->dev, &si->fsel_gpio, "ir-fsel",
+                                  GPIOD_OUT_LOW);
+       if (err)
+               goto err_mem_5;
+
+       err = sa1100_irda_get_gpio(&pdev->dev, &si->pwr_gpio, "ir-power",
+                                  GPIOD_OUT_LOW);
+       if (err)
+               goto err_mem_5;
+
+       err = sa1100_irda_get_gpio(&pdev->dev, &si->md_gpio[0], "ir-md0",
+                                  GPIOD_OUT_HIGH);
+       if (err)
+               goto err_mem_5;
+
+       err = sa1100_irda_get_gpio(&pdev->dev, &si->md_gpio[1], "ir-md1",
+                                  GPIOD_OUT_LOW);
+       if (err)
+               goto err_mem_5;
+
        sg_init_table(&si->dma_rx.sg, 1);
        sg_init_table(&si->dma_tx.sg, 1);
 
-- 
2.1.0

Reply via email to