Lines Matching +full:int +full:- +full:fwd +full:- +full:mask

1 // SPDX-License-Identifier: GPL-2.0-only
5 // Copyright (C) 2019-2020 Glider bv
7 #define DRV_NAME "gpio-aggregator"
40 static int aggr_add_gpio(struct gpio_aggregator *aggr, const char *key, in aggr_add_gpio()
41 int hwnum, unsigned int *n) in aggr_add_gpio()
45 lookups = krealloc(aggr->lookups, struct_size(lookups, table, *n + 2), in aggr_add_gpio()
48 return -ENOMEM; in aggr_add_gpio()
50 lookups->table[*n] = GPIO_LOOKUP_IDX(key, hwnum, NULL, *n, 0); in aggr_add_gpio()
53 memset(&lookups->table[*n], 0, sizeof(lookups->table[*n])); in aggr_add_gpio()
55 aggr->lookups = lookups; in aggr_add_gpio()
59 static int aggr_parse(struct gpio_aggregator *aggr) in aggr_parse()
61 char *args = skip_spaces(aggr->args); in aggr_parse()
64 unsigned int i, n = 0; in aggr_parse()
65 int error = 0; in aggr_parse()
69 return -ENOMEM; in aggr_parse()
104 error = -EINVAL; in aggr_parse()
117 int res, id; in new_device_store()
122 return -ENOMEM; in new_device_store()
124 memcpy(aggr->args, buf, count + 1); in new_device_store()
126 aggr->lookups = kzalloc(struct_size(aggr->lookups, table, 1), in new_device_store()
128 if (!aggr->lookups) { in new_device_store()
129 res = -ENOMEM; in new_device_store()
142 aggr->lookups->dev_id = kasprintf(GFP_KERNEL, "%s.%d", DRV_NAME, id); in new_device_store()
143 if (!aggr->lookups->dev_id) { in new_device_store()
144 res = -ENOMEM; in new_device_store()
152 gpiod_add_lookup_table(aggr->lookups); in new_device_store()
160 aggr->pdev = pdev; in new_device_store()
164 gpiod_remove_lookup_table(aggr->lookups); in new_device_store()
166 kfree(aggr->lookups->dev_id); in new_device_store()
172 kfree(aggr->lookups); in new_device_store()
182 platform_device_unregister(aggr->pdev); in gpio_aggregator_free()
183 gpiod_remove_lookup_table(aggr->lookups); in gpio_aggregator_free()
184 kfree(aggr->lookups->dev_id); in gpio_aggregator_free()
185 kfree(aggr->lookups); in gpio_aggregator_free()
193 unsigned int id; in delete_device_store()
194 int error; in delete_device_store()
197 return -EINVAL; in delete_device_store()
207 return -ENOENT; in delete_device_store()
221 static int __exit gpio_aggregator_idr_remove(int id, void *p, void *data) in gpio_aggregator_idr_remove()
250 #define fwd_tmp_values(fwd) &(fwd)->tmp[0] argument
251 #define fwd_tmp_descs(fwd) (void *)&(fwd)->tmp[BITS_TO_LONGS((fwd)->chip.ngpio)] argument
255 static int gpio_fwd_get_direction(struct gpio_chip *chip, unsigned int offset) in gpio_fwd_get_direction()
257 struct gpiochip_fwd *fwd = gpiochip_get_data(chip); in gpio_fwd_get_direction() local
259 return gpiod_get_direction(fwd->descs[offset]); in gpio_fwd_get_direction()
262 static int gpio_fwd_direction_input(struct gpio_chip *chip, unsigned int offset) in gpio_fwd_direction_input()
264 struct gpiochip_fwd *fwd = gpiochip_get_data(chip); in gpio_fwd_direction_input() local
266 return gpiod_direction_input(fwd->descs[offset]); in gpio_fwd_direction_input()
269 static int gpio_fwd_direction_output(struct gpio_chip *chip, in gpio_fwd_direction_output()
270 unsigned int offset, int value) in gpio_fwd_direction_output()
272 struct gpiochip_fwd *fwd = gpiochip_get_data(chip); in gpio_fwd_direction_output() local
274 return gpiod_direction_output(fwd->descs[offset], value); in gpio_fwd_direction_output()
277 static int gpio_fwd_get(struct gpio_chip *chip, unsigned int offset) in gpio_fwd_get()
279 struct gpiochip_fwd *fwd = gpiochip_get_data(chip); in gpio_fwd_get() local
281 return chip->can_sleep ? gpiod_get_value_cansleep(fwd->descs[offset]) in gpio_fwd_get()
282 : gpiod_get_value(fwd->descs[offset]); in gpio_fwd_get()
285 static int gpio_fwd_get_multiple(struct gpiochip_fwd *fwd, unsigned long *mask, in gpio_fwd_get_multiple() argument
288 struct gpio_desc **descs = fwd_tmp_descs(fwd); in gpio_fwd_get_multiple()
289 unsigned long *values = fwd_tmp_values(fwd); in gpio_fwd_get_multiple()
290 unsigned int i, j = 0; in gpio_fwd_get_multiple()
291 int error; in gpio_fwd_get_multiple()
293 bitmap_clear(values, 0, fwd->chip.ngpio); in gpio_fwd_get_multiple()
294 for_each_set_bit(i, mask, fwd->chip.ngpio) in gpio_fwd_get_multiple()
295 descs[j++] = fwd->descs[i]; in gpio_fwd_get_multiple()
297 if (fwd->chip.can_sleep) in gpio_fwd_get_multiple()
305 for_each_set_bit(i, mask, fwd->chip.ngpio) in gpio_fwd_get_multiple()
311 static int gpio_fwd_get_multiple_locked(struct gpio_chip *chip, in gpio_fwd_get_multiple_locked()
312 unsigned long *mask, unsigned long *bits) in gpio_fwd_get_multiple_locked() argument
314 struct gpiochip_fwd *fwd = gpiochip_get_data(chip); in gpio_fwd_get_multiple_locked() local
316 int error; in gpio_fwd_get_multiple_locked()
318 if (chip->can_sleep) { in gpio_fwd_get_multiple_locked()
319 mutex_lock(&fwd->mlock); in gpio_fwd_get_multiple_locked()
320 error = gpio_fwd_get_multiple(fwd, mask, bits); in gpio_fwd_get_multiple_locked()
321 mutex_unlock(&fwd->mlock); in gpio_fwd_get_multiple_locked()
323 spin_lock_irqsave(&fwd->slock, flags); in gpio_fwd_get_multiple_locked()
324 error = gpio_fwd_get_multiple(fwd, mask, bits); in gpio_fwd_get_multiple_locked()
325 spin_unlock_irqrestore(&fwd->slock, flags); in gpio_fwd_get_multiple_locked()
331 static void gpio_fwd_set(struct gpio_chip *chip, unsigned int offset, int value) in gpio_fwd_set()
333 struct gpiochip_fwd *fwd = gpiochip_get_data(chip); in gpio_fwd_set() local
335 if (chip->can_sleep) in gpio_fwd_set()
336 gpiod_set_value_cansleep(fwd->descs[offset], value); in gpio_fwd_set()
338 gpiod_set_value(fwd->descs[offset], value); in gpio_fwd_set()
341 static void gpio_fwd_set_multiple(struct gpiochip_fwd *fwd, unsigned long *mask, in gpio_fwd_set_multiple() argument
344 struct gpio_desc **descs = fwd_tmp_descs(fwd); in gpio_fwd_set_multiple()
345 unsigned long *values = fwd_tmp_values(fwd); in gpio_fwd_set_multiple()
346 unsigned int i, j = 0; in gpio_fwd_set_multiple()
348 for_each_set_bit(i, mask, fwd->chip.ngpio) { in gpio_fwd_set_multiple()
350 descs[j++] = fwd->descs[i]; in gpio_fwd_set_multiple()
353 if (fwd->chip.can_sleep) in gpio_fwd_set_multiple()
360 unsigned long *mask, unsigned long *bits) in gpio_fwd_set_multiple_locked() argument
362 struct gpiochip_fwd *fwd = gpiochip_get_data(chip); in gpio_fwd_set_multiple_locked() local
365 if (chip->can_sleep) { in gpio_fwd_set_multiple_locked()
366 mutex_lock(&fwd->mlock); in gpio_fwd_set_multiple_locked()
367 gpio_fwd_set_multiple(fwd, mask, bits); in gpio_fwd_set_multiple_locked()
368 mutex_unlock(&fwd->mlock); in gpio_fwd_set_multiple_locked()
370 spin_lock_irqsave(&fwd->slock, flags); in gpio_fwd_set_multiple_locked()
371 gpio_fwd_set_multiple(fwd, mask, bits); in gpio_fwd_set_multiple_locked()
372 spin_unlock_irqrestore(&fwd->slock, flags); in gpio_fwd_set_multiple_locked()
376 static int gpio_fwd_set_config(struct gpio_chip *chip, unsigned int offset, in gpio_fwd_set_config()
379 struct gpiochip_fwd *fwd = gpiochip_get_data(chip); in gpio_fwd_set_config() local
381 return gpiod_set_config(fwd->descs[offset], config); in gpio_fwd_set_config()
384 static int gpio_fwd_to_irq(struct gpio_chip *chip, unsigned int offset) in gpio_fwd_to_irq()
386 struct gpiochip_fwd *fwd = gpiochip_get_data(chip); in gpio_fwd_to_irq() local
388 return gpiod_to_irq(fwd->descs[offset]); in gpio_fwd_to_irq()
392 * gpiochip_fwd_create() - Create a new GPIO forwarder
402 * Return: An opaque object pointer, or an ERR_PTR()-encoded negative error
406 unsigned int ngpios, in gpiochip_fwd_create()
410 struct gpiochip_fwd *fwd; in gpiochip_fwd_create() local
412 unsigned int i; in gpiochip_fwd_create()
413 int error; in gpiochip_fwd_create()
415 fwd = devm_kzalloc(dev, struct_size(fwd, tmp, fwd_tmp_size(ngpios)), in gpiochip_fwd_create()
417 if (!fwd) in gpiochip_fwd_create()
418 return ERR_PTR(-ENOMEM); in gpiochip_fwd_create()
420 chip = &fwd->chip; in gpiochip_fwd_create()
435 chip->can_sleep = true; in gpiochip_fwd_create()
436 if (parent && parent->set_config) in gpiochip_fwd_create()
437 chip->set_config = gpio_fwd_set_config; in gpiochip_fwd_create()
440 chip->label = label; in gpiochip_fwd_create()
441 chip->parent = dev; in gpiochip_fwd_create()
442 chip->owner = THIS_MODULE; in gpiochip_fwd_create()
443 chip->get_direction = gpio_fwd_get_direction; in gpiochip_fwd_create()
444 chip->direction_input = gpio_fwd_direction_input; in gpiochip_fwd_create()
445 chip->direction_output = gpio_fwd_direction_output; in gpiochip_fwd_create()
446 chip->get = gpio_fwd_get; in gpiochip_fwd_create()
447 chip->get_multiple = gpio_fwd_get_multiple_locked; in gpiochip_fwd_create()
448 chip->set = gpio_fwd_set; in gpiochip_fwd_create()
449 chip->set_multiple = gpio_fwd_set_multiple_locked; in gpiochip_fwd_create()
450 chip->to_irq = gpio_fwd_to_irq; in gpiochip_fwd_create()
451 chip->base = -1; in gpiochip_fwd_create()
452 chip->ngpio = ngpios; in gpiochip_fwd_create()
453 fwd->descs = descs; in gpiochip_fwd_create()
455 if (chip->can_sleep) in gpiochip_fwd_create()
456 mutex_init(&fwd->mlock); in gpiochip_fwd_create()
458 spin_lock_init(&fwd->slock); in gpiochip_fwd_create()
460 error = devm_gpiochip_add_data(dev, chip, fwd); in gpiochip_fwd_create()
464 return fwd; in gpiochip_fwd_create()
472 static int gpio_aggregator_probe(struct platform_device *pdev) in gpio_aggregator_probe()
474 struct device *dev = &pdev->dev; in gpio_aggregator_probe()
476 struct gpiochip_fwd *fwd; in gpio_aggregator_probe() local
477 int i, n; in gpio_aggregator_probe()
485 return -ENOMEM; in gpio_aggregator_probe()
493 fwd = gpiochip_fwd_create(dev, n, descs); in gpio_aggregator_probe()
494 if (IS_ERR(fwd)) in gpio_aggregator_probe()
495 return PTR_ERR(fwd); in gpio_aggregator_probe()
497 platform_set_drvdata(pdev, fwd); in gpio_aggregator_probe()
504 * Add GPIO-operated devices controlled from userspace below,
521 static int __init gpio_aggregator_init(void) in gpio_aggregator_init()