1 From 0e9965786b924d979b7ca274fada7ba0c8e4ca51 Mon Sep 17 00:00:00 2001
2 From: Phil Elwell <phil@raspberrypi.com>
3 Date: Wed, 30 Sep 2020 12:00:54 +0100
4 Subject: [PATCH] gpio: Add gpio-fsm driver
6 The gpio-fsm driver implements simple state machines that allow GPIOs
7 to be controlled in response to inputs from other GPIOs - real and
8 soft/virtual - and time delays. It can:
9 + create dummy GPIOs for drivers that demand them,
10 + drive multiple GPIOs from a single input, with optional delays,
11 + add a debounce circuit to an input,
12 + drive pattern sequences onto LEDs
15 Signed-off-by: Phil Elwell <phil@raspberrypi.com>
17 gpio-fsm: Fix a build warning
19 Signed-off-by: Phil Elwell <phil@raspberrypi.com>
21 gpio-fsm: Rename 'num-soft-gpios' to avoid warning
23 As of 5.10, the Device Tree parser warns about properties that look
24 like references to "suppliers" of various services. "num-soft-gpios"
25 resembles a declaration of a GPIO called "num-soft", causing the value
26 to be interpreted as a phandle, the owner of which is checked for a
27 "#gpio-cells" property.
29 To avoid this warning, rename the gpio-fsm property to "num-swgpios".
31 Signed-off-by: Phil Elwell <phil@raspberrypi.com>
33 gpio-fsm: Show state info in /sys/class/gpio-fsm
35 Add gpio-fsm sysfs entries under /sys/class/gpio-fsm. For each state
36 machine show the current state, which state (if any) will be entered
37 after a delay, and the current value of that delay.
39 Signed-off-by: Phil Elwell <phil@raspberrypi.com>
41 gpio-fsm: Fix shutdown timeout handling
43 The driver is intended to jump directly to a shutdown state in the
44 event of a timeout during shutdown, but the sense of the test was
47 Signed-off-by: Phil Elwell <phil@raspberrypi.com>
49 gpio-fsm: Clamp the delay time to zero
51 The sysfs delay_ms value is calculated live, and it is possible for
52 the time left to appear to be negative briefly if the timer handling
53 hasn't completed. Ensure the displayed value never goes below zero,
54 for the sake of appearances.
56 Signed-off-by: Phil Elwell <phil@raspberrypi.com>
58 drivers/gpio/Kconfig | 9 +
59 drivers/gpio/Makefile | 1 +
60 drivers/gpio/gpio-fsm.c | 1210 +++++++++++++++++++++++++++
61 include/dt-bindings/gpio/gpio-fsm.h | 21 +
62 4 files changed, 1241 insertions(+)
63 create mode 100644 drivers/gpio/gpio-fsm.c
64 create mode 100644 include/dt-bindings/gpio/gpio-fsm.h
66 --- a/drivers/gpio/Kconfig
67 +++ b/drivers/gpio/Kconfig
68 @@ -1232,6 +1232,15 @@ config HTC_EGPIO
69 several HTC phones. It provides basic support for input
70 pins, output pins, and irqs.
73 + tristate "GPIO FSM support"
75 + The GPIO FSM driver allows the creation of state machines for
76 + manipulating GPIOs (both real and virtual), with state transitions
77 + triggered by GPIO edges or delays.
82 tristate "Janz VMOD-TTL Digital IO Module"
83 depends on MFD_JANZ_CMODIO
84 --- a/drivers/gpio/Makefile
85 +++ b/drivers/gpio/Makefile
86 @@ -62,6 +62,7 @@ obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93x
87 obj-$(CONFIG_GPIO_EXAR) += gpio-exar.o
88 obj-$(CONFIG_GPIO_F7188X) += gpio-f7188x.o
89 obj-$(CONFIG_GPIO_FTGPIO010) += gpio-ftgpio010.o
90 +obj-$(CONFIG_GPIO_FSM) += gpio-fsm.o
91 obj-$(CONFIG_GPIO_GE_FPGA) += gpio-ge.o
92 obj-$(CONFIG_GPIO_GPIO_MM) += gpio-gpio-mm.o
93 obj-$(CONFIG_GPIO_GRGPIO) += gpio-grgpio.o
95 +++ b/drivers/gpio/gpio-fsm.c
97 +// SPDX-License-Identifier: GPL-2.0+
101 + * This driver implements simple state machines that allow real GPIOs to be
102 + * controlled in response to inputs from other GPIOs - real and soft/virtual -
103 + * and time delays. It can:
104 + * + create dummy GPIOs for drivers that demand them
105 + * + drive multiple GPIOs from a single input, with optional delays
106 + * + add a debounce circuit to an input
107 + * + drive pattern sequences onto LEDs
110 + * Copyright (C) 2020 Raspberry Pi (Trading) Ltd.
113 +#include <linux/err.h>
114 +#include <linux/gpio.h>
115 +#include <linux/gpio/driver.h>
116 +#include <linux/interrupt.h>
117 +#include <linux/module.h>
118 +#include <linux/platform_device.h>
119 +#include <linux/sysfs.h>
121 +#include <dt-bindings/gpio/gpio-fsm.h>
123 +#define MODULE_NAME "gpio-fsm"
125 +#define GF_IO_TYPE(x) ((u32)(x) & 0xffff)
126 +#define GF_IO_INDEX(x) ((u32)(x) >> 16)
153 +struct input_gpio_state {
154 + struct gpio_fsm *gf;
155 + struct gpio_desc *desc;
156 + struct fsm_state *target;
167 + struct fsm_state *target;
170 +struct symtab_entry {
173 + struct symtab_entry *next;
176 +struct output_signal {
184 + struct output_signal *signals;
185 + struct gpio_event *gpio_events;
186 + struct gpio_event *soft_events;
187 + struct fsm_state *delay_target;
188 + struct fsm_state *shutdown_target;
189 + unsigned int num_signals;
190 + unsigned int num_gpio_events;
191 + unsigned int num_soft_events;
192 + unsigned int delay_ms;
193 + unsigned int shutdown_ms;
197 + struct gpio_chip gc;
198 + struct device *dev;
199 + spinlock_t spinlock;
200 + struct work_struct work;
201 + struct timer_list timer;
202 + wait_queue_head_t shutdown_event;
203 + struct fsm_state *states;
204 + struct input_gpio_state *input_gpio_states;
205 + struct gpio_descs *input_gpios;
206 + struct gpio_descs *output_gpios;
207 + struct soft_gpio *soft_gpios;
208 + struct fsm_state *start_state;
209 + struct fsm_state *shutdown_state;
210 + unsigned int num_states;
211 + unsigned int num_output_gpios;
212 + unsigned int num_input_gpios;
213 + unsigned int num_soft_gpios;
214 + unsigned int shutdown_timeout_ms;
215 + unsigned int shutdown_jiffies;
217 + struct fsm_state *current_state;
218 + struct fsm_state *next_state;
219 + struct fsm_state *delay_target_state;
220 + unsigned int delay_jiffies;
222 + unsigned int debug;
223 + bool shutting_down;
224 + struct symtab_entry *symtab;
227 +static struct symtab_entry *do_add_symbol(struct symtab_entry **symtab,
228 + const char *name, void *value)
230 + struct symtab_entry **p = symtab;
232 + while (*p && strcmp((*p)->name, name))
236 + /* This is an existing symbol */
238 + /* Already defined */
240 + if ((uintptr_t)value < SYM_MAX)
241 + return ERR_PTR(-EINVAL);
243 + return ERR_PTR(-EEXIST);
247 + (*p)->value = value;
250 + /* This is a new symbol */
251 + *p = kmalloc(sizeof(struct symtab_entry), GFP_KERNEL);
254 + (*p)->value = value;
261 +static int add_symbol(struct symtab_entry **symtab,
262 + const char *name, void *value)
264 + struct symtab_entry *sym = do_add_symbol(symtab, name, value);
266 + return PTR_ERR_OR_ZERO(sym);
269 +static struct symtab_entry *get_symbol(struct symtab_entry **symtab,
272 + struct symtab_entry *sym = do_add_symbol(symtab, name, NULL);
279 +static void free_symbols(struct symtab_entry **symtab)
281 + struct symtab_entry *sym = *symtab;
292 +static int gpio_fsm_get_direction(struct gpio_chip *gc, unsigned int off)
294 + struct gpio_fsm *gf = gpiochip_get_data(gc);
295 + struct soft_gpio *sg;
297 + if (off >= gf->num_soft_gpios)
299 + sg = &gf->soft_gpios[off];
304 +static int gpio_fsm_get(struct gpio_chip *gc, unsigned int off)
306 + struct gpio_fsm *gf = gpiochip_get_data(gc);
307 + struct soft_gpio *sg;
309 + if (off >= gf->num_soft_gpios)
311 + sg = &gf->soft_gpios[off];
316 +static void gpio_fsm_go_to_state(struct gpio_fsm *gf,
317 + struct fsm_state *new_state)
319 + struct input_gpio_state *inp_state;
320 + struct gpio_event *gp_ev;
321 + struct fsm_state *state;
324 + dev_dbg(gf->dev, "go_to_state(%s)\n",
325 + new_state ? new_state->name : "<unset>");
327 + spin_lock(&gf->spinlock);
329 + if (gf->next_state) {
330 + /* Something else has already requested a transition */
331 + spin_unlock(&gf->spinlock);
335 + gf->next_state = new_state;
336 + state = gf->current_state;
337 + gf->delay_target_state = NULL;
340 + /* Disarm any GPIO IRQs */
341 + for (i = 0; i < state->num_gpio_events; i++) {
342 + gp_ev = &state->gpio_events[i];
343 + inp_state = &gf->input_gpio_states[gp_ev->index];
344 + inp_state->target = NULL;
348 + spin_unlock(&gf->spinlock);
351 + schedule_work(&gf->work);
354 +static void gpio_fsm_set_soft(struct gpio_fsm *gf,
355 + unsigned int off, int val)
357 + struct soft_gpio *sg = &gf->soft_gpios[off];
358 + struct gpio_event *gp_ev;
359 + struct fsm_state *state;
362 + dev_dbg(gf->dev, "set(%d,%d)\n", off, val);
363 + state = gf->current_state;
365 + for (i = 0; i < state->num_soft_events; i++) {
366 + gp_ev = &state->soft_events[i];
367 + if (gp_ev->index == off && gp_ev->value == val) {
370 + "GF_SOFT %d->%d -> %s\n", gp_ev->index,
371 + gp_ev->value, gp_ev->target->name);
372 + gpio_fsm_go_to_state(gf, gp_ev->target);
378 +static int gpio_fsm_direction_input(struct gpio_chip *gc, unsigned int off)
380 + struct gpio_fsm *gf = gpiochip_get_data(gc);
381 + struct soft_gpio *sg;
383 + if (off >= gf->num_soft_gpios)
385 + sg = &gf->soft_gpios[off];
386 + sg->dir = GPIOF_DIR_IN;
391 +static int gpio_fsm_direction_output(struct gpio_chip *gc, unsigned int off,
394 + struct gpio_fsm *gf = gpiochip_get_data(gc);
395 + struct soft_gpio *sg;
397 + if (off >= gf->num_soft_gpios)
399 + sg = &gf->soft_gpios[off];
400 + sg->dir = GPIOF_DIR_OUT;
401 + gpio_fsm_set_soft(gf, off, value);
406 +static void gpio_fsm_set(struct gpio_chip *gc, unsigned int off, int val)
408 + struct gpio_fsm *gf;
410 + gf = gpiochip_get_data(gc);
411 + if (off < gf->num_soft_gpios)
412 + gpio_fsm_set_soft(gf, off, val);
415 +static void gpio_fsm_enter_state(struct gpio_fsm *gf,
416 + struct fsm_state *state)
418 + struct input_gpio_state *inp_state;
419 + struct output_signal *signal;
420 + struct gpio_event *event;
421 + struct gpio_desc *gpiod;
422 + struct soft_gpio *soft;
426 + dev_dbg(gf->dev, "enter_state(%s)\n", state->name);
428 + gf->current_state = state;
430 + // 1. Apply any listed signals
431 + for (i = 0; i < state->num_signals; i++) {
432 + signal = &state->signals[i];
435 + dev_info(gf->dev, " set %s %d->%d\n",
436 + (signal->type == SIGNAL_GPIO) ? "GF_OUT" :
438 + signal->index, signal->value);
439 + switch (signal->type) {
441 + gpiod = gf->output_gpios->desc[signal->index];
442 + gpiod_set_value_cansleep(gpiod, signal->value);
445 + soft = &gf->soft_gpios[signal->index];
446 + gpio_fsm_set_soft(gf, signal->index, signal->value);
451 + // 2. Exit if successfully reached shutdown state
452 + if (gf->shutting_down && state == state->shutdown_target) {
453 + wake_up(&gf->shutdown_event);
457 + // 3. Schedule a timer callback if shutting down
458 + if (state->shutdown_target) {
459 + // Remember the absolute shutdown time in case remove is called
460 + // at a later time.
461 + gf->shutdown_jiffies =
462 + jiffies + msecs_to_jiffies(state->shutdown_ms);
464 + if (gf->shutting_down) {
465 + gf->delay_jiffies = gf->shutdown_jiffies;
466 + gf->delay_target_state = state->shutdown_target;
467 + gf->delay_ms = state->shutdown_ms;
468 + mod_timer(&gf->timer, gf->delay_jiffies);
472 + // During shutdown, skip everything else
473 + if (gf->shutting_down)
476 + // Otherwise record what the shutdown time would be
477 + gf->shutdown_jiffies = jiffies + msecs_to_jiffies(state->shutdown_ms);
479 + // 4. Check soft inputs for transitions to take
480 + for (i = 0; i < state->num_soft_events; i++) {
481 + event = &state->soft_events[i];
482 + if (gf->soft_gpios[event->index].value == event->value) {
485 + "GF_SOFT %d=%d -> %s\n", event->index,
486 + event->value, event->target->name);
487 + gpio_fsm_go_to_state(gf, event->target);
492 + // 5. Check GPIOs for transitions to take, enabling the IRQs
493 + for (i = 0; i < state->num_gpio_events; i++) {
494 + event = &state->gpio_events[i];
495 + inp_state = &gf->input_gpio_states[event->index];
496 + inp_state->target = event->target;
497 + inp_state->value = event->value;
498 + inp_state->enabled = true;
500 + value = gpiod_get_value(gf->input_gpios->desc[event->index]);
502 + // Clear stale event state
503 + disable_irq(inp_state->irq);
505 + irq_set_irq_type(inp_state->irq,
506 + (inp_state->value ^ inp_state->active_low) ?
507 + IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING);
508 + enable_irq(inp_state->irq);
510 + if (value == event->value && inp_state->target) {
513 + "GF_IN %d=%d -> %s\n", event->index,
514 + event->value, event->target->name);
515 + gpio_fsm_go_to_state(gf, event->target);
520 + // 6. Schedule a timer callback if delay_target
521 + if (state->delay_target) {
522 + gf->delay_target_state = state->delay_target;
523 + gf->delay_jiffies = jiffies +
524 + msecs_to_jiffies(state->delay_ms);
525 + gf->delay_ms = state->delay_ms;
526 + mod_timer(&gf->timer, gf->delay_jiffies);
530 +static void gpio_fsm_work(struct work_struct *work)
532 + struct input_gpio_state *inp_state;
533 + struct fsm_state *new_state;
534 + struct fsm_state *state;
535 + struct gpio_event *gp_ev;
536 + struct gpio_fsm *gf;
539 + gf = container_of(work, struct gpio_fsm, work);
540 + spin_lock(&gf->spinlock);
541 + state = gf->current_state;
542 + new_state = gf->next_state;
544 + new_state = gf->delay_target_state;
545 + gf->next_state = NULL;
546 + gf->delay_target_state = NULL;
547 + spin_unlock(&gf->spinlock);
550 + /* Disable any enabled GPIO IRQs */
551 + for (i = 0; i < state->num_gpio_events; i++) {
552 + gp_ev = &state->gpio_events[i];
553 + inp_state = &gf->input_gpio_states[gp_ev->index];
554 + if (inp_state->enabled) {
555 + inp_state->enabled = false;
556 + irq_set_irq_type(inp_state->irq,
557 + IRQF_TRIGGER_NONE);
563 + gpio_fsm_enter_state(gf, new_state);
566 +static irqreturn_t gpio_fsm_gpio_irq_handler(int irq, void *dev_id)
568 + struct input_gpio_state *inp_state = dev_id;
569 + struct gpio_fsm *gf = inp_state->gf;
570 + struct fsm_state *target;
572 + target = inp_state->target;
576 + /* If the IRQ has fired then the desired state _must_ have occurred */
577 + inp_state->enabled = false;
578 + irq_set_irq_type(inp_state->irq, IRQF_TRIGGER_NONE);
580 + dev_info(gf->dev, "GF_IN %d->%d -> %s\n",
581 + inp_state->index, inp_state->value, target->name);
582 + gpio_fsm_go_to_state(gf, target);
583 + return IRQ_HANDLED;
586 +static void gpio_fsm_timer(struct timer_list *timer)
588 + struct gpio_fsm *gf = container_of(timer, struct gpio_fsm, timer);
589 + struct fsm_state *target;
591 + target = gf->delay_target_state;
596 + dev_info(gf->dev, "GF_DELAY %d -> %s\n", gf->delay_ms,
599 + gpio_fsm_go_to_state(gf, target);
602 +int gpio_fsm_parse_signals(struct gpio_fsm *gf, struct fsm_state *state,
603 + struct property *prop)
605 + const __be32 *cells = prop->value;
606 + struct output_signal *signal;
614 + if (prop->length % 8) {
615 + dev_err(gf->dev, "malformed set in state %s\n",
620 + state->num_signals = prop->length/8;
621 + state->signals = devm_kcalloc(gf->dev, state->num_signals,
622 + sizeof(struct output_signal),
624 + for (i = 0; i < state->num_signals; i++) {
625 + signal = &state->signals[i];
626 + io = be32_to_cpu(cells[0]);
627 + type = GF_IO_TYPE(io);
628 + index = GF_IO_INDEX(io);
629 + value = be32_to_cpu(cells[1]);
631 + if (type != GF_OUT && type != GF_SOFT) {
633 + "invalid set type %d in state %s\n",
634 + type, state->name);
638 + if (type == GF_OUT && index >= gf->num_output_gpios) {
640 + "invalid GF_OUT number %d in state %s\n",
641 + index, state->name);
645 + if (type == GF_SOFT && index >= gf->num_soft_gpios) {
647 + "invalid GF_SOFT number %d in state %s\n",
648 + index, state->name);
652 + if (value != 0 && value != 1) {
654 + "invalid set value %d in state %s\n",
655 + value, state->name);
659 + signal->type = (type == GF_OUT) ? SIGNAL_GPIO : SIGNAL_SOFT;
660 + signal->index = index;
661 + signal->value = value;
668 +struct gpio_event *new_event(struct gpio_event **events, int *num_events)
670 + int num = ++(*num_events);
671 + *events = krealloc(*events, num * sizeof(struct gpio_event),
673 + return *events ? *events + (num - 1) : NULL;
676 +int gpio_fsm_parse_events(struct gpio_fsm *gf, struct fsm_state *state,
677 + struct property *prop)
679 + const __be32 *cells = prop->value;
680 + struct symtab_entry *sym;
685 + if (prop->length % 8) {
687 + "malformed transitions from state %s to state %s\n",
688 + state->name, prop->name);
692 + sym = get_symbol(&gf->symtab, prop->name);
693 + num_cells = prop->length / 4;
695 + while (i < num_cells) {
696 + struct gpio_event *gp_ev;
700 + event = be32_to_cpu(cells[i++]);
701 + param = be32_to_cpu(cells[i++]);
702 + index = GF_IO_INDEX(event);
704 + switch (GF_IO_TYPE(event)) {
706 + if (index >= gf->num_input_gpios) {
708 + "invalid GF_IN %d in transitions from state %s to state %s\n",
709 + index, state->name, prop->name);
714 + "invalid GF_IN value %d in transitions from state %s to state %s\n",
715 + param, state->name, prop->name);
718 + gp_ev = new_event(&state->gpio_events,
719 + &state->num_gpio_events);
722 + gp_ev->index = index;
723 + gp_ev->value = param;
724 + gp_ev->target = (struct fsm_state *)sym;
728 + if (index >= gf->num_soft_gpios) {
730 + "invalid GF_SOFT %d in transitions from state %s to state %s\n",
731 + index, state->name, prop->name);
736 + "invalid GF_SOFT value %d in transitions from state %s to state %s\n",
737 + param, state->name, prop->name);
740 + gp_ev = new_event(&state->soft_events,
741 + &state->num_soft_events);
744 + gp_ev->index = index;
745 + gp_ev->value = param;
746 + gp_ev->target = (struct fsm_state *)sym;
750 + if (state->delay_target) {
752 + "state %s has multiple GF_DELAYs\n",
756 + state->delay_target = (struct fsm_state *)sym;
757 + state->delay_ms = param;
761 + if (state->shutdown_target == state) {
763 + "shutdown state %s has GF_SHUTDOWN\n",
766 + } else if (state->shutdown_target) {
768 + "state %s has multiple GF_SHUTDOWNs\n",
772 + state->shutdown_target =
773 + (struct fsm_state *)sym;
774 + state->shutdown_ms = param;
779 + "invalid event %08x in transitions from state %s to state %s\n",
780 + event, state->name, prop->name);
784 + if (i != num_cells) {
786 + "malformed transitions from state %s to state %s\n",
787 + state->name, prop->name);
794 +int gpio_fsm_parse_state(struct gpio_fsm *gf,
795 + struct fsm_state *state,
796 + struct device_node *np)
798 + struct symtab_entry *sym;
799 + struct property *prop;
802 + state->name = np->name;
803 + ret = add_symbol(&gf->symtab, np->name, state);
807 + dev_err(gf->dev, "'%s' is not a valid state name\n",
811 + dev_err(gf->dev, "state %s already defined\n",
815 + dev_err(gf->dev, "error %d adding state %s symbol\n",
822 + for_each_property_of_node(np, prop) {
823 + sym = get_symbol(&gf->symtab, prop->name);
829 + switch ((uintptr_t)sym->value) {
831 + ret = gpio_fsm_parse_signals(gf, state, prop);
834 + if (gf->start_state) {
835 + dev_err(gf->dev, "multiple start states\n");
838 + gf->start_state = state;
842 + state->shutdown_target = state;
843 + gf->shutdown_state = state;
849 + /* A set of transition events to this state */
850 + ret = gpio_fsm_parse_events(gf, state, prop);
858 +static void dump_all(struct gpio_fsm *gf)
862 + dev_info(gf->dev, "Input GPIOs:\n");
863 + for (i = 0; i < gf->num_input_gpios; i++)
864 + dev_info(gf->dev, " %d: %p\n", i,
865 + gf->input_gpios->desc[i]);
867 + dev_info(gf->dev, "Output GPIOs:\n");
868 + for (i = 0; i < gf->num_output_gpios; i++)
869 + dev_info(gf->dev, " %d: %p\n", i,
870 + gf->output_gpios->desc[i]);
872 + dev_info(gf->dev, "Soft GPIOs:\n");
873 + for (i = 0; i < gf->num_soft_gpios; i++)
874 + dev_info(gf->dev, " %d: %s %d\n", i,
875 + (gf->soft_gpios[i].dir == GPIOF_DIR_IN) ? "IN" : "OUT",
876 + gf->soft_gpios[i].value);
878 + dev_info(gf->dev, "Start state: %s\n",
879 + gf->start_state ? gf->start_state->name : "-");
881 + dev_info(gf->dev, "Shutdown timeout: %d ms\n",
882 + gf->shutdown_timeout_ms);
884 + for (i = 0; i < gf->num_states; i++) {
885 + struct fsm_state *state = &gf->states[i];
887 + dev_info(gf->dev, "State %s:\n", state->name);
889 + if (state->shutdown_target == state)
890 + dev_info(gf->dev, " Shutdown state\n");
892 + dev_info(gf->dev, " Signals:\n");
893 + for (j = 0; j < state->num_signals; j++) {
894 + struct output_signal *signal = &state->signals[j];
896 + dev_info(gf->dev, " %d: %s %d=%d\n", j,
897 + (signal->type == SIGNAL_GPIO) ? "GPIO" :
899 + signal->index, signal->value);
902 + dev_info(gf->dev, " GPIO events:\n");
903 + for (j = 0; j < state->num_gpio_events; j++) {
904 + struct gpio_event *event = &state->gpio_events[j];
906 + dev_info(gf->dev, " %d: %d=%d -> %s\n", j,
907 + event->index, event->value,
908 + event->target->name);
911 + dev_info(gf->dev, " Soft events:\n");
912 + for (j = 0; j < state->num_soft_events; j++) {
913 + struct gpio_event *event = &state->soft_events[j];
915 + dev_info(gf->dev, " %d: %d=%d -> %s\n", j,
916 + event->index, event->value,
917 + event->target->name);
920 + if (state->delay_target)
921 + dev_info(gf->dev, " Delay: %d ms -> %s\n",
922 + state->delay_ms, state->delay_target->name);
924 + if (state->shutdown_target && state->shutdown_target != state)
925 + dev_info(gf->dev, " Shutdown: %d ms -> %s\n",
926 + state->shutdown_ms,
927 + state->shutdown_target->name);
929 + dev_info(gf->dev, "\n");
932 +static int resolve_sym_to_state(struct gpio_fsm *gf, struct fsm_state **pstate)
934 + struct symtab_entry *sym = (struct symtab_entry *)*pstate;
939 + *pstate = sym->value;
942 + dev_err(gf->dev, "state %s not defined\n",
952 + * /sys/class/gpio-fsm/<fsm-name>/
953 + * /state ... the current state
956 +static ssize_t state_show(struct device *dev,
957 + struct device_attribute *attr, char *buf)
959 + const struct gpio_fsm *gf = dev_get_drvdata(dev);
961 + return sprintf(buf, "%s\n", gf->current_state->name);
963 +static DEVICE_ATTR_RO(state);
965 +static ssize_t delay_state_show(struct device *dev,
966 + struct device_attribute *attr, char *buf)
968 + const struct gpio_fsm *gf = dev_get_drvdata(dev);
970 + return sprintf(buf, "%s\n",
971 + gf->delay_target_state ? gf->delay_target_state->name :
975 +static DEVICE_ATTR_RO(delay_state);
977 +static ssize_t delay_ms_show(struct device *dev,
978 + struct device_attribute *attr, char *buf)
980 + const struct gpio_fsm *gf = dev_get_drvdata(dev);
983 + jiffies_left = max((int)(gf->delay_jiffies - jiffies), 0);
984 + return sprintf(buf,
985 + gf->delay_target_state ? "%u\n" : "-\n",
986 + jiffies_to_msecs(jiffies_left));
988 +static DEVICE_ATTR_RO(delay_ms);
990 +static struct attribute *gpio_fsm_attrs[] = {
991 + &dev_attr_state.attr,
992 + &dev_attr_delay_state.attr,
993 + &dev_attr_delay_ms.attr,
997 +static const struct attribute_group gpio_fsm_group = {
998 + .attrs = gpio_fsm_attrs,
999 + //.is_visible = gpio_is_visible,
1002 +static const struct attribute_group *gpio_fsm_groups[] = {
1007 +static struct attribute *gpio_fsm_class_attrs[] = {
1008 + // There are no top-level attributes
1011 +ATTRIBUTE_GROUPS(gpio_fsm_class);
1013 +static struct class gpio_fsm_class = {
1014 + .name = MODULE_NAME,
1015 + .owner = THIS_MODULE,
1017 + .class_groups = gpio_fsm_class_groups,
1020 +static int gpio_fsm_probe(struct platform_device *pdev)
1022 + struct input_gpio_state *inp_state;
1023 + struct device *dev = &pdev->dev;
1024 + struct device *sysfs_dev;
1025 + struct device_node *np = dev->of_node;
1026 + struct device_node *cp;
1027 + struct gpio_fsm *gf;
1030 + u32 num_soft_gpios;
1033 + static const char *const reserved_symbols[] = {
1034 + [SYM_NAME] = "name",
1035 + [SYM_SET] = "set",
1036 + [SYM_START] = "start_state",
1037 + [SYM_SHUTDOWN] = "shutdown_state",
1040 + if (of_property_read_u32(np, "num-swgpios", &num_soft_gpios) &&
1041 + of_property_read_u32(np, "num-soft-gpios", &num_soft_gpios)) {
1042 + dev_err(dev, "missing 'num-swgpios' property\n");
1046 + of_property_read_u32(np, "debug", &debug);
1048 + gf = devm_kzalloc(dev, sizeof(*gf), GFP_KERNEL);
1053 + gf->debug = debug;
1055 + if (of_property_read_u32(np, "shutdown-timeout-ms",
1056 + &gf->shutdown_timeout_ms))
1057 + gf->shutdown_timeout_ms = 5000;
1059 + gf->num_soft_gpios = num_soft_gpios;
1060 + gf->soft_gpios = devm_kcalloc(dev, num_soft_gpios,
1061 + sizeof(struct soft_gpio), GFP_KERNEL);
1062 + if (!gf->soft_gpios)
1064 + for (i = 0; i < num_soft_gpios; i++) {
1065 + struct soft_gpio *sg = &gf->soft_gpios[i];
1067 + sg->dir = GPIOF_DIR_IN;
1071 + gf->input_gpios = devm_gpiod_get_array_optional(dev, "input", GPIOD_IN);
1072 + if (IS_ERR(gf->input_gpios)) {
1073 + ret = PTR_ERR(gf->input_gpios);
1074 + dev_err(dev, "failed to get input gpios from DT - %d\n", ret);
1077 + gf->num_input_gpios = (gf->input_gpios ? gf->input_gpios->ndescs : 0);
1079 + gf->input_gpio_states = devm_kcalloc(dev, gf->num_input_gpios,
1080 + sizeof(struct input_gpio_state),
1082 + if (!gf->input_gpio_states)
1084 + for (i = 0; i < gf->num_input_gpios; i++) {
1085 + inp_state = &gf->input_gpio_states[i];
1086 + inp_state->desc = gf->input_gpios->desc[i];
1087 + inp_state->gf = gf;
1088 + inp_state->index = i;
1089 + inp_state->irq = gpiod_to_irq(inp_state->desc);
1090 + inp_state->active_low = gpiod_is_active_low(inp_state->desc);
1091 + if (inp_state->irq >= 0)
1092 + ret = devm_request_irq(gf->dev, inp_state->irq,
1093 + gpio_fsm_gpio_irq_handler,
1094 + IRQF_TRIGGER_NONE,
1098 + ret = inp_state->irq;
1102 + "failed to get IRQ for input gpio - %d\n",
1108 + gf->output_gpios = devm_gpiod_get_array_optional(dev, "output",
1110 + if (IS_ERR(gf->output_gpios)) {
1111 + ret = PTR_ERR(gf->output_gpios);
1112 + dev_err(dev, "failed to get output gpios from DT - %d\n", ret);
1115 + gf->num_output_gpios = (gf->output_gpios ? gf->output_gpios->ndescs :
1118 + num_states = of_get_child_count(np);
1119 + if (!num_states) {
1120 + dev_err(dev, "no states declared\n");
1123 + gf->states = devm_kcalloc(dev, num_states,
1124 + sizeof(struct fsm_state), GFP_KERNEL);
1128 + // add reserved words to the symbol table
1129 + for (i = 0; i < ARRAY_SIZE(reserved_symbols); i++) {
1130 + if (reserved_symbols[i])
1131 + add_symbol(&gf->symtab, reserved_symbols[i],
1132 + (void *)(uintptr_t)i);
1135 + // parse the state
1136 + for_each_child_of_node(np, cp) {
1137 + struct fsm_state *state = &gf->states[gf->num_states];
1139 + ret = gpio_fsm_parse_state(gf, state, cp);
1145 + if (!gf->start_state) {
1146 + dev_err(gf->dev, "no start state defined\n");
1150 + // resolve symbol pointers into state pointers
1151 + for (i = 0; !ret && i < gf->num_states; i++) {
1152 + struct fsm_state *state = &gf->states[i];
1155 + for (j = 0; !ret && j < state->num_gpio_events; j++) {
1156 + struct gpio_event *ev = &state->gpio_events[j];
1158 + ret = resolve_sym_to_state(gf, &ev->target);
1161 + for (j = 0; !ret && j < state->num_soft_events; j++) {
1162 + struct gpio_event *ev = &state->soft_events[j];
1164 + ret = resolve_sym_to_state(gf, &ev->target);
1168 + resolve_sym_to_state(gf, &state->delay_target);
1169 + if (state->shutdown_target != state)
1170 + resolve_sym_to_state(gf,
1171 + &state->shutdown_target);
1175 + if (!ret && gf->debug > 1)
1178 + free_symbols(&gf->symtab);
1183 + gf->gc.parent = dev;
1184 + gf->gc.label = np->name;
1185 + gf->gc.owner = THIS_MODULE;
1186 + gf->gc.of_node = np;
1188 + gf->gc.ngpio = num_soft_gpios;
1190 + gf->gc.get_direction = gpio_fsm_get_direction;
1191 + gf->gc.direction_input = gpio_fsm_direction_input;
1192 + gf->gc.direction_output = gpio_fsm_direction_output;
1193 + gf->gc.get = gpio_fsm_get;
1194 + gf->gc.set = gpio_fsm_set;
1195 + gf->gc.can_sleep = true;
1196 + spin_lock_init(&gf->spinlock);
1197 + INIT_WORK(&gf->work, gpio_fsm_work);
1198 + timer_setup(&gf->timer, gpio_fsm_timer, 0);
1199 + init_waitqueue_head(&gf->shutdown_event);
1201 + platform_set_drvdata(pdev, gf);
1203 + sysfs_dev = device_create_with_groups(&gpio_fsm_class, dev,
1207 + if (IS_ERR(sysfs_dev))
1208 + dev_err(gf->dev, "Error creating sysfs entry\n");
1211 + dev_info(gf->dev, "Start -> %s\n", gf->start_state->name);
1213 + gpio_fsm_go_to_state(gf, gf->start_state);
1215 + return devm_gpiochip_add_data(dev, &gf->gc, gf);
1218 +static int gpio_fsm_remove(struct platform_device *pdev)
1220 + struct gpio_fsm *gf = platform_get_drvdata(pdev);
1223 + if (gf->shutdown_state) {
1225 + dev_info(gf->dev, "Shutting down...\n");
1227 + spin_lock(&gf->spinlock);
1228 + gf->shutting_down = true;
1229 + if (gf->current_state->shutdown_target &&
1230 + gf->current_state->shutdown_target != gf->current_state) {
1231 + gf->delay_target_state =
1232 + gf->current_state->shutdown_target;
1233 + mod_timer(&gf->timer, gf->shutdown_jiffies);
1235 + spin_unlock(&gf->spinlock);
1237 + wait_event_timeout(gf->shutdown_event,
1238 + gf->current_state->shutdown_target ==
1239 + gf->current_state,
1240 + msecs_to_jiffies(gf->shutdown_timeout_ms));
1241 + /* On failure to reach a shutdown state, jump to one */
1242 + if (gf->current_state->shutdown_target != gf->current_state)
1243 + gpio_fsm_enter_state(gf, gf->shutdown_state);
1245 + cancel_work_sync(&gf->work);
1246 + del_timer_sync(&gf->timer);
1248 + /* Events aren't allocated from managed storage */
1249 + for (i = 0; i < gf->num_states; i++) {
1250 + kfree(gf->states[i].gpio_events);
1251 + kfree(gf->states[i].soft_events);
1254 + dev_info(gf->dev, "Exiting\n");
1259 +static void gpio_fsm_shutdown(struct platform_device *pdev)
1261 + gpio_fsm_remove(pdev);
1264 +static const struct of_device_id gpio_fsm_ids[] = {
1265 + { .compatible = "rpi,gpio-fsm" },
1268 +MODULE_DEVICE_TABLE(of, gpio_fsm_ids);
1270 +static struct platform_driver gpio_fsm_driver = {
1272 + .name = MODULE_NAME,
1273 + .of_match_table = of_match_ptr(gpio_fsm_ids),
1275 + .probe = gpio_fsm_probe,
1276 + .remove = gpio_fsm_remove,
1277 + .shutdown = gpio_fsm_shutdown,
1280 +static int gpio_fsm_init(void)
1284 + ret = class_register(&gpio_fsm_class);
1288 + ret = platform_driver_register(&gpio_fsm_driver);
1290 + class_unregister(&gpio_fsm_class);
1294 +module_init(gpio_fsm_init);
1296 +static void gpio_fsm_exit(void)
1298 + platform_driver_unregister(&gpio_fsm_driver);
1299 + class_unregister(&gpio_fsm_class);
1301 +module_exit(gpio_fsm_exit);
1303 +MODULE_LICENSE("GPL");
1304 +MODULE_AUTHOR("Phil Elwell <phil@raspberrypi.com>");
1305 +MODULE_DESCRIPTION("GPIO FSM driver");
1306 +MODULE_ALIAS("platform:gpio-fsm");
1308 +++ b/include/dt-bindings/gpio/gpio-fsm.h
1310 +/* SPDX-License-Identifier: GPL-2.0+ */
1312 + * This header provides constants for binding rpi,gpio-fsm.
1315 +#ifndef _DT_BINDINGS_GPIO_FSM_H
1316 +#define _DT_BINDINGS_GPIO_FSM_H
1322 +#define GF_SHUTDOWN 4
1324 +#define GF_IO(t, v) (((v) << 16) | ((t) & 0xffff))
1326 +#define GF_IP(x) GF_IO(GF_IN, (x))
1327 +#define GF_OP(x) GF_IO(GF_OUT, (x))
1328 +#define GF_SW(x) GF_IO(GF_SOFT, (x))