• Home
  • Raw
  • Download

Lines Matching +full:termination +full:- +full:gpios

1 // SPDX-License-Identifier: GPL-2.0-only
5 // Copyright (C) 2019-2020 Glider bv
7 #define DRV_NAME "gpio-aggregator"
52 return ERR_PTR(-EINVAL); in get_arg()
83 case '-': in isrange()
98 lookups = krealloc(aggr->lookups, struct_size(lookups, table, *n + 2), in aggr_add_gpio()
101 return -ENOMEM; in aggr_add_gpio()
103 lookups->table[*n] = in aggr_add_gpio()
107 memset(&lookups->table[*n], 0, sizeof(lookups->table[*n])); in aggr_add_gpio()
109 aggr->lookups = lookups; in aggr_add_gpio()
115 char *args = aggr->args; in aggr_parse()
123 return -ENOMEM; in aggr_parse()
160 pr_err("No GPIOs specified\n"); in aggr_parse()
161 error = -EINVAL; in aggr_parse()
176 /* kernfs guarantees string termination, so count + 1 is safe */ in new_device_store()
179 return -ENOMEM; in new_device_store()
181 memcpy(aggr->args, buf, count + 1); in new_device_store()
183 aggr->lookups = kzalloc(struct_size(aggr->lookups, table, 1), in new_device_store()
185 if (!aggr->lookups) { in new_device_store()
186 res = -ENOMEM; in new_device_store()
199 aggr->lookups->dev_id = kasprintf(GFP_KERNEL, "%s.%d", DRV_NAME, id); in new_device_store()
200 if (!aggr->lookups->dev_id) { in new_device_store()
201 res = -ENOMEM; in new_device_store()
209 gpiod_add_lookup_table(aggr->lookups); in new_device_store()
217 aggr->pdev = pdev; in new_device_store()
221 gpiod_remove_lookup_table(aggr->lookups); in new_device_store()
223 kfree(aggr->lookups->dev_id); in new_device_store()
229 kfree(aggr->lookups); in new_device_store()
239 platform_device_unregister(aggr->pdev); in gpio_aggregator_free()
240 gpiod_remove_lookup_table(aggr->lookups); in gpio_aggregator_free()
241 kfree(aggr->lookups->dev_id); in gpio_aggregator_free()
242 kfree(aggr->lookups); in gpio_aggregator_free()
254 return -EINVAL; in delete_device_store()
264 return -ENOENT; in delete_device_store()
311 return gpiod_get_direction(fwd->descs[offset]); in gpio_fwd_get_direction()
318 return gpiod_direction_input(fwd->descs[offset]); in gpio_fwd_direction_input()
326 return gpiod_direction_output(fwd->descs[offset], value); in gpio_fwd_direction_output()
333 return chip->can_sleep ? gpiod_get_value_cansleep(fwd->descs[offset]) in gpio_fwd_get()
334 : gpiod_get_value(fwd->descs[offset]); in gpio_fwd_get()
346 values = &fwd->tmp[0]; in gpio_fwd_get_multiple()
347 descs = (void *)&fwd->tmp[BITS_TO_LONGS(fwd->chip.ngpio)]; in gpio_fwd_get_multiple()
349 bitmap_clear(values, 0, fwd->chip.ngpio); in gpio_fwd_get_multiple()
350 for_each_set_bit(i, mask, fwd->chip.ngpio) in gpio_fwd_get_multiple()
351 descs[j++] = fwd->descs[i]; in gpio_fwd_get_multiple()
353 if (fwd->chip.can_sleep) in gpio_fwd_get_multiple()
361 for_each_set_bit(i, mask, fwd->chip.ngpio) in gpio_fwd_get_multiple()
374 if (chip->can_sleep) { in gpio_fwd_get_multiple_locked()
375 mutex_lock(&fwd->mlock); in gpio_fwd_get_multiple_locked()
377 mutex_unlock(&fwd->mlock); in gpio_fwd_get_multiple_locked()
379 spin_lock_irqsave(&fwd->slock, flags); in gpio_fwd_get_multiple_locked()
381 spin_unlock_irqrestore(&fwd->slock, flags); in gpio_fwd_get_multiple_locked()
391 if (chip->can_sleep) in gpio_fwd_set()
392 gpiod_set_value_cansleep(fwd->descs[offset], value); in gpio_fwd_set()
394 gpiod_set_value(fwd->descs[offset], value); in gpio_fwd_set()
405 values = &fwd->tmp[0]; in gpio_fwd_set_multiple()
406 descs = (void *)&fwd->tmp[BITS_TO_LONGS(fwd->chip.ngpio)]; in gpio_fwd_set_multiple()
408 for_each_set_bit(i, mask, fwd->chip.ngpio) { in gpio_fwd_set_multiple()
410 descs[j++] = fwd->descs[i]; in gpio_fwd_set_multiple()
413 if (fwd->chip.can_sleep) in gpio_fwd_set_multiple()
425 if (chip->can_sleep) { in gpio_fwd_set_multiple_locked()
426 mutex_lock(&fwd->mlock); in gpio_fwd_set_multiple_locked()
428 mutex_unlock(&fwd->mlock); in gpio_fwd_set_multiple_locked()
430 spin_lock_irqsave(&fwd->slock, flags); in gpio_fwd_set_multiple_locked()
432 spin_unlock_irqrestore(&fwd->slock, flags); in gpio_fwd_set_multiple_locked()
441 return gpiod_set_config(fwd->descs[offset], config); in gpio_fwd_set_config()
445 * gpiochip_fwd_create() - Create a new GPIO forwarder
447 * @ngpios: Number of GPIOs in the forwarder.
455 * Return: An opaque object pointer, or an ERR_PTR()-encoded negative error
471 return ERR_PTR(-ENOMEM); in gpiochip_fwd_create()
473 chip = &fwd->chip; in gpiochip_fwd_create()
484 dev_dbg(dev, "%u => gpio-%d\n", i, desc_to_gpio(descs[i])); in gpiochip_fwd_create()
487 chip->can_sleep = true; in gpiochip_fwd_create()
488 if (parent && parent->set_config) in gpiochip_fwd_create()
489 chip->set_config = gpio_fwd_set_config; in gpiochip_fwd_create()
492 chip->label = label; in gpiochip_fwd_create()
493 chip->parent = dev; in gpiochip_fwd_create()
494 chip->owner = THIS_MODULE; in gpiochip_fwd_create()
495 chip->get_direction = gpio_fwd_get_direction; in gpiochip_fwd_create()
496 chip->direction_input = gpio_fwd_direction_input; in gpiochip_fwd_create()
497 chip->direction_output = gpio_fwd_direction_output; in gpiochip_fwd_create()
498 chip->get = gpio_fwd_get; in gpiochip_fwd_create()
499 chip->get_multiple = gpio_fwd_get_multiple_locked; in gpiochip_fwd_create()
500 chip->set = gpio_fwd_set; in gpiochip_fwd_create()
501 chip->set_multiple = gpio_fwd_set_multiple_locked; in gpiochip_fwd_create()
502 chip->base = -1; in gpiochip_fwd_create()
503 chip->ngpio = ngpios; in gpiochip_fwd_create()
504 fwd->descs = descs; in gpiochip_fwd_create()
506 if (chip->can_sleep) in gpiochip_fwd_create()
507 mutex_init(&fwd->mlock); in gpiochip_fwd_create()
509 spin_lock_init(&fwd->slock); in gpiochip_fwd_create()
525 struct device *dev = &pdev->dev; in gpio_aggregator_probe()
536 return -ENOMEM; in gpio_aggregator_probe()
555 * Add GPIO-operated devices controlled from userspace below,