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