blob: d5043ec4f4ca552458093c0b2e112882c8e826ac [file] [log] [blame]
Simon Glassabe5d112022-03-04 08:43:08 -07001.. SPDX-License-Identifier: GPL-2.0+
2
3Events
4======
5
6U-Boot supports a way for various events to be handled by interested
7subsystems. This provide a generic way to handle 'hooks' like setting up the
8CPUs after driver model is active, or reading a partition table after a new
9block device is probed.
10
11Rather than using weak functions and direct calls across subsystemss, it is
12often easier to use an event.
13
Simon Glass55171ae2023-05-04 16:50:45 -060014An event consists of a type (e.g. EVT_DM_POST_INIT_F) and some optional data,
Hugo Villeneuveed356ac2023-04-25 09:46:45 -040015in `union event_data`. An event spy can be created to watch for events of a
Simon Glassabe5d112022-03-04 08:43:08 -070016particular type. When the event is created, it is sent to each spy in turn.
17
18
19Declaring a spy
20---------------
21
22To declare a spy, use something like this::
23
Simon Glass12be60d2023-08-21 21:16:58 -060024 static int snow_check_temperature(void)
Simon Glassabe5d112022-03-04 08:43:08 -070025 {
26 /* do something */
27 return 0;
28 }
Simon Glass12be60d2023-08-21 21:16:58 -060029 EVENT_SPY_SIMPLE(EVT_DM_POST_INIT_F, snow_check_temperature);
Simon Glassabe5d112022-03-04 08:43:08 -070030
Bin Meng268d25f2023-06-12 14:12:13 +080031This function is called when EVT_DM_POST_INIT_F is emitted, i.e. after the
32driver model is initialized (in U-Boot proper before and after relocation).
Simon Glassabe5d112022-03-04 08:43:08 -070033
Simon Glass12be60d2023-08-21 21:16:58 -060034If you need access to the event data, use `EVENT_SPY_FULL`, like this::
35
36 static int snow_setup_cpus(void *ctx, struct event *event)
37 {
38 /* do something that uses event->data*/
39 return 0;
40 }
41 EVENT_SPY_FULL(EVT_DM_POST_INIT_F, snow_setup_cpus);
42
43Note that the context is always NULL for a static spy. See below for information
44about how to use a dynamic spy.
45
46The return value is handled by the event emitter. If non-zero, then the error
47is returned to the function which emitted the event, i.e. the one that called
48`event_notify()`.
Simon Glassabe5d112022-03-04 08:43:08 -070049
50Debugging
51---------
52
53To assist with debugging events, enable `CONFIG_EVENT_DEBUG` and
Tom Rini01f1ab62022-04-04 10:45:33 -040054`CONFIG_CMD_EVENT`. The :doc:`../usage/cmd/event` command can then be used to
Simon Glassabe5d112022-03-04 08:43:08 -070055provide a spy list.
56
57It is also possible to list spy information from the U-Boot executable,, using
58the `event_dump.py` script::
59
60 $ scripts/event_dump.py /tmp/b/sandbox/u-boot
61 Event type Id Source location
62 -------------------- ------------------------------ ------------------------------
63 EVT_MISC_INIT_F f:sandbox_misc_init_f arch/sandbox/cpu/start.c:125
64
65This shows each event spy in U-Boot, along with the event type, function name
66(or ID) and source location.
67
68Note that if `CONFIG_EVENT_DEBUG` is not enabled, the event ID is missing, so
69the function is shown instead (with an `f:` prefix as above). Since the ID is
70generally the same as the function name, this does not matter much.
71
72The event type is decoded by the symbol used by U-Boot for the event linker
73list. Symbols have the form::
74
75 _u_boot_list_2_evspy_info_2_EVT_MISC_INIT_F
76
77so the event type can be read from the end. To manually list spy information
78in an image, use $(CROSS_COMPILE)nm::
79
80 nm u-boot |grep evspy |grep list
81 00000000002d6300 D _u_boot_list_2_evspy_info_2_EVT_MISC_INIT_F
Simon Glassd67811a2023-01-20 14:46:05 -070082
83Logging is also available. Events use category `LOGC_EVENT`, so you can enable
84logging on that, or add `#define LOG_DEBUG` to the top of `common/event.c` to
85see events being sent.
86
87
88Dynamic events
89--------------
90
91Static events provide a way of dealing with events known at build time. In some
92cases we want to attach an event handler at runtime. For example, we may wish
93to be notified when a particular device is probed or removed.
94
95This can be handled by enabling `CONFIG_EVENT_DYNAMIC`. It is then possible to
96call `event_register()` to register a new handler for a particular event.
97
Simon Glass12be60d2023-08-21 21:16:58 -060098If some context is need for the spy, you can pass a pointer to
99`event_register()` to provide that. Note that the context is only passed to
100a spy registered with `EVENT_SPY_FULL`.
101
Simon Glassd67811a2023-01-20 14:46:05 -0700102Dynamic event handlers are called after all the static event spy handlers have
103been processed. Of course, since dynamic event handlers are created at runtime
104it is not possible to use the `event_dump.py` to see them.
105
106At present there is no way to list dynamic event handlers from the command line,
107nor to deregister a dynamic event handler. These features can be added when
108needed.