diff options
Diffstat (limited to 'drivers/gpio/gpio-viperboard.c')
| -rw-r--r-- | drivers/gpio/gpio-viperboard.c | 227 |
1 files changed, 96 insertions, 131 deletions
diff --git a/drivers/gpio/gpio-viperboard.c b/drivers/gpio/gpio-viperboard.c index 5ac2919197fe..15e495c109d2 100644 --- a/drivers/gpio/gpio-viperboard.c +++ b/drivers/gpio/gpio-viperboard.c @@ -1,15 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Nano River Technologies viperboard GPIO lib driver * * (C) 2012 by Lemonage GmbH * Author: Lars Poeschel <poeschel@lemonage.de> * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * */ #include <linux/kernel.h> @@ -19,9 +14,8 @@ #include <linux/types.h> #include <linux/mutex.h> #include <linux/platform_device.h> - #include <linux/usb.h> -#include <linux/gpio.h> +#include <linux/gpio/driver.h> #include <linux/mfd/viperboard.h> @@ -85,17 +79,16 @@ MODULE_PARM_DESC(gpioa_freq, /* ----- begin of gipo a chip -------------------------------------------- */ static int vprbrd_gpioa_get(struct gpio_chip *chip, - unsigned offset) + unsigned int offset) { int ret, answer, error = 0; - struct vprbrd_gpio *gpio = - container_of(chip, struct vprbrd_gpio, gpioa); + struct vprbrd_gpio *gpio = gpiochip_get_data(chip); struct vprbrd *vb = gpio->vb; struct vprbrd_gpioa_msg *gamsg = (struct vprbrd_gpioa_msg *)vb->buf; /* if io is set to output, just return the saved value */ if (gpio->gpioa_out & (1 << offset)) - return gpio->gpioa_val & (1 << offset); + return !!(gpio->gpioa_val & (1 << offset)); mutex_lock(&vb->lock); @@ -135,54 +128,57 @@ static int vprbrd_gpioa_get(struct gpio_chip *chip, return answer; } -static void vprbrd_gpioa_set(struct gpio_chip *chip, - unsigned offset, int value) +static int vprbrd_gpioa_set(struct gpio_chip *chip, unsigned int offset, + int value) { - int ret; - struct vprbrd_gpio *gpio = - container_of(chip, struct vprbrd_gpio, gpioa); + int ret = 0; + struct vprbrd_gpio *gpio = gpiochip_get_data(chip); struct vprbrd *vb = gpio->vb; struct vprbrd_gpioa_msg *gamsg = (struct vprbrd_gpioa_msg *)vb->buf; - if (gpio->gpioa_out & (1 << offset)) { - if (value) - gpio->gpioa_val |= (1 << offset); - else - gpio->gpioa_val &= ~(1 << offset); - - mutex_lock(&vb->lock); - - gamsg->cmd = VPRBRD_GPIOA_CMD_SETOUT; - gamsg->clk = 0x00; - gamsg->offset = offset; - gamsg->t1 = 0x00; - gamsg->t2 = 0x00; - gamsg->invert = 0x00; - gamsg->pwmlevel = 0x00; - gamsg->outval = value; - gamsg->risefall = 0x00; - gamsg->answer = 0x00; - gamsg->__fill = 0x00; - - ret = usb_control_msg(vb->usb_dev, - usb_sndctrlpipe(vb->usb_dev, 0), - VPRBRD_USB_REQUEST_GPIOA, VPRBRD_USB_TYPE_OUT, - 0x0000, 0x0000, gamsg, - sizeof(struct vprbrd_gpioa_msg), VPRBRD_USB_TIMEOUT_MS); - - mutex_unlock(&vb->lock); - - if (ret != sizeof(struct vprbrd_gpioa_msg)) - dev_err(chip->dev, "usb error setting pin value\n"); + if (!(gpio->gpioa_out & (1 << offset))) + return 0; + + if (value) + gpio->gpioa_val |= (1 << offset); + else + gpio->gpioa_val &= ~(1 << offset); + + mutex_lock(&vb->lock); + + gamsg->cmd = VPRBRD_GPIOA_CMD_SETOUT; + gamsg->clk = 0x00; + gamsg->offset = offset; + gamsg->t1 = 0x00; + gamsg->t2 = 0x00; + gamsg->invert = 0x00; + gamsg->pwmlevel = 0x00; + gamsg->outval = value; + gamsg->risefall = 0x00; + gamsg->answer = 0x00; + gamsg->__fill = 0x00; + + ret = usb_control_msg(vb->usb_dev, usb_sndctrlpipe(vb->usb_dev, 0), + VPRBRD_USB_REQUEST_GPIOA, VPRBRD_USB_TYPE_OUT, + 0x0000, 0x0000, gamsg, + sizeof(struct vprbrd_gpioa_msg), + VPRBRD_USB_TIMEOUT_MS); + + mutex_unlock(&vb->lock); + + if (ret != sizeof(struct vprbrd_gpioa_msg)) { + dev_err(chip->parent, "usb error setting pin value\n"); + return -EREMOTEIO; } + + return 0; } static int vprbrd_gpioa_direction_input(struct gpio_chip *chip, - unsigned offset) + unsigned int offset) { int ret; - struct vprbrd_gpio *gpio = - container_of(chip, struct vprbrd_gpio, gpioa); + struct vprbrd_gpio *gpio = gpiochip_get_data(chip); struct vprbrd *vb = gpio->vb; struct vprbrd_gpioa_msg *gamsg = (struct vprbrd_gpioa_msg *)vb->buf; @@ -216,11 +212,10 @@ static int vprbrd_gpioa_direction_input(struct gpio_chip *chip, } static int vprbrd_gpioa_direction_output(struct gpio_chip *chip, - unsigned offset, int value) + unsigned int offset, int value) { int ret; - struct vprbrd_gpio *gpio = - container_of(chip, struct vprbrd_gpio, gpioa); + struct vprbrd_gpio *gpio = gpiochip_get_data(chip); struct vprbrd *vb = gpio->vb; struct vprbrd_gpioa_msg *gamsg = (struct vprbrd_gpioa_msg *)vb->buf; @@ -261,8 +256,8 @@ static int vprbrd_gpioa_direction_output(struct gpio_chip *chip, /* ----- begin of gipo b chip -------------------------------------------- */ -static int vprbrd_gpiob_setdir(struct vprbrd *vb, unsigned offset, - unsigned dir) +static int vprbrd_gpiob_setdir(struct vprbrd *vb, unsigned int offset, + unsigned int dir) { struct vprbrd_gpiob_msg *gbmsg = (struct vprbrd_gpiob_msg *)vb->buf; int ret; @@ -283,12 +278,11 @@ static int vprbrd_gpiob_setdir(struct vprbrd *vb, unsigned offset, } static int vprbrd_gpiob_get(struct gpio_chip *chip, - unsigned offset) + unsigned int offset) { int ret; u16 val; - struct vprbrd_gpio *gpio = - container_of(chip, struct vprbrd_gpio, gpiob); + struct vprbrd_gpio *gpio = gpiochip_get_data(chip); struct vprbrd *vb = gpio->vb; struct vprbrd_gpiob_msg *gbmsg = (struct vprbrd_gpiob_msg *)vb->buf; @@ -315,46 +309,49 @@ static int vprbrd_gpiob_get(struct gpio_chip *chip, return (gpio->gpiob_val >> offset) & 0x1; } -static void vprbrd_gpiob_set(struct gpio_chip *chip, - unsigned offset, int value) +static int vprbrd_gpiob_set(struct gpio_chip *chip, unsigned int offset, + int value) { int ret; - struct vprbrd_gpio *gpio = - container_of(chip, struct vprbrd_gpio, gpiob); + struct vprbrd_gpio *gpio = gpiochip_get_data(chip); struct vprbrd *vb = gpio->vb; struct vprbrd_gpiob_msg *gbmsg = (struct vprbrd_gpiob_msg *)vb->buf; - if (gpio->gpiob_out & (1 << offset)) { - if (value) - gpio->gpiob_val |= (1 << offset); - else - gpio->gpiob_val &= ~(1 << offset); + if (!(gpio->gpiob_out & (1 << offset))) + return 0; + + if (value) + gpio->gpiob_val |= (1 << offset); + else + gpio->gpiob_val &= ~(1 << offset); - mutex_lock(&vb->lock); + mutex_lock(&vb->lock); - gbmsg->cmd = VPRBRD_GPIOB_CMD_SETVAL; - gbmsg->val = cpu_to_be16(value << offset); - gbmsg->mask = cpu_to_be16(0x0001 << offset); + gbmsg->cmd = VPRBRD_GPIOB_CMD_SETVAL; + gbmsg->val = cpu_to_be16(value << offset); + gbmsg->mask = cpu_to_be16(0x0001 << offset); - ret = usb_control_msg(vb->usb_dev, - usb_sndctrlpipe(vb->usb_dev, 0), - VPRBRD_USB_REQUEST_GPIOB, VPRBRD_USB_TYPE_OUT, - 0x0000, 0x0000, gbmsg, - sizeof(struct vprbrd_gpiob_msg), VPRBRD_USB_TIMEOUT_MS); + ret = usb_control_msg(vb->usb_dev, usb_sndctrlpipe(vb->usb_dev, 0), + VPRBRD_USB_REQUEST_GPIOB, VPRBRD_USB_TYPE_OUT, + 0x0000, 0x0000, gbmsg, + sizeof(struct vprbrd_gpiob_msg), + VPRBRD_USB_TIMEOUT_MS); - mutex_unlock(&vb->lock); + mutex_unlock(&vb->lock); - if (ret != sizeof(struct vprbrd_gpiob_msg)) - dev_err(chip->dev, "usb error setting pin value\n"); + if (ret != sizeof(struct vprbrd_gpiob_msg)) { + dev_err(chip->parent, "usb error setting pin value\n"); + return -EREMOTEIO; } + + return 0; } static int vprbrd_gpiob_direction_input(struct gpio_chip *chip, - unsigned offset) + unsigned int offset) { int ret; - struct vprbrd_gpio *gpio = - container_of(chip, struct vprbrd_gpio, gpiob); + struct vprbrd_gpio *gpio = gpiochip_get_data(chip); struct vprbrd *vb = gpio->vb; gpio->gpiob_out &= ~(1 << offset); @@ -366,32 +363,29 @@ static int vprbrd_gpiob_direction_input(struct gpio_chip *chip, mutex_unlock(&vb->lock); if (ret) - dev_err(chip->dev, "usb error setting pin to input\n"); + dev_err(chip->parent, "usb error setting pin to input\n"); return ret; } static int vprbrd_gpiob_direction_output(struct gpio_chip *chip, - unsigned offset, int value) + unsigned int offset, int value) { int ret; - struct vprbrd_gpio *gpio = - container_of(chip, struct vprbrd_gpio, gpiob); + struct vprbrd_gpio *gpio = gpiochip_get_data(chip); struct vprbrd *vb = gpio->vb; gpio->gpiob_out |= (1 << offset); mutex_lock(&vb->lock); - ret = vprbrd_gpiob_setdir(vb, offset, 1); - if (ret) - dev_err(chip->dev, "usb error setting pin to output\n"); - mutex_unlock(&vb->lock); + if (ret) { + dev_err(chip->parent, "usb error setting pin to output\n"); + return ret; + } - vprbrd_gpiob_set(chip, offset, value); - - return ret; + return vprbrd_gpiob_set(chip, offset, value); } /* ----- end of gpio b chip ---------------------------------------------- */ @@ -409,67 +403,38 @@ static int vprbrd_gpio_probe(struct platform_device *pdev) vb_gpio->vb = vb; /* registering gpio a */ vb_gpio->gpioa.label = "viperboard gpio a"; - vb_gpio->gpioa.dev = &pdev->dev; + vb_gpio->gpioa.parent = &pdev->dev; vb_gpio->gpioa.owner = THIS_MODULE; vb_gpio->gpioa.base = -1; vb_gpio->gpioa.ngpio = 16; - vb_gpio->gpioa.can_sleep = 1; + vb_gpio->gpioa.can_sleep = true; vb_gpio->gpioa.set = vprbrd_gpioa_set; vb_gpio->gpioa.get = vprbrd_gpioa_get; vb_gpio->gpioa.direction_input = vprbrd_gpioa_direction_input; vb_gpio->gpioa.direction_output = vprbrd_gpioa_direction_output; - ret = gpiochip_add(&vb_gpio->gpioa); - if (ret < 0) { - dev_err(vb_gpio->gpioa.dev, "could not add gpio a"); - goto err_gpioa; - } + + ret = devm_gpiochip_add_data(&pdev->dev, &vb_gpio->gpioa, vb_gpio); + if (ret < 0) + return ret; /* registering gpio b */ vb_gpio->gpiob.label = "viperboard gpio b"; - vb_gpio->gpiob.dev = &pdev->dev; + vb_gpio->gpiob.parent = &pdev->dev; vb_gpio->gpiob.owner = THIS_MODULE; vb_gpio->gpiob.base = -1; vb_gpio->gpiob.ngpio = 16; - vb_gpio->gpiob.can_sleep = 1; + vb_gpio->gpiob.can_sleep = true; vb_gpio->gpiob.set = vprbrd_gpiob_set; vb_gpio->gpiob.get = vprbrd_gpiob_get; vb_gpio->gpiob.direction_input = vprbrd_gpiob_direction_input; vb_gpio->gpiob.direction_output = vprbrd_gpiob_direction_output; - ret = gpiochip_add(&vb_gpio->gpiob); - if (ret < 0) { - dev_err(vb_gpio->gpiob.dev, "could not add gpio b"); - goto err_gpiob; - } - - platform_set_drvdata(pdev, vb_gpio); - - return ret; - -err_gpiob: - if (gpiochip_remove(&vb_gpio->gpioa)) - dev_err(&pdev->dev, "%s gpiochip_remove failed\n", __func__); -err_gpioa: - return ret; -} - -static int vprbrd_gpio_remove(struct platform_device *pdev) -{ - struct vprbrd_gpio *vb_gpio = platform_get_drvdata(pdev); - int ret; - - ret = gpiochip_remove(&vb_gpio->gpiob); - if (ret == 0) - ret = gpiochip_remove(&vb_gpio->gpioa); - - return ret; + return devm_gpiochip_add_data(&pdev->dev, &vb_gpio->gpiob, vb_gpio); } static struct platform_driver vprbrd_gpio_driver = { .driver.name = "viperboard-gpio", - .driver.owner = THIS_MODULE, .probe = vprbrd_gpio_probe, - .remove = vprbrd_gpio_remove, }; static int __init vprbrd_gpio_init(void) |
