Skip to content

Commit

Permalink
mvebu: Add support for Turris Omnia MCU
Browse files Browse the repository at this point in the history
Patches taken from TurrisOS.

Signed-off-by: Marius Dinu <[email protected]>
  • Loading branch information
M95D committed Mar 18, 2024
1 parent 0dfc049 commit 34a9777
Show file tree
Hide file tree
Showing 12 changed files with 3,873 additions and 2 deletions.
3 changes: 2 additions & 1 deletion target/linux/mvebu/image/cortexa9.mk
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,8 @@ define Device/cznic_turris-omnia
DEVICE_PACKAGES := \
mkf2fs e2fsprogs kmod-fs-vfat kmod-nls-cp437 kmod-nls-iso8859-1 \
wpad-basic-mbedtls kmod-ath9k kmod-ath10k-ct ath10k-firmware-qca988x-ct \
kmod-mt7915-firmware partx-utils kmod-i2c-mux-pca954x kmod-leds-turris-omnia
kmod-mt7915-firmware partx-utils kmod-i2c-mux-pca954x kmod-leds-turris-omnia \
kmod-turris-omnia-mcu kmod-input-gpio-keys
IMAGES := sysupgrade.img.gz
IMAGE/sysupgrade.img.gz := boot-scr | boot-img | sdcard-img | gzip | append-metadata
SUPPORTED_DEVICES += armada-385-turris-omnia
Expand Down
23 changes: 22 additions & 1 deletion target/linux/mvebu/modules.mk
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,31 @@ endef
$(eval $(call KernelPackage,linkstation-poweroff))


define KernelPackage/turris-omnia-mcu
SUBMENU:=$(OTHER_MENU)
TITLE:=CZ.NIC's Turris Omnia MCU driver
DEPENDS:=@TARGET_mvebu_cortexa9
KCONFIG:= \
CONFIG_CZNIC_PLATFORMS=y \
CONFIG_TURRIS_OMNIA_MCU
FILES:=$(LINUX_DIR)/drivers/platform/cznic/turris-omnia-mcu.ko
AUTOLOAD:=$(call AutoLoad,59,turris-omnia-mcu,1)
endef

define KernelPackage/turris-omnia-mcu/description
This adds support for the features implemented by the microcontroller
on the CZ.NIC's Turris Omnia SOHO router, including true board
poweroff, the ability to configure wake up from powered off state at
a specific time, MCU watchdog and MCU connected GPIO pins.
endef

$(eval $(call KernelPackage,turris-omnia-mcu))


define KernelPackage/leds-turris-omnia
SUBMENU:=$(LEDS_MENU)
TITLE:=LED support for CZ.NIC's Turris Omnia
DEPENDS:=@TARGET_mvebu_cortexa9
DEPENDS:=@TARGET_mvebu_cortexa9 +kmod-turris-omnia-mcu
KCONFIG:=CONFIG_LEDS_TURRIS_OMNIA
FILES:=$(LINUX_DIR)/drivers/leds/leds-turris-omnia.ko
AUTOLOAD:=$(call AutoLoad,60,leds-turris-omnia,1)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
From e592d86fc0a7a2c8ae21a1055b8b1a508d2d5da9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marek=20Beh=C3=BAn?= <[email protected]>
Date: Tue, 15 Aug 2023 16:17:31 +0200
Subject: [PATCH 16/17] ARM: dts: turris-omnia: Add global LED brightness
change interrupt
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

When global LED brightness is changed, the MCU can produce an interrupt.
Add the description for this interrupt to the LED controller.

Fixes: 26ca8b52d6e1 ("ARM: dts: add support for Turris Omnia")
Signed-off-by: Marek Behún <[email protected]>
---
arch/arm/boot/dts/armada-385-turris-omnia.dts | 3 +++
1 file changed, 3 insertions(+)

