Re: [PATCH v2 1/3] gpio/mockup: add virtual gpio device

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Update email address for kamlakant.patel@xxxxxxxxxxxx

On 02/03/2016 08:14 PM, Bamvor Jian Zhang wrote:
> This patch add basic structure of a virtual gpio device(gpio-mockup)
> for testing gpio subsystem. The tester could manipulate such device
> through userspace(sysfs or char device) and check the result from
> debugfs.
>
> Currently, it support one or more gpiochip(determined by module
> parameters with base,ngpio pair). One could test the overlap of
> different gpiochip and test the direction and/or output values of
> these chips.
>
> Signed-off-by: Kamlakant Patel <kamlakant.patel@xxxxxxxxxx>
> Signed-off-by: Bamvor Jian Zhang <bamvor.zhangjian@xxxxxxxxxx>
> ---
>  Documentation/kernel-parameters.txt |   4 +
>  drivers/gpio/Kconfig                |  12 ++
>  drivers/gpio/Makefile               |   1 +
>  drivers/gpio/gpio-mockup.c          | 230 ++++++++++++++++++++++++++++++++++++
>  4 files changed, 247 insertions(+)
>  create mode 100644 drivers/gpio/gpio-mockup.c
>
> diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
> index 742f69d..cc0ce8a 100644
> --- a/Documentation/kernel-parameters.txt
> +++ b/Documentation/kernel-parameters.txt
> @@ -1278,6 +1278,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
>   Format: <unsigned int> such that (rxsize & ~0x1fffc0) == 0.
>   Default: 1024
>
> + gpio-mockup.gpio_mockup_ranges
> + [HW] Sets the ranges of gpiochip of for this device.
> + Format: <start1>,<end1>,<start2>,<end2>...
> +
>   hardlockup_all_cpu_backtrace=
>   [KNL] Should the hard-lockup detector generate
>   backtraces on all cpus.
> diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
> index cb212eb..59bebca 100644
> --- a/drivers/gpio/Kconfig
> +++ b/drivers/gpio/Kconfig
> @@ -268,6 +268,18 @@ config GPIO_MM_LANTIQ
>    (EBU) found on Lantiq SoCs. The gpios are output only as they are
>    created by attaching a 16bit latch to the bus.
>
> +config GPIO_MOCKUP
> + tristate "GPIO Testing Driver"
> + depends on GPIOLIB
> + select GPIO_SYSFS
> + help
> +  This enables GPIO Testing driver, which provides a way to test GPIO
> +  subsystem through sysfs(or char device) and debugfs. GPIO_SYSFS
> +  must be selected for this test.
> +  User could use it through the script in
> +  tools/testing/selftests/gpio/gpio-mockup.sh. Reference the usage in
> +  it.
> +
>  config GPIO_MOXART
>   bool "MOXART GPIO support"
>   depends on ARCH_MOXART
> diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
> index 548e9b5..2635e4a 100644
> --- a/drivers/gpio/Makefile
> +++ b/drivers/gpio/Makefile
> @@ -63,6 +63,7 @@ obj-$(CONFIG_GPIO_MC9S08DZ60) += gpio-mc9s08dz60.o
>  obj-$(CONFIG_GPIO_MCP23S08) += gpio-mcp23s08.o
>  obj-$(CONFIG_GPIO_ML_IOH) += gpio-ml-ioh.o
>  obj-$(CONFIG_GPIO_MM_LANTIQ) += gpio-mm-lantiq.o
> +obj-$(CONFIG_GPIO_MOCKUP)      += gpio-mockup.o
>  obj-$(CONFIG_GPIO_MOXART) += gpio-moxart.o
>  obj-$(CONFIG_GPIO_MPC5200) += gpio-mpc5200.o
>  obj-$(CONFIG_GPIO_MPC8XXX) += gpio-mpc8xxx.o
> diff --git a/drivers/gpio/gpio-mockup.c b/drivers/gpio/gpio-mockup.c
> new file mode 100644
> index 0000000..33b4b6a
> --- /dev/null
> +++ b/drivers/gpio/gpio-mockup.c
> @@ -0,0 +1,230 @@
> +/*
> + * GPIO Testing Device Driver
> + *
> + * Copyright (C) 2014  Kamlakant Patel <kamlakant.patel@xxxxxxxxxxxx>
> + * Copyright (C) 2015-2016  Bamvor Jian Zhang <bamvor.zhangjian@xxxxxxxxxx>
> + *
> + * 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/init.h>
> +#include <linux/module.h>
> +#include <linux/gpio/driver.h>
> +#include <linux/platform_device.h>
> +
> +#define GPIO_NAME "gpio-mockup"
> +#define MAX_GC 10
> +
> +enum direction {
> + IN,
> + OUT
> +};
> +
> +/*
> + * struct gpio_pin_status - structure describing a GPIO status
> + * @dir:       Configures direction of gpio as "in" or "out", 0=in, 1=out
> + * @value:     Configures status of the gpio as 0(low) or 1(high)
> + */
> +struct gpio_pin_status {
> + enum direction dir;
> + bool value;
> +};
> +
> +struct mockup_gpio_controller {
> + struct gpio_chip gc;
> + struct gpio_pin_status *stats;
> +};
> +
> +static int gpio_mockup_ranges[MAX_GC << 1];
> +static int gpio_mockup_params_nr;
> +module_param_array(gpio_mockup_ranges, int, &gpio_mockup_params_nr, 0400);
> +
> +static const char *pins_name_start = "A";
> +
> +static int
> +mockup_gpio_get(struct gpio_chip *gc, unsigned offset)
> +{
> + struct mockup_gpio_controller *cntr = container_of(gc,
> + struct mockup_gpio_controller, gc);
> +
> + return cntr->stats[offset].value;
> +}
> +
> +static void
> +mockup_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
> +{
> + struct mockup_gpio_controller *cntr = container_of(gc,
> + struct mockup_gpio_controller, gc);
> +
> + cntr->stats[offset].value = !!value;
> +}
> +
> +static int
> +mockup_gpio_dirout(struct gpio_chip *gc, unsigned offset, int value)
> +{
> + struct mockup_gpio_controller *cntr = container_of(gc,
> + struct mockup_gpio_controller, gc);
> +
> + mockup_gpio_set(gc, offset, value);
> + cntr->stats[offset].dir = OUT;
> + return 0;
> +}
> +
> +static int
> +mockup_gpio_dirin(struct gpio_chip *gc, unsigned offset)
> +{
> + struct mockup_gpio_controller *cntr = container_of(gc,
> + struct mockup_gpio_controller, gc);
> +
> + cntr->stats[offset].dir = IN;
> + return 0;
> +}
> +
> +static int
> +mockup_gpio_add(struct device *dev, struct mockup_gpio_controller *cntr,
> + const char *name, int base, int ngpio)
> +{
> + int ret;
> +
> + cntr->gc.base = base;
> + cntr->gc.ngpio = ngpio;
> + cntr->gc.label = name;
> + cntr->gc.owner = THIS_MODULE;
> + cntr->gc.parent = dev;
> + cntr->gc.get = mockup_gpio_get;
> + cntr->gc.set = mockup_gpio_set;
> + cntr->gc.direction_output = mockup_gpio_dirout;
> + cntr->gc.direction_input = mockup_gpio_dirin;
> + cntr->stats = devm_kzalloc(dev, sizeof(*cntr->stats) * cntr->gc.ngpio,
> + GFP_KERNEL);
> + if (!cntr->stats) {
> + ret = -ENOMEM;
> + goto err;
> + }
> + ret = gpiochip_add(&cntr->gc);
> + if (ret)
> + goto err;
> +
> + dev_info(dev, "gpio<%d..%d> add successful!", base, base + ngpio);
> + return 0;
> +err:
> + dev_err(dev, "gpio<%d..%d> add failed!", base, base + ngpio);
> + return ret;
> +}
> +
> +static int
> +mockup_gpio_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct mockup_gpio_controller *cntr;
> + int ret;
> + int i, j;
> + int base;
> + int ngpio;
> +
> + if (gpio_mockup_params_nr < 2)
> + return -EINVAL;
> +
> + cntr = devm_kzalloc(dev, sizeof(*cntr) * (gpio_mockup_params_nr >> 1),
> + GFP_KERNEL);
> + if (!cntr)
> + return -ENOMEM;
> +
> + platform_set_drvdata(pdev, cntr);
> +
> + for (i = 0; i < gpio_mockup_params_nr >> 1; i++) {
> + base = gpio_mockup_ranges[i * 2];
> + if (base == -1)
> + ngpio = gpio_mockup_ranges[i * 2 + 1];
> + else
> + ngpio = gpio_mockup_ranges[i * 2 + 1] - base;
> +
> + if (ngpio >= 0)
> + ret = mockup_gpio_add(dev, &cntr[i],
> + pins_name_start + i,
> + base, ngpio);
> + else
> + ret = -1;
> +
> + if (ret) {
> + if (base < 0)
> + dev_err(dev, "gpio<%d..%d> add failed, remove added gpio\n",
> + base, ngpio);
> + else
> + dev_err(dev, "gpio<%d..%d> add failed, remove added gpio\n",
> + base, base + ngpio);
> +
> + for (j = 0; j < i; j++)
> + gpiochip_remove(&cntr[j].gc);
> +
> + return ret;
> + }
> + }
> +
> + return 0;
> +}
> +
> +static int
> +mockup_gpio_remove(struct platform_device *pdev)
> +{
> + struct mockup_gpio_controller *cntr = platform_get_drvdata(pdev);
> + int i;
> +
> + for (i = 0; i < gpio_mockup_params_nr >> 1; i++)
> + gpiochip_remove(&cntr[i].gc);
> +
> + return 0;
> +}
> +
> +static struct platform_driver mockup_gpio_driver = {
> + .driver = {
> + .name           = GPIO_NAME,
> + },
> + .probe = mockup_gpio_probe,
> + .remove = mockup_gpio_remove,
> +};
> +
> +static struct platform_device *pdev;
> +static int __init
> +mock_device_init(void)
> +{
> + int err;
> +
> + pdev = platform_device_alloc(GPIO_NAME, -1);
> + if (!pdev)
> + return -ENOMEM;
> +
> + err = platform_device_add(pdev);
> + if (err) {
> + platform_device_put(pdev);
> + return err;
> + }
> +
> + err = platform_driver_register(&mockup_gpio_driver);
> + if (err) {
> + platform_device_unregister(pdev);
> + return err;
> + }
> +
> + return 0;
> +}
> +
> +static void __exit
> +mock_device_exit(void)
> +{
> + platform_driver_unregister(&mockup_gpio_driver);
> + platform_device_unregister(pdev);
> +}
> +
> +module_init(mock_device_init);
> +module_exit(mock_device_exit);
> +
> +MODULE_AUTHOR("Kamlakant Patel <kamlakant.patel@xxxxxxxxxxxx>");
> +MODULE_AUTHOR("Bamvor Jian Zhang <bamvor.zhangjian@xxxxxxxxxx>");
> +MODULE_DESCRIPTION("GPIO Testing driver");
> +MODULE_LICENSE("GPL v2");
> +
>

-- 
-----------------------------
   blog: http://aarch64.me
-----------------------------
--
To unsubscribe from this list: send the line "unsubscribe linux-gpio" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux SPI]     [Linux Kernel]     [Linux ARM (vger)]     [Linux ARM MSM]     [Linux Omap]     [Linux Arm]     [Linux Tegra]     [Fedora ARM]     [Linux for Samsung SOC]     [eCos]     [Linux Fastboot]     [Gcc Help]     [Git]     [DCCP]     [IETF Announce]     [Security]     [Linux MIPS]     [Yosemite Campsites]

  Powered by Linux