Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'ib-scmi-pinctrl-gpio' into devel

+255 -13
+59
Documentation/devicetree/bindings/gpio/pin-control-gpio.yaml
··· 1 + # SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/gpio/pin-control-gpio.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Pin control based generic GPIO controller 8 + 9 + description: 10 + The pin control-based GPIO will facilitate a pin controller's ability 11 + to drive electric lines high/low and other generic properties of a 12 + pin controller to perform general-purpose one-bit binary I/O. 13 + 14 + maintainers: 15 + - Dan Carpenter <dan.carpenter@linaro.org> 16 + 17 + properties: 18 + compatible: 19 + const: scmi-pinctrl-gpio 20 + 21 + gpio-controller: true 22 + 23 + "#gpio-cells": 24 + const: 2 25 + 26 + gpio-line-names: true 27 + 28 + gpio-ranges: true 29 + 30 + ngpios: true 31 + 32 + patternProperties: 33 + "^.+-hog(-[0-9]+)?$": 34 + type: object 35 + 36 + required: 37 + - gpio-hog 38 + 39 + required: 40 + - compatible 41 + - gpio-controller 42 + - "#gpio-cells" 43 + - gpio-ranges 44 + - ngpios 45 + 46 + additionalProperties: false 47 + 48 + examples: 49 + - | 50 + gpio { 51 + compatible = "scmi-pinctrl-gpio"; 52 + gpio-controller; 53 + #gpio-cells = <2>; 54 + ngpios = <4>; 55 + gpio-line-names = "gpio_5_17", "gpio_5_20", "gpio_5_22", "gpio_2_1"; 56 + gpio-ranges = <&scmi_pinctrl 0 30 4>; 57 + pinctrl-names = "default"; 58 + pinctrl-0 = <&keys_pins>; 59 + };
+2
drivers/firmware/arm_scmi/pinctrl.c
··· 578 578 tx->flags = cpu_to_le32(type); 579 579 580 580 ret = ph->xops->do_xfer(ph, t); 581 + if (ret == -EOPNOTSUPP) 582 + ret = 0; 581 583 ph->xops->xfer_put(ph, t); 582 584 583 585 return ret;
+13
drivers/gpio/Kconfig
··· 246 246 help 247 247 Say yes here to enable GPIO support for Broadcom STB (BCM7XXX) SoCs. 248 248 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 + 249 262 config GPIO_CADENCE 250 263 tristate "Cadence GPIO support" 251 264 depends on OF_GPIO
+1
drivers/gpio/Makefile
··· 51 51 obj-$(CONFIG_GPIO_BLZP1600) += gpio-blzp1600.o 52 52 obj-$(CONFIG_GPIO_BRCMSTB) += gpio-brcmstb.o 53 53 obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o 54 + obj-$(CONFIG_GPIO_BY_PINCTRL) += gpio-by-pinctrl.o 54 55 obj-$(CONFIG_GPIO_CADENCE) += gpio-cadence.o 55 56 obj-$(CONFIG_GPIO_CGBC) += gpio-cgbc.o 56 57 obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o
+101
drivers/gpio/gpio-by-pinctrl.c
··· 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");
+31
drivers/pinctrl/core.c
··· 30 30 #include <linux/pinctrl/consumer.h> 31 31 #include <linux/pinctrl/devinfo.h> 32 32 #include <linux/pinctrl/machine.h> 33 + #include <linux/pinctrl/pinconf.h> 33 34 #include <linux/pinctrl/pinctrl.h> 34 35 35 36 #include "core.h" ··· 938 937 return ret; 939 938 } 940 939 EXPORT_SYMBOL_GPL(pinctrl_gpio_set_config); 940 + 941 + /** 942 + * pinctrl_gpio_get_config() - Get the config for a given GPIO pin 943 + * @gc: GPIO chip structure from the GPIO subsystem 944 + * @offset: hardware offset of the GPIO relative to the controller 945 + * @config: the configuration to query. On success it holds the result 946 + * Return: 0 on success, negative errno otherwise 947 + */ 948 + int pinctrl_gpio_get_config(struct gpio_chip *gc, unsigned int offset, unsigned long *config) 949 + { 950 + struct pinctrl_gpio_range *range; 951 + struct pinctrl_dev *pctldev; 952 + int ret, pin; 953 + 954 + ret = pinctrl_get_device_gpio_range(gc, offset, &pctldev, &range); 955 + if (ret) 956 + return ret; 957 + 958 + mutex_lock(&pctldev->mutex); 959 + pin = gpio_to_pin(range, gc, offset); 960 + ret = pin_config_get_for_pin(pctldev, pin, config); 961 + mutex_unlock(&pctldev->mutex); 962 + 963 + if (ret) 964 + return ret; 965 + 966 + *config = pinconf_to_config_argument(*config); 967 + return 0; 968 + } 969 + EXPORT_SYMBOL_GPL(pinctrl_gpio_get_config); 941 970 942 971 static struct pinctrl_state *find_state(struct pinctrl *p, 943 972 const char *name)
+6
drivers/pinctrl/pinconf.h
··· 74 74 return -ENOTSUPP; 75 75 } 76 76 77 + static inline int pin_config_get_for_pin(struct pinctrl_dev *pctldev, unsigned int pin, 78 + unsigned long *config) 79 + { 80 + return -ENOTSUPP; 81 + } 82 + 77 83 #endif 78 84 79 85 #if defined(CONFIG_PINCONF) && defined(CONFIG_DEBUG_FS)
+33 -13
drivers/pinctrl/pinctrl-scmi.c
··· 251 251 case PIN_CONFIG_MODE_LOW_POWER: 252 252 *type = SCMI_PIN_LOW_POWER_MODE; 253 253 break; 254 - case PIN_CONFIG_LEVEL: 255 - *type = SCMI_PIN_OUTPUT_VALUE; 256 - break; 257 254 case PIN_CONFIG_OUTPUT_ENABLE: 258 255 *type = SCMI_PIN_OUTPUT_MODE; 259 - break; 260 - case PIN_CONFIG_OUTPUT_IMPEDANCE_OHMS: 261 - *type = SCMI_PIN_OUTPUT_VALUE; 262 256 break; 263 257 case PIN_CONFIG_POWER_SOURCE: 264 258 *type = SCMI_PIN_POWER_SOURCE; ··· 270 276 return 0; 271 277 } 272 278 279 + static int pinctrl_scmi_map_pinconf_type_get(enum pin_config_param param, 280 + enum scmi_pinctrl_conf_type *type) 281 + { 282 + if (param == PIN_CONFIG_LEVEL) { 283 + *type = SCMI_PIN_INPUT_VALUE; 284 + return 0; 285 + } 286 + 287 + return pinctrl_scmi_map_pinconf_type(param, type); 288 + } 289 + 290 + static int pinctrl_scmi_map_pinconf_type_set(enum pin_config_param param, 291 + enum scmi_pinctrl_conf_type *type) 292 + { 293 + if (param == PIN_CONFIG_LEVEL) { 294 + *type = SCMI_PIN_OUTPUT_VALUE; 295 + return 0; 296 + } 297 + 298 + return pinctrl_scmi_map_pinconf_type(param, type); 299 + } 300 + 273 301 static int pinctrl_scmi_pinconf_get(struct pinctrl_dev *pctldev, 274 302 unsigned int pin, unsigned long *config) 275 303 { ··· 306 290 307 291 config_type = pinconf_to_config_param(*config); 308 292 309 - ret = pinctrl_scmi_map_pinconf_type(config_type, &type); 293 + ret = pinctrl_scmi_map_pinconf_type_get(config_type, &type); 310 294 if (ret) 311 295 return ret; 312 296 ··· 361 345 unsigned long *configs, 362 346 unsigned int num_configs) 363 347 { 364 - int i, ret; 348 + int i, cnt, ret; 365 349 struct scmi_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); 366 350 enum scmi_pinctrl_conf_type config_type[SCMI_NUM_CONFIGS]; 367 351 u32 config_value[SCMI_NUM_CONFIGS]; ··· 377 361 if (ret) 378 362 return ret; 379 363 364 + cnt = 0; 380 365 for (i = 0; i < num_configs; i++) { 381 366 param = pinconf_to_config_param(configs[i]); 382 - ret = pinctrl_scmi_map_pinconf_type(param, &p_config_type[i]); 367 + if (param == PIN_CONFIG_PERSIST_STATE) 368 + continue; 369 + ret = pinctrl_scmi_map_pinconf_type_set(param, &p_config_type[cnt]); 383 370 if (ret) { 384 371 dev_err(pmx->dev, "Error map pinconf_type %d\n", ret); 385 372 goto free_config; 386 373 } 387 - p_config_value[i] = pinconf_to_config_argument(configs[i]); 374 + p_config_value[cnt] = pinconf_to_config_argument(configs[i]); 375 + cnt++; 388 376 } 389 377 390 - ret = pinctrl_ops->settings_conf(pmx->ph, pin, PIN_TYPE, num_configs, 378 + ret = pinctrl_ops->settings_conf(pmx->ph, pin, PIN_TYPE, cnt, 391 379 p_config_type, p_config_value); 392 380 if (ret) 393 381 dev_err(pmx->dev, "Error parsing config %d\n", ret); ··· 425 405 426 406 for (i = 0; i < num_configs; i++) { 427 407 param = pinconf_to_config_param(configs[i]); 428 - ret = pinctrl_scmi_map_pinconf_type(param, &p_config_type[i]); 408 + ret = pinctrl_scmi_map_pinconf_type_set(param, &p_config_type[i]); 429 409 if (ret) { 430 410 dev_err(pmx->dev, "Error map pinconf_type %d\n", ret); 431 411 goto free_config; ··· 460 440 return -EINVAL; 461 441 462 442 config_type = pinconf_to_config_param(*config); 463 - ret = pinctrl_scmi_map_pinconf_type(config_type, &type); 443 + ret = pinctrl_scmi_map_pinconf_type_get(config_type, &type); 464 444 if (ret) { 465 445 dev_err(pmx->dev, "Error map pinconf_type %d\n", ret); 466 446 return ret;
+9
include/linux/pinctrl/consumer.h
··· 35 35 unsigned int offset); 36 36 int pinctrl_gpio_set_config(struct gpio_chip *gc, unsigned int offset, 37 37 unsigned long config); 38 + int pinctrl_gpio_get_config(struct gpio_chip *gc, unsigned int offset, 39 + unsigned long *config); 38 40 39 41 struct pinctrl * __must_check pinctrl_get(struct device *dev); 40 42 void pinctrl_put(struct pinctrl *p); ··· 99 97 100 98 static inline int 101 99 pinctrl_gpio_direction_output(struct gpio_chip *gc, unsigned int offset) 100 + { 101 + return 0; 102 + } 103 + 104 + static inline int 105 + pinctrl_gpio_get_config(struct gpio_chip *gc, unsigned int offset, 106 + unsigned long *config) 102 107 { 103 108 return 0; 104 109 }