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+kernel@xxxxxxxxxxxxxxx> --- 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 -- To unsubscribe from this list: send the line "unsubscribe dmaengine" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html