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