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.

gpio: sim: use fwnode-based GPIO hogs

Convert gpio-sim to using software nodes for setting up simulated hogs
instead of legacy machine hogs.

Reviewed-by: Linus Walleij <linusw@kernel.org>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Link: https://patch.msgid.link/20260309-gpio-hog-fwnode-v2-3-4e61f3dbf06a@oss.qualcomm.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>

+56 -106
+56 -106
drivers/gpio/gpio-sim.c
··· 40 40 41 41 #define GPIO_SIM_NGPIO_MAX 1024 42 42 #define GPIO_SIM_PROP_MAX 5 /* Max 4 properties + sentinel. */ 43 + #define GPIO_SIM_HOG_PROP_MAX 5 43 44 #define GPIO_SIM_NUM_ATTRS 3 /* value, pull and sentinel */ 44 45 45 46 static DEFINE_IDA(gpio_sim_ida); ··· 562 561 */ 563 562 struct mutex lock; 564 563 565 - struct gpiod_hog *hogs; 566 - 567 564 struct list_head bank_list; 568 565 }; 569 566 ··· 773 774 } 774 775 } 775 776 776 - static void gpio_sim_remove_hogs(struct gpio_sim_device *dev) 777 - { 778 - struct gpiod_hog *hog; 779 - 780 - if (!dev->hogs) 781 - return; 782 - 783 - gpiod_remove_hogs(dev->hogs); 784 - 785 - for (hog = dev->hogs; hog->chip_label; hog++) { 786 - kfree(hog->chip_label); 787 - kfree(hog->line_name); 788 - } 789 - 790 - kfree(dev->hogs); 791 - dev->hogs = NULL; 792 - } 793 - 794 - static int gpio_sim_add_hogs(struct gpio_sim_device *dev) 795 - { 796 - unsigned int num_hogs = 0, idx = 0; 797 - struct gpio_sim_bank *bank; 798 - struct gpio_sim_line *line; 799 - struct gpiod_hog *hog; 800 - 801 - list_for_each_entry(bank, &dev->bank_list, siblings) { 802 - list_for_each_entry(line, &bank->line_list, siblings) { 803 - if (line->offset >= bank->num_lines) 804 - continue; 805 - 806 - if (line->hog) 807 - num_hogs++; 808 - } 809 - } 810 - 811 - if (!num_hogs) 812 - return 0; 813 - 814 - /* Allocate one more for the sentinel. */ 815 - dev->hogs = kzalloc_objs(*dev->hogs, num_hogs + 1); 816 - if (!dev->hogs) 817 - return -ENOMEM; 818 - 819 - list_for_each_entry(bank, &dev->bank_list, siblings) { 820 - list_for_each_entry(line, &bank->line_list, siblings) { 821 - if (line->offset >= bank->num_lines) 822 - continue; 823 - 824 - if (!line->hog) 825 - continue; 826 - 827 - hog = &dev->hogs[idx++]; 828 - 829 - /* 830 - * We need to make this string manually because at this 831 - * point the device doesn't exist yet and so dev_name() 832 - * is not available. 833 - */ 834 - if (gpio_sim_bank_has_label(bank)) 835 - hog->chip_label = kstrdup(bank->label, 836 - GFP_KERNEL); 837 - else 838 - hog->chip_label = kasprintf(GFP_KERNEL, 839 - "gpio-sim.%u:%pfwP", 840 - dev->id, 841 - bank->swnode); 842 - if (!hog->chip_label) { 843 - gpio_sim_remove_hogs(dev); 844 - return -ENOMEM; 845 - } 846 - 847 - /* 848 - * We need to duplicate this because the hog config 849 - * item can be removed at any time (and we can't block 850 - * it) and gpiolib doesn't make a deep copy of the hog 851 - * data. 852 - */ 853 - if (line->hog->name) { 854 - hog->line_name = kstrdup(line->hog->name, 855 - GFP_KERNEL); 856 - if (!hog->line_name) { 857 - gpio_sim_remove_hogs(dev); 858 - return -ENOMEM; 859 - } 860 - } 861 - 862 - hog->chip_hwnum = line->offset; 863 - hog->dflags = line->hog->dir; 864 - } 865 - } 866 - 867 - gpiod_add_hogs(dev->hogs); 868 - 869 - return 0; 870 - } 871 - 872 777 static struct fwnode_handle * 873 778 gpio_sim_make_bank_swnode(struct gpio_sim_bank *bank, 874 779 struct fwnode_handle *parent) ··· 820 917 return fwnode_create_software_node(properties, parent); 821 918 } 822 919 920 + static int gpio_sim_bank_add_hogs(struct gpio_sim_bank *bank) 921 + { 922 + struct property_entry properties[GPIO_SIM_HOG_PROP_MAX]; 923 + struct fwnode_handle *swnode; 924 + struct gpio_sim_line *line; 925 + struct gpio_sim_hog *hog; 926 + unsigned int idx; 927 + u32 gpios[2]; 928 + 929 + list_for_each_entry(line, &bank->line_list, siblings) { 930 + if (!line->hog) 931 + continue; 932 + 933 + hog = line->hog; 934 + 935 + gpios[0] = line->offset; 936 + gpios[1] = 0; 937 + 938 + memset(properties, 0, sizeof(properties)); 939 + 940 + idx = 0; 941 + properties[idx++] = PROPERTY_ENTRY_BOOL("gpio-hog"); 942 + properties[idx++] = PROPERTY_ENTRY_U32_ARRAY("gpios", gpios); 943 + properties[idx++] = PROPERTY_ENTRY_STRING("line-name", hog->name); 944 + 945 + switch (hog->dir) { 946 + case GPIOD_IN: 947 + properties[idx++] = PROPERTY_ENTRY_BOOL("input"); 948 + break; 949 + case GPIOD_OUT_HIGH: 950 + properties[idx++] = PROPERTY_ENTRY_BOOL("output-high"); 951 + break; 952 + case GPIOD_OUT_LOW: 953 + properties[idx++] = PROPERTY_ENTRY_BOOL("output-low"); 954 + break; 955 + default: 956 + /* Would have been validated at configfs store. */ 957 + WARN(1, "Unexpected hog direction value: %d", hog->dir); 958 + return -EINVAL; 959 + } 960 + 961 + swnode = fwnode_create_software_node(properties, bank->swnode); 962 + if (IS_ERR(swnode)) 963 + return PTR_ERR(swnode); 964 + } 965 + 966 + return 0; 967 + } 968 + 823 969 static void gpio_sim_remove_swnode_recursive(struct fwnode_handle *swnode) 824 970 { 825 971 struct fwnode_handle *child; 826 972 827 973 fwnode_for_each_child_node(swnode, child) 828 - fwnode_remove_software_node(child); 974 + gpio_sim_remove_swnode_recursive(child); 829 975 830 976 fwnode_remove_software_node(swnode); 831 977 } ··· 929 977 gpio_sim_remove_swnode_recursive(swnode); 930 978 return ret; 931 979 } 932 - } 933 980 934 - ret = gpio_sim_add_hogs(dev); 935 - if (ret) { 936 - gpio_sim_remove_swnode_recursive(swnode); 937 - return ret; 981 + ret = gpio_sim_bank_add_hogs(bank); 982 + if (ret) { 983 + gpio_sim_remove_swnode_recursive(swnode); 984 + return ret; 985 + } 938 986 } 939 987 940 988 pdevinfo.name = "gpio-sim"; ··· 943 991 944 992 ret = dev_sync_probe_register(&dev->probe_data, &pdevinfo); 945 993 if (ret) { 946 - gpio_sim_remove_hogs(dev); 947 994 gpio_sim_remove_swnode_recursive(swnode); 948 995 return ret; 949 996 } ··· 958 1007 959 1008 swnode = dev_fwnode(&dev->probe_data.pdev->dev); 960 1009 dev_sync_probe_unregister(&dev->probe_data); 961 - gpio_sim_remove_hogs(dev); 962 1010 gpio_sim_remove_swnode_recursive(swnode); 963 1011 } 964 1012