aboutsummaryrefslogtreecommitdiffstats
path: root/roms/u-boot/drivers/led
diff options
context:
space:
mode:
Diffstat (limited to 'roms/u-boot/drivers/led')
-rw-r--r--roms/u-boot/drivers/led/Kconfig402
-rw-r--r--roms/u-boot/drivers/led/Makefile11
-rw-r--r--roms/u-boot/drivers/led/led-uclass.c100
-rw-r--r--roms/u-boot/drivers/led/led_bcm6328.c245
-rw-r--r--roms/u-boot/drivers/led/led_bcm6358.c215
-rw-r--r--roms/u-boot/drivers/led/led_bcm6858.c252
-rw-r--r--roms/u-boot/drivers/led/led_cortina.c298
-rw-r--r--roms/u-boot/drivers/led/led_gpio.c135
8 files changed, 1658 insertions, 0 deletions
diff --git a/roms/u-boot/drivers/led/Kconfig b/roms/u-boot/drivers/led/Kconfig
new file mode 100644
index 000000000..cc87fbf39
--- /dev/null
+++ b/roms/u-boot/drivers/led/Kconfig
@@ -0,0 +1,402 @@
+menu "LED Support"
+
+config LED
+ bool "Enable LED support"
+ depends on DM
+ help
+ Many boards have LEDs which can be used to signal status or alerts.
+ U-Boot provides a uclass API to implement this feature. LED drivers
+ can provide access to board-specific LEDs. Use of the device tree
+ for configuration is encouraged.
+
+config LED_BCM6328
+ bool "LED Support for BCM6328"
+ depends on LED && ARCH_BMIPS
+ help
+ This option enables support for LEDs connected to the BCM6328
+ LED HW controller accessed via MMIO registers.
+ HW blinking is supported and up to 24 LEDs can be controlled.
+ All LEDs can blink at the same time but the delay is shared, which
+ means that if one LED is set to blink at 100ms and then a different
+ LED is set to blink at 200ms, both will blink at 200ms.
+
+config LED_BCM6358
+ bool "LED Support for BCM6358"
+ depends on LED && ARCH_BMIPS
+ help
+ This option enables support for LEDs connected to the BCM6358
+ LED HW controller accessed via MMIO registers.
+ HW has no blinking capabilities and up to 32 LEDs can be controlled.
+
+config LED_BCM6858
+ bool "LED Support for BCM6858"
+ depends on LED && (ARCH_BCM68360 || ARCH_BCM6858 || ARCH_BCM63158)
+ help
+ This option enables support for LEDs connected to the BCM6858
+ HW has blinking capabilities and up to 32 LEDs can be controlled.
+
+config LED_CORTINA
+ bool "LED Support for Cortina Access CAxxxx SoCs"
+ depends on LED && (CORTINA_PLATFORM)
+ help
+ This option enables support for LEDs connected to the Cortina
+ Access CAxxxx SOCs.
+
+
+config LED_BLINK
+ bool "Support LED blinking"
+ depends on LED
+ help
+ Some drivers can support automatic blinking of LEDs with a given
+ period, without needing timers or extra code to handle the timing.
+ This option enables support for this which adds slightly to the
+ code size.
+
+config SPL_LED
+ bool "Enable LED support in SPL"
+ depends on SPL && SPL_DM
+ help
+ The LED subsystem adds a small amount of overhead to the image.
+ If this is acceptable and you have a need to use LEDs in SPL,
+ enable this option. You will need to enable device tree in SPL
+ for this to work.
+
+config LED_GPIO
+ bool "LED support for GPIO-connected LEDs"
+ depends on LED && DM_GPIO
+ help
+ Enable support for LEDs which are connected to GPIO lines. These
+ GPIOs may be on the SoC or some other device which provides GPIOs.
+ The GPIO driver must used driver model. LEDs are configured using
+ the device tree.
+
+config SPL_LED_GPIO
+ bool "LED support for GPIO-connected LEDs in SPL"
+ depends on SPL_LED && DM_GPIO
+ help
+ This option is an SPL-variant of the LED_GPIO option.
+ See the help of LED_GPIO for details.
+
+config LED_STATUS
+ bool "Enable status LED API"
+ help
+ Allows common u-boot commands to use a board's leds to
+ provide status for activities like booting and downloading files.
+
+if LED_STATUS
+
+# Hidden constants
+
+config LED_STATUS_OFF
+ int
+ default 0
+
+config LED_STATUS_BLINKING
+ int
+ default 1
+
+config LED_STATUS_ON
+ int
+ default 2
+
+# Hidden constants end
+
+config LED_STATUS_GPIO
+ bool "GPIO status LED implementation"
+ help
+ The status LED can be connected to a GPIO pin. In such cases, the
+ gpio_led driver can be used as a status LED backend implementation.
+
+config LED_STATUS_BOARD_SPECIFIC
+ bool "Specific board"
+ default y
+ help
+ LED support is only for a specific board.
+
+comment "LEDs parameters"
+
+config LED_STATUS0
+ bool "Enable status LED 0"
+
+if LED_STATUS0
+
+config LED_STATUS_BIT
+ int "identification"
+ help
+ CONFIG_LED_STATUS_BIT is passed into the __led_* functions to identify
+ which LED is being acted on. As such, the chosen value must be unique
+ with respect to the other CONFIG_LED_STATUS_BIT's. Mapping the value
+ to a physical LED is the responsibility of the __led_* function.
+
+config LED_STATUS_STATE
+ int "initial state"
+ range LED_STATUS_OFF LED_STATUS_ON
+ default LED_STATUS_OFF
+ help
+ Should be set one of the following:
+ 0 - off
+ 1 - blinking
+ 2 - on
+
+config LED_STATUS_FREQ
+ int "blink frequency"
+ range 2 10
+ default 2
+ help
+ The LED blink period calculated from LED_STATUS_FREQ:
+ LED_STATUS_PERIOD = CONFIG_SYS_HZ/LED_STATUS_FREQ
+ Values range: 2 - 10
+
+endif # LED_STATUS0
+
+config LED_STATUS1
+ bool "Enable status LED 1"
+
+if LED_STATUS1
+
+config LED_STATUS_BIT1
+ int "identification"
+ help
+ CONFIG_LED_STATUS_BIT1 is passed into the __led_* functions to
+ identify which LED is being acted on. As such, the chosen value must
+ be unique with respect to the other CONFIG_LED_STATUS_BIT's. Mapping
+ the value to a physical LED is the responsibility of the __led_*
+ function.
+
+config LED_STATUS_STATE1
+ int "initial state"
+ range LED_STATUS_OFF LED_STATUS_ON
+ default LED_STATUS_OFF
+ help
+ Should be set one of the following:
+ 0 - off
+ 1 - blinking
+ 2 - on
+
+config LED_STATUS_FREQ1
+ int "blink frequency"
+ range 2 10
+ default 2
+ help
+ The LED blink period calculated from LED_STATUS_FREQ1:
+ LED_STATUS_PERIOD1 = CONFIG_SYS_HZ/LED_STATUS_FREQ1
+ Values range: 2 - 10
+
+endif # LED_STATUS1
+
+config LED_STATUS2
+ bool "Enable status LED 2"
+
+if LED_STATUS2
+
+config LED_STATUS_BIT2
+ int "identification"
+ help
+ CONFIG_LED_STATUS_BIT2 is passed into the __led_* functions to
+ identify which LED is being acted on. As such, the chosen value must
+ be unique with respect to the other CONFIG_LED_STATUS_BIT's. Mapping
+ the value to a physical LED is the responsibility of the __led_*
+ function.
+
+config LED_STATUS_STATE2
+ int "initial state"
+ range LED_STATUS_OFF LED_STATUS_ON
+ default LED_STATUS_OFF
+ help
+ Should be set one of the following:
+ 0 - off
+ 1 - blinking
+ 2 - on
+
+config LED_STATUS_FREQ2
+ int "blink frequency"
+ range 2 10
+ default 2
+ help
+ The LED blink period calculated from LED_STATUS_FREQ2:
+ LED_STATUS_PERIOD2 = CONFIG_SYS_HZ/LED_STATUS_FREQ2
+ Values range: 2 - 10
+
+endif # LED_STATUS2
+
+config LED_STATUS3
+ bool "Enable status LED 3"
+
+if LED_STATUS3
+
+config LED_STATUS_BIT3
+ int "identification"
+ help
+ CONFIG_LED_STATUS_BIT3 is passed into the __led_* functions to
+ identify which LED is being acted on. As such, the chosen value must
+ be unique with respect to the other CONFIG_LED_STATUS_BIT's. Mapping
+ the value to a physical LED is the responsibility of the __led_*
+ function.
+
+config LED_STATUS_STATE3
+ int "initial state"
+ range LED_STATUS_OFF LED_STATUS_ON
+ default LED_STATUS_OFF
+ help
+ Should be set one of the following:
+ 0 - off
+ 1 - blinking
+ 2 - on
+
+config LED_STATUS_FREQ3
+ int "blink frequency"
+ range 2 10
+ default 2
+ help
+ The LED blink period calculated from LED_STATUS_FREQ3:
+ LED_STATUS_PERIOD3 = CONFIG_SYS_HZ/LED_STATUS_FREQ3
+ Values range: 2 - 10
+
+endif # LED_STATUS3
+
+config LED_STATUS4
+ bool "Enable status LED 4"
+
+if LED_STATUS4
+
+config LED_STATUS_BIT4
+ int "identification"
+ help
+ CONFIG_LED_STATUS_BIT4 is passed into the __led_* functions to
+ identify which LED is being acted on. As such, the chosen value must
+ be unique with respect to the other CONFIG_LED_STATUS_BIT's. Mapping
+ the value to a physical LED is the responsibility of the __led_*
+ function.
+
+config LED_STATUS_STATE4
+ int "initial state"
+ range LED_STATUS_OFF LED_STATUS_ON
+ default LED_STATUS_OFF
+ help
+ Should be set one of the following:
+ 0 - off
+ 1 - blinking
+ 2 - on
+
+config LED_STATUS_FREQ4
+ int "blink frequency"
+ range 2 10
+ default 2
+ help
+ The LED blink period calculated from LED_STATUS_FREQ4:
+ LED_STATUS_PERIOD4 = CONFIG_SYS_HZ/LED_STATUS_FREQ4
+ Values range: 2 - 10
+
+endif # LED_STATUS4
+
+config LED_STATUS5
+ bool "Enable status LED 5"
+
+if LED_STATUS5
+
+config LED_STATUS_BIT5
+ int "identification"
+ help
+ CONFIG_LED_STATUS_BIT5 is passed into the __led_* functions to
+ identify which LED is being acted on. As such, the chosen value must
+ be unique with respect to the other CONFIG_LED_STATUS_BIT's. Mapping
+ the value to a physical LED is the responsibility of the __led_*
+ function.
+
+config LED_STATUS_STATE5
+ int "initial state"
+ range LED_STATUS_OFF LED_STATUS_ON
+ default LED_STATUS_OFF
+ help
+ Should be set one of the following:
+ 0 - off
+ 1 - blinking
+ 2 - on
+
+config LED_STATUS_FREQ5
+ int "blink frequency"
+ range 2 10
+ default 2
+ help
+ The LED blink period calculated from LED_STATUS_FREQ5:
+ LED_STATUS_PERIOD5 = CONFIG_SYS_HZ/LED_STATUS_FREQ5
+ Values range: 2 - 10
+
+endif # LED_STATUS5
+
+config LED_STATUS_BOOT_ENABLE
+ bool "Enable BOOT LED"
+ help
+ Enable to turn an LED on when the board is booting.
+
+if LED_STATUS_BOOT_ENABLE
+
+config LED_STATUS_BOOT
+ int "LED to light when the board is booting"
+ help
+ Valid enabled LED device number.
+
+endif # LED_STATUS_BOOT_ENABLE
+
+config LED_STATUS_RED_ENABLE
+ bool "Enable red LED"
+ help
+ Enable red status LED.
+
+if LED_STATUS_RED_ENABLE
+
+config LED_STATUS_RED
+ int "Red LED identification"
+ help
+ Valid enabled LED device number.
+
+endif # LED_STATUS_RED_ENABLE
+
+config LED_STATUS_YELLOW_ENABLE
+ bool "Enable yellow LED"
+ help
+ Enable yellow status LED.
+
+if LED_STATUS_YELLOW_ENABLE
+
+config LED_STATUS_YELLOW
+ int "Yellow LED identification"
+ help
+ Valid enabled LED device number.
+
+endif # LED_STATUS_YELLOW_ENABLE
+
+config LED_STATUS_BLUE_ENABLE
+ bool "Enable blue LED"
+ help
+ Enable blue status LED.
+
+if LED_STATUS_BLUE_ENABLE
+
+config LED_STATUS_BLUE
+ int "Blue LED identification"
+ help
+ Valid enabled LED device number.
+
+endif # LED_STATUS_BLUE_ENABLE
+
+config LED_STATUS_GREEN_ENABLE
+ bool "Enable green LED"
+ help
+ Enable green status LED.
+
+if LED_STATUS_GREEN_ENABLE
+
+config LED_STATUS_GREEN
+ int "Green LED identification"
+ help
+ Valid enabled LED device number (0-5).
+
+endif # LED_STATUS_GREEN_ENABLE
+
+config LED_STATUS_CMD
+ bool "Enable status LED commands"
+
+endif # LED_STATUS
+
+endmenu
diff --git a/roms/u-boot/drivers/led/Makefile b/roms/u-boot/drivers/led/Makefile
new file mode 100644
index 000000000..8e3ae7f14
--- /dev/null
+++ b/roms/u-boot/drivers/led/Makefile
@@ -0,0 +1,11 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (c) 2015 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+
+obj-y += led-uclass.o
+obj-$(CONFIG_LED_BCM6328) += led_bcm6328.o
+obj-$(CONFIG_LED_BCM6358) += led_bcm6358.o
+obj-$(CONFIG_LED_BCM6858) += led_bcm6858.o
+obj-$(CONFIG_$(SPL_)LED_GPIO) += led_gpio.o
+obj-$(CONFIG_LED_CORTINA) += led_cortina.o
diff --git a/roms/u-boot/drivers/led/led-uclass.c b/roms/u-boot/drivers/led/led-uclass.c
new file mode 100644
index 000000000..e15a2967f
--- /dev/null
+++ b/roms/u-boot/drivers/led/led-uclass.c
@@ -0,0 +1,100 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2015 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <led.h>
+#include <dm/device-internal.h>
+#include <dm/root.h>
+#include <dm/uclass-internal.h>
+
+int led_get_by_label(const char *label, struct udevice **devp)
+{
+ struct udevice *dev;
+ struct uclass *uc;
+ int ret;
+
+ ret = uclass_get(UCLASS_LED, &uc);
+ if (ret)
+ return ret;
+ uclass_foreach_dev(dev, uc) {
+ struct led_uc_plat *uc_plat = dev_get_uclass_plat(dev);
+
+ /* Ignore the top-level LED node */
+ if (uc_plat->label && !strcmp(label, uc_plat->label))
+ return uclass_get_device_tail(dev, 0, devp);
+ }
+
+ return -ENODEV;
+}
+
+int led_set_state(struct udevice *dev, enum led_state_t state)
+{
+ struct led_ops *ops = led_get_ops(dev);
+
+ if (!ops->set_state)
+ return -ENOSYS;
+
+ return ops->set_state(dev, state);
+}
+
+enum led_state_t led_get_state(struct udevice *dev)
+{
+ struct led_ops *ops = led_get_ops(dev);
+
+ if (!ops->get_state)
+ return -ENOSYS;
+
+ return ops->get_state(dev);
+}
+
+#ifdef CONFIG_LED_BLINK
+int led_set_period(struct udevice *dev, int period_ms)
+{
+ struct led_ops *ops = led_get_ops(dev);
+
+ if (!ops->set_period)
+ return -ENOSYS;
+
+ return ops->set_period(dev, period_ms);
+}
+#endif
+
+int led_default_state(void)
+{
+ struct udevice *dev;
+ struct uclass *uc;
+ const char *default_state;
+ int ret;
+
+ ret = uclass_get(UCLASS_LED, &uc);
+ if (ret)
+ return ret;
+ for (uclass_find_first_device(UCLASS_LED, &dev);
+ dev;
+ uclass_find_next_device(&dev)) {
+ default_state = dev_read_string(dev, "default-state");
+ if (!default_state)
+ continue;
+ ret = device_probe(dev);
+ if (ret)
+ return ret;
+ if (!strncmp(default_state, "on", 2))
+ led_set_state(dev, LEDST_ON);
+ else if (!strncmp(default_state, "off", 3))
+ led_set_state(dev, LEDST_OFF);
+ /* default-state = "keep" : device is only probed */
+ }
+
+ return ret;
+}
+
+UCLASS_DRIVER(led) = {
+ .id = UCLASS_LED,
+ .name = "led",
+ .per_device_plat_auto = sizeof(struct led_uc_plat),
+};
diff --git a/roms/u-boot/drivers/led/led_bcm6328.c b/roms/u-boot/drivers/led/led_bcm6328.c
new file mode 100644
index 000000000..bf8207d63
--- /dev/null
+++ b/roms/u-boot/drivers/led/led_bcm6328.c
@@ -0,0 +1,245 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <led.h>
+#include <log.h>
+#include <asm/io.h>
+#include <dm/lists.h>
+
+#define LEDS_MAX 24
+
+/* LED Init register */
+#define LED_INIT_REG 0x00
+#define LED_INIT_FASTINTV_MS 20
+#define LED_INIT_FASTINTV_SHIFT 6
+#define LED_INIT_FASTINTV_MASK (0x3f << LED_INIT_FASTINTV_SHIFT)
+#define LED_INIT_SLEDEN_SHIFT 12
+#define LED_INIT_SLEDEN_MASK (1 << LED_INIT_SLEDEN_SHIFT)
+#define LED_INIT_SLEDMUX_SHIFT 13
+#define LED_INIT_SLEDMUX_MASK (1 << LED_INIT_SLEDMUX_SHIFT)
+#define LED_INIT_SLEDCLKNPOL_SHIFT 14
+#define LED_INIT_SLEDCLKNPOL_MASK (1 << LED_INIT_SLEDCLKNPOL_SHIFT)
+#define LED_INIT_SLEDDATAPPOL_SHIFT 15
+#define LED_INIT_SLEDDATANPOL_MASK (1 << LED_INIT_SLEDDATAPPOL_SHIFT)
+#define LED_INIT_SLEDSHIFTDIR_SHIFT 16
+#define LED_INIT_SLEDSHIFTDIR_MASK (1 << LED_INIT_SLEDSHIFTDIR_SHIFT)
+
+/* LED Mode registers */
+#define LED_MODE_REG_HI 0x04
+#define LED_MODE_REG_LO 0x08
+#define LED_MODE_ON 0
+#define LED_MODE_FAST 1
+#define LED_MODE_BLINK 2
+#define LED_MODE_OFF 3
+#define LED_MODE_MASK 0x3
+
+struct bcm6328_led_priv {
+ void __iomem *regs;
+ void __iomem *mode;
+ uint8_t shift;
+ bool active_low;
+};
+
+static unsigned long bcm6328_led_get_mode(struct bcm6328_led_priv *priv)
+{
+ return ((readl_be(priv->mode) >> priv->shift) & LED_MODE_MASK);
+}
+
+static int bcm6328_led_set_mode(struct bcm6328_led_priv *priv, uint8_t mode)
+{
+ clrsetbits_be32(priv->mode, (LED_MODE_MASK << priv->shift),
+ (mode << priv->shift));
+
+ return 0;
+}
+
+static enum led_state_t bcm6328_led_get_state(struct udevice *dev)
+{
+ struct bcm6328_led_priv *priv = dev_get_priv(dev);
+ enum led_state_t state = LEDST_OFF;
+
+ switch (bcm6328_led_get_mode(priv)) {
+#ifdef CONFIG_LED_BLINK
+ case LED_MODE_BLINK:
+ case LED_MODE_FAST:
+ state = LEDST_BLINK;
+ break;
+#endif
+ case LED_MODE_OFF:
+ state = (priv->active_low ? LEDST_ON : LEDST_OFF);
+ break;
+ case LED_MODE_ON:
+ state = (priv->active_low ? LEDST_OFF : LEDST_ON);
+ break;
+ }
+
+ return state;
+}
+
+static int bcm6328_led_set_state(struct udevice *dev, enum led_state_t state)
+{
+ struct bcm6328_led_priv *priv = dev_get_priv(dev);
+ unsigned long mode;
+
+ switch (state) {
+#ifdef CONFIG_LED_BLINK
+ case LEDST_BLINK:
+ mode = LED_MODE_BLINK;
+ break;
+#endif
+ case LEDST_OFF:
+ mode = (priv->active_low ? LED_MODE_ON : LED_MODE_OFF);
+ break;
+ case LEDST_ON:
+ mode = (priv->active_low ? LED_MODE_OFF : LED_MODE_ON);
+ break;
+ case LEDST_TOGGLE:
+ if (bcm6328_led_get_state(dev) == LEDST_OFF)
+ return bcm6328_led_set_state(dev, LEDST_ON);
+ else
+ return bcm6328_led_set_state(dev, LEDST_OFF);
+ break;
+ default:
+ return -ENOSYS;
+ }
+
+ return bcm6328_led_set_mode(priv, mode);
+}
+
+#ifdef CONFIG_LED_BLINK
+static unsigned long bcm6328_blink_delay(int delay)
+{
+ unsigned long bcm6328_delay = delay;
+
+ bcm6328_delay += (LED_INIT_FASTINTV_MS / 2);
+ bcm6328_delay /= LED_INIT_FASTINTV_MS;
+ bcm6328_delay <<= LED_INIT_FASTINTV_SHIFT;
+
+ if (bcm6328_delay > LED_INIT_FASTINTV_MASK)
+ return LED_INIT_FASTINTV_MASK;
+ else
+ return bcm6328_delay;
+}
+
+static int bcm6328_led_set_period(struct udevice *dev, int period_ms)
+{
+ struct bcm6328_led_priv *priv = dev_get_priv(dev);
+
+ clrsetbits_be32(priv->regs + LED_INIT_REG, LED_INIT_FASTINTV_MASK,
+ bcm6328_blink_delay(period_ms));
+
+ return 0;
+}
+#endif
+
+static const struct led_ops bcm6328_led_ops = {
+ .get_state = bcm6328_led_get_state,
+ .set_state = bcm6328_led_set_state,
+#ifdef CONFIG_LED_BLINK
+ .set_period = bcm6328_led_set_period,
+#endif
+};
+
+static int bcm6328_led_probe(struct udevice *dev)
+{
+ struct led_uc_plat *uc_plat = dev_get_uclass_plat(dev);
+
+ /* Top-level LED node */
+ if (!uc_plat->label) {
+ void __iomem *regs;
+ u32 set_bits = 0;
+
+ regs = dev_remap_addr(dev);
+ if (!regs)
+ return -EINVAL;
+
+ if (dev_read_bool(dev, "brcm,serial-leds"))
+ set_bits |= LED_INIT_SLEDEN_MASK;
+ if (dev_read_bool(dev, "brcm,serial-mux"))
+ set_bits |= LED_INIT_SLEDMUX_MASK;
+ if (dev_read_bool(dev, "brcm,serial-clk-low"))
+ set_bits |= LED_INIT_SLEDCLKNPOL_MASK;
+ if (!dev_read_bool(dev, "brcm,serial-dat-low"))
+ set_bits |= LED_INIT_SLEDDATANPOL_MASK;
+ if (!dev_read_bool(dev, "brcm,serial-shift-inv"))
+ set_bits |= LED_INIT_SLEDSHIFTDIR_MASK;
+
+ clrsetbits_be32(regs + LED_INIT_REG, ~0, set_bits);
+ } else {
+ struct bcm6328_led_priv *priv = dev_get_priv(dev);
+ unsigned int pin;
+
+ priv->regs = dev_remap_addr(dev_get_parent(dev));
+ if (!priv->regs)
+ return -EINVAL;
+
+ pin = dev_read_u32_default(dev, "reg", LEDS_MAX);
+ if (pin >= LEDS_MAX)
+ return -EINVAL;
+
+ if (pin < 8) {
+ /* LEDs 0-7 (bits 47:32) */
+ priv->mode = priv->regs + LED_MODE_REG_HI;
+ priv->shift = (pin << 1);
+ } else {
+ /* LEDs 8-23 (bits 31:0) */
+ priv->mode = priv->regs + LED_MODE_REG_LO;
+ priv->shift = ((pin - 8) << 1);
+ }
+
+ if (dev_read_bool(dev, "active-low"))
+ priv->active_low = true;
+ }
+
+ return 0;
+}
+
+static int bcm6328_led_bind(struct udevice *parent)
+{
+ ofnode node;
+
+ dev_for_each_subnode(node, parent) {
+ struct led_uc_plat *uc_plat;
+ struct udevice *dev;
+ const char *label;
+ int ret;
+
+ label = ofnode_read_string(node, "label");
+ if (!label) {
+ debug("%s: node %s has no label\n", __func__,
+ ofnode_get_name(node));
+ return -EINVAL;
+ }
+
+ ret = device_bind_driver_to_node(parent, "bcm6328-led",
+ ofnode_get_name(node),
+ node, &dev);
+ if (ret)
+ return ret;
+
+ uc_plat = dev_get_uclass_plat(dev);
+ uc_plat->label = label;
+ }
+
+ return 0;
+}
+
+static const struct udevice_id bcm6328_led_ids[] = {
+ { .compatible = "brcm,bcm6328-leds" },
+ { /* sentinel */ }
+};
+
+U_BOOT_DRIVER(bcm6328_led) = {
+ .name = "bcm6328-led",
+ .id = UCLASS_LED,
+ .of_match = bcm6328_led_ids,
+ .ops = &bcm6328_led_ops,
+ .bind = bcm6328_led_bind,
+ .probe = bcm6328_led_probe,
+ .priv_auto = sizeof(struct bcm6328_led_priv),
+};
diff --git a/roms/u-boot/drivers/led/led_bcm6358.c b/roms/u-boot/drivers/led/led_bcm6358.c
new file mode 100644
index 000000000..3e57cdfd1
--- /dev/null
+++ b/roms/u-boot/drivers/led/led_bcm6358.c
@@ -0,0 +1,215 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <led.h>
+#include <log.h>
+#include <asm/io.h>
+#include <dm/lists.h>
+#include <linux/delay.h>
+
+#define LEDS_MAX 32
+#define LEDS_WAIT 100
+
+/* LED Mode register */
+#define LED_MODE_REG 0x0
+#define LED_MODE_OFF 0
+#define LED_MODE_ON 1
+#define LED_MODE_MASK 1
+
+/* LED Control register */
+#define LED_CTRL_REG 0x4
+#define LED_CTRL_CLK_MASK 0x3
+#define LED_CTRL_CLK_1 0
+#define LED_CTRL_CLK_2 1
+#define LED_CTRL_CLK_4 2
+#define LED_CTRL_CLK_8 3
+#define LED_CTRL_POL_SHIFT 2
+#define LED_CTRL_POL_MASK (1 << LED_CTRL_POL_SHIFT)
+#define LED_CTRL_BUSY_SHIFT 3
+#define LED_CTRL_BUSY_MASK (1 << LED_CTRL_BUSY_SHIFT)
+
+struct bcm6358_led_priv {
+ void __iomem *regs;
+ uint8_t pin;
+ bool active_low;
+};
+
+static void bcm6358_led_busy(void __iomem *regs)
+{
+ while (readl_be(regs + LED_CTRL_REG) & LED_CTRL_BUSY_MASK)
+ udelay(LEDS_WAIT);
+}
+
+static unsigned long bcm6358_led_get_mode(struct bcm6358_led_priv *priv)
+{
+ bcm6358_led_busy(priv->regs);
+
+ return (readl_be(priv->regs + LED_MODE_REG) >> priv->pin) &
+ LED_MODE_MASK;
+}
+
+static int bcm6358_led_set_mode(struct bcm6358_led_priv *priv, uint8_t mode)
+{
+ bcm6358_led_busy(priv->regs);
+
+ clrsetbits_be32(priv->regs + LED_MODE_REG,
+ (LED_MODE_MASK << priv->pin),
+ (mode << priv->pin));
+
+ return 0;
+}
+
+static enum led_state_t bcm6358_led_get_state(struct udevice *dev)
+{
+ struct bcm6358_led_priv *priv = dev_get_priv(dev);
+ enum led_state_t state = LEDST_OFF;
+
+ switch (bcm6358_led_get_mode(priv)) {
+ case LED_MODE_OFF:
+ state = (priv->active_low ? LEDST_ON : LEDST_OFF);
+ break;
+ case LED_MODE_ON:
+ state = (priv->active_low ? LEDST_OFF : LEDST_ON);
+ break;
+ }
+
+ return state;
+}
+
+static int bcm6358_led_set_state(struct udevice *dev, enum led_state_t state)
+{
+ struct bcm6358_led_priv *priv = dev_get_priv(dev);
+ unsigned long mode;
+
+ switch (state) {
+ case LEDST_OFF:
+ mode = (priv->active_low ? LED_MODE_ON : LED_MODE_OFF);
+ break;
+ case LEDST_ON:
+ mode = (priv->active_low ? LED_MODE_OFF : LED_MODE_ON);
+ break;
+ case LEDST_TOGGLE:
+ if (bcm6358_led_get_state(dev) == LEDST_OFF)
+ return bcm6358_led_set_state(dev, LEDST_ON);
+ else
+ return bcm6358_led_set_state(dev, LEDST_OFF);
+ break;
+ default:
+ return -ENOSYS;
+ }
+
+ return bcm6358_led_set_mode(priv, mode);
+}
+
+static const struct led_ops bcm6358_led_ops = {
+ .get_state = bcm6358_led_get_state,
+ .set_state = bcm6358_led_set_state,
+};
+
+static int bcm6358_led_probe(struct udevice *dev)
+{
+ struct led_uc_plat *uc_plat = dev_get_uclass_plat(dev);
+
+ /* Top-level LED node */
+ if (!uc_plat->label) {
+ void __iomem *regs;
+ unsigned int clk_div;
+ u32 set_bits = 0;
+
+ regs = dev_remap_addr(dev);
+ if (!regs)
+ return -EINVAL;
+
+ if (dev_read_bool(dev, "brcm,clk-dat-low"))
+ set_bits |= LED_CTRL_POL_MASK;
+ clk_div = dev_read_u32_default(dev, "brcm,clk-div",
+ LED_CTRL_CLK_1);
+ switch (clk_div) {
+ case 8:
+ set_bits |= LED_CTRL_CLK_8;
+ break;
+ case 4:
+ set_bits |= LED_CTRL_CLK_4;
+ break;
+ case 2:
+ set_bits |= LED_CTRL_CLK_2;
+ break;
+ default:
+ set_bits |= LED_CTRL_CLK_1;
+ break;
+ }
+
+ bcm6358_led_busy(regs);
+ clrsetbits_be32(regs + LED_CTRL_REG,
+ LED_CTRL_POL_MASK | LED_CTRL_CLK_MASK,
+ set_bits);
+ } else {
+ struct bcm6358_led_priv *priv = dev_get_priv(dev);
+ unsigned int pin;
+
+ priv->regs = dev_remap_addr(dev);
+ if (!priv->regs)
+ return -EINVAL;
+
+ pin = dev_read_u32_default(dev, "reg", LEDS_MAX);
+ if (pin >= LEDS_MAX)
+ return -EINVAL;
+
+ priv->pin = pin;
+
+ if (dev_read_bool(dev, "active-low"))
+ priv->active_low = true;
+ }
+
+ return 0;
+}
+
+static int bcm6358_led_bind(struct udevice *parent)
+{
+ ofnode node;
+
+ dev_for_each_subnode(node, parent) {
+ struct led_uc_plat *uc_plat;
+ struct udevice *dev;
+ const char *label;
+ int ret;
+
+ label = ofnode_read_string(node, "label");
+ if (!label) {
+ debug("%s: node %s has no label\n", __func__,
+ ofnode_get_name(node));
+ return -EINVAL;
+ }
+
+ ret = device_bind_driver_to_node(parent, "bcm6358-led",
+ ofnode_get_name(node),
+ node, &dev);
+ if (ret)
+ return ret;
+
+ uc_plat = dev_get_uclass_plat(dev);
+ uc_plat->label = label;
+ }
+
+ return 0;
+}
+
+static const struct udevice_id bcm6358_led_ids[] = {
+ { .compatible = "brcm,bcm6358-leds" },
+ { /* sentinel */ }
+};
+
+U_BOOT_DRIVER(bcm6358_led) = {
+ .name = "bcm6358-led",
+ .id = UCLASS_LED,
+ .of_match = bcm6358_led_ids,
+ .bind = bcm6358_led_bind,
+ .probe = bcm6358_led_probe,
+ .priv_auto = sizeof(struct bcm6358_led_priv),
+ .ops = &bcm6358_led_ops,
+};
diff --git a/roms/u-boot/drivers/led/led_bcm6858.c b/roms/u-boot/drivers/led/led_bcm6858.c
new file mode 100644
index 000000000..fbf46a114
--- /dev/null
+++ b/roms/u-boot/drivers/led/led_bcm6858.c
@@ -0,0 +1,252 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Philippe Reynes <philippe.reynes@softathome.com>
+ *
+ * based on:
+ * drivers/led/led_bcm6328.c
+ * drivers/led/led_bcm6358.c
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <led.h>
+#include <log.h>
+#include <asm/io.h>
+#include <dm/lists.h>
+#include <linux/bitops.h>
+
+#define LEDS_MAX 32
+#define LEDS_WAIT 100
+
+/* LED Mode register */
+#define LED_MODE_REG 0x0
+#define LED_MODE_OFF 0
+#define LED_MODE_ON 1
+#define LED_MODE_MASK 1
+
+/* LED Controller Global settings register */
+#define LED_CTRL_REG 0x00
+#define LED_CTRL_MASK 0x1f
+#define LED_CTRL_LED_TEST_MODE BIT(0)
+#define LED_CTRL_SERIAL_LED_DATA_PPOL BIT(1)
+#define LED_CTRL_SERIAL_LED_CLK_POL BIT(2)
+#define LED_CTRL_SERIAL_LED_EN_POL BIT(3)
+#define LED_CTRL_SERIAL_LED_MSB_FIRST BIT(4)
+
+/* LED Controller IP LED source select register */
+#define LED_HW_LED_EN_REG 0x08
+/* LED Flash control register0 */
+#define LED_FLASH_RATE_CONTROL_REG0 0x10
+/* Soft LED input register */
+#define LED_SW_LED_IP_REG 0xb8
+/* Parallel LED Output Polarity Register */
+#define LED_PLED_OP_PPOL_REG 0xc0
+
+struct bcm6858_led_priv {
+ void __iomem *regs;
+ u8 pin;
+};
+
+#ifdef CONFIG_LED_BLINK
+/*
+ * The value for flash rate are:
+ * 0 : no blinking
+ * 1 : rate is 25 Hz => 40 ms (period)
+ * 2 : rate is 12.5 Hz => 80 ms (period)
+ * 3 : rate is 6.25 Hz => 160 ms (period)
+ * 4 : rate is 3.125 Hz => 320 ms (period)
+ * 5 : rate is 1.5625 Hz => 640 ms (period)
+ * 6 : rate is 0.7815 Hz => 1280 ms (period)
+ * 7 : rate is 0.390625 Hz => 2560 ms (period)
+ */
+static const int bcm6858_flash_rate[8] = {
+ 0, 40, 80, 160, 320, 640, 1280, 2560
+};
+
+static u32 bcm6858_flash_rate_value(int period_ms)
+{
+ unsigned long value = 7;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(bcm6858_flash_rate); i++) {
+ if (period_ms <= bcm6858_flash_rate[i]) {
+ value = i;
+ break;
+ }
+ }
+
+ return value;
+}
+
+static int bcm6858_led_set_period(struct udevice *dev, int period_ms)
+{
+ struct bcm6858_led_priv *priv = dev_get_priv(dev);
+ u32 offset, shift, mask, value;
+
+ offset = (priv->pin / 8) * 4;
+ shift = (priv->pin % 8) * 4;
+ mask = 0x7 << shift;
+ value = bcm6858_flash_rate_value(period_ms) << shift;
+
+ clrbits_32(priv->regs + LED_FLASH_RATE_CONTROL_REG0 + offset, mask);
+ setbits_32(priv->regs + LED_FLASH_RATE_CONTROL_REG0 + offset, value);
+
+ return 0;
+}
+#endif
+
+static enum led_state_t bcm6858_led_get_state(struct udevice *dev)
+{
+ struct bcm6858_led_priv *priv = dev_get_priv(dev);
+ enum led_state_t state = LEDST_OFF;
+ u32 sw_led_ip;
+
+ sw_led_ip = readl(priv->regs + LED_SW_LED_IP_REG);
+ if (sw_led_ip & (1 << priv->pin))
+ state = LEDST_ON;
+
+ return state;
+}
+
+static int bcm6858_led_set_state(struct udevice *dev, enum led_state_t state)
+{
+ struct bcm6858_led_priv *priv = dev_get_priv(dev);
+
+ switch (state) {
+ case LEDST_OFF:
+ clrbits_32(priv->regs + LED_SW_LED_IP_REG, (1 << priv->pin));
+#ifdef CONFIG_LED_BLINK
+ bcm6858_led_set_period(dev, 0);
+#endif
+ break;
+ case LEDST_ON:
+ setbits_32(priv->regs + LED_SW_LED_IP_REG, (1 << priv->pin));
+#ifdef CONFIG_LED_BLINK
+ bcm6858_led_set_period(dev, 0);
+#endif
+ break;
+ case LEDST_TOGGLE:
+ if (bcm6858_led_get_state(dev) == LEDST_OFF)
+ return bcm6858_led_set_state(dev, LEDST_ON);
+ else
+ return bcm6858_led_set_state(dev, LEDST_OFF);
+ break;
+#ifdef CONFIG_LED_BLINK
+ case LEDST_BLINK:
+ setbits_32(priv->regs + LED_SW_LED_IP_REG, (1 << priv->pin));
+ break;
+#endif
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static const struct led_ops bcm6858_led_ops = {
+ .get_state = bcm6858_led_get_state,
+ .set_state = bcm6858_led_set_state,
+#ifdef CONFIG_LED_BLINK
+ .set_period = bcm6858_led_set_period,
+#endif
+};
+
+static int bcm6858_led_probe(struct udevice *dev)
+{
+ struct led_uc_plat *uc_plat = dev_get_uclass_plat(dev);
+
+ /* Top-level LED node */
+ if (!uc_plat->label) {
+ void __iomem *regs;
+ u32 set_bits = 0;
+
+ regs = dev_remap_addr(dev);
+ if (!regs)
+ return -EINVAL;
+
+ if (dev_read_bool(dev, "brcm,serial-led-msb-first"))
+ set_bits |= LED_CTRL_SERIAL_LED_MSB_FIRST;
+ if (dev_read_bool(dev, "brcm,serial-led-en-pol"))
+ set_bits |= LED_CTRL_SERIAL_LED_EN_POL;
+ if (dev_read_bool(dev, "brcm,serial-led-clk-pol"))
+ set_bits |= LED_CTRL_SERIAL_LED_CLK_POL;
+ if (dev_read_bool(dev, "brcm,serial-led-data-ppol"))
+ set_bits |= LED_CTRL_SERIAL_LED_DATA_PPOL;
+ if (dev_read_bool(dev, "brcm,led-test-mode"))
+ set_bits |= LED_CTRL_LED_TEST_MODE;
+
+ clrsetbits_32(regs + LED_CTRL_REG, ~0, set_bits);
+ } else {
+ struct bcm6858_led_priv *priv = dev_get_priv(dev);
+ void __iomem *regs;
+ unsigned int pin;
+
+ regs = dev_remap_addr(dev_get_parent(dev));
+ if (!regs)
+ return -EINVAL;
+
+ pin = dev_read_u32_default(dev, "reg", LEDS_MAX);
+ if (pin >= LEDS_MAX)
+ return -EINVAL;
+
+ priv->regs = regs;
+ priv->pin = pin;
+
+ /* this led is managed by software */
+ clrbits_32(regs + LED_HW_LED_EN_REG, 1 << pin);
+
+ /* configure the polarity */
+ if (dev_read_bool(dev, "active-low"))
+ clrbits_32(regs + LED_PLED_OP_PPOL_REG, 1 << pin);
+ else
+ setbits_32(regs + LED_PLED_OP_PPOL_REG, 1 << pin);
+ }
+
+ return 0;
+}
+
+static int bcm6858_led_bind(struct udevice *parent)
+{
+ ofnode node;
+
+ dev_for_each_subnode(node, parent) {
+ struct led_uc_plat *uc_plat;
+ struct udevice *dev;
+ const char *label;
+ int ret;
+
+ label = ofnode_read_string(node, "label");
+ if (!label) {
+ debug("%s: node %s has no label\n", __func__,
+ ofnode_get_name(node));
+ return -EINVAL;
+ }
+
+ ret = device_bind_driver_to_node(parent, "bcm6858-led",
+ ofnode_get_name(node),
+ node, &dev);
+ if (ret)
+ return ret;
+
+ uc_plat = dev_get_uclass_plat(dev);
+ uc_plat->label = label;
+ }
+
+ return 0;
+}
+
+static const struct udevice_id bcm6858_led_ids[] = {
+ { .compatible = "brcm,bcm6858-leds" },
+ { /* sentinel */ }
+};
+
+U_BOOT_DRIVER(bcm6858_led) = {
+ .name = "bcm6858-led",
+ .id = UCLASS_LED,
+ .of_match = bcm6858_led_ids,
+ .bind = bcm6858_led_bind,
+ .probe = bcm6858_led_probe,
+ .priv_auto = sizeof(struct bcm6858_led_priv),
+ .ops = &bcm6858_led_ops,
+};
diff --git a/roms/u-boot/drivers/led/led_cortina.c b/roms/u-boot/drivers/led/led_cortina.c
new file mode 100644
index 000000000..598c0a03d
--- /dev/null
+++ b/roms/u-boot/drivers/led/led_cortina.c
@@ -0,0 +1,298 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/*
+ * Copyright (C) 2020 Cortina-Access
+ * Author: Jway Lin <jway.lin@cortina-access.com>
+ *
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <led.h>
+#include <log.h>
+#include <asm/io.h>
+#include <dm/lists.h>
+#include <linux/bitops.h>
+
+#define LED_MAX_HW_BLINK 127
+#define LED_MAX_COUNT 16
+
+/* LED_CONTROL fields */
+#define LED_BLINK_RATE1_SHIFT 0
+#define LED_BLINK_RATE1_MASK 0xff
+#define LED_BLINK_RATE2_SHIFT 8
+#define LED_BLINK_RATE2_MASK 0xff
+#define LED_CLK_TEST BIT(16)
+#define LED_CLK_POLARITY BIT(17)
+#define LED_CLK_TEST_MODE BIT(16)
+#define LED_CLK_TEST_RX_TEST BIT(30)
+#define LED_CLK_TEST_TX_TEST BIT(31)
+
+/* LED_CONFIG fields */
+#define LED_EVENT_ON_SHIFT 0
+#define LED_EVENT_ON_MASK 0x7
+#define LED_EVENT_BLINK_SHIFT 3
+#define LED_EVENT_BLINK_MASK 0x7
+#define LED_EVENT_OFF_SHIFT 6
+#define LED_EVENT_OFF_MASK 0x7
+#define LED_OFF_ON_SHIFT 9
+#define LED_OFF_ON_MASK 0x3
+#define LED_PORT_SHIFT 11
+#define LED_PORT_MASK 0x7
+#define LED_OFF_VAL BIT(14)
+#define LED_SW_EVENT BIT(15)
+#define LED_BLINK_SEL BIT(16)
+
+/* LED_CONFIG structures */
+struct cortina_led_cfg {
+ void __iomem *regs;
+ u32 pin; /* LED pin nubmer */
+ bool active_low; /*Active-High or Active-Low*/
+ u32 off_event; /* set led off event (RX,TX,SW)*/
+ u32 blink_event; /* set led blink event (RX,TX,SW)*/
+ u32 on_event; /* set led on event (RX,TX,SW)*/
+ u32 port; /* corresponding ethernet port */
+ int blink_sel; /* select blink-rate1 or blink-rate2 */
+};
+
+/* LED_control structures */
+struct cortina_led_plat {
+ void __iomem *ctrl_regs;
+ u16 rate1; /* blink rate setting 0 */
+ u16 rate2; /* blink rate setting 1 */
+};
+
+enum ca_led_state_t {
+ CA_EVENT_MODE = 0,
+ CA_LED_ON = 1,
+ CA_LED_OFF,
+};
+
+static void cortina_led_write(void __iomem *reg, unsigned long data)
+{
+ writel(data, reg);
+}
+
+static unsigned long cortina_led_read(void __iomem *reg)
+{
+ return readl(reg);
+}
+
+static enum led_state_t cortina_led_get_state(struct udevice *dev)
+{
+ struct cortina_led_cfg *priv = dev_get_priv(dev);
+ enum led_state_t state = LEDST_OFF;
+ u32 val;
+
+ val = readl(priv->regs);
+
+ if (val & LED_SW_EVENT)
+ state = LEDST_ON;
+
+ return state;
+}
+
+static int cortina_led_set_state(struct udevice *dev, enum led_state_t state)
+{
+ u32 val;
+ struct cortina_led_cfg *priv = dev_get_priv(dev);
+
+ val = readl(priv->regs);
+ val &= ~(LED_OFF_ON_MASK << LED_OFF_ON_SHIFT);
+
+ switch (state) {
+ case LEDST_OFF:
+ val &= ~LED_SW_EVENT;
+ val |= CA_LED_OFF << LED_OFF_ON_SHIFT;
+ cortina_led_write(priv->regs, val);
+ break;
+ case LEDST_ON:
+ val |= LED_SW_EVENT;
+ val |= CA_LED_ON << LED_OFF_ON_SHIFT;
+ cortina_led_write(priv->regs, val);
+ break;
+ case LEDST_TOGGLE:
+ if (cortina_led_get_state(dev) == LEDST_OFF)
+ return cortina_led_set_state(dev, LEDST_ON);
+ else
+ return cortina_led_set_state(dev, LEDST_OFF);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static const struct led_ops cortina_led_ops = {
+ .get_state = cortina_led_get_state,
+ .set_state = cortina_led_set_state,
+};
+
+static int ca_led_of_to_plat(struct udevice *dev)
+{
+ struct led_uc_plat *uc_plat = dev_get_uclass_plat(dev);
+
+ /* Top-level LED node */
+ if (!uc_plat->label) {
+ struct cortina_led_plat *plt = dev_get_plat(dev);
+
+ plt->rate1 =
+ dev_read_u32_default(dev, "Cortina,blink-rate1", 256);
+ plt->rate2 =
+ dev_read_u32_default(dev, "Cortina,blink-rate2", 512);
+ plt->ctrl_regs = dev_remap_addr(dev);
+ } else {
+ struct cortina_led_cfg *priv = dev_get_priv(dev);
+
+ priv->regs = dev_remap_addr(dev_get_parent(dev));
+ priv->pin = dev_read_u32_default(dev, "pin", LED_MAX_COUNT);
+ priv->blink_sel = dev_read_u32_default(dev, "blink-sel", 0);
+ priv->off_event = dev_read_u32_default(dev, "off-event", 0);
+ priv->blink_event = dev_read_u32_default(dev, "blink-event", 0);
+ priv->on_event = dev_read_u32_default(dev, "on-event", 0);
+ priv->port = dev_read_u32_default(dev, "port", 0);
+
+ if (dev_read_bool(dev, "active-low"))
+ priv->active_low = true;
+ else
+ priv->active_low = false;
+ }
+
+ return 0;
+}
+
+static int cortina_led_probe(struct udevice *dev)
+{
+ struct led_uc_plat *uc_plat = dev_get_uclass_plat(dev);
+
+ /* Top-level LED node */
+ if (!uc_plat->label) {
+ struct cortina_led_plat *plat = dev_get_plat(dev);
+ u32 reg_value, val;
+ u16 rate1, rate2;
+
+ if (!plat->ctrl_regs)
+ return -EINVAL;
+
+ reg_value = 0;
+ reg_value |= LED_CLK_POLARITY;
+
+ rate1 = plat->rate1;
+ rate2 = plat->rate2;
+
+ val = rate1 / 16 - 1;
+ rate1 = val > LED_MAX_HW_BLINK ?
+ LED_MAX_HW_BLINK : val;
+ reg_value |= (rate1 & LED_BLINK_RATE1_MASK) <<
+ LED_BLINK_RATE1_SHIFT;
+
+ val = rate2 / 16 - 1;
+ rate2 = val > LED_MAX_HW_BLINK ?
+ LED_MAX_HW_BLINK : val;
+ reg_value |= (rate2 & LED_BLINK_RATE2_MASK) <<
+ LED_BLINK_RATE2_SHIFT;
+
+ cortina_led_write(plat->ctrl_regs, reg_value);
+
+ } else {
+ struct cortina_led_cfg *priv = dev_get_priv(dev);
+ void __iomem *regs;
+ u32 val, port, off_event, blink_event, on_event;
+
+ regs = priv->regs;
+ if (!regs)
+ return -EINVAL;
+
+ if (priv->pin >= LED_MAX_COUNT)
+ return -EINVAL;
+
+ priv->regs = regs + 4 + priv->pin * 4;
+
+ val = cortina_led_read(priv->regs);
+
+ if (priv->active_low)
+ val |= LED_OFF_VAL;
+ else
+ val &= ~LED_OFF_VAL;
+
+ if (priv->blink_sel == 0)
+ val &= ~LED_BLINK_SEL;
+ else if (priv->blink_sel == 1)
+ val |= LED_BLINK_SEL;
+
+ off_event = priv->off_event;
+ val &= ~(LED_EVENT_OFF_MASK << LED_EVENT_OFF_SHIFT);
+ if (off_event != 0)
+ val |= BIT(off_event) << LED_EVENT_OFF_SHIFT;
+
+ blink_event = priv->blink_event;
+ val &= ~(LED_EVENT_BLINK_MASK << LED_EVENT_BLINK_SHIFT);
+ if (blink_event != 0)
+ val |= BIT(blink_event) << LED_EVENT_BLINK_SHIFT;
+
+ on_event = priv->on_event;
+ val &= ~(LED_EVENT_ON_MASK << LED_EVENT_ON_SHIFT);
+ if (on_event != 0)
+ val |= BIT(on_event) << LED_EVENT_ON_SHIFT;
+
+ port = priv->port;
+ val &= ~(LED_PORT_MASK << LED_PORT_SHIFT);
+ val |= port << LED_PORT_SHIFT;
+
+ /* force off */
+ val &= ~(LED_OFF_ON_MASK << LED_OFF_ON_SHIFT);
+ val |= CA_LED_OFF << LED_OFF_ON_SHIFT;
+
+ cortina_led_write(priv->regs, val);
+ }
+
+ return 0;
+}
+
+static int cortina_led_bind(struct udevice *parent)
+{
+ ofnode node;
+
+ dev_for_each_subnode(node, parent) {
+ struct led_uc_plat *uc_plat;
+ struct udevice *dev;
+ const char *label;
+ int ret;
+
+ label = ofnode_read_string(node, "label");
+ if (!label) {
+ debug("%s: node %s has no label\n", __func__,
+ ofnode_get_name(node));
+ return -EINVAL;
+ }
+
+ ret = device_bind_driver_to_node(parent, "ca-leds",
+ ofnode_get_name(node),
+ node, &dev);
+ if (ret)
+ return ret;
+ uc_plat = dev_get_uclass_plat(dev);
+ uc_plat->label = label;
+ }
+
+ return 0;
+}
+
+static const struct udevice_id ca_led_ids[] = {
+ { .compatible = "cortina,ca-leds" },
+ { /* sentinel */ }
+};
+
+U_BOOT_DRIVER(cortina_led) = {
+ .name = "ca-leds",
+ .id = UCLASS_LED,
+ .of_match = ca_led_ids,
+ .of_to_plat = ca_led_of_to_plat,
+ .bind = cortina_led_bind,
+ .probe = cortina_led_probe,
+ .plat_auto = sizeof(struct cortina_led_plat),
+ .priv_auto = sizeof(struct cortina_led_cfg),
+ .ops = &cortina_led_ops,
+};
diff --git a/roms/u-boot/drivers/led/led_gpio.c b/roms/u-boot/drivers/led/led_gpio.c
new file mode 100644
index 000000000..67ece3cbc
--- /dev/null
+++ b/roms/u-boot/drivers/led/led_gpio.c
@@ -0,0 +1,135 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2015 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <led.h>
+#include <log.h>
+#include <malloc.h>
+#include <asm/gpio.h>
+#include <dm/lists.h>
+
+struct led_gpio_priv {
+ struct gpio_desc gpio;
+};
+
+static int gpio_led_set_state(struct udevice *dev, enum led_state_t state)
+{
+ struct led_gpio_priv *priv = dev_get_priv(dev);
+ int ret;
+
+ if (!dm_gpio_is_valid(&priv->gpio))
+ return -EREMOTEIO;
+ switch (state) {
+ case LEDST_OFF:
+ case LEDST_ON:
+ break;
+ case LEDST_TOGGLE:
+ ret = dm_gpio_get_value(&priv->gpio);
+ if (ret < 0)
+ return ret;
+ state = !ret;
+ break;
+ default:
+ return -ENOSYS;
+ }
+
+ return dm_gpio_set_value(&priv->gpio, state);
+}
+
+static enum led_state_t gpio_led_get_state(struct udevice *dev)
+{
+ struct led_gpio_priv *priv = dev_get_priv(dev);
+ int ret;
+
+ if (!dm_gpio_is_valid(&priv->gpio))
+ return -EREMOTEIO;
+ ret = dm_gpio_get_value(&priv->gpio);
+ if (ret < 0)
+ return ret;
+
+ return ret ? LEDST_ON : LEDST_OFF;
+}
+
+static int led_gpio_probe(struct udevice *dev)
+{
+ struct led_uc_plat *uc_plat = dev_get_uclass_plat(dev);
+ struct led_gpio_priv *priv = dev_get_priv(dev);
+ int ret;
+
+ /* Ignore the top-level LED node */
+ if (!uc_plat->label)
+ return 0;
+
+ ret = gpio_request_by_name(dev, "gpios", 0, &priv->gpio, GPIOD_IS_OUT);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int led_gpio_remove(struct udevice *dev)
+{
+ /*
+ * The GPIO driver may have already been removed. We will need to
+ * address this more generally.
+ */
+#ifndef CONFIG_SANDBOX
+ struct led_gpio_priv *priv = dev_get_priv(dev);
+
+ if (dm_gpio_is_valid(&priv->gpio))
+ dm_gpio_free(dev, &priv->gpio);
+#endif
+
+ return 0;
+}
+
+static int led_gpio_bind(struct udevice *parent)
+{
+ struct udevice *dev;
+ ofnode node;
+ int ret;
+
+ dev_for_each_subnode(node, parent) {
+ struct led_uc_plat *uc_plat;
+ const char *label;
+
+ label = ofnode_read_string(node, "label");
+ if (!label)
+ label = ofnode_get_name(node);
+ ret = device_bind_driver_to_node(parent, "gpio_led",
+ ofnode_get_name(node),
+ node, &dev);
+ if (ret)
+ return ret;
+ uc_plat = dev_get_uclass_plat(dev);
+ uc_plat->label = label;
+ }
+
+ return 0;
+}
+
+static const struct led_ops gpio_led_ops = {
+ .set_state = gpio_led_set_state,
+ .get_state = gpio_led_get_state,
+};
+
+static const struct udevice_id led_gpio_ids[] = {
+ { .compatible = "gpio-leds" },
+ { }
+};
+
+U_BOOT_DRIVER(led_gpio) = {
+ .name = "gpio_led",
+ .id = UCLASS_LED,
+ .of_match = led_gpio_ids,
+ .ops = &gpio_led_ops,
+ .priv_auto = sizeof(struct led_gpio_priv),
+ .bind = led_gpio_bind,
+ .probe = led_gpio_probe,
+ .remove = led_gpio_remove,
+};