• 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"
50 lookups = krealloc(aggr->lookups, struct_size(lookups, table, *n + 2), in aggr_add_gpio()
53 return -ENOMEM; in aggr_add_gpio()
55 lookups->table[*n] = GPIO_LOOKUP_IDX(key, hwnum, NULL, *n, 0); in aggr_add_gpio()
58 memset(&lookups->table[*n], 0, sizeof(lookups->table[*n])); in aggr_add_gpio()
60 aggr->lookups = lookups; in aggr_add_gpio()
66 char *args = skip_spaces(aggr->args); in aggr_parse()
74 return -ENOMEM; in aggr_parse()
108 pr_err("No GPIOs specified\n"); in aggr_parse()
109 error = -EINVAL; in aggr_parse()
125 return -ENOENT; in new_device_store()
127 /* kernfs guarantees string termination, so count + 1 is safe */ in new_device_store()
130 res = -ENOMEM; in new_device_store()
134 memcpy(aggr->args, buf, count + 1); in new_device_store()
136 aggr->lookups = kzalloc(struct_size(aggr->lookups, table, 1), in new_device_store()
138 if (!aggr->lookups) { in new_device_store()
139 res = -ENOMEM; in new_device_store()
152 aggr->lookups->dev_id = kasprintf(GFP_KERNEL, "%s.%d", DRV_NAME, id); in new_device_store()
153 if (!aggr->lookups->dev_id) { in new_device_store()
154 res = -ENOMEM; in new_device_store()
162 gpiod_add_lookup_table(aggr->lookups); in new_device_store()
170 aggr->pdev = pdev; in new_device_store()
175 gpiod_remove_lookup_table(aggr->lookups); in new_device_store()
177 kfree(aggr->lookups->dev_id); in new_device_store()
183 kfree(aggr->lookups); in new_device_store()
195 platform_device_unregister(aggr->pdev); in gpio_aggregator_free()
196 gpiod_remove_lookup_table(aggr->lookups); in gpio_aggregator_free()
197 kfree(aggr->lookups->dev_id); in gpio_aggregator_free()
198 kfree(aggr->lookups); in gpio_aggregator_free()
210 return -EINVAL; in delete_device_store()
217 return -ENOENT; in delete_device_store()
224 return -ENOENT; in delete_device_store()
275 #define fwd_tmp_values(fwd) &(fwd)->tmp[0]
276 #define fwd_tmp_descs(fwd) (void *)&(fwd)->tmp[BITS_TO_LONGS((fwd)->chip.ngpio)]
284 return gpiod_get_direction(fwd->descs[offset]); in gpio_fwd_get_direction()
291 return gpiod_direction_input(fwd->descs[offset]); in gpio_fwd_direction_input()
299 return gpiod_direction_output(fwd->descs[offset], value); in gpio_fwd_direction_output()
306 return chip->can_sleep ? gpiod_get_value_cansleep(fwd->descs[offset]) in gpio_fwd_get()
307 : gpiod_get_value(fwd->descs[offset]); in gpio_fwd_get()
318 bitmap_clear(values, 0, fwd->chip.ngpio); in gpio_fwd_get_multiple()
319 for_each_set_bit(i, mask, fwd->chip.ngpio) in gpio_fwd_get_multiple()
320 descs[j++] = fwd->descs[i]; in gpio_fwd_get_multiple()
322 if (fwd->chip.can_sleep) in gpio_fwd_get_multiple()
330 for_each_set_bit(i, mask, fwd->chip.ngpio) in gpio_fwd_get_multiple()
343 if (chip->can_sleep) { in gpio_fwd_get_multiple_locked()
344 mutex_lock(&fwd->mlock); in gpio_fwd_get_multiple_locked()
346 mutex_unlock(&fwd->mlock); in gpio_fwd_get_multiple_locked()
348 spin_lock_irqsave(&fwd->slock, flags); in gpio_fwd_get_multiple_locked()
350 spin_unlock_irqrestore(&fwd->slock, flags); in gpio_fwd_get_multiple_locked()
360 bool is_active_low = gpiod_is_active_low(fwd->descs[offset]); in gpio_fwd_delay()
363 delay_timings = &fwd->delay_timings[offset]; in gpio_fwd_delay()
365 delay_us = delay_timings->ramp_up_us; in gpio_fwd_delay()
367 delay_us = delay_timings->ramp_down_us; in gpio_fwd_delay()
371 if (chip->can_sleep) in gpio_fwd_delay()
381 if (chip->can_sleep) in gpio_fwd_set()
382 gpiod_set_value_cansleep(fwd->descs[offset], value); in gpio_fwd_set()
384 gpiod_set_value(fwd->descs[offset], value); in gpio_fwd_set()
386 if (fwd->delay_timings) in gpio_fwd_set()
397 for_each_set_bit(i, mask, fwd->chip.ngpio) { in gpio_fwd_set_multiple()
399 descs[j++] = fwd->descs[i]; in gpio_fwd_set_multiple()
402 if (fwd->chip.can_sleep) in gpio_fwd_set_multiple()
414 if (chip->can_sleep) { in gpio_fwd_set_multiple_locked()
415 mutex_lock(&fwd->mlock); in gpio_fwd_set_multiple_locked()
417 mutex_unlock(&fwd->mlock); in gpio_fwd_set_multiple_locked()
419 spin_lock_irqsave(&fwd->slock, flags); in gpio_fwd_set_multiple_locked()
421 spin_unlock_irqrestore(&fwd->slock, flags); in gpio_fwd_set_multiple_locked()
430 return gpiod_set_config(fwd->descs[offset], config); in gpio_fwd_set_config()
437 return gpiod_to_irq(fwd->descs[offset]); in gpio_fwd_to_irq()
442 * for the GPIO ramp-up or ramp-down delays. This can serve the following
444 * - Open-drain output using an RC filter
457 if (gpiospec->args_count != chip->of_gpio_n_cells) in gpiochip_fwd_delay_of_xlate()
458 return -EINVAL; in gpiochip_fwd_delay_of_xlate()
460 line = gpiospec->args[0]; in gpiochip_fwd_delay_of_xlate()
461 if (line >= chip->ngpio) in gpiochip_fwd_delay_of_xlate()
462 return -EINVAL; in gpiochip_fwd_delay_of_xlate()
464 timings = &fwd->delay_timings[line]; in gpiochip_fwd_delay_of_xlate()
465 timings->ramp_up_us = gpiospec->args[1]; in gpiochip_fwd_delay_of_xlate()
466 timings->ramp_down_us = gpiospec->args[2]; in gpiochip_fwd_delay_of_xlate()
474 fwd->delay_timings = devm_kcalloc(dev, chip->ngpio, in gpiochip_fwd_setup_delay_line()
475 sizeof(*fwd->delay_timings), in gpiochip_fwd_setup_delay_line()
477 if (!fwd->delay_timings) in gpiochip_fwd_setup_delay_line()
478 return -ENOMEM; in gpiochip_fwd_setup_delay_line()
480 chip->of_xlate = gpiochip_fwd_delay_of_xlate; in gpiochip_fwd_setup_delay_line()
481 chip->of_gpio_n_cells = 3; in gpiochip_fwd_setup_delay_line()
494 * gpiochip_fwd_create() - Create a new GPIO forwarder
496 * @ngpios: Number of GPIOs in the forwarder.
505 * Return: An opaque object pointer, or an ERR_PTR()-encoded negative error
522 return ERR_PTR(-ENOMEM); in gpiochip_fwd_create()
524 chip = &fwd->chip; in gpiochip_fwd_create()
539 chip->can_sleep = true; in gpiochip_fwd_create()
540 if (parent && parent->set_config) in gpiochip_fwd_create()
541 chip->set_config = gpio_fwd_set_config; in gpiochip_fwd_create()
544 chip->label = label; in gpiochip_fwd_create()
545 chip->parent = dev; in gpiochip_fwd_create()
546 chip->owner = THIS_MODULE; in gpiochip_fwd_create()
547 chip->get_direction = gpio_fwd_get_direction; in gpiochip_fwd_create()
548 chip->direction_input = gpio_fwd_direction_input; in gpiochip_fwd_create()
549 chip->direction_output = gpio_fwd_direction_output; in gpiochip_fwd_create()
550 chip->get = gpio_fwd_get; in gpiochip_fwd_create()
551 chip->get_multiple = gpio_fwd_get_multiple_locked; in gpiochip_fwd_create()
552 chip->set = gpio_fwd_set; in gpiochip_fwd_create()
553 chip->set_multiple = gpio_fwd_set_multiple_locked; in gpiochip_fwd_create()
554 chip->to_irq = gpio_fwd_to_irq; in gpiochip_fwd_create()
555 chip->base = -1; in gpiochip_fwd_create()
556 chip->ngpio = ngpios; in gpiochip_fwd_create()
557 fwd->descs = descs; in gpiochip_fwd_create()
559 if (chip->can_sleep) in gpiochip_fwd_create()
560 mutex_init(&fwd->mlock); in gpiochip_fwd_create()
562 spin_lock_init(&fwd->slock); in gpiochip_fwd_create()
584 struct device *dev = &pdev->dev; in gpio_aggregator_probe()
596 return -ENOMEM; in gpio_aggregator_probe()
615 .compatible = "gpio-delay",
619 * Add GPIO-operated devices controlled from userspace below,