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.

reset: gpio: add a devlink between reset-gpio and its consumer

The device that requests the reset control managed by the reset-gpio
device is effectively its consumer but the devlink is only established
between it and the GPIO controller exposing the reset pin. Add a devlink
between the consumer of the reset control and its supplier. This will
allow us to simplify the GPIOLIB code managing shared GPIOs when
handling the corner case of reset-gpio and gpiolib-shared interacting.
While at it and since we need to store the address of the auxiliary
device: don't allocate memory for the device separately but fold it into
struct reset_gpio_lookup instead.

Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de>
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>

authored by

Bartosz Golaszewski and committed by
Philipp Zabel
a9b95ce3 fe3da77f

+55 -24
+55 -24
drivers/reset/core.c
··· 77 77 * @of_args: phandle to the reset controller with all the args like GPIO number 78 78 * @swnode: Software node containing the reference to the GPIO provider 79 79 * @list: list entry for the reset_gpio_lookup_list 80 + * @adev: Auxiliary device representing the reset controller 80 81 */ 81 82 struct reset_gpio_lookup { 82 83 struct of_phandle_args of_args; 83 84 struct fwnode_handle *swnode; 84 85 struct list_head list; 86 + struct auxiliary_device adev; 85 87 }; 86 88 87 89 static const char *rcdev_name(struct reset_controller_dev *rcdev) ··· 826 824 827 825 static void reset_gpio_aux_device_release(struct device *dev) 828 826 { 829 - struct auxiliary_device *adev = to_auxiliary_dev(dev); 830 827 831 - kfree(adev); 832 828 } 833 829 834 - static int reset_add_gpio_aux_device(struct device *parent, 835 - struct fwnode_handle *swnode, 836 - int id, void *pdata) 830 + static int reset_create_gpio_aux_device(struct reset_gpio_lookup *rgpio_dev, 831 + struct device *parent, int id) 837 832 { 838 - struct auxiliary_device *adev; 833 + struct auxiliary_device *adev = &rgpio_dev->adev; 839 834 int ret; 840 - 841 - adev = kzalloc_obj(*adev); 842 - if (!adev) 843 - return -ENOMEM; 844 835 845 836 adev->id = id; 846 837 adev->name = "gpio"; 847 838 adev->dev.parent = parent; 848 - adev->dev.platform_data = pdata; 839 + adev->dev.platform_data = &rgpio_dev->of_args; 849 840 adev->dev.release = reset_gpio_aux_device_release; 850 - device_set_node(&adev->dev, swnode); 841 + device_set_node(&adev->dev, rgpio_dev->swnode); 851 842 852 843 ret = auxiliary_device_init(adev); 853 - if (ret) { 854 - kfree(adev); 844 + if (ret) 855 845 return ret; 856 - } 857 846 858 847 ret = __auxiliary_device_add(adev, "reset"); 859 848 if (ret) { 860 849 auxiliary_device_uninit(adev); 861 - kfree(adev); 862 850 return ret; 863 851 } 864 852 865 - return ret; 853 + return 0; 854 + } 855 + 856 + static void reset_gpio_add_devlink(struct device_node *np, 857 + struct reset_gpio_lookup *rgpio_dev) 858 + { 859 + struct device *consumer; 860 + 861 + /* 862 + * We must use get_dev_from_fwnode() and not of_find_device_by_node() 863 + * because the latter only considers the platform bus while we want to 864 + * get consumers of any kind that can be associated with firmware 865 + * nodes: auxiliary, soundwire, etc. 866 + */ 867 + consumer = get_dev_from_fwnode(of_fwnode_handle(np)); 868 + if (consumer) { 869 + if (!device_link_add(consumer, &rgpio_dev->adev.dev, 870 + DL_FLAG_AUTOREMOVE_CONSUMER)) 871 + pr_warn("Failed to create a device link between reset-gpio and its consumer"); 872 + 873 + put_device(consumer); 874 + } 875 + /* 876 + * else { } 877 + * 878 + * TODO: If ever there's a case where we need to support shared 879 + * reset-gpios retrieved from a device node for which there's no 880 + * device present yet, this is where we'd set up a notifier waiting 881 + * for the device to appear in the system. This would be a lot of code 882 + * that would go unused for now so let's cross that bridge when and if 883 + * we get there. 884 + */ 866 885 } 867 886 868 887 /* 869 - * @args: phandle to the GPIO provider with all the args like GPIO number 888 + * @np: OF-node associated with the consumer 889 + * @args: phandle to the GPIO provider with all the args like GPIO number 870 890 */ 871 - static int __reset_add_reset_gpio_device(const struct of_phandle_args *args) 891 + static int __reset_add_reset_gpio_device(struct device_node *np, 892 + const struct of_phandle_args *args) 872 893 { 873 894 struct property_entry properties[3] = { }; 874 895 unsigned int offset, of_flags, lflags; ··· 941 916 942 917 list_for_each_entry(rgpio_dev, &reset_gpio_lookup_list, list) { 943 918 if (args->np == rgpio_dev->of_args.np) { 944 - if (of_phandle_args_equal(args, &rgpio_dev->of_args)) 945 - return 0; /* Already on the list, done */ 919 + if (of_phandle_args_equal(args, &rgpio_dev->of_args)) { 920 + /* 921 + * Already on the list, create the device link 922 + * and stop here. 923 + */ 924 + reset_gpio_add_devlink(np, rgpio_dev); 925 + return 0; 926 + } 946 927 } 947 928 } 948 929 ··· 982 951 goto err_put_of_node; 983 952 } 984 953 985 - ret = reset_add_gpio_aux_device(parent, rgpio_dev->swnode, id, 986 - &rgpio_dev->of_args); 954 + ret = reset_create_gpio_aux_device(rgpio_dev, parent, id); 987 955 if (ret) 988 956 goto err_del_swnode; 989 957 958 + reset_gpio_add_devlink(np, rgpio_dev); 990 959 list_add(&rgpio_dev->list, &reset_gpio_lookup_list); 991 960 992 961 return 0; ··· 1066 1035 1067 1036 gpio_fallback = true; 1068 1037 1069 - ret = __reset_add_reset_gpio_device(&args); 1038 + ret = __reset_add_reset_gpio_device(node, &args); 1070 1039 if (ret) { 1071 1040 rstc = ERR_PTR(ret); 1072 1041 goto out_put;