Skip to content

Commit 7671f49

Browse files
AKASHI Takahirolinusw
authored andcommitted
gpio: gpio-by-pinctrl: add pinctrl based generic GPIO driver
The ARM SCMI pinctrl protocol allows GPIO access. Instead of creating a new SCMI GPIO driver, this driver is a generic GPIO driver that uses standard pinctrl interfaces. Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org> Signed-off-by: Dan Carpenter <dan.carpenter@linaro.org> Reviewed-by: Linus Walleij <linusw@kernel.org> Acked-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com> Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com> Signed-off-by: Linus Walleij <linusw@kernel.org>
1 parent 05a8a80 commit 7671f49

3 files changed

Lines changed: 115 additions & 0 deletions

File tree

drivers/gpio/Kconfig

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,19 @@ config GPIO_BRCMSTB
246246
help
247247
Say yes here to enable GPIO support for Broadcom STB (BCM7XXX) SoCs.
248248

249+
config GPIO_BY_PINCTRL
250+
tristate "GPIO support based on a pure pin control backend"
251+
depends on GPIOLIB
252+
help
253+
Support for generic GPIO handling based on top of pin control.
254+
Traditionally, firmware creates a GPIO interface or a pin
255+
controller interface and we have a driver to support it. But
256+
in SCMI, the pin control interface is generic and we can
257+
create a simple GPIO device based on the pin control interface
258+
without doing anything custom.
259+
260+
This driver used to do GPIO over the ARM SCMI protocol.
261+
249262
config GPIO_CADENCE
250263
tristate "Cadence GPIO support"
251264
depends on OF_GPIO

drivers/gpio/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ obj-$(CONFIG_GPIO_BD9571MWV) += gpio-bd9571mwv.o
5151
obj-$(CONFIG_GPIO_BLZP1600) += gpio-blzp1600.o
5252
obj-$(CONFIG_GPIO_BRCMSTB) += gpio-brcmstb.o
5353
obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o
54+
obj-$(CONFIG_GPIO_BY_PINCTRL) += gpio-by-pinctrl.o
5455
obj-$(CONFIG_GPIO_CADENCE) += gpio-cadence.o
5556
obj-$(CONFIG_GPIO_CGBC) += gpio-cgbc.o
5657
obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o

drivers/gpio/gpio-by-pinctrl.c

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
//
3+
// Copyright (C) 2026 Linaro Inc.
4+
// Author: AKASHI takahiro <takahiro.akashi@linaro.org>
5+
6+
#include <linux/errno.h>
7+
#include <linux/gpio/driver.h>
8+
#include <linux/mod_devicetable.h>
9+
#include <linux/module.h>
10+
#include <linux/pinctrl/consumer.h>
11+
#include <linux/platform_device.h>
12+
#include <linux/types.h>
13+
14+
#include "gpiolib.h"
15+
16+
static int pin_control_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
17+
{
18+
unsigned long config;
19+
int ret;
20+
21+
config = PIN_CONFIG_OUTPUT_ENABLE;
22+
ret = pinctrl_gpio_get_config(gc, offset, &config);
23+
if (ret)
24+
return ret;
25+
if (config)
26+
return GPIO_LINE_DIRECTION_OUT;
27+
28+
return GPIO_LINE_DIRECTION_IN;
29+
}
30+
31+
static int pin_control_gpio_direction_output(struct gpio_chip *chip,
32+
unsigned int offset, int val)
33+
{
34+
return pinctrl_gpio_direction_output(chip, offset);
35+
}
36+
37+
static int pin_control_gpio_get(struct gpio_chip *chip, unsigned int offset)
38+
{
39+
unsigned long config;
40+
int ret;
41+
42+
config = PIN_CONFIG_LEVEL;
43+
ret = pinctrl_gpio_get_config(chip, offset, &config);
44+
if (ret)
45+
return ret;
46+
47+
return !!config;
48+
}
49+
50+
static int pin_control_gpio_set(struct gpio_chip *chip, unsigned int offset,
51+
int val)
52+
{
53+
unsigned long config;
54+
55+
config = pinconf_to_config_packed(PIN_CONFIG_LEVEL, val);
56+
return pinctrl_gpio_set_config(chip, offset, config);
57+
}
58+
59+
static int pin_control_gpio_probe(struct platform_device *pdev)
60+
{
61+
struct device *dev = &pdev->dev;
62+
struct gpio_chip *chip;
63+
64+
chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
65+
if (!chip)
66+
return -ENOMEM;
67+
68+
chip->label = dev_name(dev);
69+
chip->parent = dev;
70+
chip->base = -1;
71+
72+
chip->request = gpiochip_generic_request;
73+
chip->free = gpiochip_generic_free;
74+
chip->get_direction = pin_control_gpio_get_direction;
75+
chip->direction_input = pinctrl_gpio_direction_input;
76+
chip->direction_output = pin_control_gpio_direction_output;
77+
chip->get = pin_control_gpio_get;
78+
chip->set = pin_control_gpio_set;
79+
chip->set_config = gpiochip_generic_config;
80+
81+
return devm_gpiochip_add_data(dev, chip, NULL);
82+
}
83+
84+
static const struct of_device_id pin_control_gpio_match[] = {
85+
{ .compatible = "scmi-pinctrl-gpio" },
86+
{ /* sentinel */ }
87+
};
88+
MODULE_DEVICE_TABLE(of, pin_control_gpio_match);
89+
90+
static struct platform_driver pin_control_gpio_driver = {
91+
.probe = pin_control_gpio_probe,
92+
.driver = {
93+
.name = "pin-control-gpio",
94+
.of_match_table = pin_control_gpio_match,
95+
},
96+
};
97+
module_platform_driver(pin_control_gpio_driver);
98+
99+
MODULE_AUTHOR("AKASHI Takahiro <takahiro.akashi@linaro.org>");
100+
MODULE_DESCRIPTION("Pinctrl based GPIO driver");
101+
MODULE_LICENSE("GPL");

0 commit comments

Comments
 (0)