mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Imre Kaloz <kaloz@kernel.org>
To: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Cc: linux-mips@vger.kernel.org, linux-kernel@vger.kernel.org,
	Lee Jones <lee@kernel.org>, Pavel Machek <pavel@kernel.org>,
	linux-leds@vger.kernel.org
Subject: [PATCH v2 51/53] leds: Add driver for the SGI Fuel and Tezro front-panel LEDs
Date: Tue, 13 Oct 2026 15:17:11 +0200	[thread overview]
Message-ID: <bdc0fa8089faf9ce4ff80695035173ab59357227.1791890466.git.kaloz@kernel.org> (raw)
In-Reply-To: <cover.1791890466.git.kaloz@kernel.org>

The SGI Fuel and Tezro front-panel LEDs are set through the L1 system
controller, whose LED request switches off every LED outside its mask,
so send the pattern of both LEDs on each change. Probe takes over the
PROM's state without writing it.

Signed-off-by: Imre Kaloz <kaloz@kernel.org>
---
 drivers/leds/Kconfig     |  12 ++++
 drivers/leds/Makefile    |   1 +
 drivers/leds/leds-ip35.c | 144 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 157 insertions(+)
 create mode 100644 drivers/leds/leds-ip35.c

diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index d0d3182236be..9ca75364264b 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -1035,6 +1035,18 @@ config LEDS_IP30
 	  To compile this driver as a module, choose M here: the module
 	  will be called leds-ip30.
 
+config LEDS_IP35
+	tristate "LED support for SGI Fuel and Tezro"
+	depends on LEDS_CLASS
+	depends on SGI_IP27
+	help
+	  This option enables support for the red and white front-panel
+	  LEDs of SGI Fuel and Tezro workstations, which the L1 system
+	  controller drives.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called leds-ip35.
+
 config LEDS_ACER_A500
 	tristate "Power button LED support for Acer Iconia Tab A500"
 	depends on LEDS_CLASS && MFD_ACER_A500_EC
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index a68244bd50fb..b45d1d70c431 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -36,6 +36,7 @@ obj-$(CONFIG_LEDS_GPIO_REGISTER)	+= leds-gpio-register.o
 obj-$(CONFIG_LEDS_HP6XX)		+= leds-hp6xx.o
 obj-$(CONFIG_LEDS_INTEL_SS4200)		+= leds-ss4200.o
 obj-$(CONFIG_LEDS_IP30)			+= leds-ip30.o
+obj-$(CONFIG_LEDS_IP35)			+= leds-ip35.o
 obj-$(CONFIG_LEDS_IPAQ_MICRO)		+= leds-ipaq-micro.o
 obj-$(CONFIG_LEDS_IS31FL319X)		+= leds-is31fl319x.o
 obj-$(CONFIG_LEDS_IS31FL32XX)		+= leds-is31fl32xx.o
