Lines Matching +full:output +full:- +full:ngpios

1 // SPDX-License-Identifier: GPL-2.0-only
5 // Copyright (C) 2019-2020 Glider bv
7 #define DRV_NAME "gpio-aggregator"
35 #include "dev-sync-probe.h"
91 return -ENOMEM; in gpio_aggregator_alloc()
99 new->id = ret; in gpio_aggregator_alloc()
100 INIT_LIST_HEAD(&new->list_head); in gpio_aggregator_alloc()
101 mutex_init(&new->lock); in gpio_aggregator_alloc()
109 idr_remove(&gpio_aggregator_idr, aggr->id); in gpio_aggregator_free()
111 mutex_destroy(&aggr->lock); in gpio_aggregator_free()
120 lookups = krealloc(aggr->lookups, struct_size(lookups, table, *n + 2), in gpio_aggregator_add_gpio()
123 return -ENOMEM; in gpio_aggregator_add_gpio()
125 lookups->table[*n] = GPIO_LOOKUP_IDX(key, hwnum, NULL, *n, 0); in gpio_aggregator_add_gpio()
128 memset(&lookups->table[*n], 0, sizeof(lookups->table[*n])); in gpio_aggregator_add_gpio()
130 aggr->lookups = lookups; in gpio_aggregator_add_gpio()
136 lockdep_assert_held(&aggr->lock); in gpio_aggregator_is_active()
138 return aggr->probe_data.pdev && platform_get_drvdata(aggr->probe_data.pdev); in gpio_aggregator_is_active()
144 lockdep_assert_held(&aggr->lock); in gpio_aggregator_is_activating()
146 return aggr->probe_data.pdev && !platform_get_drvdata(aggr->probe_data.pdev); in gpio_aggregator_is_activating()
151 lockdep_assert_held(&aggr->lock); in gpio_aggregator_count_lines()
153 return list_count_nodes(&aggr->list_head); in gpio_aggregator_count_lines()
164 return ERR_PTR(-ENOMEM); in gpio_aggregator_line_alloc()
167 line->key = kstrdup(key, GFP_KERNEL); in gpio_aggregator_line_alloc()
168 if (!line->key) { in gpio_aggregator_line_alloc()
170 return ERR_PTR(-ENOMEM); in gpio_aggregator_line_alloc()
174 line->flags = GPIO_LOOKUP_FLAGS_DEFAULT; in gpio_aggregator_line_alloc()
175 line->parent = parent; in gpio_aggregator_line_alloc()
176 line->idx = idx; in gpio_aggregator_line_alloc()
177 line->offset = offset; in gpio_aggregator_line_alloc()
178 INIT_LIST_HEAD(&line->entry); in gpio_aggregator_line_alloc()
188 lockdep_assert_held(&aggr->lock); in gpio_aggregator_line_add()
190 list_for_each_entry(tmp, &aggr->list_head, entry) { in gpio_aggregator_line_add()
191 if (tmp->idx > line->idx) { in gpio_aggregator_line_add()
192 list_add_tail(&line->entry, &tmp->entry); in gpio_aggregator_line_add()
196 list_add_tail(&line->entry, &aggr->list_head); in gpio_aggregator_line_add()
202 lockdep_assert_held(&aggr->lock); in gpio_aggregator_line_del()
204 list_del(&line->entry); in gpio_aggregator_line_del()
211 list_for_each_entry_safe(line, tmp, &aggr->list_head, entry) { in gpio_aggregator_free_lines()
212 configfs_unregister_group(&line->group); in gpio_aggregator_free_lines()
214 * Normally, we acquire aggr->lock within the configfs in gpio_aggregator_free_lines()
217 * aggr->lock could cause a deadlock. Fortunately, this is in gpio_aggregator_free_lines()
223 scoped_guard(mutex, &aggr->lock) in gpio_aggregator_free_lines()
225 kfree(line->key); in gpio_aggregator_free_lines()
226 kfree(line->name); in gpio_aggregator_free_lines()
254 #define fwd_tmp_values(fwd) (&(fwd)->tmp[0])
255 #define fwd_tmp_descs(fwd) ((void *)&(fwd)->tmp[BITS_TO_LONGS((fwd)->chip.ngpio)])
257 #define fwd_tmp_size(ngpios) (BITS_TO_LONGS((ngpios)) + (ngpios)) argument
263 return test_bit(offset, fwd->valid_mask) ? 0 : -ENODEV; in gpio_fwd_request()
272 * -ENODEV if there is no GPIO desc for the line. in gpio_fwd_get_direction()
274 if (!test_bit(offset, fwd->valid_mask)) in gpio_fwd_get_direction()
275 return -ENODEV; in gpio_fwd_get_direction()
277 return gpiod_get_direction(fwd->descs[offset]); in gpio_fwd_get_direction()
284 return gpiod_direction_input(fwd->descs[offset]); in gpio_fwd_direction_input()
292 return gpiod_direction_output(fwd->descs[offset], value); in gpio_fwd_direction_output()
299 return chip->can_sleep ? gpiod_get_value_cansleep(fwd->descs[offset]) in gpio_fwd_get()
300 : gpiod_get_value(fwd->descs[offset]); in gpio_fwd_get()
311 bitmap_clear(values, 0, fwd->chip.ngpio); in gpio_fwd_get_multiple()
312 for_each_set_bit(i, mask, fwd->chip.ngpio) in gpio_fwd_get_multiple()
313 descs[j++] = fwd->descs[i]; in gpio_fwd_get_multiple()
315 if (fwd->chip.can_sleep) in gpio_fwd_get_multiple()
323 for_each_set_bit(i, mask, fwd->chip.ngpio) in gpio_fwd_get_multiple()
336 if (chip->can_sleep) { in gpio_fwd_get_multiple_locked()
337 mutex_lock(&fwd->mlock); in gpio_fwd_get_multiple_locked()
339 mutex_unlock(&fwd->mlock); in gpio_fwd_get_multiple_locked()
341 spin_lock_irqsave(&fwd->slock, flags); in gpio_fwd_get_multiple_locked()
343 spin_unlock_irqrestore(&fwd->slock, flags); in gpio_fwd_get_multiple_locked()
353 bool is_active_low = gpiod_is_active_low(fwd->descs[offset]); in gpio_fwd_delay()
356 delay_timings = &fwd->delay_timings[offset]; in gpio_fwd_delay()
358 delay_us = delay_timings->ramp_up_us; in gpio_fwd_delay()
360 delay_us = delay_timings->ramp_down_us; in gpio_fwd_delay()
364 if (chip->can_sleep) in gpio_fwd_delay()
375 if (chip->can_sleep) in gpio_fwd_set()
376 ret = gpiod_set_value_cansleep(fwd->descs[offset], value); in gpio_fwd_set()
378 ret = gpiod_set_value(fwd->descs[offset], value); in gpio_fwd_set()
382 if (fwd->delay_timings) in gpio_fwd_set()
395 for_each_set_bit(i, mask, fwd->chip.ngpio) { in gpio_fwd_set_multiple()
397 descs[j++] = fwd->descs[i]; in gpio_fwd_set_multiple()
400 if (fwd->chip.can_sleep) in gpio_fwd_set_multiple()
415 if (chip->can_sleep) { in gpio_fwd_set_multiple_locked()
416 mutex_lock(&fwd->mlock); in gpio_fwd_set_multiple_locked()
418 mutex_unlock(&fwd->mlock); in gpio_fwd_set_multiple_locked()
420 spin_lock_irqsave(&fwd->slock, flags); in gpio_fwd_set_multiple_locked()
422 spin_unlock_irqrestore(&fwd->slock, flags); in gpio_fwd_set_multiple_locked()
433 return gpiod_set_config(fwd->descs[offset], config); in gpio_fwd_set_config()
440 return gpiod_to_irq(fwd->descs[offset]); in gpio_fwd_to_irq()
445 * for the GPIO ramp-up or ramp-down delays. This can serve the following
447 * - Open-drain output using an RC filter
460 if (gpiospec->args_count != chip->of_gpio_n_cells) in gpiochip_fwd_delay_of_xlate()
461 return -EINVAL; in gpiochip_fwd_delay_of_xlate()
463 line = gpiospec->args[0]; in gpiochip_fwd_delay_of_xlate()
464 if (line >= chip->ngpio) in gpiochip_fwd_delay_of_xlate()
465 return -EINVAL; in gpiochip_fwd_delay_of_xlate()
467 timings = &fwd->delay_timings[line]; in gpiochip_fwd_delay_of_xlate()
468 timings->ramp_up_us = gpiospec->args[1]; in gpiochip_fwd_delay_of_xlate()
469 timings->ramp_down_us = gpiospec->args[2]; in gpiochip_fwd_delay_of_xlate()
476 struct gpio_chip *chip = &fwd->chip; in gpiochip_fwd_setup_delay_line()
478 fwd->delay_timings = devm_kcalloc(chip->parent, chip->ngpio, in gpiochip_fwd_setup_delay_line()
479 sizeof(*fwd->delay_timings), in gpiochip_fwd_setup_delay_line()
481 if (!fwd->delay_timings) in gpiochip_fwd_setup_delay_line()
482 return -ENOMEM; in gpiochip_fwd_setup_delay_line()
484 chip->of_xlate = gpiochip_fwd_delay_of_xlate; in gpiochip_fwd_setup_delay_line()
485 chip->of_gpio_n_cells = 3; in gpiochip_fwd_setup_delay_line()
497 * gpiochip_fwd_get_gpiochip - Get the GPIO chip for the GPIO forwarder
504 return &fwd->chip; in gpiochip_fwd_get_gpiochip()
509 * gpiochip_fwd_get_data - Get driver-private data for the GPIO forwarder
512 * Returns: The driver-private data for the GPIO forwarder
516 return fwd->data; in gpiochip_fwd_get_data()
521 * gpiochip_fwd_gpio_request - Request a line of the GPIO forwarder
536 * gpiochip_fwd_gpio_get_direction - Return the current direction of a GPIO forwarder line
540 * Returns: 0 for output, 1 for input, or an error code in case of error.
551 * gpiochip_fwd_gpio_direction_output - Set a GPIO forwarder line direction to
552 * output
569 * gpiochip_fwd_gpio_direction_input - Set a GPIO forwarder line direction to input
584 * gpiochip_fwd_gpio_get - Return a GPIO forwarder line's value
600 * gpiochip_fwd_gpio_get_multiple - Get values for multiple GPIO forwarder lines
619 * gpiochip_fwd_gpio_set - Assign value to a GPIO forwarder line.
635 * gpiochip_fwd_gpio_set_multiple - Assign values to multiple GPIO forwarder lines
637 * @mask: bit mask array; one bit per output; BITS_PER_LONG bits per word
639 * @bits: bit value array; one bit per output; BITS_PER_LONG bits per word
654 * gpiochip_fwd_gpio_set_config - Set @config for a GPIO forwarder line
659 * Returns: 0 on success, %-ENOTSUPP if the controller doesn't support setting
672 * gpiochip_fwd_gpio_to_irq - Return the IRQ corresponding to a GPIO forwarder line
688 * devm_gpiochip_fwd_alloc - Allocate and initialize a new GPIO forwarder
690 * @ngpios: Number of GPIOs in the forwarder
692 * Returns: An opaque object pointer, or an ERR_PTR()-encoded negative error
696 unsigned int ngpios) in devm_gpiochip_fwd_alloc() argument
701 fwd = devm_kzalloc(dev, struct_size(fwd, tmp, fwd_tmp_size(ngpios)), GFP_KERNEL); in devm_gpiochip_fwd_alloc()
703 return ERR_PTR(-ENOMEM); in devm_gpiochip_fwd_alloc()
705 fwd->descs = devm_kcalloc(dev, ngpios, sizeof(*fwd->descs), GFP_KERNEL); in devm_gpiochip_fwd_alloc()
706 if (!fwd->descs) in devm_gpiochip_fwd_alloc()
707 return ERR_PTR(-ENOMEM); in devm_gpiochip_fwd_alloc()
709 fwd->valid_mask = devm_bitmap_zalloc(dev, ngpios, GFP_KERNEL); in devm_gpiochip_fwd_alloc()
710 if (!fwd->valid_mask) in devm_gpiochip_fwd_alloc()
711 return ERR_PTR(-ENOMEM); in devm_gpiochip_fwd_alloc()
713 chip = &fwd->chip; in devm_gpiochip_fwd_alloc()
715 chip->label = dev_name(dev); in devm_gpiochip_fwd_alloc()
716 chip->parent = dev; in devm_gpiochip_fwd_alloc()
717 chip->owner = THIS_MODULE; in devm_gpiochip_fwd_alloc()
718 chip->request = gpio_fwd_request; in devm_gpiochip_fwd_alloc()
719 chip->get_direction = gpio_fwd_get_direction; in devm_gpiochip_fwd_alloc()
720 chip->direction_input = gpio_fwd_direction_input; in devm_gpiochip_fwd_alloc()
721 chip->direction_output = gpio_fwd_direction_output; in devm_gpiochip_fwd_alloc()
722 chip->get = gpio_fwd_get; in devm_gpiochip_fwd_alloc()
723 chip->get_multiple = gpio_fwd_get_multiple_locked; in devm_gpiochip_fwd_alloc()
724 chip->set = gpio_fwd_set; in devm_gpiochip_fwd_alloc()
725 chip->set_multiple = gpio_fwd_set_multiple_locked; in devm_gpiochip_fwd_alloc()
726 chip->set_config = gpio_fwd_set_config; in devm_gpiochip_fwd_alloc()
727 chip->to_irq = gpio_fwd_to_irq; in devm_gpiochip_fwd_alloc()
728 chip->base = -1; in devm_gpiochip_fwd_alloc()
729 chip->ngpio = ngpios; in devm_gpiochip_fwd_alloc()
736 * gpiochip_fwd_desc_add - Add a GPIO desc in the forwarder
746 struct gpio_chip *chip = &fwd->chip; in gpiochip_fwd_desc_add()
748 if (offset >= chip->ngpio) in gpiochip_fwd_desc_add()
749 return -EINVAL; in gpiochip_fwd_desc_add()
751 if (test_and_set_bit(offset, fwd->valid_mask)) in gpiochip_fwd_desc_add()
752 return -EEXIST; in gpiochip_fwd_desc_add()
759 chip->can_sleep = true; in gpiochip_fwd_desc_add()
761 fwd->descs[offset] = desc; in gpiochip_fwd_desc_add()
763 dev_dbg(chip->parent, "%u => gpio %d irq %d\n", offset, in gpiochip_fwd_desc_add()
771 * gpiochip_fwd_desc_free - Remove a GPIO desc from the forwarder
777 if (test_and_clear_bit(offset, fwd->valid_mask)) in gpiochip_fwd_desc_free()
778 gpiod_put(fwd->descs[offset]); in gpiochip_fwd_desc_free()
783 * gpiochip_fwd_register - Register a GPIO forwarder
785 * @data: driver-private data associated with this forwarder
791 struct gpio_chip *chip = &fwd->chip; in gpiochip_fwd_register()
797 if (!bitmap_full(fwd->valid_mask, chip->ngpio)) in gpiochip_fwd_register()
798 chip->can_sleep = true; in gpiochip_fwd_register()
800 if (chip->can_sleep) in gpiochip_fwd_register()
801 mutex_init(&fwd->mlock); in gpiochip_fwd_register()
803 spin_lock_init(&fwd->slock); in gpiochip_fwd_register()
805 fwd->data = data; in gpiochip_fwd_register()
807 return devm_gpiochip_add_data(chip->parent, chip, fwd); in gpiochip_fwd_register()
812 * gpiochip_fwd_create() - Create a new GPIO forwarder
814 * @ngpios: Number of GPIOs in the forwarder.
816 * This array must contain @ngpios entries, and can be deallocated
823 * Return: An opaque object pointer, or an ERR_PTR()-encoded negative error
827 unsigned int ngpios, in gpiochip_fwd_create() argument
835 fwd = devm_gpiochip_fwd_alloc(dev, ngpios); in gpiochip_fwd_create()
839 for (i = 0; i < ngpios; i++) { in gpiochip_fwd_create()
895 return ERR_PTR(-ENOMEM); in gpio_aggregator_make_device_sw_node()
898 list_for_each_entry(line, &aggr->list_head, entry) in gpio_aggregator_make_device_sw_node()
899 line_names[n++] = line->name ?: ""; in gpio_aggregator_make_device_sw_node()
902 "gpio-line-names", in gpio_aggregator_make_device_sw_node()
917 return -EINVAL; in gpio_aggregator_activate()
919 aggr->lookups = kzalloc(struct_size(aggr->lookups, table, 1), in gpio_aggregator_activate()
921 if (!aggr->lookups) in gpio_aggregator_activate()
922 return -ENOMEM; in gpio_aggregator_activate()
932 pdevinfo.id = aggr->id; in gpio_aggregator_activate()
936 list_for_each_entry(line, &aggr->list_head, entry) { in gpio_aggregator_activate()
938 * - Either GPIO chip label or line name must be configured in gpio_aggregator_activate()
939 * (i.e. line->key must be non-NULL) in gpio_aggregator_activate()
940 * - Line directories must be named with sequential numeric in gpio_aggregator_activate()
943 if (!line->key || line->idx != n) { in gpio_aggregator_activate()
944 ret = -EINVAL; in gpio_aggregator_activate()
948 if (line->offset < 0) in gpio_aggregator_activate()
949 ret = gpio_aggregator_add_gpio(aggr, line->key, in gpio_aggregator_activate()
952 ret = gpio_aggregator_add_gpio(aggr, line->key, in gpio_aggregator_activate()
953 line->offset, &n); in gpio_aggregator_activate()
958 aggr->lookups->dev_id = kasprintf(GFP_KERNEL, "%s.%d", DRV_NAME, aggr->id); in gpio_aggregator_activate()
959 if (!aggr->lookups->dev_id) { in gpio_aggregator_activate()
960 ret = -ENOMEM; in gpio_aggregator_activate()
964 gpiod_add_lookup_table(aggr->lookups); in gpio_aggregator_activate()
966 ret = dev_sync_probe_register(&aggr->probe_data, &pdevinfo); in gpio_aggregator_activate()
973 kfree(aggr->lookups->dev_id); in gpio_aggregator_activate()
974 gpiod_remove_lookup_table(aggr->lookups); in gpio_aggregator_activate()
978 kfree(aggr->lookups); in gpio_aggregator_activate()
985 dev_sync_probe_unregister(&aggr->probe_data); in gpio_aggregator_deactivate()
986 gpiod_remove_lookup_table(aggr->lookups); in gpio_aggregator_deactivate()
987 kfree(aggr->lookups->dev_id); in gpio_aggregator_deactivate()
988 kfree(aggr->lookups); in gpio_aggregator_deactivate()
994 struct configfs_subsystem *subsys = aggr->group.cg_subsys; in gpio_aggregator_lockup_configfs()
1002 list_for_each_entry(line, &aggr->list_head, entry) { in gpio_aggregator_lockup_configfs()
1005 subsys, &line->group.cg_item); in gpio_aggregator_lockup_configfs()
1008 &line->group.cg_item); in gpio_aggregator_lockup_configfs()
1016 struct gpio_aggregator *aggr = line->parent; in gpio_aggregator_line_key_show()
1018 guard(mutex)(&aggr->lock); in gpio_aggregator_line_key_show()
1020 return sysfs_emit(page, "%s\n", line->key ?: ""); in gpio_aggregator_line_key_show()
1028 struct gpio_aggregator *aggr = line->parent; in gpio_aggregator_line_key_store()
1033 return -ENOMEM; in gpio_aggregator_line_key_store()
1037 guard(mutex)(&aggr->lock); in gpio_aggregator_line_key_store()
1041 return -EBUSY; in gpio_aggregator_line_key_store()
1043 kfree(line->key); in gpio_aggregator_line_key_store()
1044 line->key = no_free_ptr(key); in gpio_aggregator_line_key_store()
1054 struct gpio_aggregator *aggr = line->parent; in gpio_aggregator_line_name_show()
1056 guard(mutex)(&aggr->lock); in gpio_aggregator_line_name_show()
1058 return sysfs_emit(page, "%s\n", line->name ?: ""); in gpio_aggregator_line_name_show()
1066 struct gpio_aggregator *aggr = line->parent; in gpio_aggregator_line_name_store()
1071 return -ENOMEM; in gpio_aggregator_line_name_store()
1075 guard(mutex)(&aggr->lock); in gpio_aggregator_line_name_store()
1079 return -EBUSY; in gpio_aggregator_line_name_store()
1081 kfree(line->name); in gpio_aggregator_line_name_store()
1082 line->name = no_free_ptr(name); in gpio_aggregator_line_name_store()
1092 struct gpio_aggregator *aggr = line->parent; in gpio_aggregator_line_offset_show()
1094 guard(mutex)(&aggr->lock); in gpio_aggregator_line_offset_show()
1096 return sysfs_emit(page, "%d\n", line->offset); in gpio_aggregator_line_offset_show()
1104 struct gpio_aggregator *aggr = line->parent; in gpio_aggregator_line_offset_store()
1112 * When offset == -1, 'key' represents a line name to lookup. in gpio_aggregator_line_offset_store()
1117 * the greatest offset we can accept is (U16_MAX - 1). in gpio_aggregator_line_offset_store()
1119 if (offset > (U16_MAX - 1) || offset < -1) in gpio_aggregator_line_offset_store()
1120 return -EINVAL; in gpio_aggregator_line_offset_store()
1122 guard(mutex)(&aggr->lock); in gpio_aggregator_line_offset_store()
1126 return -EBUSY; in gpio_aggregator_line_offset_store()
1128 line->offset = offset; in gpio_aggregator_line_offset_store()
1147 guard(mutex)(&aggr->lock); in gpio_aggregator_device_dev_name_show()
1149 pdev = aggr->probe_data.pdev; in gpio_aggregator_device_dev_name_show()
1151 return sysfs_emit(page, "%s\n", dev_name(&pdev->dev)); in gpio_aggregator_device_dev_name_show()
1153 return sysfs_emit(page, "%s.%d\n", DRV_NAME, aggr->id); in gpio_aggregator_device_dev_name_show()
1162 guard(mutex)(&aggr->lock); in gpio_aggregator_device_live_show()
1181 return -ENOENT; in gpio_aggregator_device_live_store()
1183 if (live && !aggr->init_via_sysfs) in gpio_aggregator_device_live_store()
1186 scoped_guard(mutex, &aggr->lock) { in gpio_aggregator_device_live_store()
1189 ret = -EPERM; in gpio_aggregator_device_live_store()
1200 if (live == !!ret && !aggr->init_via_sysfs) in gpio_aggregator_device_live_store()
1219 struct gpio_aggregator *aggr = line->parent; in gpio_aggregator_line_release()
1221 guard(mutex)(&aggr->lock); in gpio_aggregator_line_release()
1224 kfree(line->key); in gpio_aggregator_line_release()
1225 kfree(line->name); in gpio_aggregator_line_release()
1257 struct gpio_aggregator *aggr = to_gpio_aggregator(&group->cg_item); in gpio_aggregator_device_make_group()
1264 return ERR_PTR(-EINVAL); in gpio_aggregator_device_make_group()
1266 if (aggr->init_via_sysfs) in gpio_aggregator_device_make_group()
1273 return ERR_PTR(-EPERM); in gpio_aggregator_device_make_group()
1275 guard(mutex)(&aggr->lock); in gpio_aggregator_device_make_group()
1278 return ERR_PTR(-EBUSY); in gpio_aggregator_device_make_group()
1280 list_for_each_entry(line, &aggr->list_head, entry) in gpio_aggregator_device_make_group()
1281 if (line->idx == idx) in gpio_aggregator_device_make_group()
1282 return ERR_PTR(-EINVAL); in gpio_aggregator_device_make_group()
1284 line = gpio_aggregator_line_alloc(aggr, idx, NULL, -1); in gpio_aggregator_device_make_group()
1288 config_group_init_type_name(&line->group, name, &gpio_aggregator_line_type); in gpio_aggregator_device_make_group()
1292 return &line->group; in gpio_aggregator_device_make_group()
1313 * "_sysfs" prefix is reserved for auto-generated config group in gpio_aggregator_make_group()
1317 sizeof(AGGREGATOR_LEGACY_PREFIX) - 1) == 0) in gpio_aggregator_make_group()
1318 return ERR_PTR(-EINVAL); in gpio_aggregator_make_group()
1325 config_group_init_type_name(&aggr->group, name, &gpio_aggregator_device_type); in gpio_aggregator_make_group()
1326 dev_sync_probe_init(&aggr->probe_data); in gpio_aggregator_make_group()
1328 return &aggr->group; in gpio_aggregator_make_group()
1354 char *args = skip_spaces(aggr->args); in gpio_aggregator_parse()
1364 return -ENOMEM; in gpio_aggregator_parse()
1374 line = gpio_aggregator_line_alloc(aggr, n, key, -1); in gpio_aggregator_parse()
1379 config_group_init_type_name(&line->group, name, in gpio_aggregator_parse()
1381 error = configfs_register_group(&aggr->group, in gpio_aggregator_parse()
1382 &line->group); in gpio_aggregator_parse()
1385 scoped_guard(mutex, &aggr->lock) in gpio_aggregator_parse()
1410 config_group_init_type_name(&line->group, name, in gpio_aggregator_parse()
1412 error = configfs_register_group(&aggr->group, in gpio_aggregator_parse()
1413 &line->group); in gpio_aggregator_parse()
1416 scoped_guard(mutex, &aggr->lock) in gpio_aggregator_parse()
1429 error = -EINVAL; in gpio_aggregator_parse()
1450 return -ENOENT; in gpio_aggregator_new_device_store()
1457 memcpy(aggr->args, buf, count + 1); in gpio_aggregator_new_device_store()
1459 aggr->init_via_sysfs = true; in gpio_aggregator_new_device_store()
1460 aggr->lookups = kzalloc(struct_size(aggr->lookups, table, 1), in gpio_aggregator_new_device_store()
1462 if (!aggr->lookups) { in gpio_aggregator_new_device_store()
1463 res = -ENOMEM; in gpio_aggregator_new_device_store()
1467 aggr->lookups->dev_id = kasprintf(GFP_KERNEL, "%s.%d", DRV_NAME, aggr->id); in gpio_aggregator_new_device_store()
1468 if (!aggr->lookups->dev_id) { in gpio_aggregator_new_device_store()
1469 res = -ENOMEM; in gpio_aggregator_new_device_store()
1473 scnprintf(name, sizeof(name), "%s.%d", AGGREGATOR_LEGACY_PREFIX, aggr->id); in gpio_aggregator_new_device_store()
1474 config_group_init_type_name(&aggr->group, name, &gpio_aggregator_device_type); in gpio_aggregator_new_device_store()
1480 dev_sync_probe_init(&aggr->probe_data); in gpio_aggregator_new_device_store()
1484 &aggr->group); in gpio_aggregator_new_device_store()
1492 gpiod_add_lookup_table(aggr->lookups); in gpio_aggregator_new_device_store()
1494 pdev = platform_device_register_data(NULL, DRV_NAME, aggr->id, &meta, sizeof(meta)); in gpio_aggregator_new_device_store()
1500 aggr->probe_data.pdev = pdev; in gpio_aggregator_new_device_store()
1505 gpiod_remove_lookup_table(aggr->lookups); in gpio_aggregator_new_device_store()
1507 configfs_unregister_group(&aggr->group); in gpio_aggregator_new_device_store()
1509 kfree(aggr->lookups->dev_id); in gpio_aggregator_new_device_store()
1511 kfree(aggr->lookups); in gpio_aggregator_new_device_store()
1524 scoped_guard(mutex, &aggr->lock) { in gpio_aggregator_destroy()
1530 configfs_unregister_group(&aggr->group); in gpio_aggregator_destroy()
1542 return -EINVAL; in gpio_aggregator_delete_device_store()
1549 return -ENOENT; in gpio_aggregator_delete_device_store()
1557 if (aggr && aggr->init_via_sysfs) in gpio_aggregator_delete_device_store()
1562 return -ENOENT; in gpio_aggregator_delete_device_store()
1588 struct device *dev = &pdev->dev; in gpio_aggregator_probe()
1601 return -ENOMEM; in gpio_aggregator_probe()
1603 meta = dev_get_platdata(&pdev->dev); in gpio_aggregator_probe()
1604 if (meta && meta->init_via_sysfs) in gpio_aggregator_probe()
1619 descs[i] == ERR_PTR(-EPROBE_DEFER)) { in gpio_aggregator_probe()
1621 return -ENODEV; in gpio_aggregator_probe()
1639 .compatible = "gpio-delay",
1643 * Add GPIO-operated devices controlled from userspace below,