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