1 /* SPDX-License-Identifier: GPL-2.0+ */
2 /*
3 * Copyright (c) 2015 Google, Inc
4 * Written by Simon Glass <sjg@chromium.org>
5 */
6
7 #ifndef __LED_H
8 #define __LED_H
9
10 #include <stdbool.h>
11 #include <cyclic.h>
12 #include <dm/ofnode.h>
13
14 /**
15 * DOC: Overview
16 *
17 * Generic LED API provided when a supported compatible is defined in DeviceTree.
18 *
19 * To enable support for LEDs, enable the `CONFIG_LED` Kconfig option.
20 *
21 * The most common implementation is for GPIO-connected LEDs. If using GPIO-connected LEDs,
22 * enable the `LED_GPIO` Kconfig option.
23 *
24 * `LED_BLINK` support requires LED driver support and is therefore optional. If LED blink
25 * functionality is needed, enable the `LED_BLINK` Kconfig option. If LED driver doesn't
26 * support HW Blink, SW Blink can be used with the Cyclic framework by enabling the
27 * CONFIG_LED_SW_BLINK.
28 *
29 * Boot and Activity LEDs are also supported. These LEDs can signal various system operations
30 * during runtime, such as boot initialization, file transfers, and flash write/erase operations.
31 *
32 * To enable a Boot LED, enable `CONFIG_LED_BOOT` and define in `/options/u-boot` root node the
33 * property `boot-led`. This will enable the specified LED to blink and turn ON when
34 * the bootloader initializes correctly.
35 *
36 * To enable an Activity LED, enable `CONFIG_LED_ACTIVITY` and define in `/options/u-boot` root
37 * node the property `activity-led`.
38 * This will enable the specified LED to blink and turn ON during file transfers or flash
39 * write/erase operations.
40 *
41 * Both Boot and Activity LEDs provide a simple API to turn the LED ON or OFF:
42 * `led_boot_on()`, `led_boot_off()`, `led_activity_on()`, and `led_activity_off()`.
43 *
44 * Both configurations can optionally define a `boot/activity-led-period` property
45 * if `CONFIG_LED_BLINK` or `CONFIG_LED_SW_BLINK` is enabled for LED blink operations, which
46 * is usually used by the Activity LED. If not defined the default value of 250 (ms) is used.
47 *
48 * When `CONFIG_LED_BLINK` or `CONFIG_LED_SW_BLINK` is enabled, additional APIs are exposed:
49 * `led_boot_blink()` and `led_activity_blink()`. Note that if `CONFIG_LED_BLINK` or
50 * `CONFIG_LED_SW_BLINK` is disabled, these APIs will behave like the `led_boot_on()` and
51 * `led_activity_on()` APIs, respectively.
52 */
53
54 struct udevice;
55
56 /*
57 * value imported from linux:include/linux/uapi/linux/uleds.h
58 */
59 #define LED_MAX_NAME_SIZE 64
60
61 enum led_state_t {
62 LEDST_OFF = 0,
63 LEDST_ON = 1,
64 LEDST_TOGGLE,
65 LEDST_BLINK,
66
67 LEDST_COUNT,
68 };
69
70 enum led_sw_blink_state_t {
71 LED_SW_BLINK_ST_DISABLED,
72 LED_SW_BLINK_ST_NOT_READY,
73 LED_SW_BLINK_ST_OFF,
74 LED_SW_BLINK_ST_ON,
75 };
76
77 struct led_sw_blink {
78 enum led_sw_blink_state_t state;
79 struct udevice *dev;
80 struct cyclic_info cyclic;
81 const char cyclic_name[0];
82 };
83
84 /**
85 * struct led_uc_plat - Platform data the uclass stores about each device
86 *
87 * @label: LED label
88 * @default_state: LED default state
89 * @name: LED name, derived from function, color or function-enumerator
90 * property.
91 * @sw_blink: LED software blink struct
92 */
93 struct led_uc_plat {
94 const char *label;
95 enum led_state_t default_state;
96 char name[LED_MAX_NAME_SIZE];
97 #ifdef CONFIG_LED_SW_BLINK
98 struct led_sw_blink *sw_blink;
99 #endif
100 };
101
102 /**
103 * struct led_uc_priv - Private data the uclass stores about each device
104 *
105 * @boot_led_label: Boot LED label
106 * @activity_led_label: Activity LED label
107 * @boot_led_dev: Boot LED dev
108 * @activity_led_dev: Activity LED dev
109 * @boot_led_period: Boot LED blink period
110 * @activity_led_period: Activity LED blink period
111 */
112 struct led_uc_priv {
113 #ifdef CONFIG_LED_BOOT
114 const char *boot_led_label;
115 int boot_led_period;
116 #endif
117 #ifdef CONFIG_LED_ACTIVITY
118 const char *activity_led_label;
119 int activity_led_period;
120 #endif
121 };
122
123 struct led_ops {
124 /**
125 * set_state() - set the state of an LED
126 *
127 * @dev: LED device to change
128 * @state: LED state to set
129 * @return 0 if OK, -ve on error
130 */
131 int (*set_state)(struct udevice *dev, enum led_state_t state);
132
133 /**
134 * led_get_state() - get the state of an LED
135 *
136 * @dev: LED device to change
137 * @return LED state led_state_t, or -ve on error
138 */
139 enum led_state_t (*get_state)(struct udevice *dev);
140
141 #ifdef CONFIG_LED_BLINK
142 /**
143 * led_set_period() - set the blink period of an LED
144 *
145 * Thie records the period if supported, or returns -ENOSYS if not.
146 * To start the LED blinking, use set_state().
147 *
148 * @dev: LED device to change
149 * @period_ms: LED blink period in milliseconds
150 * @return 0 if OK, -ve on error
151 */
152 int (*set_period)(struct udevice *dev, int period_ms);
153 #endif
154 };
155
156 #define led_get_ops(dev) ((struct led_ops *)(dev)->driver->ops)
157
158 /**
159 * led_get_by_label() - Find an LED device by label
160 *
161 * @label: LED label to look up
162 * @devp: Returns the associated device, if found
163 * Return: 0 if found, -ENODEV if not found, other -ve on error
164 */
165 int led_get_by_label(const char *label, struct udevice **devp);
166
167 /**
168 * led_set_state() - set the state of an LED
169 *
170 * @dev: LED device to change
171 * @state: LED state to set
172 * Return: 0 if OK, -ve on error
173 */
174 int led_set_state(struct udevice *dev, enum led_state_t state);
175
176 /**
177 * led_get_state() - get the state of an LED
178 *
179 * @dev: LED device to change
180 * Return: LED state led_state_t, or -ve on error
181 */
182 enum led_state_t led_get_state(struct udevice *dev);
183
184 /**
185 * led_set_period() - set the blink period of an LED
186 *
187 * @dev: LED device to change
188 * @period_ms: LED blink period in milliseconds
189 * Return: 0 if OK, -ve on error
190 */
191 int led_set_period(struct udevice *dev, int period_ms);
192
193 /**
194 * led_bind_generic() - bind children of parent to given driver
195 *
196 * @parent: Top-level LED device
197 * @driver_name: Driver for handling individual child nodes
198 */
199 int led_bind_generic(struct udevice *parent, const char *driver_name);
200
201 /* Internal functions for software blinking. Do not use them in your code */
202 int led_sw_set_period(struct udevice *dev, int period_ms);
203 bool led_sw_is_blinking(struct udevice *dev);
204 bool led_sw_on_state_change(struct udevice *dev, enum led_state_t state);
205
206 #ifdef CONFIG_LED_BOOT
207
208 /**
209 * led_boot_on() - turn ON the designated LED for booting
210 *
211 * Return: 0 if OK, -ve on error
212 */
213 int led_boot_on(void);
214
215 /**
216 * led_boot_off() - turn OFF the designated LED for booting
217 *
218 * Return: 0 if OK, -ve on error
219 */
220 int led_boot_off(void);
221
222 #if defined(CONFIG_LED_BLINK) || defined(CONFIG_LED_SW_BLINK)
223 /**
224 * led_boot_blink() - turn ON the designated LED for booting
225 *
226 * Return: 0 if OK, -ve on error
227 */
228 int led_boot_blink(void);
229
230 #else
231 /* If LED BLINK is not supported/enabled, fallback to LED ON */
232 #define led_boot_blink led_boot_on
233 #endif
234 #else
led_boot_on(void)235 static inline int led_boot_on(void)
236 {
237 return -ENOSYS;
238 }
239
led_boot_off(void)240 static inline int led_boot_off(void)
241 {
242 return -ENOSYS;
243 }
244
led_boot_blink(void)245 static inline int led_boot_blink(void)
246 {
247 return -ENOSYS;
248 }
249 #endif
250
251 #ifdef CONFIG_LED_ACTIVITY
252
253 /**
254 * led_activity_on() - turn ON the designated LED for activity
255 *
256 * Return: 0 if OK, -ve on error
257 */
258 int led_activity_on(void);
259
260 /**
261 * led_activity_off() - turn OFF the designated LED for activity
262 *
263 * Return: 0 if OK, -ve on error
264 */
265 int led_activity_off(void);
266
267 #if defined(CONFIG_LED_BLINK) || defined(CONFIG_LED_SW_BLINK)
268 /**
269 * led_activity_blink() - turn ON the designated LED for activity
270 *
271 * Return: 0 if OK, -ve on error
272 */
273 int led_activity_blink(void);
274 #else
275 /* If LED BLINK is not supported/enabled, fallback to LED ON */
276 #define led_activity_blink led_activity_on
277 #endif
278 #else
led_activity_on(void)279 static inline int led_activity_on(void)
280 {
281 return -ENOSYS;
282 }
283
led_activity_off(void)284 static inline int led_activity_off(void)
285 {
286 return -ENOSYS;
287 }
288
led_activity_blink(void)289 static inline int led_activity_blink(void)
290 {
291 return -ENOSYS;
292 }
293 #endif
294
295 #endif
296