summaryrefslogtreecommitdiff
path: root/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0016-Add-LED-control-support.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0016-Add-LED-control-support.patch')
-rw-r--r--meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0016-Add-LED-control-support.patch457
1 files changed, 457 insertions, 0 deletions
diff --git a/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0016-Add-LED-control-support.patch b/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0016-Add-LED-control-support.patch
new file mode 100644
index 000000000..774767f97
--- /dev/null
+++ b/meta-openbmc-mods/meta-ast2600/recipes-bsp/u-boot/files/0016-Add-LED-control-support.patch
@@ -0,0 +1,457 @@
+From d88bb32a5c33f356926a309289497f1b1e7c9aa1 Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Fri, 2 Apr 2021 09:48:38 -0700
+Subject: [PATCH] Add LED control support
+
+This commit adds LED control support including customization and improvement
+on led-gpio and led-uclass driver to support 'blink' mode. LEDs will behave
+like below.
+
+Normal u-boot : Green LED blinks at 1Hz + ID LED blinks at 3Hz
+FFU u-boot : Amber LED solid on + ID LED solid on
+MFG detected : Green LED blinks at 3Hz + ID LED blinks at 3Hz
+Failure Recovery : Amber LED blinks at 3Hz + ID LED solid on
+Jumping to Kernel : Green LED solid on + ID LED solid on
+
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ arch/arm/dts/ast2600-intel.dts | 4 +-
+ board/aspeed/ast2600_intel/intel.c | 66 +++++++++++++++++++++++++++++-
+ cmd/net.c | 23 +++++++++--
+ drivers/led/led-uclass.c | 37 +++++++++++++++++
+ drivers/led/led_gpio.c | 62 ++++++++++++++++++++++++++++
+ include/led.h | 42 ++++++++++++++++++-
+ 6 files changed, 226 insertions(+), 8 deletions(-)
+
+diff --git a/arch/arm/dts/ast2600-intel.dts b/arch/arm/dts/ast2600-intel.dts
+index c7970c16a474..7cae636554b6 100644
+--- a/arch/arm/dts/ast2600-intel.dts
++++ b/arch/arm/dts/ast2600-intel.dts
+@@ -58,8 +58,8 @@
+ };
+ hb-led {
+ label = "hb";
+- gpios = <&gpio0 25 GPIO_ACTIVE_LOW>;
+- linux,default-trigger = "heartbeat";
++ gpios = <&gpio0 173 GPIO_ACTIVE_LOW>;
++ default-state = "on";
+ };
+ };
+ };
+diff --git a/board/aspeed/ast2600_intel/intel.c b/board/aspeed/ast2600_intel/intel.c
+index 6e442cf01472..46f169589915 100644
+--- a/board/aspeed/ast2600_intel/intel.c
++++ b/board/aspeed/ast2600_intel/intel.c
+@@ -5,6 +5,7 @@
+ #include <common.h>
+ #include <asm/gpio.h>
+ #include <asm/io.h>
++#include <led.h>
+ #include <malloc.h>
+
+ /* use GPIOC0 on intel boards */
+@@ -26,7 +27,27 @@ int read_ffuj(void)
+ return ret;
+ ret = dm_gpio_get_value(&desc);
+ dm_gpio_free(desc.dev, &desc);
+- return ret;
++
++ if (ret) {
++ struct udevice *dev;
++
++ /* FFU mode: ChassisID - Solid Blue, StatusLED - Solid Amber */
++ ret = led_get_by_label("green", &dev);
++ if (!ret)
++ led_set_state(dev, LEDST_OFF);
++
++ ret = led_get_by_label("amber", &dev);
++ if (!ret)
++ led_set_state(dev, LEDST_ON);
++
++ ret = led_get_by_label("id", &dev);
++ if (!ret)
++ led_set_state(dev, LEDST_ON);
++
++ return 1;
++ }
++
++ return 0;
+ }
+
+ /* gpio_abort is a weak symbol in common/autoboot.c */
+@@ -264,6 +285,11 @@ static void timer_callback(void *cookie)
+ dummy = readl(0x1e78e07c);
+ dummy = readl(0x1e78f07c);
+ break;
++#ifdef CONFIG_LED_BLINK
++ case 1:
++ led_blink_update();
++ break;
++#endif
+ }
+ }
+
+@@ -286,10 +312,20 @@ int board_early_init_f(void)
+
+ int board_early_init_r(void)
+ {
++ struct udevice *dev;
++ int ret;
++
+ debug("board_early_init_r\n");
+
+ enable_onboard_tpm();
+
++ led_default_state();
++#ifdef CONFIG_LED_BLINK
++ ret = led_get_by_label("id", &dev);
++ if (!ret)
++ led_set_period(dev, 160);
++#endif
++
+ return 0;
+ }
+
+@@ -366,6 +402,11 @@ int board_late_init(void)
+ if (readl(SCU_BASE | SCU_014) == REV_ID_AST2600A0)
+ timer_enable(0, ONE_MSEC_IN_USEC, timer_callback, (void *)0);
+
++#ifdef CONFIG_LED_BLINK
++ timer_enable(1, LED_BLINK_UPDATE_TICK_MS * ONE_MSEC_IN_USEC,
++ timer_callback, (void *)1);
++#endif
++
+ espi_init();
+
+ /* Add reset reason to bootargs */
+@@ -391,6 +432,29 @@ void board_init(void)
+ }
+ */
+
++void board_preboot_os(void)
++{
++ struct udevice *dev;
++ int ret;
++
++ /*
++ * last second before OS booting
++ * ChassisID - Solid Blue, StatusLED - Solid Green
++ */
++
++ ret = led_get_by_label("green", &dev);
++ if (!ret)
++ led_set_state(dev, LEDST_ON);
++
++ ret = led_get_by_label("amber", &dev);
++ if (!ret)
++ led_set_state(dev, LEDST_OFF);
++
++ ret = led_get_by_label("id", &dev);
++ if (!ret)
++ led_set_state(dev, LEDST_ON);
++}
++
+ #ifdef CONFIG_WATCHDOG
+ /* watchdog stuff */
+ void watchdog_init(void)
+diff --git a/cmd/net.c b/cmd/net.c
+index 7d2c21ba4d22..a6b03654cdbf 100644
+--- a/cmd/net.c
++++ b/cmd/net.c
+@@ -10,6 +10,7 @@
+ #include <common.h>
+ #include <command.h>
+ #include <net.h>
++#include <led.h>
+
+ static int netboot_common(enum proto_t, cmd_tbl_t *, int, char * const []);
+
+@@ -183,6 +184,10 @@ static int netboot_common(enum proto_t proto, cmd_tbl_t *cmdtp, int argc,
+ int size;
+ ulong addr;
+
++#ifdef CONFIG_LED_BLINK
++ led_blink_disable();
++#endif
++
+ net_boot_file_name_explicit = false;
+
+ /* pre-set load_addr */
+@@ -229,7 +234,8 @@ static int netboot_common(enum proto_t proto, cmd_tbl_t *cmdtp, int argc,
+ if (strict_strtoul(argv[1], 16, &save_addr) < 0 ||
+ strict_strtoul(argv[2], 16, &save_size) < 0) {
+ printf("Invalid address/size\n");
+- return CMD_RET_USAGE;
++ rcode = CMD_RET_USAGE;
++ goto exit;
+ }
+ net_boot_file_name_explicit = true;
+ copy_filename(net_boot_file_name, argv[3],
+@@ -238,14 +244,16 @@ static int netboot_common(enum proto_t proto, cmd_tbl_t *cmdtp, int argc,
+ #endif
+ default:
+ bootstage_error(BOOTSTAGE_ID_NET_START);
+- return CMD_RET_USAGE;
++ rcode = CMD_RET_USAGE;
++ goto exit;
+ }
+ bootstage_mark(BOOTSTAGE_ID_NET_START);
+
+ size = net_loop(proto);
+ if (size < 0) {
+ bootstage_error(BOOTSTAGE_ID_NET_NETLOOP_OK);
+- return CMD_RET_FAILURE;
++ rcode = CMD_RET_FAILURE;
++ goto exit;
+ }
+ bootstage_mark(BOOTSTAGE_ID_NET_NETLOOP_OK);
+
+@@ -255,7 +263,8 @@ static int netboot_common(enum proto_t proto, cmd_tbl_t *cmdtp, int argc,
+ /* done if no file was loaded (no errors though) */
+ if (size == 0) {
+ bootstage_error(BOOTSTAGE_ID_NET_LOADED);
+- return CMD_RET_SUCCESS;
++ rcode = CMD_RET_SUCCESS;
++ goto exit;
+ }
+
+ bootstage_mark(BOOTSTAGE_ID_NET_LOADED);
+@@ -266,6 +275,12 @@ static int netboot_common(enum proto_t proto, cmd_tbl_t *cmdtp, int argc,
+ bootstage_mark(BOOTSTAGE_ID_NET_DONE);
+ else
+ bootstage_error(BOOTSTAGE_ID_NET_DONE_ERR);
++
++exit:
++#ifdef CONFIG_LED_BLINK
++ led_blink_enable();
++#endif
++
+ return rcode;
+ }
+
+diff --git a/drivers/led/led-uclass.c b/drivers/led/led-uclass.c
+index 2859475a6b8e..264e0735c815 100644
+--- a/drivers/led/led-uclass.c
++++ b/drivers/led/led-uclass.c
+@@ -62,6 +62,39 @@ int led_set_period(struct udevice *dev, int period_ms)
+
+ return ops->set_period(dev, period_ms);
+ }
++
++static bool blink_enable = true;
++
++void led_blink_enable(void)
++{
++ blink_enable = true;
++}
++
++void led_blink_disable(void)
++{
++ blink_enable = false;
++}
++
++int led_blink_update(void)
++{
++ struct udevice *dev;
++
++ if (!blink_enable)
++ return 0;
++
++ for (uclass_find_first_device(UCLASS_LED, &dev);
++ dev;
++ uclass_find_next_device(&dev)) {
++ if (device_active(dev) && led_get_state(dev) == LEDST_BLINK) {
++ struct led_ops *ops = led_get_ops(dev);
++
++ if (ops && ops->update_blink)
++ ops->update_blink(dev);
++ }
++ }
++
++ return 0;
++}
+ #endif
+
+ int led_default_state(void)
+@@ -87,6 +120,10 @@ int led_default_state(void)
+ led_set_state(dev, LEDST_ON);
+ else if (!strncmp(default_state, "off", 3))
+ led_set_state(dev, LEDST_OFF);
++#ifdef CONFIG_LED_BLINK
++ else if (!strncmp(default_state, "blink", 5))
++ led_set_state(dev, LEDST_BLINK);
++#endif
+ /* default-state = "keep" : device is only probed */
+ }
+
+diff --git a/drivers/led/led_gpio.c b/drivers/led/led_gpio.c
+index 93f6b913c647..a88efde71a69 100644
+--- a/drivers/led/led_gpio.c
++++ b/drivers/led/led_gpio.c
+@@ -13,8 +13,45 @@
+
+ struct led_gpio_priv {
+ struct gpio_desc gpio;
++#ifdef CONFIG_LED_BLINK
++ int period;
++ int period_tick_count;
++ enum led_state_t state;
++#endif
+ };
+
++#ifdef CONFIG_LED_BLINK
++static int gpio_led_set_period(struct udevice *dev, int period_ms)
++{
++ struct led_gpio_priv *priv = dev_get_priv(dev);
++
++ if (period_ms < LED_BLINK_UPDATE_TICK_MS)
++ period_ms = LED_BLINK_PERIOD_DEFAULT_MS;
++
++ priv->period = period_ms / LED_BLINK_UPDATE_TICK_MS;
++ priv->period_tick_count = priv->period;
++
++ return 0;
++}
++
++static int gpio_led_update_blink(struct udevice *dev)
++{
++ struct led_gpio_priv *priv = dev_get_priv(dev);
++ int ret;
++
++ if (priv->period_tick_count) {
++ priv->period_tick_count--;
++ } else {
++ ret = dm_gpio_get_value(&priv->gpio);
++ if (ret >= 0)
++ dm_gpio_set_value(&priv->gpio, !ret);
++ priv->period_tick_count = priv->period;
++ }
++
++ return 0;
++}
++#endif
++
+ static int gpio_led_set_state(struct udevice *dev, enum led_state_t state)
+ {
+ struct led_gpio_priv *priv = dev_get_priv(dev);
+@@ -25,6 +62,9 @@ static int gpio_led_set_state(struct udevice *dev, enum led_state_t state)
+ switch (state) {
+ case LEDST_OFF:
+ case LEDST_ON:
++#ifdef CONFIG_LED_BLINK
++ case LEDST_BLINK:
++#endif
+ break;
+ case LEDST_TOGGLE:
+ ret = dm_gpio_get_value(&priv->gpio);
+@@ -36,6 +76,20 @@ static int gpio_led_set_state(struct udevice *dev, enum led_state_t state)
+ return -ENOSYS;
+ }
+
++#ifdef CONFIG_LED_BLINK
++ priv->state = state;
++
++ if (priv->state == LEDST_BLINK) {
++ if (priv->period < LED_BLINK_UPDATE_TICK_MS) {
++ priv->period = LED_BLINK_PERIOD_DEFAULT_MS /
++ LED_BLINK_UPDATE_TICK_MS;
++ priv->period_tick_count = priv->period;
++ }
++
++ return dm_gpio_set_value(&priv->gpio, LEDST_ON);
++ }
++#endif
++
+ return dm_gpio_set_value(&priv->gpio, state);
+ }
+
+@@ -46,6 +100,10 @@ static enum led_state_t gpio_led_get_state(struct udevice *dev)
+
+ if (!dm_gpio_is_valid(&priv->gpio))
+ return -EREMOTEIO;
++#ifdef CONFIG_LED_BLINK
++ if (priv->state == LEDST_BLINK)
++ return LEDST_BLINK;
++#endif
+ ret = dm_gpio_get_value(&priv->gpio);
+ if (ret < 0)
+ return ret;
+@@ -117,6 +175,10 @@ static int led_gpio_bind(struct udevice *parent)
+ static const struct led_ops gpio_led_ops = {
+ .set_state = gpio_led_set_state,
+ .get_state = gpio_led_get_state,
++#ifdef CONFIG_LED_BLINK
++ .set_period = gpio_led_set_period,
++ .update_blink = gpio_led_update_blink,
++#endif
+ };
+
+ static const struct udevice_id led_gpio_ids[] = {
+diff --git a/include/led.h b/include/led.h
+index 7bfdddfd6fab..583dbd2f8f0e 100644
+--- a/include/led.h
++++ b/include/led.h
+@@ -32,7 +32,6 @@ enum led_state_t {
+ #ifdef CONFIG_LED_BLINK
+ LEDST_BLINK,
+ #endif
+-
+ LEDST_COUNT,
+ };
+
+@@ -66,6 +65,17 @@ struct led_ops {
+ * @return 0 if OK, -ve on error
+ */
+ int (*set_period)(struct udevice *dev, int period_ms);
++
++ /**
++ * update_blink() - update blink output of an LED
++ *
++ * This should be called in every tick for updating blink behavior of an
++ * LED.
++ *
++ * @dev: LED device to change
++ * @return 0 if OK, -ve on error
++ */
++ int (*update_blink)(struct udevice *dev);
+ #endif
+ };
+
+@@ -115,4 +125,34 @@ int led_set_period(struct udevice *dev, int period_ms);
+ */
+ int led_default_state(void);
+
++#ifdef CONFIG_LED_BLINK
++#define LED_BLINK_UPDATE_TICK_MS 10
++#define LED_BLINK_PERIOD_DEFAULT_MS 500
++
++/**
++ * led_blink_enable() - enable blinking for all LEDs that have the blink state
++ *
++ * This enables blinking for all LEDs that have the blink state.
++ *
++ */
++void led_blink_enable(void);
++
++/**
++ * led_blink_disable() - disable blinking for all LEDs that have the blink state
++ *
++ * This disables blinking for all LEDs that have the blink state.
++ *
++ */
++void led_blink_disable(void);
++
++/**
++ * led_blink_update() - timer tick callback for updating blink behavior
++ *
++ * This should be called on every LED_BLINK_UPDATE_TICK_MS for updating blink
++ * behavior of all LEDs that have the blink state.
++ *
++ */
++int led_blink_update(void);
++#endif
++
+ #endif
+--
+2.17.1
+