[U-Boot] [PATCH 0/3] dm: led: add BCM6358 serial leds support

BCM6358 supports controlling serial LEDs (74x164) both by using spi-gpio or its LEDs controller.
Álvaro Fernández Rojas (3): dm: led: add BCM6358 led driver mips: bmips: add bcm6358-led driver support for BCM6358 mips: bmips: add NeufBox 4 (Sercomm) board
arch/mips/dts/brcm,bcm6358.dtsi | 9 ++ arch/mips/dts/sfr,nb4-ser.dts | 93 ++++++++++++++++ board/sfr/nb4_ser/Kconfig | 12 ++ board/sfr/nb4_ser/MAINTAINERS | 6 + board/sfr/nb4_ser/Makefile | 5 + board/sfr/nb4_ser/nb4-ser.c | 7 ++ configs/sfr_nb4-ser_ram_defconfig | 52 +++++++++ drivers/led/Kconfig | 7 ++ drivers/led/Makefile | 1 + drivers/led/led_bcm6358.c | 227 ++++++++++++++++++++++++++++++++++++++ include/configs/sfr_nb4_ser.h | 20 ++++ 11 files changed, 439 insertions(+) create mode 100644 arch/mips/dts/sfr,nb4-ser.dts create mode 100644 board/sfr/nb4_ser/Kconfig create mode 100644 board/sfr/nb4_ser/MAINTAINERS create mode 100644 board/sfr/nb4_ser/Makefile create mode 100644 board/sfr/nb4_ser/nb4-ser.c create mode 100644 configs/sfr_nb4-ser_ram_defconfig create mode 100644 drivers/led/led_bcm6358.c create mode 100644 include/configs/sfr_nb4_ser.h

