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

Merge tag 'reset-gpio-for-v6.19' of https://git.pengutronix.de/git/pza/linux into soc/drivers-late

Reset/GPIO/swnode changes for v6.19

* Extend software node implementation, allowing its properties to reference
existing firmware nodes.
* Update the GPIO property interface to use reworked swnode macros.
* Rework reset-gpio code to use GPIO lookup via swnode.
* Fix spi-cs42l43 driver to work with swnode changes.

* tag 'reset-gpio-for-v6.19' of https://git.pengutronix.de/git/pza/linux:
reset: gpio: use software nodes to setup the GPIO lookup
reset: gpio: convert the driver to using the auxiliary bus
reset: make the provider of reset-gpios the parent of the reset device
reset: order includes alphabetically in reset/core.c
gpio: swnode: allow referencing GPIO chips by firmware nodes
spi: cs42l43: Use actual ACPI firmware node for chip selects
software node: allow referencing firmware nodes
software node: increase the reference of the swnode by its fwnode
software node: read the reference args via the fwnode API

Signed-off-by: Arnd Bergmann <arnd@arndb.de>

+141 -111
+24 -6
drivers/base/swnode.c
··· 535 535 ref_array = prop->pointer; 536 536 ref = &ref_array[index]; 537 537 538 - refnode = software_node_fwnode(ref->node); 538 + /* 539 + * A software node can reference other software nodes or firmware 540 + * nodes (which are the abstraction layer sitting on top of them). 541 + * This is done to ensure we can create references to static software 542 + * nodes before they're registered with the firmware node framework. 543 + * At the time the reference is being resolved, we expect the swnodes 544 + * in question to already have been registered and to be backed by 545 + * a firmware node. This is why we use the fwnode API below to read the 546 + * relevant properties and bump the reference count. 547 + */ 548 + 549 + if (ref->swnode) 550 + refnode = software_node_fwnode(ref->swnode); 551 + else if (ref->fwnode) 552 + refnode = ref->fwnode; 553 + else 554 + return -EINVAL; 555 + 539 556 if (!refnode) 540 557 return -ENOENT; 541 558 542 559 if (nargs_prop) { 543 - error = property_entry_read_int_array(ref->node->properties, 544 - nargs_prop, sizeof(u32), 545 - &nargs_prop_val, 1); 560 + error = fwnode_property_read_u32(refnode, nargs_prop, &nargs_prop_val); 546 561 if (error) 547 562 return error; 548 563 ··· 570 555 if (!args) 571 556 return 0; 572 557 573 - args->fwnode = software_node_get(refnode); 558 + args->fwnode = fwnode_handle_get(refnode); 574 559 args->nargs = nargs; 575 560 576 561 for (i = 0; i < nargs; i++) ··· 650 635 651 636 ref = prop->pointer; 652 637 653 - return software_node_get(software_node_fwnode(ref[0].node)); 638 + if (!ref->swnode) 639 + return NULL; 640 + 641 + return software_node_get(software_node_fwnode(ref->swnode)); 654 642 } 655 643 656 644 static struct fwnode_handle *
+2 -1
drivers/gpio/gpiolib-swnode.c
··· 31 31 32 32 gdev_node = to_software_node(fwnode); 33 33 if (!gdev_node || !gdev_node->name) 34 - return ERR_PTR(-EINVAL); 34 + goto fwnode_lookup; 35 35 36 36 /* 37 37 * Check for a special node that identifies undefined GPIOs, this is ··· 41 41 !strcmp(gdev_node->name, GPIOLIB_SWNODE_UNDEFINED_NAME)) 42 42 return ERR_PTR(-ENOENT); 43 43 44 + fwnode_lookup: 44 45 gdev = gpio_device_find_by_fwnode(fwnode); 45 46 return gdev ?: ERR_PTR(-EPROBE_DEFER); 46 47 }
+1
drivers/reset/Kconfig
··· 89 89 config RESET_GPIO 90 90 tristate "GPIO reset controller" 91 91 depends on GPIOLIB 92 + select AUXILIARY_BUS 92 93 help 93 94 This enables a generic reset controller for resets attached via 94 95 GPIOs. Typically for OF platforms this driver expects "reset-gpios"
+84 -62
drivers/reset/core.c
··· 4 4 * 5 5 * Copyright 2013 Philipp Zabel, Pengutronix 6 6 */ 7 + 8 + #include <linux/acpi.h> 7 9 #include <linux/atomic.h> 10 + #include <linux/auxiliary_bus.h> 8 11 #include <linux/cleanup.h> 9 12 #include <linux/device.h> 10 13 #include <linux/err.h> 11 14 #include <linux/export.h> 12 - #include <linux/kernel.h> 13 - #include <linux/kref.h> 14 15 #include <linux/gpio/driver.h> 15 16 #include <linux/gpio/machine.h> 17 + #include <linux/gpio/property.h> 16 18 #include <linux/idr.h> 19 + #include <linux/kernel.h> 20 + #include <linux/kref.h> 17 21 #include <linux/module.h> 18 22 #include <linux/of.h> 19 - #include <linux/acpi.h> 20 - #include <linux/platform_device.h> 21 23 #include <linux/reset.h> 22 24 #include <linux/reset-controller.h> 23 25 #include <linux/slab.h> ··· 78 76 /** 79 77 * struct reset_gpio_lookup - lookup key for ad-hoc created reset-gpio devices 80 78 * @of_args: phandle to the reset controller with all the args like GPIO number 79 + * @swnode: Software node containing the reference to the GPIO provider 81 80 * @list: list entry for the reset_gpio_lookup_list 82 81 */ 83 82 struct reset_gpio_lookup { 84 83 struct of_phandle_args of_args; 84 + struct fwnode_handle *swnode; 85 85 struct list_head list; 86 86 }; 87 87 ··· 852 848 kref_put(&rstc->refcnt, __reset_control_release); 853 849 } 854 850 855 - static int __reset_add_reset_gpio_lookup(int id, struct device_node *np, 856 - unsigned int gpio, 857 - unsigned int of_flags) 851 + static void reset_gpio_aux_device_release(struct device *dev) 858 852 { 859 - const struct fwnode_handle *fwnode = of_fwnode_handle(np); 860 - unsigned int lookup_flags; 861 - const char *label_tmp; 853 + struct auxiliary_device *adev = to_auxiliary_dev(dev); 862 854 863 - /* 864 - * Later we map GPIO flags between OF and Linux, however not all 865 - * constants from include/dt-bindings/gpio/gpio.h and 866 - * include/linux/gpio/machine.h match each other. 867 - */ 868 - if (of_flags > GPIO_ACTIVE_LOW) { 869 - pr_err("reset-gpio code does not support GPIO flags %u for GPIO %u\n", 870 - of_flags, gpio); 871 - return -EINVAL; 855 + kfree(adev); 856 + } 857 + 858 + static int reset_add_gpio_aux_device(struct device *parent, 859 + struct fwnode_handle *swnode, 860 + int id, void *pdata) 861 + { 862 + struct auxiliary_device *adev; 863 + int ret; 864 + 865 + adev = kzalloc(sizeof(*adev), GFP_KERNEL); 866 + if (!adev) 867 + return -ENOMEM; 868 + 869 + adev->id = id; 870 + adev->name = "gpio"; 871 + adev->dev.parent = parent; 872 + adev->dev.platform_data = pdata; 873 + adev->dev.release = reset_gpio_aux_device_release; 874 + device_set_node(&adev->dev, swnode); 875 + 876 + ret = auxiliary_device_init(adev); 877 + if (ret) { 878 + kfree(adev); 879 + return ret; 872 880 } 873 881 874 - struct gpio_device *gdev __free(gpio_device_put) = gpio_device_find_by_fwnode(fwnode); 875 - if (!gdev) 876 - return -EPROBE_DEFER; 882 + ret = __auxiliary_device_add(adev, "reset"); 883 + if (ret) { 884 + auxiliary_device_uninit(adev); 885 + kfree(adev); 886 + return ret; 887 + } 877 888 878 - label_tmp = gpio_device_get_label(gdev); 879 - if (!label_tmp) 880 - return -EINVAL; 881 - 882 - char *label __free(kfree) = kstrdup(label_tmp, GFP_KERNEL); 883 - if (!label) 884 - return -ENOMEM; 885 - 886 - /* Size: one lookup entry plus sentinel */ 887 - struct gpiod_lookup_table *lookup __free(kfree) = kzalloc(struct_size(lookup, table, 2), 888 - GFP_KERNEL); 889 - if (!lookup) 890 - return -ENOMEM; 891 - 892 - lookup->dev_id = kasprintf(GFP_KERNEL, "reset-gpio.%d", id); 893 - if (!lookup->dev_id) 894 - return -ENOMEM; 895 - 896 - lookup_flags = GPIO_PERSISTENT; 897 - lookup_flags |= of_flags & GPIO_ACTIVE_LOW; 898 - lookup->table[0] = GPIO_LOOKUP(no_free_ptr(label), gpio, "reset", 899 - lookup_flags); 900 - 901 - /* Not freed on success, because it is persisent subsystem data. */ 902 - gpiod_add_lookup_table(no_free_ptr(lookup)); 903 - 904 - return 0; 889 + return ret; 905 890 } 906 891 907 892 /* ··· 898 905 */ 899 906 static int __reset_add_reset_gpio_device(const struct of_phandle_args *args) 900 907 { 908 + struct property_entry properties[2] = { }; 909 + unsigned int offset, of_flags, lflags; 901 910 struct reset_gpio_lookup *rgpio_dev; 902 - struct platform_device *pdev; 911 + struct device *parent; 903 912 int id, ret; 904 913 905 914 /* ··· 920 925 */ 921 926 lockdep_assert_not_held(&reset_list_mutex); 922 927 928 + offset = args->args[0]; 929 + of_flags = args->args[1]; 930 + 931 + /* 932 + * Later we map GPIO flags between OF and Linux, however not all 933 + * constants from include/dt-bindings/gpio/gpio.h and 934 + * include/linux/gpio/machine.h match each other. 935 + * 936 + * FIXME: Find a better way of translating OF flags to GPIO lookup 937 + * flags. 938 + */ 939 + if (of_flags > GPIO_ACTIVE_LOW) { 940 + pr_err("reset-gpio code does not support GPIO flags %u for GPIO %u\n", 941 + of_flags, offset); 942 + return -EINVAL; 943 + } 944 + 945 + struct gpio_device *gdev __free(gpio_device_put) = 946 + gpio_device_find_by_fwnode(of_fwnode_handle(args->np)); 947 + if (!gdev) 948 + return -EPROBE_DEFER; 949 + 923 950 guard(mutex)(&reset_gpio_lookup_mutex); 924 951 925 952 list_for_each_entry(rgpio_dev, &reset_gpio_lookup_list, list) { ··· 950 933 return 0; /* Already on the list, done */ 951 934 } 952 935 } 936 + 937 + lflags = GPIO_PERSISTENT | (of_flags & GPIO_ACTIVE_LOW); 938 + parent = gpio_device_to_device(gdev); 939 + properties[0] = PROPERTY_ENTRY_GPIO("reset-gpios", parent->fwnode, offset, lflags); 953 940 954 941 id = ida_alloc(&reset_gpio_ida, GFP_KERNEL); 955 942 if (id < 0) ··· 966 945 goto err_ida_free; 967 946 } 968 947 969 - ret = __reset_add_reset_gpio_lookup(id, args->np, args->args[0], 970 - args->args[1]); 971 - if (ret < 0) 972 - goto err_kfree; 973 - 974 948 rgpio_dev->of_args = *args; 975 949 /* 976 950 * We keep the device_node reference, but of_args.np is put at the end ··· 973 957 * Hold reference as long as rgpio_dev memory is valid. 974 958 */ 975 959 of_node_get(rgpio_dev->of_args.np); 976 - pdev = platform_device_register_data(NULL, "reset-gpio", id, 977 - &rgpio_dev->of_args, 978 - sizeof(rgpio_dev->of_args)); 979 - ret = PTR_ERR_OR_ZERO(pdev); 960 + 961 + rgpio_dev->swnode = fwnode_create_software_node(properties, NULL); 962 + if (IS_ERR(rgpio_dev->swnode)) { 963 + ret = PTR_ERR(rgpio_dev->swnode); 964 + goto err_put_of_node; 965 + } 966 + 967 + ret = reset_add_gpio_aux_device(parent, rgpio_dev->swnode, id, 968 + &rgpio_dev->of_args); 980 969 if (ret) 981 - goto err_put; 970 + goto err_del_swnode; 982 971 983 972 list_add(&rgpio_dev->list, &reset_gpio_lookup_list); 984 973 985 974 return 0; 986 975 987 - err_put: 976 + err_del_swnode: 977 + fwnode_remove_software_node(rgpio_dev->swnode); 978 + err_put_of_node: 988 979 of_node_put(rgpio_dev->of_args.np); 989 - err_kfree: 990 980 kfree(rgpio_dev); 991 981 err_ida_free: 992 982 ida_free(&reset_gpio_ida, id);
+10 -9
drivers/reset/reset-gpio.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 2 3 + #include <linux/auxiliary_bus.h> 3 4 #include <linux/gpio/consumer.h> 4 5 #include <linux/mod_devicetable.h> 5 6 #include <linux/module.h> 6 7 #include <linux/of.h> 7 - #include <linux/platform_device.h> 8 8 #include <linux/reset-controller.h> 9 9 10 10 struct reset_gpio_priv { ··· 61 61 of_node_put(data); 62 62 } 63 63 64 - static int reset_gpio_probe(struct platform_device *pdev) 64 + static int reset_gpio_probe(struct auxiliary_device *adev, 65 + const struct auxiliary_device_id *id) 65 66 { 66 - struct device *dev = &pdev->dev; 67 + struct device *dev = &adev->dev; 67 68 struct of_phandle_args *platdata = dev_get_platdata(dev); 68 69 struct reset_gpio_priv *priv; 69 70 int ret; ··· 76 75 if (!priv) 77 76 return -ENOMEM; 78 77 79 - platform_set_drvdata(pdev, &priv->rc); 78 + auxiliary_set_drvdata(adev, &priv->rc); 80 79 81 80 priv->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); 82 81 if (IS_ERR(priv->reset)) ··· 100 99 return devm_reset_controller_register(dev, &priv->rc); 101 100 } 102 101 103 - static const struct platform_device_id reset_gpio_ids[] = { 104 - { .name = "reset-gpio", }, 102 + static const struct auxiliary_device_id reset_gpio_ids[] = { 103 + { .name = "reset.gpio" }, 105 104 {} 106 105 }; 107 - MODULE_DEVICE_TABLE(platform, reset_gpio_ids); 106 + MODULE_DEVICE_TABLE(auxiliary, reset_gpio_ids); 108 107 109 - static struct platform_driver reset_gpio_driver = { 108 + static struct auxiliary_driver reset_gpio_driver = { 110 109 .probe = reset_gpio_probe, 111 110 .id_table = reset_gpio_ids, 112 111 .driver = { 113 112 .name = "reset-gpio", 114 113 }, 115 114 }; 116 - module_platform_driver(reset_gpio_driver); 115 + module_auxiliary_driver(reset_gpio_driver); 117 116 118 117 MODULE_AUTHOR("Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>"); 119 118 MODULE_DESCRIPTION("Generic GPIO reset driver");
+10 -30
drivers/spi/spi-cs42l43.c
··· 52 52 .mode = SPI_MODE_0, 53 53 }; 54 54 55 - static const struct software_node cs42l43_gpiochip_swnode = { 56 - .name = "cs42l43-pinctrl", 57 - }; 58 - 59 - static const struct software_node_ref_args cs42l43_cs_refs[] = { 60 - SOFTWARE_NODE_REFERENCE(&cs42l43_gpiochip_swnode, 0, GPIO_ACTIVE_LOW), 61 - SOFTWARE_NODE_REFERENCE(&swnode_gpio_undefined), 62 - }; 63 - 64 - static const struct property_entry cs42l43_cs_props[] = { 65 - PROPERTY_ENTRY_REF_ARRAY("cs-gpios", cs42l43_cs_refs), 66 - {} 67 - }; 68 - 69 55 static int cs42l43_spi_tx(struct regmap *regmap, const u8 *buf, unsigned int len) 70 56 { 71 57 const u8 *end = buf + len; ··· 310 324 fwnode_handle_put(data); 311 325 } 312 326 313 - static void cs42l43_release_sw_node(void *data) 314 - { 315 - software_node_unregister(&cs42l43_gpiochip_swnode); 316 - } 317 - 318 327 static int cs42l43_spi_probe(struct platform_device *pdev) 319 328 { 320 329 struct cs42l43 *cs42l43 = dev_get_drvdata(pdev->dev.parent); ··· 372 391 fwnode_property_read_u32(xu_fwnode, "01fa-sidecar-instances", &nsidecars); 373 392 374 393 if (nsidecars) { 394 + struct software_node_ref_args args[] = { 395 + SOFTWARE_NODE_REFERENCE(fwnode, 0, GPIO_ACTIVE_LOW), 396 + SOFTWARE_NODE_REFERENCE(&swnode_gpio_undefined), 397 + }; 398 + struct property_entry props[] = { 399 + PROPERTY_ENTRY_REF_ARRAY("cs-gpios", args), 400 + { } 401 + }; 402 + 375 403 ret = fwnode_property_read_u32(xu_fwnode, "01fa-spk-id-val", &spkid); 376 404 if (!ret) { 377 405 dev_dbg(priv->dev, "01fa-spk-id-val = %d\n", spkid); ··· 393 403 "Failed to get spk-id-gpios\n"); 394 404 } 395 405 396 - ret = software_node_register(&cs42l43_gpiochip_swnode); 397 - if (ret) 398 - return dev_err_probe(priv->dev, ret, 399 - "Failed to register gpio swnode\n"); 400 - 401 - ret = devm_add_action_or_reset(priv->dev, cs42l43_release_sw_node, NULL); 402 - if (ret) 403 - return ret; 404 - 405 - ret = device_create_managed_software_node(&priv->ctlr->dev, 406 - cs42l43_cs_props, NULL); 406 + ret = device_create_managed_software_node(&priv->ctlr->dev, props, NULL); 407 407 if (ret) 408 408 return dev_err_probe(priv->dev, ret, "Failed to add swnode\n"); 409 409 } else {
+10 -3
include/linux/property.h
··· 355 355 356 356 /** 357 357 * struct software_node_ref_args - Reference property with additional arguments 358 - * @node: Reference to a software node 358 + * @swnode: Reference to a software node 359 + * @fwnode: Alternative reference to a firmware node handle 359 360 * @nargs: Number of elements in @args array 360 361 * @args: Integer arguments 361 362 */ 362 363 struct software_node_ref_args { 363 - const struct software_node *node; 364 + const struct software_node *swnode; 365 + struct fwnode_handle *fwnode; 364 366 unsigned int nargs; 365 367 u64 args[NR_FWNODE_REFERENCE_ARGS]; 366 368 }; 367 369 368 370 #define SOFTWARE_NODE_REFERENCE(_ref_, ...) \ 369 371 (const struct software_node_ref_args) { \ 370 - .node = _ref_, \ 372 + .swnode = _Generic(_ref_, \ 373 + const struct software_node *: _ref_, \ 374 + default: NULL), \ 375 + .fwnode = _Generic(_ref_, \ 376 + struct fwnode_handle *: _ref_, \ 377 + default: NULL), \ 371 378 .nargs = COUNT_ARGS(__VA_ARGS__), \ 372 379 .args = { __VA_ARGS__ }, \ 373 380 }