diff --git a/drivers/leds/leds-ip35.c b/drivers/leds/leds-ip35.c
new file mode 100644
index 000000000000..fba918265e3d
--- /dev/null
+++ b/drivers/leds/leds-ip35.c
@@ -0,0 +1,144 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * LED driver for the SGI Fuel and Tezro front panels, which the L1
+ * system controller drives.
+ *
+ * Copyright (C) 2026 Imre Kaloz <kaloz@kernel.org>
+ */
+
+#include <linux/leds.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+
+#include <dt-bindings/leds/common.h>
+
+#include <asm/sn/l1.h>
+
+struct ip35_leds;
+
+struct ip35_led {
+	struct led_classdev cdev;
+	struct ip35_leds *leds;
+	unsigned int mask;
+	unsigned int state;
+};
+
+struct ip35_leds {
+	struct mutex lock;	/* protects ->state of both LEDs */
+	struct ip35_led led[2];
+};
+
+/*
+ * ON and BLINK switch off every LED outside their mask, so each change
+ * sends the pattern of both LEDs. A steady LED next to a blinking one
+ * cannot be shown; the blinking one wins.
+ */
+static int ip35_led_update(struct ip35_led *led, unsigned int state)
+{
+	struct ip35_leds *leds = led->leds;
+	unsigned int old, on = 0, blink = 0;
+	int i, ret;
+
+	mutex_lock(&leds->lock);
+
+	old = led->state;
+	led->state = state;
+
+	for (i = 0; i < ARRAY_SIZE(leds->led); i++) {
+		if (leds->led[i].state == L1_LED_ON)
+			on |= leds->led[i].mask;
+		else if (leds->led[i].state == L1_LED_BLINK)
+			blink |= leds->led[i].mask;
+	}
+
+	if (blink)
+		ret = l1_set_leds(blink, L1_LED_BLINK);
+	else if (on)
+		ret = l1_set_leds(on, L1_LED_ON);
+	else
+		ret = l1_set_leds(L1_LED_RED | L1_LED_WHITE, L1_LED_OFF);
+
+	if (ret)
+		led->state = old;
+
+	mutex_unlock(&leds->lock);
+
+	return ret;
+}
+
+static int ip35_led_set(struct led_classdev *cdev, enum led_brightness value)
+{
+	struct ip35_led *led = container_of(cdev, struct ip35_led, cdev);
+
+	return ip35_led_update(led, value ? L1_LED_ON : L1_LED_OFF);
+}
+
+/* The L1 blinks at a fixed 2 s period of its own, whatever the delays. */
+static int ip35_led_blink_set(struct led_classdev *cdev,
+			      unsigned long *delay_on,
+			      unsigned long *delay_off)
+{
+	struct ip35_led *led = container_of(cdev, struct ip35_led, cdev);
+
+	*delay_on = 1000;
+	*delay_off = 1000;
+
+	return ip35_led_update(led, L1_LED_BLINK);
+}
+
+/* The PROM leaves the white LED lit and the red one dark. */
+static const struct {
+	const char *name;
+	unsigned int mask;
+	unsigned int state;
+} ip35_led_info[] = {
+	{ "white:" LED_FUNCTION_STATUS, L1_LED_WHITE, L1_LED_ON },
+	{ "red:" LED_FUNCTION_FAULT, L1_LED_RED, L1_LED_OFF },
+};
+
+static int ip35_leds_probe(struct platform_device *pdev)
+{
+	struct ip35_leds *leds;
+	int i, ret;
+
+	leds = devm_kzalloc(&pdev->dev, sizeof(*leds), GFP_KERNEL);
+	if (!leds)
+		return -ENOMEM;
+
+	ret = devm_mutex_init(&pdev->dev, &leds->lock);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < ARRAY_SIZE(leds->led); i++) {
+		struct ip35_led *led = &leds->led[i];
+
+		led->leds = leds;
+		led->mask = ip35_led_info[i].mask;
+		led->state = ip35_led_info[i].state;
+		led->cdev.name = ip35_led_info[i].name;
+		led->cdev.max_brightness = 1;
+		led->cdev.brightness = led->state == L1_LED_ON;
+		led->cdev.brightness_set_blocking = ip35_led_set;
+		led->cdev.blink_set = ip35_led_blink_set;
+
+		ret = devm_led_classdev_register(&pdev->dev, &led->cdev);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static struct platform_driver ip35_leds_driver = {
+	.probe		= ip35_leds_probe,
+	.driver		= {
+		.name	= "ip35-leds",
+	},
+};
+module_platform_driver(ip35_leds_driver);
+
+MODULE_AUTHOR("Imre Kaloz <kaloz@kernel.org>");
+MODULE_DESCRIPTION("SGI Fuel and Tezro front-panel LED driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:ip35-leds");
-- 
2.47.3


  parent reply	other threads:[~2026-10-13 13:20 UTC|newest]

Thread overview: 60+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-13 13:16 [PATCH v2 00/53] MIPS: SGI-IP27: add support for the IP35 (Bedrock hub) machines Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 01/53] MIPS: PCI: xtalk-bridge: refuse device numbers past the last slot Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 02/53] MIPS: PCI: xtalk-bridge: assign slots the PROM leaves unconfigured Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 03/53] MIPS: PCI: xtalk-bridge: write a type 1 IOC3 through the type 1 window Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 04/53] MIPS: PCI: xtalk-bridge: flush config space writes Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 05/53] MIPS: PCI: xtalk-bridge: reassign slots whose devio window maps elsewhere Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 06/53] MIPS: Xtalk: guard the widget identification table from assembly Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 07/53] MIPS: SGI-IP27: dump the NMI save areas the CPU scan recorded Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 08/53] MIPS: SGI-IP27: add REMOTE_HUB_PI_S()/REMOTE_HUB_PI_L() Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 09/53] MIPS: SGI-IP27: detect Bedrock hubs at boot Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 10/53] MIPS: SGI-IP27: widen Kconfig for the Bedrock-based machines Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 11/53] MIPS: SGI-IP27: fold the dead SN1 arm out of klconfig.h Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 12/53] MIPS: SGI-IP27: choose the node address layout at runtime Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 13/53] MIPS: SGI-IP27: add the Bedrock hub register windows Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 14/53] MIPS: SGI-IP27: decode a Bedrock hub's node id and system size Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 15/53] MIPS: SGI-IP27: put a Bedrock hub's boot CPU in slot 0 Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 16/53] MIPS: SGI-IP27: lay out node memory in 1GB banks on Bedrock hubs Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 17/53] MIPS: SGI-IP27: reserve the bottom 64MB of node 0 " Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 18/53] MIPS: SGI-IP27: route interrupt masks and slices through both PIs Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 19/53] MIPS: SGI-IP27: address a CPU's own PI for NMI, IPI and RT counter Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 20/53] MIPS: SGI-IP27: take a CPU's node from the CPU table in per_cpu_init() Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 21/53] MIPS: SGI-IP27: resolve the mapped-kernel node shift at runtime Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 22/53] MIPS: SGI-IP27: load the kernel at node offset 0x40000 Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 23/53] MIPS: SGI-IP27: xbow_probe(): recognize KLTYPE_PBRICK_XBOW Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 24/53] MIPS: ip27_defconfig: enable the IOC3 MFD, its cell drivers and tg3 Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 25/53] net: ethernet: sgi: ioc3-eth: apply the DMA attributes only to 64-bit addresses Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 26/53] MIPS: SGI-IP27: pick the XBridge and PIC DMA address form by mask Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 27/53] MIPS: SGI-IP27: recognize the PXBow crossbar Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 28/53] MIPS: PCI: xtalk-bridge: recognize the PIC widget's 64-bit-only registers Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 29/53] MIPS: PCI: xtalk-bridge: match PIC's register-level differences Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 30/53] rtc: m48t35: support the SGI IP35 timekeeper's 1968 year base Imre Kaloz
2026-10-13 14:28   ` Alexandre Belloni
2026-10-13 13:16 ` [PATCH v2 31/53] mfd: ioc3: Add support for IOC4 Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 32/53] MIPS: SGI-IP27: dispatch the early console between IOC3 and IOC4 Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 33/53] MIPS: SGI-IP27: add L1 system controller support Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 34/53] MIPS: SGI-IP27: wire the L1 into reset and the Ethernet address Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 35/53] MIPS: PCI: xtalk-bridge: take the board part number from the L1 Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 36/53] mfd: ioc3: Add IP34 system-board entry to ioc3_infos[] Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 37/53] mfd: ioc3: Cross the serial IRQs on the Origin 300 IO8 Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 38/53] net: ethernet: sgi: ioc3-eth: fall back to the platform MAC address Imre Kaloz
2026-10-13 13:16 ` [PATCH v2 39/53] MIPS: SGI-IP27: don't register a w1 master on an XBridge or PIC Imre Kaloz
2026-10-13 13:17 ` [PATCH v2 40/53] MIPS: SGI-IP27: report a Bedrock machine as SGI IP35 Imre Kaloz
2026-10-13 13:17 ` [PATCH v2 41/53] MIPS: SGI-IP27: identify the machine by the L1 brick type Imre Kaloz
2026-10-13 13:17 ` [PATCH v2 42/53] MIPS: SGI-IP27: register the Odyssey graphics widget Imre Kaloz
2026-10-13 13:17 ` [PATCH v2 43/53] MIPS: SGI-IP27: take the console from the KLCONFIG header on IP35 Imre Kaloz
2026-10-13 13:17 ` [PATCH v2 44/53] MIPS: SGI-IP27: give each CPU its own topology package id Imre Kaloz
2026-10-13 13:17 ` [PATCH v2 45/53] ata: add pata_sgiioc4 driver for the SGI IOC4 ATA/ATAPI controller Imre Kaloz
2026-10-13 13:17 ` [PATCH v2 46/53] mfd: ioc3: Add IOC4 ATA/ATAPI cell Imre Kaloz
2026-10-13 13:17 ` [PATCH v2 47/53] MAINTAINERS: add an entry for the SGI IOC4 ATA driver Imre Kaloz
2026-10-13 13:25   ` Damien Le Moal
2026-10-13 13:38     ` Imre Kaloz
2026-10-13 15:13       ` Damien Le Moal
2026-10-13 13:17 ` [PATCH v2 48/53] MIPS: ip27_defconfig: update for the onboard hardware Imre Kaloz
2026-10-13 13:17 ` [PATCH v2 49/53] MIPS: ip27_defconfig: enable pata_sgiioc4 and the DVD-ROM path Imre Kaloz
2026-10-13 13:17 ` [PATCH v2 50/53] MIPS: SGI-IP27: add L1 front-panel LED and display requests Imre Kaloz
2026-10-13 13:17 ` Imre Kaloz [this message]
2026-10-13 13:17 ` [PATCH v2 52/53] MIPS: SGI-IP27: show the OS state on the Fuel and Tezro front panels Imre Kaloz
2026-10-13 13:17 ` [PATCH v2 53/53] MIPS: ip27_defconfig: enable the Fuel and Tezro front-panel LEDs Imre Kaloz
2026-10-13 13:35 ` [PATCH v2 00/53] MIPS: SGI-IP27: add support for the IP35 (Bedrock hub) machines Niklas Cassel
2026-10-13 14:25   ` Imre Kaloz

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=bdc0fa8089faf9ce4ff80695035173ab59357227.1791890466.git.kaloz@kernel.org \
    --to=kaloz@kernel.org \
    --cc=lee@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-leds@vger.kernel.org \
    --cc=linux-mips@vger.kernel.org \
    --cc=pavel@kernel.org \
    --cc=tsbogend@alpha.franken.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®