@@ -394,6 +394,12 @@ void __noreturn load_and_boot_kernel(bool is_reboot)
*/
occ_pstates_init();
+ /*
+ * LED related SPCN commands might take a while to
+ * complete. Call this as late as possible.
+ */
+ create_led_device_nodes();
+
/* Set kernel command line argument if specified */
#ifdef KERNEL_COMMAND_LINE
dt_add_property_string(dt_chosen, "bootargs", KERNEL_COMMAND_LINE);
new file mode 100644
@@ -0,0 +1,33 @@
+Service Indicators (LEDS)
+-------------------------
+
+The 'led' node under 'ibm,opal' lists service indicators available in the
+system and their capabilities.
+
+led {
+ compatible = "ibm,opal-v3-led";
+ phandle = <0x1000006b>;
+ linux,phandle = <0x1000006b>;
+
+ U78C9.001.RST0027-P1-C1 {
+ led-types = "identify", "fault";
+ led-loc = "descendent";
+ phandle = <0x1000006f>;
+ linux,phandle = <0x1000006f>;
+ };
+ ...
+ ...
+};
+
+'compatible' property describes LEDs compatibility.
+
+Each node under 'led' node describes location code of FRU/Enclosure.
+
+The properties under each node:
+
+ led-types : Supported indicators (attention/identify/fault).
+
+ led-loc : enclosure/descendent(FRU) location code.
+
+These LEDs can be accessed through OPAL_LEDS_{GET/SET}_INDICATOR interfaces.
+Refer to doc/opal-api/opal-led-get-set-114-115.txt for interface details.
@@ -24,6 +24,7 @@
#include <spcn.h>
#include <lock.h>
#include <errorlog.h>
+#include <opal-api.h>
#include "fsp-leds.h"
@@ -1048,6 +1049,65 @@ static struct fsp_client fsp_indicator_client = {
};
/*
+ * create_led_device_node
+ *
+ * Creates the system parent LED device node and all individual
+ * child LED device nodes under it. This is called right before
+ * starting the payload (Linux) to ensure that the SPCN command
+ * sequence to fetch the LED location code list has been finished
+ * and to have a better chance of creating the deviced nodes.
+ */
+void create_led_device_nodes(void)
+{
+ struct fsp_led_data *led, *next;
+ struct dt_node *pled, *cled;
+
+ if (!fsp_present())
+ return;
+
+ /* Make sure LED list read is completed */
+ while (led_support == LED_STATE_READING)
+ opal_run_pollers();
+
+ if (led_support == LED_STATE_ABSENT) {
+ prlog(PR_WARNING, PREFIX "LED support not available, \
+ hence device tree nodes will not be created\n");
+ return;
+ }
+
+ if (!opal_node) {
+ prlog(PR_WARNING, PREFIX
+ "OPAL parent device node not available\n");
+ return;
+ }
+
+ /* LED parent node */
+ pled = dt_new(opal_node, "led");
+ if (!pled) {
+ prlog(PR_WARNING, PREFIX
+ "Parent device node creation failed\n");
+ return;
+ }
+ dt_add_property_strings(pled, "compatible", "ibm,opal-v3-led");
+
+ /* LED child nodes */
+ list_for_each_safe(&cec_ledq, led, next, link) {
+ cled = dt_new(pled, led->loc_code);
+ if (!cled) {
+ prlog(PR_WARNING, PREFIX
+ "Child device node creation failed\n");
+ continue;
+ }
+
+ dt_add_property_strings(cled, "led-types", "identify", "fault");
+ if (is_enclosure_led(led->loc_code))
+ dt_add_property_strings(cled, "led-loc", "enclosure");
+ else
+ dt_add_property_strings(cled, "led-loc", "descendent");
+ }
+}
+
+/*
* Process the received LED data from SPCN
*
* Every LED state data is added into the CEC list. If the location
@@ -783,6 +783,7 @@ extern void fsp_init_diag(void);
/* LED */
extern void fsp_led_init(void);
+extern void create_led_device_nodes(void);
/* EPOW */
extern void fsp_epow_init(void);