GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)

This commit is contained in:
lai
2026-09-06 03:52:57 +08:00
commit b1928b41c0
21813 changed files with 4413081 additions and 0 deletions
@@ -0,0 +1,394 @@
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_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_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
@@ -0,0 +1,10 @@
# 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
@@ -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_platdata(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_platdata_auto_alloc_size = sizeof(struct led_uc_plat),
};
@@ -0,0 +1,244 @@
// 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 <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_platdata(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_platdata(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_alloc_size = sizeof(struct bcm6328_led_priv),
};
@@ -0,0 +1,213 @@
// 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 <asm/io.h>
#include <dm/lists.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_platdata(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_platdata(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_alloc_size = sizeof(struct bcm6358_led_priv),
.ops = &bcm6358_led_ops,
};
@@ -0,0 +1,250 @@
// 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 <asm/io.h>
#include <dm/lists.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
/* Soft LED input polarity register */
#define LED_SW_LED_IP_PPOL_REG 0xbc
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_platdata(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_SW_LED_IP_PPOL_REG, 1 << pin);
else
setbits_32(regs + LED_SW_LED_IP_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_platdata(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_alloc_size = sizeof(struct bcm6858_led_priv),
.ops = &bcm6858_led_ops,
};
@@ -0,0 +1,136 @@
// 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 <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_platdata(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) {
debug("%s: node %s has no label\n", __func__,
ofnode_get_name(node));
return -EINVAL;
}
ret = device_bind_driver_to_node(parent, "gpio_led",
ofnode_get_name(node),
node, &dev);
if (ret)
return ret;
uc_plat = dev_get_uclass_platdata(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_alloc_size = sizeof(struct led_gpio_priv),
.bind = led_gpio_bind,
.probe = led_gpio_probe,
.remove = led_gpio_remove,
};