This driver is a simplified version of linux/drivers/leds/leds-bcm6358.c
Signed-off-by: Álvaro Fernández Rojas noltari@gmail.com --- drivers/led/Kconfig | 7 ++ drivers/led/Makefile | 1 + drivers/led/led_bcm6358.c | 227 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 235 insertions(+) create mode 100644 drivers/led/led_bcm6358.c
diff --git a/drivers/led/Kconfig b/drivers/led/Kconfig index 50b27bd..e78502b 100644 --- a/drivers/led/Kconfig +++ b/drivers/led/Kconfig @@ -16,6 +16,13 @@ config LED_BCM6328 This option enables support for LEDs connected to the BCM6328 LED HW controller accessed via MMIO registers.
+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. + config LED_BLINK bool "Support LED blinking" depends on LED diff --git a/drivers/led/Makefile b/drivers/led/Makefile index d371ed5..9d079f8 100644 --- a/drivers/led/Makefile +++ b/drivers/led/Makefile @@ -7,4 +7,5 @@
obj-y += led-uclass.o obj-$(CONFIG_LED_BCM6328) += led_bcm6328.o +obj-$(CONFIG_LED_BCM6358) += led_bcm6358.o obj-$(CONFIG_$(SPL_)LED_GPIO) += led_gpio.o diff --git a/drivers/led/led_bcm6358.c b/drivers/led/led_bcm6358.c new file mode 100644 index 0000000..f792378 --- /dev/null +++ b/drivers/led/led_bcm6358.c @@ -0,0 +1,227 @@ +/* + * Copyright (C) 2017 Álvaro Fernández Rojas noltari@gmail.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#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) + +DECLARE_GLOBAL_DATA_PTR; + +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); + fdt_addr_t addr; + fdt_size_t size; + + /* Top-level LED node */ + if (!uc_plat->label) { + void __iomem *regs; + unsigned int clk_div; + u32 set_bits = 0; + + addr = dev_get_addr_size_index(dev, 0, &size); + if (addr == FDT_ADDR_T_NONE) + return -EINVAL; + + regs = ioremap(addr, size); + + if (fdt_getprop(gd->fdt_blob, dev_of_offset(dev), + "brcm,clk-dat-low", NULL)) + set_bits |= LED_CTRL_POL_MASK; + clk_div = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(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; + + addr = dev_get_addr_size_index(dev_get_parent(dev), 0, &size); + if (addr == FDT_ADDR_T_NONE) + return -EINVAL; + + pin = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(dev), "reg", + LEDS_MAX); + if (pin >= LEDS_MAX) + return -EINVAL; + + priv->regs = ioremap(addr, size); + priv->pin = pin; + + if (fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "active-low", + NULL)) + priv->active_low = true; + } + + return 0; +} + +static int bcm6358_led_bind(struct udevice *parent) +{ + const void *blob = gd->fdt_blob; + int node; + + for (node = fdt_first_subnode(blob, dev_of_offset(parent)); + node > 0; + node = fdt_next_subnode(blob, node)) { + struct led_uc_plat *uc_plat; + struct udevice *dev; + const char *label; + int ret; + + label = fdt_getprop(blob, node, "label", NULL); + if (!label) { + debug("%s: node %s has no label\n", __func__, + fdt_get_name(blob, node, NULL)); + return -EINVAL; + } + + ret = device_bind_driver_to_node(parent, "bcm6358-led", + fdt_get_name(blob, node, NULL), + 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, +};

On 3 May 2017 at 07:09, Álvaro Fernández Rojas noltari@gmail.com wrote:
This driver is a simplified version of linux/drivers/leds/leds-bcm6358.c
Signed-off-by: Álvaro Fernández Rojas noltari@gmail.com
drivers/led/Kconfig | 7 ++ drivers/led/Makefile | 1 + drivers/led/led_bcm6358.c | 227 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 235 insertions(+) create mode 100644 drivers/led/led_bcm6358.c
Similar comments to the earlier LED driver.
Reviewed-by: Simon Glass sjg@chromium.org

This driver can control up to 32 serial leds.
Signed-off-by: Álvaro Fernández Rojas noltari@gmail.com --- arch/mips/dts/brcm,bcm6358.dtsi | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/arch/mips/dts/brcm,bcm6358.dtsi b/arch/mips/dts/brcm,bcm6358.dtsi index 4c94555..edd0002 100644 --- a/arch/mips/dts/brcm,bcm6358.dtsi +++ b/arch/mips/dts/brcm,bcm6358.dtsi @@ -92,6 +92,15 @@ status = "disabled"; };
+ leds: led-controller@fffe00d0 { + compatible = "brcm,bcm6358-leds"; + reg = <0xfffe00d0 0x8>; + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + uart0: serial@fffe0100 { compatible = "brcm,bcm6345-uart"; reg = <0xfffe0100 0x18>;

On 3 May 2017 at 07:09, Álvaro Fernández Rojas noltari@gmail.com wrote:
This driver can control up to 32 serial leds.
Signed-off-by: Álvaro Fernández Rojas noltari@gmail.com
arch/mips/dts/brcm,bcm6358.dtsi | 9 +++++++++ 1 file changed, 9 insertions(+)
Reviewed-by: Simon Glass sjg@chromium.org

This serves as an example for bcm6358-leds.
Signed-off-by: Álvaro Fernández Rojas noltari@gmail.com --- arch/mips/dts/sfr,nb4-ser.dts | 93 +++++++++++++++++++++++++++++++++++++++ board/sfr/nb4_ser/Kconfig | 12 +++++ board/sfr/nb4_ser/MAINTAINERS | 6 +++ board/sfr/nb4_ser/Makefile | 5 +++ board/sfr/nb4_ser/nb4-ser.c | 7 +++ configs/sfr_nb4-ser_ram_defconfig | 52 ++++++++++++++++++++++ include/configs/sfr_nb4_ser.h | 20 +++++++++ 7 files changed, 195 insertions(+) create mode 100644 arch/mips/dts/sfr,nb4-ser.dts create mode 100644 board/sfr/nb4_ser/Kconfig create mode 100644 board/sfr/nb4_ser/MAINTAINERS create mode 100644 board/sfr/nb4_ser/Makefile create mode 100644 board/sfr/nb4_ser/nb4-ser.c create mode 100644 configs/sfr_nb4-ser_ram_defconfig create mode 100644 include/configs/sfr_nb4_ser.h
diff --git a/arch/mips/dts/sfr,nb4-ser.dts b/arch/mips/dts/sfr,nb4-ser.dts new file mode 100644 index 0000000..f2092e9 --- /dev/null +++ b/arch/mips/dts/sfr,nb4-ser.dts @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2017 Álvaro Fernández Rojas noltari@gmail.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/dts-v1/; + +#include "brcm,bcm6358.dtsi" + +/ { + model = "SFR NeufBox 4 (Sercomm) Board"; + compatible = "sfr,nb4-ser", "brcm,bcm6358"; + + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + gpio-leds { + compatible = "gpio-leds"; + + traffic_white { + label = "NB4-SER:white:traffic"; + gpios = <&gpio0 2 GPIO_ACTIVE_LOW>; + }; + + service_blue { + label = "NB4-SER:blue:service"; + gpios = <&gpio0 4 GPIO_ACTIVE_LOW>; + }; + + wifi_white { + label = "NB4-SER:white:wifi"; + gpios = <&gpio0 15 GPIO_ACTIVE_LOW>; + }; + + service_red { + label = "NB4-SER:red:service"; + gpios = <&gpio0 29 GPIO_ACTIVE_LOW>; + }; + + service_green { + label = "NB4-SER:green:service"; + gpios = <&gpio0 30 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&gpio0 { + status = "okay"; +}; + +&leds { + status = "okay"; + brcm,clk-div = <1>; + + led@0 { + reg = <0>; + active-low; + label = "NB4-SER:white:alarm"; + }; + + led@2 { + reg = <2>; + active-low; + label = "NB4-SER:white:tv"; + }; + + led@3 { + reg = <3>; + active-low; + label = "NB4-SER:white:tel"; + }; + + led@4 { + reg = <4>; + active-low; + label = "NB4-SER:white:adsl"; + }; +}; + +&pflash { + status = "okay"; +}; + +&uart0 { + u-boot,dm-pre-reloc; + status = "okay"; +}; diff --git a/board/sfr/nb4_ser/Kconfig b/board/sfr/nb4_ser/Kconfig new file mode 100644 index 0000000..78aefb5 --- /dev/null +++ b/board/sfr/nb4_ser/Kconfig @@ -0,0 +1,12 @@ +if BOARD_SFR_NB4_SER + +config SYS_BOARD + default "nb4_ser" + +config SYS_VENDOR + default "sfr" + +config SYS_CONFIG_NAME + default "sfr_nb4_ser" + +endif diff --git a/board/sfr/nb4_ser/MAINTAINERS b/board/sfr/nb4_ser/MAINTAINERS new file mode 100644 index 0000000..bf80267 --- /dev/null +++ b/board/sfr/nb4_ser/MAINTAINERS @@ -0,0 +1,6 @@ +SFR NEUFBOX 4 SERCOMM BOARD +M: Álvaro Fernández Rojas noltari@gmail.com +S: Maintained +F: board/sfr/nb4_ser/ +F: include/configs/sfr_nb4_ser.h +F: configs/sfr_nb4-ser_ram_defconfig diff --git a/board/sfr/nb4_ser/Makefile b/board/sfr/nb4_ser/Makefile new file mode 100644 index 0000000..f3b1404 --- /dev/null +++ b/board/sfr/nb4_ser/Makefile @@ -0,0 +1,5 @@ +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += nb4-ser.o diff --git a/board/sfr/nb4_ser/nb4-ser.c b/board/sfr/nb4_ser/nb4-ser.c new file mode 100644 index 0000000..d181ca6 --- /dev/null +++ b/board/sfr/nb4_ser/nb4-ser.c @@ -0,0 +1,7 @@ +/* + * Copyright (C) 2017 Álvaro Fernández Rojas noltari@gmail.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> diff --git a/configs/sfr_nb4-ser_ram_defconfig b/configs/sfr_nb4-ser_ram_defconfig new file mode 100644 index 0000000..8b885e3 --- /dev/null +++ b/configs/sfr_nb4-ser_ram_defconfig @@ -0,0 +1,52 @@ +CONFIG_ARCH_BMIPS=y +CONFIG_BAUDRATE=115200 +CONFIG_BCM6345_GPIO=y +CONFIG_BCM6345_SERIAL=y +CONFIG_BMIPS_BOOT_RAM=y +CONFIG_BOARD_SFR_NB4_SER=y +CONFIG_CFI_FLASH=y +# CONFIG_CMD_BOOTD is not set +CONFIG_CMD_BOOTM=y +CONFIG_CMD_CPU=y +# CONFIG_CMD_CRC32 is not set +# CONFIG_CMD_EDITENV is not set +# CONFIG_CMD_ELF is not set +# CONFIG_CMD_ENV_EXISTS is not set +# CONFIG_CMD_EXPORTENV is not set +CONFIG_CMD_FLASH=y +# CONFIG_CMD_FPGA is not set +# CONFIG_CMD_GPIO is not set +# CONFIG_CMD_IMLS is not set +# CONFIG_CMD_IMPORTENV is not set +CONFIG_CMD_LED=y +CONFIG_CMD_LICENSE=y +CONFIG_CMD_LOADB=y +# CONFIG_CMD_LOADS is not set +CONFIG_CMD_MEMINFO=y +# CONFIG_CMD_MISC is not set +# CONFIG_CMD_NET is not set +# CONFIG_CMD_NFS is not set +# CONFIG_CMD_SAVEENV is not set +# CONFIG_CMD_XIMG is not set +CONFIG_DEFAULT_DEVICE_TREE="sfr,nb4-ser" +CONFIG_DISPLAY_CPUINFO=y +# CONFIG_DM_DEVICE_REMOVE is not set +CONFIG_DM_GPIO=y +CONFIG_DM_SERIAL=y +CONFIG_HUSH_PARSER=y +CONFIG_LED=y +CONFIG_LED_BCM6358=y +CONFIG_LED_GPIO=y +CONFIG_MIPS=y +# CONFIG_MIPS_BOOT_CMDLINE_LEGACY is not set +# CONFIG_MIPS_BOOT_ENV_LEGACY is not set +CONFIG_MIPS_BOOT_FDT=y +CONFIG_MTD=y +CONFIG_MTD_DEVICE=y +CONFIG_MTD_NOR_FLASH=y +CONFIG_OF_STDOUT_VIA_ALIAS=y +CONFIG_SOC_BMIPS_BCM6358=y +# CONFIG_SPL_SERIAL_PRESENT is not set +# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set +CONFIG_SYS_PROMPT="NB4-SER # " +CONFIG_SYS_TEXT_BASE=0x80010000 diff --git a/include/configs/sfr_nb4_ser.h b/include/configs/sfr_nb4_ser.h new file mode 100644 index 0000000..ab64518 --- /dev/null +++ b/include/configs/sfr_nb4_ser.h @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2017 Álvaro Fernández Rojas noltari@gmail.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <configs/bmips_common.h> +#include <configs/bmips_bcm6358.h> + +#define CONFIG_REMAKE_ELF + +#define CONFIG_ENV_IS_NOWHERE +#define CONFIG_ENV_SIZE (8 * 1024) + +#define CONFIG_AUTO_COMPLETE +#define CONFIG_CMDLINE_EDITING +#define CONFIG_SYS_LONGHELP + +#define CONFIG_SYS_FLASH_CFI 1 +#define CONFIG_FLASH_CFI_DRIVER 1

On 3 May 2017 at 07:09, Álvaro Fernández Rojas noltari@gmail.com wrote:
This serves as an example for bcm6358-leds.
Signed-off-by: Álvaro Fernández Rojas noltari@gmail.com
arch/mips/dts/sfr,nb4-ser.dts | 93 +++++++++++++++++++++++++++++++++++++++ board/sfr/nb4_ser/Kconfig | 12 +++++ board/sfr/nb4_ser/MAINTAINERS | 6 +++ board/sfr/nb4_ser/Makefile | 5 +++ board/sfr/nb4_ser/nb4-ser.c | 7 +++ configs/sfr_nb4-ser_ram_defconfig | 52 ++++++++++++++++++++++ include/configs/sfr_nb4_ser.h | 20 +++++++++ 7 files changed, 195 insertions(+) create mode 100644 arch/mips/dts/sfr,nb4-ser.dts create mode 100644 board/sfr/nb4_ser/Kconfig create mode 100644 board/sfr/nb4_ser/MAINTAINERS create mode 100644 board/sfr/nb4_ser/Makefile create mode 100644 board/sfr/nb4_ser/nb4-ser.c create mode 100644 configs/sfr_nb4-ser_ram_defconfig create mode 100644 include/configs/sfr_nb4_ser.h
Reviewed-by: Simon Glass sjg@chromium.org

BCM6358 supports controlling serial LEDs (74x164) both by using spi-gpio or its LEDs controller.
v2: Introduce changes suggested by Simon Glass
Álvaro Fernández Rojas (3): dm: led: add BCM6358 led driver mips: bmips: add bcm6358-led driver support for BCM6358 mips: bmips: add NeufBox 4 (Sercomm) board
arch/mips/dts/brcm,bcm6358.dtsi | 9 + arch/mips/dts/sfr,nb4-ser.dts | 93 ++++++++++ board/sfr/nb4_ser/Kconfig | 12 ++ board/sfr/nb4_ser/MAINTAINERS | 6 + board/sfr/nb4_ser/Makefile | 5 + board/sfr/nb4_ser/nb4-ser.c | 7 + configs/sfr_nb4-ser_ram_defconfig | 52 ++++++ doc/device-tree-bindings/leds/leds-bcm6358.txt | 141 +++++++++++++++ drivers/led/Kconfig | 8 + drivers/led/Makefile | 1 + drivers/led/led_bcm6358.c | 227 +++++++++++++++++++++++++ include/configs/sfr_nb4_ser.h | 20 +++ 12 files changed, 581 insertions(+) create mode 100644 arch/mips/dts/sfr,nb4-ser.dts create mode 100644 board/sfr/nb4_ser/Kconfig create mode 100644 board/sfr/nb4_ser/MAINTAINERS create mode 100644 board/sfr/nb4_ser/Makefile create mode 100644 board/sfr/nb4_ser/nb4-ser.c create mode 100644 configs/sfr_nb4-ser_ram_defconfig create mode 100644 doc/device-tree-bindings/leds/leds-bcm6358.txt create mode 100644 drivers/led/led_bcm6358.c create mode 100644 include/configs/sfr_nb4_ser.h

This driver is a simplified version of linux/drivers/leds/leds-bcm6358.c
Signed-off-by: Álvaro Fernández Rojas noltari@gmail.com Reviewed-by: Simon Glass sjg@chromium.org --- v2: Introduce changes suggested by Simon Glass: - Add DT binding file. - Add features description. - Switch to fdtdec_get_bool().
doc/device-tree-bindings/leds/leds-bcm6358.txt | 141 +++++++++++++++ drivers/led/Kconfig | 8 + drivers/led/Makefile | 1 + drivers/led/led_bcm6358.c | 227 +++++++++++++++++++++++++ 4 files changed, 377 insertions(+) create mode 100644 doc/device-tree-bindings/leds/leds-bcm6358.txt create mode 100644 drivers/led/led_bcm6358.c
diff --git a/doc/device-tree-bindings/leds/leds-bcm6358.txt b/doc/device-tree-bindings/leds/leds-bcm6358.txt new file mode 100644 index 0000000..e394d9e --- /dev/null +++ b/doc/device-tree-bindings/leds/leds-bcm6358.txt @@ -0,0 +1,141 @@ +LEDs connected to Broadcom BCM6358 controller + +This controller is present on BCM6358 and BCM6368. +In these SoCs there are Serial LEDs (LEDs connected to a 74x164 controller), +which can either be controlled by software (exporting the 74x164 as spi-gpio. +See Documentation/devicetree/bindings/gpio/gpio-74x164.txt), or +by hardware using this driver. + +Required properties: + - compatible : should be "brcm,bcm6358-leds". + - #address-cells : must be 1. + - #size-cells : must be 0. + - reg : BCM6358 LED controller address and size. + +Optional properties: + - brcm,clk-div : SCK signal divider. Possible values are 1, 2, 4 and 8. + Default : 1 + - brcm,clk-dat-low : Boolean, makes clock and data signals active low. + Default : false + +Each LED is represented as a sub-node of the brcm,bcm6358-leds device. + +LED sub-node required properties: + - reg : LED pin number (only LEDs 0 to 31 are valid). + +LED sub-node optional properties: + - label : see Documentation/devicetree/bindings/leds/common.txt + - active-low : Boolean, makes LED active low. + Default : false + +Examples: +Scenario 1 : BCM6358 + leds0: led-controller@fffe00d0 { + compatible = "brcm,bcm6358-leds"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0xfffe00d0 0x8>; + + alarm_white { + reg = <0>; + active-low; + label = "white:alarm"; + }; + tv_white { + reg = <2>; + active-low; + label = "white:tv"; + }; + tel_white { + reg = <3>; + active-low; + label = "white:tel"; + }; + adsl_white { + reg = <4>; + active-low; + label = "white:adsl"; + }; + }; + +Scenario 2 : BCM6368 + leds0: led-controller@100000d0 { + compatible = "brcm,bcm6358-leds"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x100000d0 0x8>; + brcm,pol-low; + brcm,clk-div = <4>; + + power_red { + reg = <0>; + active-low; + label = "red:power"; + }; + power_green { + reg = <1>; + active-low; + label = "green:power"; + default-state = "on"; + }; + power_blue { + reg = <2>; + label = "blue:power"; + }; + broadband_red { + reg = <3>; + active-low; + label = "red:broadband"; + }; + broadband_green { + reg = <4>; + label = "green:broadband"; + }; + broadband_blue { + reg = <5>; + active-low; + label = "blue:broadband"; + }; + wireless_red { + reg = <6>; + active-low; + label = "red:wireless"; + }; + wireless_green { + reg = <7>; + active-low; + label = "green:wireless"; + }; + wireless_blue { + reg = <8>; + label = "blue:wireless"; + }; + phone_red { + reg = <9>; + active-low; + label = "red:phone"; + }; + phone_green { + reg = <10>; + active-low; + label = "green:phone"; + }; + phone_blue { + reg = <11>; + label = "blue:phone"; + }; + upgrading_red { + reg = <12>; + active-low; + label = "red:upgrading"; + }; + upgrading_green { + reg = <13>; + active-low; + label = "green:upgrading"; + }; + upgrading_blue { + reg = <14>; + label = "blue:upgrading"; + }; + }; diff --git a/drivers/led/Kconfig b/drivers/led/Kconfig index dc19f4f..5da5c4a 100644 --- a/drivers/led/Kconfig +++ b/drivers/led/Kconfig @@ -20,6 +20,14 @@ config LED_BCM6328 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_BLINK bool "Support LED blinking" depends on LED diff --git a/drivers/led/Makefile b/drivers/led/Makefile index d371ed5..9d079f8 100644 --- a/drivers/led/Makefile +++ b/drivers/led/Makefile @@ -7,4 +7,5 @@
obj-y += led-uclass.o obj-$(CONFIG_LED_BCM6328) += led_bcm6328.o +obj-$(CONFIG_LED_BCM6358) += led_bcm6358.o obj-$(CONFIG_$(SPL_)LED_GPIO) += led_gpio.o diff --git a/drivers/led/led_bcm6358.c b/drivers/led/led_bcm6358.c new file mode 100644 index 0000000..11caecd --- /dev/null +++ b/drivers/led/led_bcm6358.c @@ -0,0 +1,227 @@ +/* + * Copyright (C) 2017 Álvaro Fernández Rojas noltari@gmail.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#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) + +DECLARE_GLOBAL_DATA_PTR; + +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); + fdt_addr_t addr; + fdt_size_t size; + + /* Top-level LED node */ + if (!uc_plat->label) { + void __iomem *regs; + unsigned int clk_div; + u32 set_bits = 0; + + addr = dev_get_addr_size_index(dev, 0, &size); + if (addr == FDT_ADDR_T_NONE) + return -EINVAL; + + regs = ioremap(addr, size); + + if (fdtdec_get_bool(gd->fdt_blob, dev_of_offset(dev), + "brcm,clk-dat-low")) + set_bits |= LED_CTRL_POL_MASK; + clk_div = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(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; + + addr = dev_get_addr_size_index(dev_get_parent(dev), 0, &size); + if (addr == FDT_ADDR_T_NONE) + return -EINVAL; + + pin = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(dev), "reg", + LEDS_MAX); + if (pin >= LEDS_MAX) + return -EINVAL; + + priv->regs = ioremap(addr, size); + priv->pin = pin; + + if (fdtdec_get_bool(gd->fdt_blob, dev_of_offset(dev), + "active-low")) + priv->active_low = true; + } + + return 0; +} + +static int bcm6358_led_bind(struct udevice *parent) +{ + const void *blob = gd->fdt_blob; + int node; + + for (node = fdt_first_subnode(blob, dev_of_offset(parent)); + node > 0; + node = fdt_next_subnode(blob, node)) { + struct led_uc_plat *uc_plat; + struct udevice *dev; + const char *label; + int ret; + + label = fdt_getprop(blob, node, "label", NULL); + if (!label) { + debug("%s: node %s has no label\n", __func__, + fdt_get_name(blob, node, NULL)); + return -EINVAL; + } + + ret = device_bind_driver_to_node(parent, "bcm6358-led", + fdt_get_name(blob, node, NULL), + 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, +};

This driver can control up to 32 serial leds.
Signed-off-by: Álvaro Fernández Rojas noltari@gmail.com Reviewed-by: Simon Glass sjg@chromium.org --- v2: no changes.
arch/mips/dts/brcm,bcm6358.dtsi | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/arch/mips/dts/brcm,bcm6358.dtsi b/arch/mips/dts/brcm,bcm6358.dtsi index 4c94555..edd0002 100644 --- a/arch/mips/dts/brcm,bcm6358.dtsi +++ b/arch/mips/dts/brcm,bcm6358.dtsi @@ -92,6 +92,15 @@ status = "disabled"; };
+ leds: led-controller@fffe00d0 { + compatible = "brcm,bcm6358-leds"; + reg = <0xfffe00d0 0x8>; + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + uart0: serial@fffe0100 { compatible = "brcm,bcm6345-uart"; reg = <0xfffe0100 0x18>;

This serves as an example for bcm6358-leds.
Signed-off-by: Álvaro Fernández Rojas noltari@gmail.com Reviewed-by: Simon Glass sjg@chromium.org --- v2: no changes.
arch/mips/dts/sfr,nb4-ser.dts | 93 +++++++++++++++++++++++++++++++++++++++ board/sfr/nb4_ser/Kconfig | 12 +++++ board/sfr/nb4_ser/MAINTAINERS | 6 +++ board/sfr/nb4_ser/Makefile | 5 +++ board/sfr/nb4_ser/nb4-ser.c | 7 +++ configs/sfr_nb4-ser_ram_defconfig | 52 ++++++++++++++++++++++ include/configs/sfr_nb4_ser.h | 20 +++++++++ 7 files changed, 195 insertions(+) create mode 100644 arch/mips/dts/sfr,nb4-ser.dts create mode 100644 board/sfr/nb4_ser/Kconfig create mode 100644 board/sfr/nb4_ser/MAINTAINERS create mode 100644 board/sfr/nb4_ser/Makefile create mode 100644 board/sfr/nb4_ser/nb4-ser.c create mode 100644 configs/sfr_nb4-ser_ram_defconfig create mode 100644 include/configs/sfr_nb4_ser.h
diff --git a/arch/mips/dts/sfr,nb4-ser.dts b/arch/mips/dts/sfr,nb4-ser.dts new file mode 100644 index 0000000..f2092e9 --- /dev/null +++ b/arch/mips/dts/sfr,nb4-ser.dts @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2017 Álvaro Fernández Rojas noltari@gmail.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/dts-v1/; + +#include "brcm,bcm6358.dtsi" + +/ { + model = "SFR NeufBox 4 (Sercomm) Board"; + compatible = "sfr,nb4-ser", "brcm,bcm6358"; + + aliases { + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + gpio-leds { + compatible = "gpio-leds"; + + traffic_white { + label = "NB4-SER:white:traffic"; + gpios = <&gpio0 2 GPIO_ACTIVE_LOW>; + }; + + service_blue { + label = "NB4-SER:blue:service"; + gpios = <&gpio0 4 GPIO_ACTIVE_LOW>; + }; + + wifi_white { + label = "NB4-SER:white:wifi"; + gpios = <&gpio0 15 GPIO_ACTIVE_LOW>; + }; + + service_red { + label = "NB4-SER:red:service"; + gpios = <&gpio0 29 GPIO_ACTIVE_LOW>; + }; + + service_green { + label = "NB4-SER:green:service"; + gpios = <&gpio0 30 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&gpio0 { + status = "okay"; +}; + +&leds { + status = "okay"; + brcm,clk-div = <1>; + + led@0 { + reg = <0>; + active-low; + label = "NB4-SER:white:alarm"; + }; + + led@2 { + reg = <2>; + active-low; + label = "NB4-SER:white:tv"; + }; + + led@3 { + reg = <3>; + active-low; + label = "NB4-SER:white:tel"; + }; + + led@4 { + reg = <4>; + active-low; + label = "NB4-SER:white:adsl"; + }; +}; + +&pflash { + status = "okay"; +}; + +&uart0 { + u-boot,dm-pre-reloc; + status = "okay"; +}; diff --git a/board/sfr/nb4_ser/Kconfig b/board/sfr/nb4_ser/Kconfig new file mode 100644 index 0000000..78aefb5 --- /dev/null +++ b/board/sfr/nb4_ser/Kconfig @@ -0,0 +1,12 @@ +if BOARD_SFR_NB4_SER + +config SYS_BOARD + default "nb4_ser" + +config SYS_VENDOR + default "sfr" + +config SYS_CONFIG_NAME + default "sfr_nb4_ser" + +endif diff --git a/board/sfr/nb4_ser/MAINTAINERS b/board/sfr/nb4_ser/MAINTAINERS new file mode 100644 index 0000000..bf80267 --- /dev/null +++ b/board/sfr/nb4_ser/MAINTAINERS @@ -0,0 +1,6 @@ +SFR NEUFBOX 4 SERCOMM BOARD +M: Álvaro Fernández Rojas noltari@gmail.com +S: Maintained +F: board/sfr/nb4_ser/ +F: include/configs/sfr_nb4_ser.h +F: configs/sfr_nb4-ser_ram_defconfig diff --git a/board/sfr/nb4_ser/Makefile b/board/sfr/nb4_ser/Makefile new file mode 100644 index 0000000..f3b1404 --- /dev/null +++ b/board/sfr/nb4_ser/Makefile @@ -0,0 +1,5 @@ +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += nb4-ser.o diff --git a/board/sfr/nb4_ser/nb4-ser.c b/board/sfr/nb4_ser/nb4-ser.c new file mode 100644 index 0000000..d181ca6 --- /dev/null +++ b/board/sfr/nb4_ser/nb4-ser.c @@ -0,0 +1,7 @@ +/* + * Copyright (C) 2017 Álvaro Fernández Rojas noltari@gmail.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> diff --git a/configs/sfr_nb4-ser_ram_defconfig b/configs/sfr_nb4-ser_ram_defconfig new file mode 100644 index 0000000..8b885e3 --- /dev/null +++ b/configs/sfr_nb4-ser_ram_defconfig @@ -0,0 +1,52 @@ +CONFIG_ARCH_BMIPS=y +CONFIG_BAUDRATE=115200 +CONFIG_BCM6345_GPIO=y +CONFIG_BCM6345_SERIAL=y +CONFIG_BMIPS_BOOT_RAM=y +CONFIG_BOARD_SFR_NB4_SER=y +CONFIG_CFI_FLASH=y +# CONFIG_CMD_BOOTD is not set +CONFIG_CMD_BOOTM=y +CONFIG_CMD_CPU=y +# CONFIG_CMD_CRC32 is not set +# CONFIG_CMD_EDITENV is not set +# CONFIG_CMD_ELF is not set +# CONFIG_CMD_ENV_EXISTS is not set +# CONFIG_CMD_EXPORTENV is not set +CONFIG_CMD_FLASH=y +# CONFIG_CMD_FPGA is not set +# CONFIG_CMD_GPIO is not set +# CONFIG_CMD_IMLS is not set +# CONFIG_CMD_IMPORTENV is not set +CONFIG_CMD_LED=y +CONFIG_CMD_LICENSE=y +CONFIG_CMD_LOADB=y +# CONFIG_CMD_LOADS is not set +CONFIG_CMD_MEMINFO=y +# CONFIG_CMD_MISC is not set +# CONFIG_CMD_NET is not set +# CONFIG_CMD_NFS is not set +# CONFIG_CMD_SAVEENV is not set +# CONFIG_CMD_XIMG is not set +CONFIG_DEFAULT_DEVICE_TREE="sfr,nb4-ser" +CONFIG_DISPLAY_CPUINFO=y +# CONFIG_DM_DEVICE_REMOVE is not set +CONFIG_DM_GPIO=y +CONFIG_DM_SERIAL=y +CONFIG_HUSH_PARSER=y +CONFIG_LED=y +CONFIG_LED_BCM6358=y +CONFIG_LED_GPIO=y +CONFIG_MIPS=y +# CONFIG_MIPS_BOOT_CMDLINE_LEGACY is not set +# CONFIG_MIPS_BOOT_ENV_LEGACY is not set +CONFIG_MIPS_BOOT_FDT=y +CONFIG_MTD=y +CONFIG_MTD_DEVICE=y +CONFIG_MTD_NOR_FLASH=y +CONFIG_OF_STDOUT_VIA_ALIAS=y +CONFIG_SOC_BMIPS_BCM6358=y +# CONFIG_SPL_SERIAL_PRESENT is not set +# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set +CONFIG_SYS_PROMPT="NB4-SER # " +CONFIG_SYS_TEXT_BASE=0x80010000 diff --git a/include/configs/sfr_nb4_ser.h b/include/configs/sfr_nb4_ser.h new file mode 100644 index 0000000..ab64518 --- /dev/null +++ b/include/configs/sfr_nb4_ser.h @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2017 Álvaro Fernández Rojas noltari@gmail.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <configs/bmips_common.h> +#include <configs/bmips_bcm6358.h> + +#define CONFIG_REMAKE_ELF + +#define CONFIG_ENV_IS_NOWHERE +#define CONFIG_ENV_SIZE (8 * 1024) + +#define CONFIG_AUTO_COMPLETE +#define CONFIG_CMDLINE_EDITING +#define CONFIG_SYS_LONGHELP + +#define CONFIG_SYS_FLASH_CFI 1 +#define CONFIG_FLASH_CFI_DRIVER 1

Am 03.05.2017 um 15:09 schrieb Álvaro Fernández Rojas:
BCM6358 supports controlling serial LEDs (74x164) both by using spi-gpio or its LEDs controller.
Álvaro Fernández Rojas (3): dm: led: add BCM6358 led driver mips: bmips: add bcm6358-led driver support for BCM6358 mips: bmips: add NeufBox 4 (Sercomm) board
arch/mips/dts/brcm,bcm6358.dtsi | 9 ++ arch/mips/dts/sfr,nb4-ser.dts | 93 ++++++++++++++++ board/sfr/nb4_ser/Kconfig | 12 ++ board/sfr/nb4_ser/MAINTAINERS | 6 + board/sfr/nb4_ser/Makefile | 5 + board/sfr/nb4_ser/nb4-ser.c | 7 ++ configs/sfr_nb4-ser_ram_defconfig | 52 +++++++++ drivers/led/Kconfig | 7 ++ drivers/led/Makefile | 1 + drivers/led/led_bcm6358.c | 227 ++++++++++++++++++++++++++++++++++++++ include/configs/sfr_nb4_ser.h | 20 ++++ 11 files changed, 439 insertions(+) create mode 100644 arch/mips/dts/sfr,nb4-ser.dts create mode 100644 board/sfr/nb4_ser/Kconfig create mode 100644 board/sfr/nb4_ser/MAINTAINERS create mode 100644 board/sfr/nb4_ser/Makefile create mode 100644 board/sfr/nb4_ser/nb4-ser.c create mode 100644 configs/sfr_nb4-ser_ram_defconfig create mode 100644 drivers/led/led_bcm6358.c create mode 100644 include/configs/sfr_nb4_ser.h
series applied to u-boot-mips/next, thanks
participants (3)
-
Daniel Schwierzeck
-
Simon Glass
-
Álvaro Fernández Rojas