diff --git a/arch/arm/boot/dts/armada-385-turris-omnia.dts b/arch/arm/boot/dts/armada-385-turris-omnia.dts
index 60b6923d79ec..2778d5e2efd1 100644
--- a/arch/arm/boot/dts/armada-385-turris-omnia.dts
+++ b/arch/arm/boot/dts/armada-385-turris-omnia.dts
@@ -224,6 +224,9 @@ led-controller@2b {
#size-cells = <0>;
status = "okay";

+ interrupt-parent = <&mcu>;
+ interrupts = <11 IRQ_TYPE_NONE>;
+
/*
* LEDs are controlled by MCU (STM32F0) at
* address 0x2b.
--
2.41.0

Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
From f88ea2c70c0046ef185f3e72a8a81e492a5d52ce Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marek=20Beh=C3=BAn?= <[email protected]>
Date: Tue, 15 Aug 2023 18:25:14 +0200
Subject: [PATCH 17/17] leds: turris-omnia: notify sysfs on MCU global LEDs
brightness change
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Recall that on Turris Omnia, the LED controller has a global brightness
property, which allows the user to make the front LED panel dimmer.

There is also a button on the front panel, which by default is
configured so that pressing it changes the global brightness to a lower
value (unless it is at 0%, in which case pressing the button changes the
global brightness to 100%).

Newer versions of the MCU firmware support informing the SOC that the
brightness was changed by button press event via an interrupt.

Now that we have the turris-omnia-mcu driver which adds support for MCU
interrupts, add the ability to inform the userspace that the global
brightness was changed via sysfs notification.

Signed-off-by: Marek Behún <[email protected]>
---
drivers/leds/leds-turris-omnia.c | 38 ++++++++++++++++++++++++++++++++
1 file changed, 38 insertions(+)

diff --git a/drivers/leds/leds-turris-omnia.c b/drivers/leds/leds-turris-omnia.c
index 9cd49833c6b2..fa80c88e18e1 100644
--- a/drivers/leds/leds-turris-omnia.c
+++ b/drivers/leds/leds-turris-omnia.c
@@ -23,6 +23,7 @@

#define CMD_GET_FEATURES 0x10
#define FEAT_LED_GAMMA_CORRECTION BIT(5)
+#define FEAT_BRIGHTNESS_INT BIT(10)

/* LED controller commands at I2C address 0x2b */
#define CMD_LED_MODE 0x03
@@ -54,6 +55,7 @@ struct omnia_leds {
struct i2c_client *client;
struct mutex lock;
bool has_gamma_correction;
+ struct kernfs_node *brightness_kn;
struct omnia_led leds[];
};

@@ -431,6 +433,24 @@ static struct attribute *omnia_led_controller_attrs[] = {
};
ATTRIBUTE_GROUPS(omnia_led_controller);

+static irqreturn_t omnia_brightness_changed_handler(int irq, void *dev_id)
+{
+ struct omnia_leds *leds = dev_id;
+ struct device *dev = &leds->client->dev;
+
+ if (!leds->brightness_kn) {
+ leds->brightness_kn = sysfs_get_dirent(dev->kobj.sd,
+ "brightness");
+
+ if (!leds->brightness_kn)
+ return IRQ_NONE;
+ }
+
+ sysfs_notify_dirent(leds->brightness_kn);
+
+ return IRQ_HANDLED;
+}
+
static int omnia_mcu_get_features(const struct i2c_client *client)
{
u16 reply;
@@ -458,6 +478,7 @@ static int omnia_leds_probe(struct i2c_client *client,
{
struct device *dev = &client->dev;
struct device_node *np = dev_of_node(dev), *child;
+ bool has_brightness_interrupt;
struct omnia_leds *leds;
struct omnia_led *led;
int ret, count;
@@ -485,6 +506,8 @@ static int omnia_leds_probe(struct i2c_client *client,
return ret;
}

+ has_brightness_interrupt = ret & FEAT_BRIGHTNESS_INT;
+
leds->has_gamma_correction = ret & FEAT_LED_GAMMA_CORRECTION;
if (!leds->has_gamma_correction) {
dev_info(dev,
@@ -512,13 +535,28 @@ static int omnia_leds_probe(struct i2c_client *client,
led += ret;
}

+ /* If MCU supports global brigthness change interrupt, handle it */
+ if (has_brightness_interrupt) {
+ ret = devm_request_any_context_irq(dev, client->irq,
+ omnia_brightness_changed_handler,
+ IRQF_ONESHOT,
+ "leds-turris-omnia", leds);
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "Cannot request IRQ\n");
+ }
+
return 0;
}

static int omnia_leds_remove(struct i2c_client *client)
{
+ struct omnia_leds *leds = i2c_get_clientdata(client);
u8 buf[5];

+ /* Release global brightness sysfs node */
+ if (leds->brightness_kn)
+ sysfs_put(leds->brightness_kn);
+
/* put all LEDs into default (HW triggered) mode */
omnia_cmd_write_u8(client, CMD_LED_MODE,
CMD_LED_MODE_LED(OMNIA_BOARD_LEDS));
--
2.41.0

Loading

0 comments on commit 34a9777

Please sign in to comment.