950-0348-gpio-Add-gpio-fsm-driver.patch 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182
  1. From 69f26eddc66378e33866cb30fc36309cd1d71b4a Mon Sep 17 00:00:00 2001
  2. From: Phil Elwell <[email protected]>
  3. Date: Wed, 30 Sep 2020 12:00:54 +0100
  4. Subject: [PATCH] gpio: Add gpio-fsm driver
  5. The gpio-fsm driver implements simple state machines that allow GPIOs
  6. to be controlled in response to inputs from other GPIOs - real and
  7. soft/virtual - and time delays. It can:
  8. + create dummy GPIOs for drivers that demand them,
  9. + drive multiple GPIOs from a single input, with optional delays,
  10. + add a debounce circuit to an input,
  11. + drive pattern sequences onto LEDs
  12. etc.
  13. Signed-off-by: Phil Elwell <[email protected]>
  14. ---
  15. drivers/gpio/Kconfig | 9 +
  16. drivers/gpio/Makefile | 1 +
  17. drivers/gpio/gpio-fsm.c | 1103 +++++++++++++++++++++++++++
  18. include/dt-bindings/gpio/gpio-fsm.h | 21 +
  19. 4 files changed, 1134 insertions(+)
  20. create mode 100644 drivers/gpio/gpio-fsm.c
  21. create mode 100644 include/dt-bindings/gpio/gpio-fsm.h
  22. --- a/drivers/gpio/Kconfig
  23. +++ b/drivers/gpio/Kconfig
  24. @@ -1164,6 +1164,15 @@ config HTC_EGPIO
  25. several HTC phones. It provides basic support for input
  26. pins, output pins, and irqs.
  27. +config GPIO_FSM
  28. + tristate "GPIO FSM support"
  29. + help
  30. + The GPIO FSM driver allows the creation of state machines for
  31. + manipulating GPIOs (both real and virtual), with state transitions
  32. + triggered by GPIO edges or delays.
  33. +
  34. + If unsure, say N.
  35. +
  36. config GPIO_JANZ_TTL
  37. tristate "Janz VMOD-TTL Digital IO Module"
  38. depends on MFD_JANZ_CMODIO
  39. --- a/drivers/gpio/Makefile
  40. +++ b/drivers/gpio/Makefile
  41. @@ -61,6 +61,7 @@ obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93x
  42. obj-$(CONFIG_GPIO_EXAR) += gpio-exar.o
  43. obj-$(CONFIG_GPIO_F7188X) += gpio-f7188x.o
  44. obj-$(CONFIG_GPIO_FTGPIO010) += gpio-ftgpio010.o
  45. +obj-$(CONFIG_GPIO_FSM) += gpio-fsm.o
  46. obj-$(CONFIG_GPIO_GE_FPGA) += gpio-ge.o
  47. obj-$(CONFIG_GPIO_GPIO_MM) += gpio-gpio-mm.o
  48. obj-$(CONFIG_GPIO_GRGPIO) += gpio-grgpio.o
  49. --- /dev/null
  50. +++ b/drivers/gpio/gpio-fsm.c
  51. @@ -0,0 +1,1103 @@
  52. +// SPDX-License-Identifier: GPL-2.0+
  53. +/*
  54. + * GPIO FSM driver
  55. + *
  56. + * This driver implements simple state machines that allow real GPIOs to be
  57. + * controlled in response to inputs from other GPIOs - real and soft/virtual -
  58. + * and time delays. It can:
  59. + * + create dummy GPIOs for drivers that demand them
  60. + * + drive multiple GPIOs from a single input, with optional delays
  61. + * + add a debounce circuit to an input
  62. + * + drive pattern sequences onto LEDs
  63. + * etc.
  64. + *
  65. + * Copyright (C) 2020 Raspberry Pi (Trading) Ltd.
  66. + */
  67. +
  68. +#include <linux/err.h>
  69. +#include <linux/gpio.h>
  70. +#include <linux/gpio/driver.h>
  71. +#include <linux/interrupt.h>
  72. +#include <linux/module.h>
  73. +#include <linux/platform_device.h>
  74. +
  75. +#include <dt-bindings/gpio/gpio-fsm.h>
  76. +
  77. +#define MODULE_NAME "gpio-fsm"
  78. +
  79. +#define GF_IO_TYPE(x) ((u32)(x) & 0xffff)
  80. +#define GF_IO_INDEX(x) ((u32)(x) >> 16)
  81. +
  82. +enum {
  83. + SIGNAL_GPIO,
  84. + SIGNAL_SOFT
  85. +};
  86. +
  87. +enum {
  88. + INPUT_GPIO,
  89. + INPUT_SOFT
  90. +};
  91. +
  92. +enum {
  93. + SYM_UNDEFINED,
  94. + SYM_NAME,
  95. + SYM_SET,
  96. + SYM_START,
  97. + SYM_SHUTDOWN,
  98. +
  99. + SYM_MAX
  100. +};
  101. +
  102. +struct soft_gpio {
  103. + int dir;
  104. + int value;
  105. +};
  106. +
  107. +struct input_gpio_state {
  108. + struct gpio_fsm *gf;
  109. + struct gpio_desc *desc;
  110. + struct fsm_state *target;
  111. + int index;
  112. + int value;
  113. + int irq;
  114. + bool enabled;
  115. + bool active_low;
  116. +};
  117. +
  118. +struct gpio_event {
  119. + int index;
  120. + int value;
  121. + struct fsm_state *target;
  122. +};
  123. +
  124. +struct symtab_entry {
  125. + const char *name;
  126. + void *value;
  127. + struct symtab_entry *next;
  128. +};
  129. +
  130. +struct output_signal {
  131. + u8 type;
  132. + u8 value;
  133. + u16 index;
  134. +};
  135. +
  136. +struct fsm_state {
  137. + const char *name;
  138. + struct output_signal *signals;
  139. + struct gpio_event *gpio_events;
  140. + struct gpio_event *soft_events;
  141. + struct fsm_state *delay_target;
  142. + struct fsm_state *shutdown_target;
  143. + unsigned int num_signals;
  144. + unsigned int num_gpio_events;
  145. + unsigned int num_soft_events;
  146. + unsigned int delay_ms;
  147. + unsigned int shutdown_ms;
  148. +};
  149. +
  150. +struct gpio_fsm {
  151. + struct gpio_chip gc;
  152. + struct device *dev;
  153. + spinlock_t spinlock;
  154. + struct work_struct work;
  155. + struct timer_list timer;
  156. + wait_queue_head_t shutdown_event;
  157. + struct fsm_state *states;
  158. + struct input_gpio_state *input_gpio_states;
  159. + struct gpio_descs *input_gpios;
  160. + struct gpio_descs *output_gpios;
  161. + struct soft_gpio *soft_gpios;
  162. + struct fsm_state *start_state;
  163. + struct fsm_state *shutdown_state;
  164. + unsigned int num_states;
  165. + unsigned int num_output_gpios;
  166. + unsigned int num_input_gpios;
  167. + unsigned int num_soft_gpios;
  168. + unsigned int shutdown_timeout_ms;
  169. + unsigned int shutdown_jiffies;
  170. +
  171. + struct fsm_state *current_state;
  172. + struct fsm_state *next_state;
  173. + struct fsm_state *delay_target_state;
  174. + int delay_ms;
  175. + unsigned int debug;
  176. + bool shutting_down;
  177. + struct symtab_entry *symtab;
  178. +};
  179. +
  180. +static struct symtab_entry *do_add_symbol(struct symtab_entry **symtab,
  181. + const char *name, void *value)
  182. +{
  183. + struct symtab_entry **p = symtab;
  184. +
  185. + while (*p && strcmp((*p)->name, name))
  186. + p = &(*p)->next;
  187. +
  188. + if (*p) {
  189. + /* This is an existing symbol */
  190. + if ((*p)->value) {
  191. + /* Already defined */
  192. + if (value) {
  193. + if ((uintptr_t)value < SYM_MAX)
  194. + return ERR_PTR(-EINVAL);
  195. + else
  196. + return ERR_PTR(-EEXIST);
  197. + }
  198. + } else {
  199. + /* Undefined */
  200. + (*p)->value = value;
  201. + }
  202. + } else {
  203. + /* This is a new symbol */
  204. + *p = kmalloc(sizeof(struct symtab_entry), GFP_KERNEL);
  205. + if (*p) {
  206. + (*p)->name = name;
  207. + (*p)->value = value;
  208. + (*p)->next = NULL;
  209. + }
  210. + }
  211. + return *p;
  212. +}
  213. +
  214. +static int add_symbol(struct symtab_entry **symtab,
  215. + const char *name, void *value)
  216. +{
  217. + struct symtab_entry *sym = do_add_symbol(symtab, name, value);
  218. +
  219. + return PTR_ERR_OR_ZERO(sym);
  220. +}
  221. +
  222. +static struct symtab_entry *get_symbol(struct symtab_entry **symtab,
  223. + const char *name)
  224. +{
  225. + struct symtab_entry *sym = do_add_symbol(symtab, name, NULL);
  226. +
  227. + if (IS_ERR(sym))
  228. + return NULL;
  229. + return sym;
  230. +}
  231. +
  232. +static void free_symbols(struct symtab_entry **symtab)
  233. +{
  234. + struct symtab_entry *sym = *symtab;
  235. + void *p;
  236. +
  237. + *symtab = NULL;
  238. + while (sym) {
  239. + p = sym;
  240. + sym = sym->next;
  241. + kfree(p);
  242. + }
  243. +}
  244. +
  245. +static int gpio_fsm_get_direction(struct gpio_chip *gc, unsigned int off)
  246. +{
  247. + struct gpio_fsm *gf = gpiochip_get_data(gc);
  248. + struct soft_gpio *sg;
  249. +
  250. + if (off >= gf->num_soft_gpios)
  251. + return -EINVAL;
  252. + sg = &gf->soft_gpios[off];
  253. +
  254. + return sg->dir;
  255. +}
  256. +
  257. +static int gpio_fsm_get(struct gpio_chip *gc, unsigned int off)
  258. +{
  259. + struct gpio_fsm *gf = gpiochip_get_data(gc);
  260. + struct soft_gpio *sg;
  261. +
  262. + if (off >= gf->num_soft_gpios)
  263. + return -EINVAL;
  264. + sg = &gf->soft_gpios[off];
  265. +
  266. + return sg->value;
  267. +}
  268. +
  269. +static void gpio_fsm_go_to_state(struct gpio_fsm *gf,
  270. + struct fsm_state *new_state)
  271. +{
  272. + struct input_gpio_state *inp_state;
  273. + struct gpio_event *gp_ev;
  274. + struct fsm_state *state;
  275. + int i;
  276. +
  277. + dev_dbg(gf->dev, "go_to_state(%s)\n",
  278. + new_state ? new_state->name : "<unset>");
  279. +
  280. + spin_lock(&gf->spinlock);
  281. +
  282. + if (gf->next_state) {
  283. + /* Something else has already requested a transition */
  284. + spin_unlock(&gf->spinlock);
  285. + return;
  286. + }
  287. +
  288. + gf->next_state = new_state;
  289. + state = gf->current_state;
  290. + gf->delay_target_state = NULL;
  291. +
  292. + if (state) {
  293. + /* Disarm any GPIO IRQs */
  294. + for (i = 0; i < state->num_gpio_events; i++) {
  295. + gp_ev = &state->gpio_events[i];
  296. + inp_state = &gf->input_gpio_states[gp_ev->index];
  297. + inp_state->target = NULL;
  298. + }
  299. + }
  300. +
  301. + spin_unlock(&gf->spinlock);
  302. +
  303. + if (new_state)
  304. + schedule_work(&gf->work);
  305. +}
  306. +
  307. +static void gpio_fsm_set_soft(struct gpio_fsm *gf,
  308. + unsigned int off, int val)
  309. +{
  310. + struct soft_gpio *sg = &gf->soft_gpios[off];
  311. + struct gpio_event *gp_ev;
  312. + struct fsm_state *state;
  313. + int i;
  314. +
  315. + dev_dbg(gf->dev, "set(%d,%d)\n", off, val);
  316. + state = gf->current_state;
  317. + sg->value = val;
  318. + for (i = 0; i < state->num_soft_events; i++) {
  319. + gp_ev = &state->soft_events[i];
  320. + if (gp_ev->index == off && gp_ev->value == val) {
  321. + if (gf->debug)
  322. + dev_info(gf->dev,
  323. + "GF_SOFT %d->%d -> %s\n", gp_ev->index,
  324. + gp_ev->value, gp_ev->target->name);
  325. + gpio_fsm_go_to_state(gf, gp_ev->target);
  326. + break;
  327. + }
  328. + }
  329. +}
  330. +
  331. +static int gpio_fsm_direction_input(struct gpio_chip *gc, unsigned int off)
  332. +{
  333. + struct gpio_fsm *gf = gpiochip_get_data(gc);
  334. + struct soft_gpio *sg;
  335. +
  336. + if (off >= gf->num_soft_gpios)
  337. + return -EINVAL;
  338. + sg = &gf->soft_gpios[off];
  339. + sg->dir = GPIOF_DIR_IN;
  340. +
  341. + return 0;
  342. +}
  343. +
  344. +static int gpio_fsm_direction_output(struct gpio_chip *gc, unsigned int off,
  345. + int value)
  346. +{
  347. + struct gpio_fsm *gf = gpiochip_get_data(gc);
  348. + struct soft_gpio *sg;
  349. +
  350. + if (off >= gf->num_soft_gpios)
  351. + return -EINVAL;
  352. + sg = &gf->soft_gpios[off];
  353. + sg->dir = GPIOF_DIR_OUT;
  354. + gpio_fsm_set_soft(gf, off, value);
  355. +
  356. + return 0;
  357. +}
  358. +
  359. +static void gpio_fsm_set(struct gpio_chip *gc, unsigned int off, int val)
  360. +{
  361. + struct gpio_fsm *gf;
  362. +
  363. + gf = gpiochip_get_data(gc);
  364. + if (off < gf->num_soft_gpios)
  365. + gpio_fsm_set_soft(gf, off, val);
  366. +}
  367. +
  368. +static void gpio_fsm_enter_state(struct gpio_fsm *gf,
  369. + struct fsm_state *state)
  370. +{
  371. + struct input_gpio_state *inp_state;
  372. + struct output_signal *signal;
  373. + struct gpio_event *event;
  374. + struct gpio_desc *gpiod;
  375. + struct soft_gpio *soft;
  376. + int value;
  377. + int i;
  378. +
  379. + dev_dbg(gf->dev, "enter_state(%s)\n", state->name);
  380. +
  381. + gf->current_state = state;
  382. +
  383. + // 1. Apply any listed signals
  384. + for (i = 0; i < state->num_signals; i++) {
  385. + signal = &state->signals[i];
  386. +
  387. + if (gf->debug)
  388. + dev_info(gf->dev, " set %s %d->%d\n",
  389. + (signal->type == SIGNAL_GPIO) ? "GF_OUT" :
  390. + "GF_SOFT",
  391. + signal->index, signal->value);
  392. + switch (signal->type) {
  393. + case SIGNAL_GPIO:
  394. + gpiod = gf->output_gpios->desc[signal->index];
  395. + gpiod_set_value_cansleep(gpiod, signal->value);
  396. + break;
  397. + case SIGNAL_SOFT:
  398. + soft = &gf->soft_gpios[signal->index];
  399. + gpio_fsm_set_soft(gf, signal->index, signal->value);
  400. + break;
  401. + }
  402. + }
  403. +
  404. + // 2. Exit if successfully reached shutdown state
  405. + if (gf->shutting_down && state == state->shutdown_target) {
  406. + wake_up(&gf->shutdown_event);
  407. + return;
  408. + }
  409. +
  410. + // 3. Schedule a timer callback if shutting down
  411. + if (state->shutdown_target) {
  412. + // Remember the absolute shutdown time in case remove is called
  413. + // at a later time.
  414. + gf->shutdown_jiffies =
  415. + jiffies + msecs_to_jiffies(state->shutdown_ms);
  416. +
  417. + if (gf->shutting_down) {
  418. + gf->delay_target_state = state->shutdown_target;
  419. + gf->delay_ms = state->shutdown_ms;
  420. + mod_timer(&gf->timer, gf->shutdown_jiffies);
  421. + }
  422. + }
  423. +
  424. + // During shutdown, skip everything else
  425. + if (gf->shutting_down)
  426. + return;
  427. +
  428. + // Otherwise record what the shutdown time would be
  429. + gf->shutdown_jiffies = jiffies + msecs_to_jiffies(state->shutdown_ms);
  430. +
  431. + // 4. Check soft inputs for transitions to take
  432. + for (i = 0; i < state->num_soft_events; i++) {
  433. + event = &state->soft_events[i];
  434. + if (gf->soft_gpios[event->index].value == event->value) {
  435. + if (gf->debug)
  436. + dev_info(gf->dev,
  437. + "GF_SOFT %d=%d -> %s\n", event->index,
  438. + event->value, event->target->name);
  439. + gpio_fsm_go_to_state(gf, event->target);
  440. + return;
  441. + }
  442. + }
  443. +
  444. + // 5. Check GPIOs for transitions to take, enabling the IRQs
  445. + for (i = 0; i < state->num_gpio_events; i++) {
  446. + event = &state->gpio_events[i];
  447. + inp_state = &gf->input_gpio_states[event->index];
  448. + inp_state->target = event->target;
  449. + inp_state->value = event->value;
  450. + inp_state->enabled = true;
  451. +
  452. + value = gpiod_get_value(gf->input_gpios->desc[event->index]);
  453. +
  454. + // Clear stale event state
  455. + disable_irq(inp_state->irq);
  456. +
  457. + irq_set_irq_type(inp_state->irq,
  458. + (inp_state->value ^ inp_state->active_low) ?
  459. + IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING);
  460. + enable_irq(inp_state->irq);
  461. +
  462. + if (value == event->value && inp_state->target) {
  463. + if (gf->debug)
  464. + dev_info(gf->dev,
  465. + "GF_IN %d=%d -> %s\n", event->index,
  466. + event->value, event->target->name);
  467. + gpio_fsm_go_to_state(gf, event->target);
  468. + return;
  469. + }
  470. + }
  471. +
  472. + // 6. Schedule a timer callback if delay_target
  473. + if (state->delay_target) {
  474. + gf->delay_target_state = state->delay_target;
  475. + gf->delay_ms = state->delay_ms;
  476. + mod_timer(&gf->timer,
  477. + jiffies + msecs_to_jiffies(state->delay_ms));
  478. + }
  479. +}
  480. +
  481. +static void gpio_fsm_work(struct work_struct *work)
  482. +{
  483. + struct input_gpio_state *inp_state;
  484. + struct fsm_state *new_state;
  485. + struct fsm_state *state;
  486. + struct gpio_event *gp_ev;
  487. + struct gpio_fsm *gf;
  488. + int i;
  489. +
  490. + gf = container_of(work, struct gpio_fsm, work);
  491. + spin_lock(&gf->spinlock);
  492. + state = gf->current_state;
  493. + new_state = gf->next_state;
  494. + if (!new_state)
  495. + new_state = gf->delay_target_state;
  496. + gf->next_state = NULL;
  497. + gf->delay_target_state = NULL;
  498. + spin_unlock(&gf->spinlock);
  499. +
  500. + if (state) {
  501. + /* Disable any enabled GPIO IRQs */
  502. + for (i = 0; i < state->num_gpio_events; i++) {
  503. + gp_ev = &state->gpio_events[i];
  504. + inp_state = &gf->input_gpio_states[gp_ev->index];
  505. + if (inp_state->enabled) {
  506. + inp_state->enabled = false;
  507. + irq_set_irq_type(inp_state->irq,
  508. + IRQF_TRIGGER_NONE);
  509. + }
  510. + }
  511. + }
  512. +
  513. + if (new_state)
  514. + gpio_fsm_enter_state(gf, new_state);
  515. +}
  516. +
  517. +static irqreturn_t gpio_fsm_gpio_irq_handler(int irq, void *dev_id)
  518. +{
  519. + struct input_gpio_state *inp_state = dev_id;
  520. + struct gpio_fsm *gf = inp_state->gf;
  521. + struct fsm_state *target;
  522. +
  523. + target = inp_state->target;
  524. + if (!target)
  525. + return IRQ_NONE;
  526. +
  527. + /* If the IRQ has fired then the desired state _must_ have occurred */
  528. + inp_state->enabled = false;
  529. + irq_set_irq_type(inp_state->irq, IRQF_TRIGGER_NONE);
  530. + if (gf->debug)
  531. + dev_info(gf->dev, "GF_IN %d->%d -> %s\n",
  532. + inp_state->index, inp_state->value, target->name);
  533. + gpio_fsm_go_to_state(gf, target);
  534. + return IRQ_HANDLED;
  535. +}
  536. +
  537. +static void gpio_fsm_timer(struct timer_list *timer)
  538. +{
  539. + struct gpio_fsm *gf = container_of(timer, struct gpio_fsm, timer);
  540. + struct fsm_state *target;
  541. +
  542. + target = gf->delay_target_state;
  543. + if (!target)
  544. + return;
  545. +
  546. + if (gf->debug)
  547. + dev_info(gf->dev, "GF_DELAY %d -> %s\n", gf->delay_ms,
  548. + target->name);
  549. +
  550. + gpio_fsm_go_to_state(gf, target);
  551. +}
  552. +
  553. +int gpio_fsm_parse_signals(struct gpio_fsm *gf, struct fsm_state *state,
  554. + struct property *prop)
  555. +{
  556. + const __be32 *cells = prop->value;
  557. + struct output_signal *signal;
  558. + u32 io;
  559. + u32 type;
  560. + u32 index;
  561. + u32 value;
  562. + int ret = 0;
  563. + int i;
  564. +
  565. + if (prop->length % 8) {
  566. + dev_err(gf->dev, "malformed set in state %s\n",
  567. + state->name);
  568. + return -EINVAL;
  569. + }
  570. +
  571. + state->num_signals = prop->length/8;
  572. + state->signals = devm_kcalloc(gf->dev, state->num_signals,
  573. + sizeof(struct output_signal),
  574. + GFP_KERNEL);
  575. + for (i = 0; i < state->num_signals; i++) {
  576. + signal = &state->signals[i];
  577. + io = be32_to_cpu(cells[0]);
  578. + type = GF_IO_TYPE(io);
  579. + index = GF_IO_INDEX(io);
  580. + value = be32_to_cpu(cells[1]);
  581. +
  582. + if (type != GF_OUT && type != GF_SOFT) {
  583. + dev_err(gf->dev,
  584. + "invalid set type %d in state %s\n",
  585. + type, state->name);
  586. + ret = -EINVAL;
  587. + break;
  588. + }
  589. + if (type == GF_OUT && index >= gf->num_output_gpios) {
  590. + dev_err(gf->dev,
  591. + "invalid GF_OUT number %d in state %s\n",
  592. + index, state->name);
  593. + ret = -EINVAL;
  594. + break;
  595. + }
  596. + if (type == GF_SOFT && index >= gf->num_soft_gpios) {
  597. + dev_err(gf->dev,
  598. + "invalid GF_SOFT number %d in state %s\n",
  599. + index, state->name);
  600. + ret = -EINVAL;
  601. + break;
  602. + }
  603. + if (value != 0 && value != 1) {
  604. + dev_err(gf->dev,
  605. + "invalid set value %d in state %s\n",
  606. + value, state->name);
  607. + ret = -EINVAL;
  608. + break;
  609. + }
  610. + signal->type = (type == GF_OUT) ? SIGNAL_GPIO : SIGNAL_SOFT;
  611. + signal->index = index;
  612. + signal->value = value;
  613. + cells += 2;
  614. + }
  615. +
  616. + return ret;
  617. +}
  618. +
  619. +struct gpio_event *new_event(struct gpio_event **events, int *num_events)
  620. +{
  621. + int num = ++(*num_events);
  622. + *events = krealloc(*events, num * sizeof(struct gpio_event),
  623. + GFP_KERNEL);
  624. + return *events ? *events + (num - 1) : NULL;
  625. +}
  626. +
  627. +int gpio_fsm_parse_events(struct gpio_fsm *gf, struct fsm_state *state,
  628. + struct property *prop)
  629. +{
  630. + const __be32 *cells = prop->value;
  631. + struct symtab_entry *sym;
  632. + int num_cells;
  633. + int ret = 0;
  634. + int i;
  635. +
  636. + if (prop->length % 8) {
  637. + dev_err(gf->dev,
  638. + "malformed transitions from state %s to state %s\n",
  639. + state->name, prop->name);
  640. + return -EINVAL;
  641. + }
  642. +
  643. + sym = get_symbol(&gf->symtab, prop->name);
  644. + num_cells = prop->length / 4;
  645. + i = 0;
  646. + while (i < num_cells) {
  647. + struct gpio_event *gp_ev;
  648. + u32 event, param;
  649. + u32 index;
  650. +
  651. + event = be32_to_cpu(cells[i++]);
  652. + param = be32_to_cpu(cells[i++]);
  653. + index = GF_IO_INDEX(event);
  654. +
  655. + switch (GF_IO_TYPE(event)) {
  656. + case GF_IN:
  657. + if (index >= gf->num_input_gpios) {
  658. + dev_err(gf->dev,
  659. + "invalid GF_IN %d in transitions from state %s to state %s\n",
  660. + index, state->name, prop->name);
  661. + return -EINVAL;
  662. + }
  663. + if (param > 1) {
  664. + dev_err(gf->dev,
  665. + "invalid GF_IN value %d in transitions from state %s to state %s\n",
  666. + param, state->name, prop->name);
  667. + return -EINVAL;
  668. + }
  669. + gp_ev = new_event(&state->gpio_events,
  670. + &state->num_gpio_events);
  671. + if (!gp_ev)
  672. + return -ENOMEM;
  673. + gp_ev->index = index;
  674. + gp_ev->value = param;
  675. + gp_ev->target = (struct fsm_state *)sym;
  676. + break;
  677. +
  678. + case GF_SOFT:
  679. + if (index >= gf->num_soft_gpios) {
  680. + dev_err(gf->dev,
  681. + "invalid GF_SOFT %d in transitions from state %s to state %s\n",
  682. + index, state->name, prop->name);
  683. + return -EINVAL;
  684. + }
  685. + if (param > 1) {
  686. + dev_err(gf->dev,
  687. + "invalid GF_SOFT value %d in transitions from state %s to state %s\n",
  688. + param, state->name, prop->name);
  689. + return -EINVAL;
  690. + }
  691. + gp_ev = new_event(&state->soft_events,
  692. + &state->num_soft_events);
  693. + if (!gp_ev)
  694. + return -ENOMEM;
  695. + gp_ev->index = index;
  696. + gp_ev->value = param;
  697. + gp_ev->target = (struct fsm_state *)sym;
  698. + break;
  699. +
  700. + case GF_DELAY:
  701. + if (state->delay_target) {
  702. + dev_err(gf->dev,
  703. + "state %s has multiple GF_DELAYs\n",
  704. + state->name);
  705. + return -EINVAL;
  706. + }
  707. + state->delay_target = (struct fsm_state *)sym;
  708. + state->delay_ms = param;
  709. + break;
  710. +
  711. + case GF_SHUTDOWN:
  712. + if (state->shutdown_target == state) {
  713. + dev_err(gf->dev,
  714. + "shutdown state %s has GF_SHUTDOWN\n",
  715. + state->name);
  716. + return -EINVAL;
  717. + } else if (state->shutdown_target) {
  718. + dev_err(gf->dev,
  719. + "state %s has multiple GF_SHUTDOWNs\n",
  720. + state->name);
  721. + return -EINVAL;
  722. + }
  723. + state->shutdown_target =
  724. + (struct fsm_state *)sym;
  725. + state->shutdown_ms = param;
  726. + break;
  727. +
  728. + default:
  729. + dev_err(gf->dev,
  730. + "invalid event %08x in transitions from state %s to state %s\n",
  731. + event, state->name, prop->name);
  732. + return -EINVAL;
  733. + }
  734. + }
  735. + if (i != num_cells) {
  736. + dev_err(gf->dev,
  737. + "malformed transitions from state %s to state %s\n",
  738. + state->name, prop->name);
  739. + return -EINVAL;
  740. + }
  741. +
  742. + return ret;
  743. +}
  744. +
  745. +int gpio_fsm_parse_state(struct gpio_fsm *gf,
  746. + struct fsm_state *state,
  747. + struct device_node *np)
  748. +{
  749. + struct symtab_entry *sym;
  750. + struct property *prop;
  751. + int ret;
  752. +
  753. + state->name = np->name;
  754. + ret = add_symbol(&gf->symtab, np->name, state);
  755. + if (ret) {
  756. + switch (ret) {
  757. + case -EINVAL:
  758. + dev_err(gf->dev, "'%s' is not a valid state name\n",
  759. + np->name);
  760. + break;
  761. + case -EEXIST:
  762. + dev_err(gf->dev, "state %s already defined\n",
  763. + np->name);
  764. + break;
  765. + default:
  766. + dev_err(gf->dev, "error %d adding state %s symbol\n",
  767. + ret, np->name);
  768. + break;
  769. + }
  770. + return ret;
  771. + }
  772. +
  773. + for_each_property_of_node(np, prop) {
  774. + sym = get_symbol(&gf->symtab, prop->name);
  775. + if (!sym) {
  776. + ret = -ENOMEM;
  777. + break;
  778. + }
  779. +
  780. + switch ((uintptr_t)sym->value) {
  781. + case SYM_SET:
  782. + ret = gpio_fsm_parse_signals(gf, state, prop);
  783. + break;
  784. + case SYM_START:
  785. + if (gf->start_state) {
  786. + dev_err(gf->dev, "multiple start states\n");
  787. + ret = -EINVAL;
  788. + } else {
  789. + gf->start_state = state;
  790. + }
  791. + break;
  792. + case SYM_SHUTDOWN:
  793. + state->shutdown_target = state;
  794. + gf->shutdown_state = state;
  795. + break;
  796. + case SYM_NAME:
  797. + /* Ignore */
  798. + break;
  799. + default:
  800. + /* A set of transition events to this state */
  801. + ret = gpio_fsm_parse_events(gf, state, prop);
  802. + break;
  803. + }
  804. + }
  805. +
  806. + return ret;
  807. +}
  808. +
  809. +static void dump_all(struct gpio_fsm *gf)
  810. +{
  811. + int i, j;
  812. +
  813. + dev_info(gf->dev, "Input GPIOs:\n");
  814. + for (i = 0; i < gf->num_input_gpios; i++)
  815. + dev_info(gf->dev, " %d: %p\n", i,
  816. + gf->input_gpios->desc[i]);
  817. +
  818. + dev_info(gf->dev, "Output GPIOs:\n");
  819. + for (i = 0; i < gf->num_output_gpios; i++)
  820. + dev_info(gf->dev, " %d: %p\n", i,
  821. + gf->output_gpios->desc[i]);
  822. +
  823. + dev_info(gf->dev, "Soft GPIOs:\n");
  824. + for (i = 0; i < gf->num_soft_gpios; i++)
  825. + dev_info(gf->dev, " %d: %s %d\n", i,
  826. + (gf->soft_gpios[i].dir == GPIOF_DIR_IN) ? "IN" : "OUT",
  827. + gf->soft_gpios[i].value);
  828. +
  829. + dev_info(gf->dev, "Start state: %s\n",
  830. + gf->start_state ? gf->start_state->name : "-");
  831. +
  832. + dev_info(gf->dev, "Shutdown timeout: %d ms\n",
  833. + gf->shutdown_timeout_ms);
  834. +
  835. + for (i = 0; i < gf->num_states; i++) {
  836. + struct fsm_state *state = &gf->states[i];
  837. +
  838. + dev_info(gf->dev, "State %s:\n", state->name);
  839. +
  840. + if (state->shutdown_target == state)
  841. + dev_info(gf->dev, " Shutdown state\n");
  842. +
  843. + dev_info(gf->dev, " Signals:\n");
  844. + for (j = 0; j < state->num_signals; j++) {
  845. + struct output_signal *signal = &state->signals[j];
  846. +
  847. + dev_info(gf->dev, " %d: %s %d=%d\n", j,
  848. + (signal->type == SIGNAL_GPIO) ? "GPIO" :
  849. + "SOFT",
  850. + signal->index, signal->value);
  851. + }
  852. +
  853. + dev_info(gf->dev, " GPIO events:\n");
  854. + for (j = 0; j < state->num_gpio_events; j++) {
  855. + struct gpio_event *event = &state->gpio_events[j];
  856. +
  857. + dev_info(gf->dev, " %d: %d=%d -> %s\n", j,
  858. + event->index, event->value,
  859. + event->target->name);
  860. + }
  861. +
  862. + dev_info(gf->dev, " Soft events:\n");
  863. + for (j = 0; j < state->num_soft_events; j++) {
  864. + struct gpio_event *event = &state->soft_events[j];
  865. +
  866. + dev_info(gf->dev, " %d: %d=%d -> %s\n", j,
  867. + event->index, event->value,
  868. + event->target->name);
  869. + }
  870. +
  871. + if (state->delay_target)
  872. + dev_info(gf->dev, " Delay: %d ms -> %s\n",
  873. + state->delay_ms, state->delay_target->name);
  874. +
  875. + if (state->shutdown_target && state->shutdown_target != state)
  876. + dev_info(gf->dev, " Shutdown: %d ms -> %s\n",
  877. + state->shutdown_ms,
  878. + state->shutdown_target->name);
  879. + }
  880. + dev_info(gf->dev, "\n");
  881. +}
  882. +
  883. +static int resolve_sym_to_state(struct gpio_fsm *gf, struct fsm_state **pstate)
  884. +{
  885. + struct symtab_entry *sym = (struct symtab_entry *)*pstate;
  886. +
  887. + if (!sym)
  888. + return -ENOMEM;
  889. +
  890. + *pstate = sym->value;
  891. +
  892. + if (!*pstate) {
  893. + dev_err(gf->dev, "state %s not defined\n",
  894. + sym->name);
  895. + return -EINVAL;
  896. + }
  897. +
  898. + return 0;
  899. +}
  900. +
  901. +static int gpio_fsm_probe(struct platform_device *pdev)
  902. +{
  903. + struct input_gpio_state *inp_state;
  904. + struct device *dev = &pdev->dev;
  905. + struct device_node *np = dev->of_node;
  906. + struct device_node *cp;
  907. + struct gpio_fsm *gf;
  908. + u32 debug = 0;
  909. + int num_states;
  910. + u32 num_soft_gpios;
  911. + int ret;
  912. + int i;
  913. + static const char *const reserved_symbols[] = {
  914. + [SYM_NAME] = "name",
  915. + [SYM_SET] = "set",
  916. + [SYM_START] = "start_state",
  917. + [SYM_SHUTDOWN] = "shutdown_state",
  918. + };
  919. +
  920. + if (of_property_read_u32(np, "num-soft-gpios", &num_soft_gpios)) {
  921. + dev_err(dev, "missing 'num-soft-gpios' property\n");
  922. + return -EINVAL;
  923. + }
  924. +
  925. + of_property_read_u32(np, "debug", &debug);
  926. +
  927. + gf = devm_kzalloc(dev, sizeof(*gf), GFP_KERNEL);
  928. + if (!gf)
  929. + return -ENOMEM;
  930. +
  931. + gf->dev = dev;
  932. + gf->debug = debug;
  933. +
  934. + if (of_property_read_u32(np, "shutdown-timeout-ms",
  935. + &gf->shutdown_timeout_ms))
  936. + gf->shutdown_timeout_ms = 5000;
  937. +
  938. + gf->num_soft_gpios = num_soft_gpios;
  939. + gf->soft_gpios = devm_kcalloc(dev, num_soft_gpios,
  940. + sizeof(struct soft_gpio), GFP_KERNEL);
  941. + if (!gf->soft_gpios)
  942. + return -ENOMEM;
  943. + for (i = 0; i < num_soft_gpios; i++) {
  944. + struct soft_gpio *sg = &gf->soft_gpios[i];
  945. +
  946. + sg->dir = GPIOF_DIR_IN;
  947. + sg->value = 0;
  948. + }
  949. +
  950. + gf->input_gpios = devm_gpiod_get_array_optional(dev, "input", GPIOD_IN);
  951. + if (IS_ERR(gf->input_gpios)) {
  952. + ret = PTR_ERR(gf->input_gpios);
  953. + dev_err(dev, "failed to get input gpios from DT - %d\n", ret);
  954. + return ret;
  955. + }
  956. + gf->num_input_gpios = (gf->input_gpios ? gf->input_gpios->ndescs : 0);
  957. +
  958. + gf->input_gpio_states = devm_kcalloc(dev, gf->num_input_gpios,
  959. + sizeof(struct input_gpio_state),
  960. + GFP_KERNEL);
  961. + if (!gf->input_gpio_states)
  962. + return -ENOMEM;
  963. + for (i = 0; i < gf->num_input_gpios; i++) {
  964. + inp_state = &gf->input_gpio_states[i];
  965. + inp_state->desc = gf->input_gpios->desc[i];
  966. + inp_state->gf = gf;
  967. + inp_state->index = i;
  968. + inp_state->irq = gpiod_to_irq(inp_state->desc);
  969. + inp_state->active_low = gpiod_is_active_low(inp_state->desc);
  970. + if (inp_state->irq >= 0)
  971. + ret = devm_request_irq(gf->dev, inp_state->irq,
  972. + gpio_fsm_gpio_irq_handler,
  973. + IRQF_TRIGGER_NONE,
  974. + dev_name(dev),
  975. + inp_state);
  976. + else
  977. + ret = inp_state->irq;
  978. +
  979. + if (ret) {
  980. + dev_err(dev,
  981. + "failed to get IRQ for input gpio - %d\n",
  982. + ret);
  983. + return ret;
  984. + }
  985. + }
  986. +
  987. + gf->output_gpios = devm_gpiod_get_array_optional(dev, "output",
  988. + GPIOD_OUT_LOW);
  989. + if (IS_ERR(gf->output_gpios)) {
  990. + ret = PTR_ERR(gf->output_gpios);
  991. + dev_err(dev, "failed to get output gpios from DT - %d\n", ret);
  992. + return ret;
  993. + }
  994. + gf->num_output_gpios = (gf->output_gpios ? gf->output_gpios->ndescs :
  995. + 0);
  996. +
  997. + num_states = of_get_child_count(np);
  998. + if (!num_states) {
  999. + dev_err(dev, "no states declared\n");
  1000. + return -EINVAL;
  1001. + }
  1002. + gf->states = devm_kcalloc(dev, num_states,
  1003. + sizeof(struct fsm_state), GFP_KERNEL);
  1004. + if (!gf->states)
  1005. + return -ENOMEM;
  1006. +
  1007. + // add reserved words to the symbol table
  1008. + for (i = 0; i < ARRAY_SIZE(reserved_symbols); i++) {
  1009. + if (reserved_symbols[i])
  1010. + add_symbol(&gf->symtab, reserved_symbols[i], (void *)i);
  1011. + }
  1012. +
  1013. + // parse the state
  1014. + for_each_child_of_node(np, cp) {
  1015. + struct fsm_state *state = &gf->states[gf->num_states];
  1016. +
  1017. + ret = gpio_fsm_parse_state(gf, state, cp);
  1018. + if (ret)
  1019. + return ret;
  1020. + gf->num_states++;
  1021. + }
  1022. +
  1023. + if (!gf->start_state) {
  1024. + dev_err(gf->dev, "no start state defined\n");
  1025. + return -EINVAL;
  1026. + }
  1027. +
  1028. + // resolve symbol pointers into state pointers
  1029. + for (i = 0; !ret && i < gf->num_states; i++) {
  1030. + struct fsm_state *state = &gf->states[i];
  1031. + int j;
  1032. +
  1033. + for (j = 0; !ret && j < state->num_gpio_events; j++) {
  1034. + struct gpio_event *ev = &state->gpio_events[j];
  1035. +
  1036. + ret = resolve_sym_to_state(gf, &ev->target);
  1037. + }
  1038. +
  1039. + for (j = 0; !ret && j < state->num_soft_events; j++) {
  1040. + struct gpio_event *ev = &state->soft_events[j];
  1041. +
  1042. + ret = resolve_sym_to_state(gf, &ev->target);
  1043. + }
  1044. +
  1045. + if (!ret) {
  1046. + resolve_sym_to_state(gf, &state->delay_target);
  1047. + if (state->shutdown_target != state)
  1048. + resolve_sym_to_state(gf,
  1049. + &state->shutdown_target);
  1050. + }
  1051. + }
  1052. +
  1053. + if (!ret && gf->debug > 1)
  1054. + dump_all(gf);
  1055. +
  1056. + free_symbols(&gf->symtab);
  1057. +
  1058. + if (ret)
  1059. + return ret;
  1060. +
  1061. + gf->gc.parent = dev;
  1062. + gf->gc.label = np->name;
  1063. + gf->gc.owner = THIS_MODULE;
  1064. + gf->gc.of_node = np;
  1065. + gf->gc.base = -1;
  1066. + gf->gc.ngpio = num_soft_gpios;
  1067. +
  1068. + gf->gc.get_direction = gpio_fsm_get_direction;
  1069. + gf->gc.direction_input = gpio_fsm_direction_input;
  1070. + gf->gc.direction_output = gpio_fsm_direction_output;
  1071. + gf->gc.get = gpio_fsm_get;
  1072. + gf->gc.set = gpio_fsm_set;
  1073. + gf->gc.can_sleep = true;
  1074. + spin_lock_init(&gf->spinlock);
  1075. + INIT_WORK(&gf->work, gpio_fsm_work);
  1076. + timer_setup(&gf->timer, gpio_fsm_timer, 0);
  1077. + init_waitqueue_head(&gf->shutdown_event);
  1078. +
  1079. + platform_set_drvdata(pdev, gf);
  1080. +
  1081. + if (gf->debug)
  1082. + dev_info(gf->dev, "Start -> %s\n", gf->start_state->name);
  1083. +
  1084. + gpio_fsm_go_to_state(gf, gf->start_state);
  1085. +
  1086. + return devm_gpiochip_add_data(dev, &gf->gc, gf);
  1087. +}
  1088. +
  1089. +static int gpio_fsm_remove(struct platform_device *pdev)
  1090. +{
  1091. + struct gpio_fsm *gf = platform_get_drvdata(pdev);
  1092. + int i;
  1093. +
  1094. + if (gf->shutdown_state) {
  1095. + if (gf->debug)
  1096. + dev_info(gf->dev, "Shutting down...\n");
  1097. +
  1098. + spin_lock(&gf->spinlock);
  1099. + gf->shutting_down = true;
  1100. + if (gf->current_state->shutdown_target &&
  1101. + gf->current_state->shutdown_target != gf->current_state) {
  1102. + gf->delay_target_state =
  1103. + gf->current_state->shutdown_target;
  1104. + mod_timer(&gf->timer, gf->shutdown_jiffies);
  1105. + }
  1106. + spin_unlock(&gf->spinlock);
  1107. +
  1108. + wait_event_timeout(gf->shutdown_event,
  1109. + gf->current_state->shutdown_target ==
  1110. + gf->current_state,
  1111. + msecs_to_jiffies(gf->shutdown_timeout_ms));
  1112. + if (gf->current_state->shutdown_target == gf->current_state)
  1113. + gpio_fsm_enter_state(gf, gf->shutdown_state);
  1114. + }
  1115. + cancel_work_sync(&gf->work);
  1116. + del_timer_sync(&gf->timer);
  1117. +
  1118. + /* Events aren't allocated from managed storage */
  1119. + for (i = 0; i < gf->num_states; i++) {
  1120. + kfree(gf->states[i].gpio_events);
  1121. + kfree(gf->states[i].soft_events);
  1122. + }
  1123. + if (gf->debug)
  1124. + dev_info(gf->dev, "Exiting\n");
  1125. +
  1126. + return 0;
  1127. +}
  1128. +
  1129. +static void gpio_fsm_shutdown(struct platform_device *pdev)
  1130. +{
  1131. + gpio_fsm_remove(pdev);
  1132. +}
  1133. +
  1134. +static const struct of_device_id gpio_fsm_ids[] = {
  1135. + { .compatible = "rpi,gpio-fsm" },
  1136. + { }
  1137. +};
  1138. +MODULE_DEVICE_TABLE(of, gpio_fsm_ids);
  1139. +
  1140. +static struct platform_driver gpio_fsm_driver = {
  1141. + .driver = {
  1142. + .name = MODULE_NAME,
  1143. + .of_match_table = of_match_ptr(gpio_fsm_ids),
  1144. + },
  1145. + .probe = gpio_fsm_probe,
  1146. + .remove = gpio_fsm_remove,
  1147. + .shutdown = gpio_fsm_shutdown,
  1148. +};
  1149. +module_platform_driver(gpio_fsm_driver);
  1150. +
  1151. +MODULE_LICENSE("GPL");
  1152. +MODULE_AUTHOR("Phil Elwell <[email protected]>");
  1153. +MODULE_DESCRIPTION("GPIO FSM driver");
  1154. +MODULE_ALIAS("platform:gpio-fsm");
  1155. --- /dev/null
  1156. +++ b/include/dt-bindings/gpio/gpio-fsm.h
  1157. @@ -0,0 +1,21 @@
  1158. +/* SPDX-License-Identifier: GPL-2.0+ */
  1159. +/*
  1160. + * This header provides constants for binding rpi,gpio-fsm.
  1161. + */
  1162. +
  1163. +#ifndef _DT_BINDINGS_GPIO_FSM_H
  1164. +#define _DT_BINDINGS_GPIO_FSM_H
  1165. +
  1166. +#define GF_IN 0
  1167. +#define GF_OUT 1
  1168. +#define GF_SOFT 2
  1169. +#define GF_DELAY 3
  1170. +#define GF_SHUTDOWN 4
  1171. +
  1172. +#define GF_IO(t, v) (((v) << 16) | ((t) & 0xffff))
  1173. +
  1174. +#define GF_IP(x) GF_IO(GF_IN, (x))
  1175. +#define GF_OP(x) GF_IO(GF_OUT, (x))
  1176. +#define GF_SW(x) GF_IO(GF_SOFT, (x))
  1177. +
  1178. +#endif