Skip to contentSkip to conversation

Turris Omnia MCU driver

PATCH Superseded Marek Behún 4 participants 31 messages Jun 5, 2024 – Jun 17, 2024

Subsystems (7)

v11 of 13 Superseded Latest is v13 →

lore
Share & tools
lore

Marek Behún

author maintainer
#0 lore raw

v11 cover Turris Omnia MCU driver

Hello Andy, Hans, Ilpo, Arnd, Gregory, and others,

this is v11 of the series adding Turris Omnia MCU driver.

Changes since v10:
- dropped patch 7 from v10 ("Add support for digital message signing via debugfs"). This must be done via different kernel API (should be doable via keyctl), but this requires more work which I currently don't have, unfortunately
- in patch 3 where I introduce support for MCU connected GPIOs changed u32 types to unsigned long where it made sense, in order to be able to use __assign_bit(), __set_bit(), test_bit(). This was suggested by Andy.
- in patch 3 deduplicated code in omnia_gpio_get_multiple()
- moved the "fixing" in patch 3 of functions introduced in patch 2 to patch 2, this was a rebasing error in v10
- changed date to September 2024 and KernelVersion to 6.11 in Documentation/ABI/testing/sysfs-bus-i2c-devices-turris-omnia-mcu

Links to previous cover letters (v1 to v10):
https://patchwork.kernel.org/project/linux-soc/cover/[email protected]/
https://patchwork.kernel.org/project/linux-soc/cover/[email protected]/
https://patchwork.kernel.org/project/linux-soc/cover/[email protected]/
https://patchwork.kernel.org/project/linux-soc/cover/[email protected]/
https://patchwork.kernel.org/project/linux-soc/cover/[email protected]/
https://patchwork.kernel.org/project/linux-soc/cover/[email protected]/
https://patchwork.kernel.org/project/linux-soc/cover/[email protected]/
https://patchwork.kernel.org/project/linux-soc/cover/[email protected]/
https://patchwork.kernel.org/project/linux-soc/cover/[email protected]/
https://patchwork.kernel.org/project/linux-soc/cover/[email protected]/

Marek Behún (8):
dt-bindings: firmware: add cznic,turris-omnia-mcu binding
platform: cznic: Add preliminary support for Turris Omnia MCU
platform: cznic: turris-omnia-mcu: Add support for MCU connected GPIOs
platform: cznic: turris-omnia-mcu: Add support for poweroff and wakeup
platform: cznic: turris-omnia-mcu: Add support for MCU watchdog
platform: cznic: turris-omnia-mcu: Add support for MCU provided TRNG
ARM: dts: turris-omnia: Add MCU system-controller node
ARM: dts: turris-omnia: Add GPIO key node for front button

 .../sysfs-bus-i2c-devices-turris-omnia-mcu    |  113 ++
 .../firmware/cznic,turris-omnia-mcu.yaml      |   86 ++
 MAINTAINERS                                   |    4 +
 .../dts/marvell/armada-385-turris-omnia.dts   |   35 +-
 drivers/platform/Kconfig                      |    2 +
 drivers/platform/Makefile                     |    1 +
 drivers/platform/cznic/Kconfig                |   48 +
 drivers/platform/cznic/Makefile               |    8 +
 .../platform/cznic/turris-omnia-mcu-base.c    |  407 +++++++
 .../platform/cznic/turris-omnia-mcu-gpio.c    | 1071 +++++++++++++++++
 .../cznic/turris-omnia-mcu-sys-off-wakeup.c   |  257 ++++
 .../platform/cznic/turris-omnia-mcu-trng.c    |  103 ++
 .../cznic/turris-omnia-mcu-watchdog.c         |  128 ++
 drivers/platform/cznic/turris-omnia-mcu.h     |  194 +++
 include/linux/turris-omnia-mcu-interface.h    |  249 ++++
 15 files changed, 2705 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/ABI/testing/sysfs-bus-i2c-devices-turris-omnia-mcu
 create mode 100644 Documentation/devicetree/bindings/firmware/cznic,turris-omnia-mcu.yaml
 create mode 100644 drivers/platform/cznic/Kconfig
 create mode 100644 drivers/platform/cznic/Makefile
 create mode 100644 drivers/platform/cznic/turris-omnia-mcu-base.c
 create mode 100644 drivers/platform/cznic/turris-omnia-mcu-gpio.c
 create mode 100644 drivers/platform/cznic/turris-omnia-mcu-sys-off-wakeup.c
 create mode 100644 drivers/platform/cznic/turris-omnia-mcu-trng.c
 create mode 100644 drivers/platform/cznic/turris-omnia-mcu-watchdog.c
 create mode 100644 drivers/platform/cznic/turris-omnia-mcu.h
 create mode 100644 include/linux/turris-omnia-mcu-interface.h
Signature · 1 line
2.44.2
author maintainer
#1 lore raw

PATCH v11 1/8 dt-bindings: firmware: add cznic,turris-omnia-mcu binding

Add binding for cznic,turris-omnia-mcu, the device-tree node representing the system-controller features provided by the MCU on the Turris Omnia router.

---
 .../firmware/cznic,turris-omnia-mcu.yaml      | 86 +++++++++++++++++++
 MAINTAINERS                                   |  1 +
 2 files changed, 87 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/firmware/cznic,turris-omnia-mcu.yaml
Documentation/devicetree/bindings/firmware/cznic,turris-omnia-mcu.yaml new file +86 -0
new file mode 100644
index 000000000000..af9249695ef5
@@ -0,0 +1,86 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/firmware/cznic,turris-omnia-mcu.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: CZ.NIC's Turris Omnia MCU
+
+maintainers:
+  - Marek Behún <[email protected]>
+
+description:
+  The MCU on Turris Omnia acts as a system controller providing additional
+  GPIOs, interrupts, watchdog, system power off and wakeup configuration.
+
+properties:
+  compatible:
+    const: cznic,turris-omnia-mcu
+
+  reg:
+    description: MCU I2C slave address
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  interrupt-controller: true
+
+  '#interrupt-cells':
+    const: 2
+    description: |
+      The first cell specifies the interrupt number (0 to 63), the second cell
+      specifies interrupt type (which can be one of IRQ_TYPE_EDGE_RISING,
+      IRQ_TYPE_EDGE_FALLING or IRQ_TYPE_EDGE_BOTH).
+      The interrupt numbers correspond sequentially to GPIO numbers, taking the
+      GPIO banks into account:
+        IRQ number   GPIO bank   GPIO pin within bank
+           0 - 15      0           0 - 15
+          16 - 47      1           0 - 31
+          48 - 63      2           0 - 15
+      There are several exceptions:
+        IRQ number   meaning
+          11           LED panel brightness changed by button press
+          13           TRNG entropy ready
+          14           ECDSA message signature computation done
+
+  gpio-controller: true
+
+  '#gpio-cells':
+    const: 3
+    description:
+      The first cell is bank number (0, 1 or 2), the second cell is pin number
+      within the bank (0 to 15 for banks 0 and 2, 0 to 31 for bank 1), and the
+      third cell specifies consumer flags.
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - interrupt-controller
+  - gpio-controller
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/irq.h>
+
+    i2c {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        system-controller@2a {
+            compatible = "cznic,turris-omnia-mcu";
+            reg = <0x2a>;
+
+            interrupt-parent = <&gpio1>;
+            interrupts = <11 IRQ_TYPE_NONE>;
+
+            gpio-controller;
+            #gpio-cells = <3>;
+
+            interrupt-controller;
+            #interrupt-cells = <2>;
+        };
+    };
MAINTAINERS +1 -0
index 8754ac2c259d..ee8b6dcd8f53 100644
@@ -2211,6 +2211,7 @@ F:	Documentation/ABI/testing/sysfs-bus-moxtet-devices
 F:	Documentation/ABI/testing/sysfs-firmware-turris-mox-rwtm
 F:	Documentation/devicetree/bindings/bus/moxtet.txt
 F:	Documentation/devicetree/bindings/firmware/cznic,turris-mox-rwtm.txt
+F:	Documentation/devicetree/bindings/firmware/cznic,turris-omnia-mcu.yaml
 F:	Documentation/devicetree/bindings/gpio/gpio-moxtet.txt
 F:	Documentation/devicetree/bindings/leds/cznic,turris-omnia-leds.yaml
 F:	Documentation/devicetree/bindings/watchdog/armada-37xx-wdt.txt
Signature · 1 line
2.44.2
author maintainer
#2 lore raw

PATCH v11 2/8 platform: cznic: Add preliminary support for Turris Omnia MCU

In reply to Marek Behún

Add the basic skeleton for a new platform driver for the microcontroller found on the Turris Omnia board.

---
 .../sysfs-bus-i2c-devices-turris-omnia-mcu    |  81 ++++
 MAINTAINERS                                   |   3 +
 drivers/platform/Kconfig                      |   2 +
 drivers/platform/Makefile                     |   1 +
 drivers/platform/cznic/Kconfig                |  25 ++
 drivers/platform/cznic/Makefile               |   4 +
 .../platform/cznic/turris-omnia-mcu-base.c    | 393 ++++++++++++++++++
 drivers/platform/cznic/turris-omnia-mcu.h     |  74 ++++
 include/linux/turris-omnia-mcu-interface.h    | 249 +++++++++++
 9 files changed, 832 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-bus-i2c-devices-turris-omnia-mcu
 create mode 100644 drivers/platform/cznic/Kconfig
 create mode 100644 drivers/platform/cznic/Makefile
 create mode 100644 drivers/platform/cznic/turris-omnia-mcu-base.c
 create mode 100644 drivers/platform/cznic/turris-omnia-mcu.h
 create mode 100644 include/linux/turris-omnia-mcu-interface.h
Documentation/ABI/testing/sysfs-bus-i2c-devices-turris-omnia-mcu new file +81 -0
new file mode 100644
index 000000000000..9bc5aad00de0
@@ -0,0 +1,81 @@
+What:		/sys/bus/i2c/devices/<mcu_device>/board_revision
+Date:		September 2024
+KernelVersion:	6.11
+Contact:	Marek Behún <[email protected]>
+Description:	(RO) Contains board revision number.
+
+		Only available if board information is burned in the MCU (older
+		revisions have board information burned in the ATSHA204-A chip).
+
+		Format: %u.
+
+What:		/sys/bus/i2c/devices/<mcu_device>/first_mac_address
+Date:		September 2024
+KernelVersion:	6.11
+Contact:	Marek Behún <[email protected]>
+Description:	(RO) Contains device first MAC address. Each Turris Omnia is
+		allocated 3 MAC addresses. The two additional addresses are
+		computed from the first one by incrementing it.
+
+		Only available if board information is burned in the MCU (older
+		revisions have board information burned in the ATSHA204-A chip).
+
+		Format: %pM.
+
+What:		/sys/bus/i2c/devices/<mcu_device>/fw_features
+Date:		September 2024
+KernelVersion:	6.11
+Contact:	Marek Behún <[email protected]>
+Description:	(RO) Newer versions of the microcontroller firmware report the
+		features they support. These can be read from this file. If the
+		MCU firmware is too old, this file reads 0x0.
+
+		Format: 0x%x.
+
+What:		/sys/bus/i2c/devices/<mcu_device>/fw_version_hash_application
+Date:		September 2024
+KernelVersion:	6.11
+Contact:	Marek Behún <[email protected]>
+Description:	(RO) Contains the version hash (commit hash) of the application
+		part of the microcontroller firmware.
+
+		Format: %s.
+
+What:		/sys/bus/i2c/devices/<mcu_device>/fw_version_hash_bootloader
+Date:		September 2024
+KernelVersion:	6.11
+Contact:	Marek Behún <[email protected]>
+Description:	(RO) Contains the version hash (commit hash) of the bootloader
+		part of the microcontroller firmware.
+
+		Format: %s.
+
+What:		/sys/bus/i2c/devices/<mcu_device>/mcu_type
+Date:		September 2024
+KernelVersion:	6.11
+Contact:	Marek Behún <[email protected]>
+Description:	(RO) Contains the microcontroller type (STM32, GD32, MKL).
+
+		Format: %s.
+
+What:		/sys/bus/i2c/devices/<mcu_device>/reset_selector
+Date:		September 2024
+KernelVersion:	6.11
+Contact:	Marek Behún <[email protected]>
+Description:	(RO) Contains the selected factory reset level, determined by
+		how long the rear reset button was held by the user during board
+		reset.
+
+		Format: %i.
+
+What:		/sys/bus/i2c/devices/<mcu_device>/serial_number
+Date:		September 2024
+KernelVersion:	6.11
+Contact:	Marek Behún <[email protected]>
+Description:	(RO) Contains the 64-bit board serial number in hexadecimal
+		format.
+
+		Only available if board information is burned in the MCU (older
+		revisions have board information burned in the ATSHA204-A chip).
+
+		Format: %016X.
MAINTAINERS +3 -0
index ee8b6dcd8f53..9f6dca4627c2 100644
@@ -2207,6 +2207,7 @@ M:	Marek Behún <[email protected]>
 S:	Maintained
 W:	https://www.turris.cz/
 F:	Documentation/ABI/testing/debugfs-moxtet
+F:	Documentation/ABI/testing/sysfs-bus-i2c-devices-turris-omnia-mcu
 F:	Documentation/ABI/testing/sysfs-bus-moxtet-devices
 F:	Documentation/ABI/testing/sysfs-firmware-turris-mox-rwtm
 F:	Documentation/devicetree/bindings/bus/moxtet.txt
@@ -2220,10 +2221,12 @@ F:	drivers/firmware/turris-mox-rwtm.c
 F:	drivers/gpio/gpio-moxtet.c
 F:	drivers/leds/leds-turris-omnia.c
 F:	drivers/mailbox/armada-37xx-rwtm-mailbox.c
+F:	drivers/platform/cznic/
 F:	drivers/watchdog/armada_37xx_wdt.c
 F:	include/dt-bindings/bus/moxtet.h
 F:	include/linux/armada-37xx-rwtm-mailbox.h
 F:	include/linux/moxtet.h
+F:	include/linux/turris-omnia-mcu-interface.h
 
 ARM/FARADAY FA526 PORT
 M:	Hans Ulli Kroll <[email protected]>
drivers/platform/Kconfig +2 -0
index 81a298517df2..960fd6a82450 100644
@@ -7,6 +7,8 @@ source "drivers/platform/goldfish/Kconfig"
 
 source "drivers/platform/chrome/Kconfig"
 
+source "drivers/platform/cznic/Kconfig"
+
 source "drivers/platform/mellanox/Kconfig"
 
 source "drivers/platform/olpc/Kconfig"
drivers/platform/Makefile +1 -0
index fbbe4f77aa5d..bf69cc8d7429 100644
@@ -10,5 +10,6 @@ obj-$(CONFIG_MIPS)		+= mips/
 obj-$(CONFIG_OLPC_EC)		+= olpc/
 obj-$(CONFIG_GOLDFISH)		+= goldfish/
 obj-$(CONFIG_CHROME_PLATFORMS)	+= chrome/
+obj-$(CONFIG_CZNIC_PLATFORMS)	+= cznic/
 obj-$(CONFIG_SURFACE_PLATFORMS)	+= surface/
 obj-$(CONFIG_ARM64)		+= arm64/
drivers/platform/cznic/Kconfig new file +25 -0
new file mode 100644
index 000000000000..db5f4a673d28
@@ -0,0 +1,25 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# For a description of the syntax of this configuration file,
+# see Documentation/kbuild/kconfig-language.rst.
+#
+
+menuconfig CZNIC_PLATFORMS
+	bool "Platform support for CZ.NIC's Turris hardware"
+	help
+	  Say Y here to be able to choose driver support for CZ.NIC's Turris
+	  devices. This option alone does not add any kernel code.
+
+if CZNIC_PLATFORMS
+
+config TURRIS_OMNIA_MCU
+	tristate "Turris Omnia MCU driver"
+	depends on MACH_ARMADA_38X || COMPILE_TEST
+	depends on I2C
+	help
+	  Say Y here to add support for the features implemented by the
+	  microcontroller on the CZ.NIC's Turris Omnia SOHO router.
+	  To compile this driver as a module, choose M here; the module will be
+	  called turris-omnia-mcu.
+
+endif # CZNIC_PLATFORMS
drivers/platform/cznic/Makefile new file +4 -0
new file mode 100644
index 000000000000..31adca73bb94
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+obj-$(CONFIG_TURRIS_OMNIA_MCU)	+= turris-omnia-mcu.o
+turris-omnia-mcu-y		:= turris-omnia-mcu-base.o
drivers/platform/cznic/turris-omnia-mcu-base.c new file +393 -0

393 lines not on this page · raw message

drivers/platform/cznic/turris-omnia-mcu.h new file +74 -0

74 lines not on this page · raw message

include/linux/turris-omnia-mcu-interface.h new file +249 -0

249 lines not on this page · raw message

Signature · 1 line
2.44.2
Reviewed-by on v11 2/8
#3 lore raw

Re: [PATCH v11 2/8] platform: cznic: Add preliminary support for Turris Omnia MCU

Quoted 3 lines · Marek Behún

Add the basic skeleton for a new platform driver for the microcontroller found on the Turris Omnia board.

...

I paid attention to this block because of ETH_ALEN, see below.

drivers/platform/cznic/turris-omnia-mcu-base.c line 14

Quoted 8 lines
drivers/platform/cznic/turris-omnia-mcu-base.c new file +7 -0
+#include <linux/array_size.h>
+#include <linux/bits.h>
+#include <linux/device.h>
+#include <linux/hex.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
 
+#include <linux/turris-omnia-mcu-interface.h>

This is part of the niche of the driver, I would move it

Quoted 1 line

+#include <linux/types.h>

t is followed by s :-)

drivers/platform/cznic/turris-omnia-mcu-base.c line 17

Quoted 2 lines
drivers/platform/cznic/turris-omnia-mcu-base.c new file +2 -0
+#include <linux/string.h>
+#include <linux/sysfs.h>

...here as a separate group.

Quoted 1 line

+#include "turris-omnia-mcu.h"

...

drivers/platform/cznic/turris-omnia-mcu-base.c line 338

Quoted 2 lines
drivers/platform/cznic/turris-omnia-mcu-base.c new file +2 -0
+       /* we can't use ether_addr_copy() because reply is not u16-aligned */
+       memcpy(mcu->board_first_mac, &reply[9], ETH_ALEN);

The inclusion block misses the header for ETH_ALEN, but I realise that instead it's better to use sizeof() as it makes this rely to the real size of the buffer and header is not needed either.

...

Other than above LGTM, FWIW,

Signature · 2 lines
With Best Regards,
Andy Shevchenko
author maintainer
#4 lore raw

PATCH v11 3/8 platform: cznic: turris-omnia-mcu: Add support for MCU connected GPIOs

In reply to Marek Behún

Add support for GPIOs connected to the MCU on the Turris Omnia board.

This includes:
- front button pin
- enable pins for USB regulators
- MiniPCIe / mSATA card presence pins in MiniPCIe port 0
- LED output pins from WAN ethernet PHY, LAN switch and MiniPCIe ports
- on board revisions 32+ also various peripheral resets and another voltage regulator enable pin

---
 .../sysfs-bus-i2c-devices-turris-omnia-mcu    |   16 +
 drivers/platform/cznic/Kconfig                |   15 +
 drivers/platform/cznic/Makefile               |    1 +
 .../platform/cznic/turris-omnia-mcu-base.c    |    3 +-
 .../platform/cznic/turris-omnia-mcu-gpio.c    | 1071 +++++++++++++++++
 drivers/platform/cznic/turris-omnia-mcu.h     |   68 ++
 6 files changed, 1173 insertions(+), 1 deletion(-)
 create mode 100644 drivers/platform/cznic/turris-omnia-mcu-gpio.c
Documentation/ABI/testing/sysfs-bus-i2c-devices-turris-omnia-mcu +16 -0
index 9bc5aad00de0..86360249080c 100644
@@ -22,6 +22,22 @@ Description:	(RO) Contains device first MAC address. Each Turris Omnia is
 
 		Format: %pM.
 
+What:		/sys/bus/i2c/devices/<mcu_device>/front_button_mode
+Date:		September 2024
+KernelVersion:	6.11
+Contact:	Marek Behún <[email protected]>
+Description:	(RW) The front button on the Turris Omnia router can be
+		configured either to change the intensity of all the LEDs on the
+		front panel, or to send the press event to the CPU as an
+		interrupt.
+
+		This file switches between these two modes:
+		- "mcu" makes the button press event be handled by the MCU to
+		  change the LEDs panel intensity.
+		- "cpu" makes the button press event be handled by the CPU.
+
+		Format: %s.
+
 What:		/sys/bus/i2c/devices/<mcu_device>/fw_features
 Date:		September 2024
 KernelVersion:	6.11
drivers/platform/cznic/Kconfig +15 -0
index db5f4a673d28..d95e7c83c7ae 100644
@@ -16,9 +16,24 @@ config TURRIS_OMNIA_MCU
 	tristate "Turris Omnia MCU driver"
 	depends on MACH_ARMADA_38X || COMPILE_TEST
 	depends on I2C
+	select GPIOLIB
+	select GPIOLIB_IRQCHIP
 	help
 	  Say Y here to add support for the features implemented by the
 	  microcontroller on the CZ.NIC's Turris Omnia SOHO router.
+	  The features include:
+	  - GPIO pins
+	    - to get front button press events (the front button can be
+	      configured either to generate press events to the CPU or to change
+	      front LEDs panel brightness)
+	    - to enable / disable USB port voltage regulators and to detect
+	      USB overcurrent
+	    - to detect MiniPCIe / mSATA card presence in MiniPCIe port 0
+	    - to configure resets of various peripherals on board revisions 32+
+	    - to enable / disable the VHV voltage regulator to the SOC in order
+	      to be able to program SOC's OTP on board revisions 32+
+	    - to get input from the LED output pins of the WAN ethernet PHY, LAN
+	      switch and MiniPCIe ports
 	  To compile this driver as a module, choose M here; the module will be
 	  called turris-omnia-mcu.
 
drivers/platform/cznic/Makefile +1 -0
index 31adca73bb94..53fd8f1777a3 100644
@@ -2,3 +2,4 @@
 
 obj-$(CONFIG_TURRIS_OMNIA_MCU)	+= turris-omnia-mcu.o
 turris-omnia-mcu-y		:= turris-omnia-mcu-base.o
+turris-omnia-mcu-y		+= turris-omnia-mcu-gpio.o
drivers/platform/cznic/turris-omnia-mcu-base.c +2 -1
index a5ae2ba9abb6..03a5f19c6665 100644
@@ -196,6 +196,7 @@ static const struct attribute_group omnia_mcu_base_group = {
 
 static const struct attribute_group *omnia_mcu_groups[] = {
 	&omnia_mcu_base_group,
+	&omnia_mcu_gpio_group,
 	NULL
 };
 
@@ -370,7 +371,7 @@ static int omnia_mcu_probe(struct i2c_client *client)
 					     "Cannot read board info\n");
 	}
 
-	return 0;
+	return omnia_mcu_register_gpiochip(mcu);
 }
 
 static const struct of_device_id of_omnia_mcu_match[] = {
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +1071 -0

1,071 lines not on this page · raw message

drivers/platform/cznic/turris-omnia-mcu.h +68 -0

98 lines not on this page · raw message

Signature · 1 line
2.44.2
#5 lore raw

Re: [PATCH v11 3/8] platform: cznic: turris-omnia-mcu: Add support for MCU connected GPIOs

Quoted 10 lines · Marek Behún

Add support for GPIOs connected to the MCU on the Turris Omnia board.

This includes:
- front button pin
- enable pins for USB regulators
- MiniPCIe / mSATA card presence pins in MiniPCIe port 0
- LED output pins from WAN ethernet PHY, LAN switch and MiniPCIe ports
- on board revisions 32+ also various peripheral resets and another voltage regulator enable pin

...

Quoted 4 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +4 -0
+#include <linux/array_size.h>
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+#include <linux/bug.h>

drivers/platform/cznic/turris-omnia-mcu-gpio.c line 20

Quoted 10 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +9 -0
+#include <linux/cleanup.h>
+#include <linux/device.h>
+#include <linux/devm-helpers.h>
+#include <linux/gpio/driver.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/mutex.h>
+#include <linux/sysfs.h>
 
+#include <linux/turris-omnia-mcu-interface.h>

As per previous patch.

Quoted 5 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +5 -0
+#include <linux/types.h>
+#include <linux/workqueue.h>
+#include <asm/unaligned.h>
+
+#include "turris-omnia-mcu.h"

...

drivers/platform/cznic/turris-omnia-mcu-gpio.c line 77

Quoted 5 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +5 -0
+struct omnia_gpio {
+       u8 cmd, ctl_cmd, bit, ctl_bit, int_bit;
+       bool has_int;
+       u16 feat, feat_mask;
+};

This is hard to follow, please make one field per line.

...

drivers/platform/cznic/turris-omnia-mcu-gpio.c line 86

Quoted 9 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +8 -0
+#define _DEF_GPIO(_cmd, _ctl_cmd, _bit, _ctl_bit, _int_bit, _feat, _feat_mask) \
+       {                                                               \
+               .cmd = _cmd,                                            \
+               .ctl_cmd = _ctl_cmd,                                    \
+               .bit = _bit,                                            \
+               .ctl_bit = _ctl_bit,                                    \
+               .int_bit = _int_bit,                                    \
 
+               .has_int = (_int_bit) != -1,                            \

Useless field, you can always perform this check in the code Since you have int_bit field defined. Filling it with kinda garbage is not an excuse, you can just define the INVALID_IRQ like many drivers do that want to use unsigned types.

#define OMNIA_GPIO_INVALID_INT_BIT 0xff

Possibly to have
static inline is_int_bit_valid(struct omnia_gpio *gpio) {
return gpio->int_bit != OMNIA_GPIO_INVALID_INT_BIT;
}

...

drivers/platform/cznic/turris-omnia-mcu-gpio.c line 338

Quoted 7 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +6 -0
+       /*
+        * If firmware does support the new interrupt API, we may have cached
+        * the value of a GPIO in the interrupt service routine. If not, read
+        * the relevant bit now.
+        */
 
+       if (gpio->has_int && test_bit(gpio->int_bit, &mcu->is_cached))

See above.

drivers/platform/cznic/turris-omnia-mcu-gpio.c line 410

Quoted 12 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +9 -0
+               return test_bit(gpio->int_bit, &mcu->cached);
+
+       return omnia_cmd_read_bit(mcu->client, gpio->cmd, BIT(gpio->bit));
+}
 
 
+       /* assign relevant bits in result */
+       for_each_set_bit(i, mask, ARRAY_SIZE(omnia_gpios)) {
+               field = _relevant_field_for_sts_cmd(omnia_gpios[i].cmd,
+                                                   &sts, &ext_sts, &ext_ctl);
 
+               if (field)

Perhaps

if (!field)

    continue;

?

drivers/platform/cznic/turris-omnia-mcu-gpio.c line 412

Quoted 2 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +2 -0
+                       __assign_bit(i, bits,
+                                    test_bit(omnia_gpios[i].bit, field));

This will become one line after the above change.

Quoted 4 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +4 -0
+       }
+
+       return 0;
+}

...

Quoted 1 line

+ int i;

Why signed?

Quoted 9 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +9 -0
+       for_each_set_bit(i, mask, ARRAY_SIZE(omnia_gpios)) {
+               unsigned long *field, *field_mask;
+               u8 bit = omnia_gpios[i].ctl_bit;
+
+               switch (omnia_gpios[i].ctl_cmd) {
+               case OMNIA_CMD_GENERAL_CONTROL:
+                       field = &ctl;
+                       field_mask = &ctl_mask;
+                       break;

drivers/platform/cznic/turris-omnia-mcu-gpio.c line 458

Quoted 10 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +9 -0
+               case OMNIA_CMD_EXT_CONTROL:
+                       field = &ext_ctl;
+                       field_mask = &ext_ctl_mask;
+                       break;
+               default:
+                       field = field_mask = NULL;
+                       break;
+               }
 
+               if (field) {

Like the above

if (!field)

    continue;
Quoted 4 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +4 -0
+                       __set_bit(bit, field_mask);
+                       __assign_bit(bit, field, test_bit(i, bits));
+               }
+       }

...

drivers/platform/cznic/turris-omnia-mcu-gpio.c line 579

Quoted 2 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +2 -0
+       if (!(type & IRQ_TYPE_EDGE_BOTH)) {
+               dev_err(dev, "irq %u: unsupported type %u\n", d->irq, type);

You have hwirq, no need to dereference again.

Quoted 2 lines
(quoted diff) +2 -0
+               return -EINVAL;
+       }

...

Quoted 5 lines

+/**
+ * omnia_mask_interleave - Interleaves the bytes from @rising and @falling

+ *     @dst: the destination u8 array of interleaved bytes
+ *     @rising: rising mask
+ *     @falling: falling mask

Why so many spaces before @? One is enough.

Quoted 15 lines

+ *
+ * Interleaves the little-endian bytes from @rising and @falling words.
+ *
+ * If @rising = (r0, r1, r2, r3) and @falling = (f0, f1, f2, f3), the result is
+ * @dst = (r0, f0, r1, f1, r2, f2, r3, f3).
+ *
+ * The MCU receives an interrupt mask and reports a pending interrupt bitmap in
+ * this interleaved format. The rationale behind this is that the low-indexed
+ * bits are more important - in many cases, the user will be interested only in
+ * interrupts with indexes 0 to 7, and so the system can stop reading after
+ * first 2 bytes (r0, f0), to save time on the slow I2C bus.
+ *
+ * Feel free to remove this function and its inverse, omnia_mask_deinterleave,
+ * and use an appropriate bitmap_*() function once such a function exists.
+ */

drivers/platform/cznic/turris-omnia-mcu-gpio.c line 622

Quoted 2 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +2 -0
+static void
+omnia_mask_interleave(u8 *dst, unsigned long rising, unsigned long falling)

But rising and failing should be either u64 or unsigned long *.

Review

Quoted 2 lines
(quoted diff) +2 -0
+{
+       for (int i = 0; i < sizeof(u32); ++i) {

In other cases you use:
1) unsigned
2) post-increment

What makes this one special?

Quoted 4 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +4 -0
+               dst[2 * i] = rising >> (8 * i);
+               dst[2 * i + 1] = falling >> (8 * i);
+       }
+}

...

Quoted 8 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +8 -0
+/**
+ * omnia_mask_deinterleave - Deinterleaves the bytes into @rising and @falling
+ *     @src: the source u8 array containing the interleaved bytes
+ *     @rising: pointer where to store the rising mask gathered from @src
+ *     @falling: pointer where to store the falling mask gathered from @src
+ *
+ * This is the inverse function to omnia_mask_interleave.
+ */

drivers/platform/cznic/turris-omnia-mcu-gpio.c line 647

Quoted 10 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +10 -0
+static void omnia_mask_deinterleave(const u8 *src, unsigned long *rising,
+                                   unsigned long *falling)
+{
+       *rising = *falling = 0;
+
+       for (int i = 0; i < sizeof(u32); ++i) {
+               *rising |= src[2 * i] << (8 * i);
+               *falling |= src[2 * i + 1] << (8 * i);
+       }
+}

Same comments as per above function.

Signature · 2 lines
With Best Regards,
Andy Shevchenko
#6 lore raw

Re: [PATCH v11 3/8] platform: cznic: turris-omnia-mcu: Add support for MCU connected GPIOs

Quoted 1 line · Andy Shevchenko

On Wed, Jun 5, 2024 at 7:19 PM Marek Behún <[email protected]> wrote:

...

Quoted 19 lines
Quoted 5 lines

+/**
+ * omnia_mask_interleave - Interleaves the bytes from @rising and @falling

+ *     @dst: the destination u8 array of interleaved bytes
+ *     @rising: rising mask
+ *     @falling: falling mask

Why so many spaces before @? One is enough.

Quoted 11 lines

+ *
+ * Interleaves the little-endian bytes from @rising and @falling words.
+ *
+ * If @rising = (r0, r1, r2, r3) and @falling = (f0, f1, f2, f3), the result is
+ * @dst = (r0, f0, r1, f1, r2, f2, r3, f3).
+ *
+ * The MCU receives an interrupt mask and reports a pending interrupt bitmap in
+ * this interleaved format. The rationale behind this is that the low-indexed
+ * bits are more important - in many cases, the user will be interested only in
+ * interrupts with indexes 0 to 7, and so the system can stop reading after
+ * first 2 bytes (r0, f0), to save time on the slow I2C bus.

Quoted 8 lines

drivers/platform/cznic/turris-omnia-mcu-gpio.c line 622

Quoted 6 lines

+ *
+ * Feel free to remove this function and its inverse, omnia_mask_deinterleave,
+ * and use an appropriate bitmap_*() function once such a function exists.
+ */

drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +2 -0
+static void
+omnia_mask_interleave(u8 *dst, unsigned long rising, unsigned long falling)

But rising and failing should be either u64 or unsigned long *.

Ah, sorry, I misread the use, discard this single comment.

Quoted 36 lines

Review

Quoted 2 lines
(quoted diff) +2 -0
+{
+       for (int i = 0; i < sizeof(u32); ++i) {

In other cases you use:
1) unsigned
2) post-increment

What makes this one special?

Quoted 4 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +4 -0
+               dst[2 * i] = rising >> (8 * i);
+               dst[2 * i + 1] = falling >> (8 * i);
+       }
+}

...

Quoted 8 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +8 -0
+/**
+ * omnia_mask_deinterleave - Deinterleaves the bytes into @rising and @falling
+ *     @src: the source u8 array containing the interleaved bytes
+ *     @rising: pointer where to store the rising mask gathered from @src
+ *     @falling: pointer where to store the falling mask gathered from @src
+ *
+ * This is the inverse function to omnia_mask_interleave.
+ */

drivers/platform/cznic/turris-omnia-mcu-gpio.c line 647

Quoted 10 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +10 -0
+static void omnia_mask_deinterleave(const u8 *src, unsigned long *rising,
+                                   unsigned long *falling)
+{
+       *rising = *falling = 0;
+
+       for (int i = 0; i < sizeof(u32); ++i) {
+               *rising |= src[2 * i] << (8 * i);
+               *falling |= src[2 * i + 1] << (8 * i);
+       }
+}

Same comments as per above function.

Signature · 2 lines
With Best Regards,
Andy Shevchenko
author maintainer
#7 lore raw

PATCH v11 4/8 platform: cznic: turris-omnia-mcu: Add support for poweroff and wakeup

In reply to Marek Behún

Add support for true board poweroff (MCU can disable all unnecessary voltage regulators) and wakeup at a specified time, implemented via a RTC driver so that the rtcwake utility can be used to configure it.

---
 .../sysfs-bus-i2c-devices-turris-omnia-mcu    |  16 ++
 drivers/platform/cznic/Kconfig                |   4 +
 drivers/platform/cznic/Makefile               |   1 +
 .../platform/cznic/turris-omnia-mcu-base.c    |   5 +
 .../cznic/turris-omnia-mcu-sys-off-wakeup.c   | 257 ++++++++++++++++++
 drivers/platform/cznic/turris-omnia-mcu.h     |  20 ++
 6 files changed, 303 insertions(+)
 create mode 100644 drivers/platform/cznic/turris-omnia-mcu-sys-off-wakeup.c
Documentation/ABI/testing/sysfs-bus-i2c-devices-turris-omnia-mcu +16 -0
index 86360249080c..307a55f599cb 100644
@@ -38,6 +38,22 @@ Description:	(RW) The front button on the Turris Omnia router can be
 
 		Format: %s.
 
+What:		/sys/bus/i2c/devices/<mcu_device>/front_button_poweron
+Date:		September 2024
+KernelVersion:	6.11
+Contact:	Marek Behún <[email protected]>
+Description:	(RW) Newer versions of the microcontroller firmware of the
+		Turris Omnia router support powering off the router into true
+		low power mode. The router can be powered on by pressing the
+		front button.
+
+		This file configures whether front button power on is enabled.
+
+		This file is present only if the power off feature is supported
+		by the firmware.
+
+		Format: %i.
+
 What:		/sys/bus/i2c/devices/<mcu_device>/fw_features
 Date:		September 2024
 KernelVersion:	6.11
drivers/platform/cznic/Kconfig +4 -0
index d95e7c83c7ae..c1e719235517 100644
@@ -18,10 +18,14 @@ config TURRIS_OMNIA_MCU
 	depends on I2C
 	select GPIOLIB
 	select GPIOLIB_IRQCHIP
+	select RTC_CLASS
 	help
 	  Say Y here to add support for the features implemented by the
 	  microcontroller on the CZ.NIC's Turris Omnia SOHO router.
 	  The features include:
+	  - board poweroff into true low power mode (with voltage regulators
+	    disabled) and the ability to configure wake up from this mode (via
+	    rtcwake)
 	  - GPIO pins
 	    - to get front button press events (the front button can be
 	      configured either to generate press events to the CPU or to change
drivers/platform/cznic/Makefile +1 -0
index 53fd8f1777a3..a185ef882e44 100644
@@ -3,3 +3,4 @@
 obj-$(CONFIG_TURRIS_OMNIA_MCU)	+= turris-omnia-mcu.o
 turris-omnia-mcu-y		:= turris-omnia-mcu-base.o
 turris-omnia-mcu-y		+= turris-omnia-mcu-gpio.o
+turris-omnia-mcu-y		+= turris-omnia-mcu-sys-off-wakeup.o
drivers/platform/cznic/turris-omnia-mcu-base.c +5 -0
index 03a5f19c6665..479f355f730a 100644
@@ -197,6 +197,7 @@ static const struct attribute_group omnia_mcu_base_group = {
 static const struct attribute_group *omnia_mcu_groups[] = {
 	&omnia_mcu_base_group,
 	&omnia_mcu_gpio_group,
+	&omnia_mcu_poweroff_group,
 	NULL
 };
 
@@ -371,6 +372,10 @@ static int omnia_mcu_probe(struct i2c_client *client)
 					     "Cannot read board info\n");
 	}
 
+	err = omnia_mcu_register_sys_off_and_wakeup(mcu);
+	if (err)
+		return err;
+
 	return omnia_mcu_register_gpiochip(mcu);
 }
 
drivers/platform/cznic/turris-omnia-mcu-sys-off-wakeup.c new file +257 -0

257 lines not on this page · raw message

drivers/platform/cznic/turris-omnia-mcu.h +20 -0
index 3d2dd0054499..5df421b03878 100644
@@ -12,9 +12,11 @@
 #include <linux/gpio/driver.h>
 #include <linux/if_ether.h>
 #include <linux/mutex.h>
+#include <linux/rtc.h>
 #include <linux/types.h>
 #include <linux/workqueue.h>
 #include <asm/byteorder.h>
+#include <asm/unaligned.h>
 
 struct i2c_client;
 
@@ -36,6 +38,11 @@ struct omnia_mcu {
 	struct delayed_work button_release_emul_work;
 	unsigned long last_status;
 	bool button_pressed_emul;
+
+	/* RTC device for configuring wake-up */
+	struct rtc_device *rtcdev;
+	u32 rtc_alarm;
+	bool front_button_poweron;
 };
 
 int omnia_cmd_write_read(const struct i2c_client *client,
@@ -48,6 +55,17 @@ static inline int omnia_cmd_write(const struct i2c_client *client, void *cmd,
 	return omnia_cmd_write_read(client, cmd, len, NULL, 0);
 }
 
+static inline int omnia_cmd_write_u32(const struct i2c_client *client, u8 cmd,
+				      u32 val)
+{
+	u8 buf[5];
+
+	buf[0] = cmd;
+	put_unaligned_le32(val, &buf[1]);
+
+	return omnia_cmd_write(client, buf, sizeof(buf));
+}
+
 static inline int omnia_cmd_read(const struct i2c_client *client, u8 cmd,
 				 void *reply, unsigned int len)
 {
@@ -136,7 +154,9 @@ static inline int omnia_cmd_read_u8(const struct i2c_client *client, u8 cmd,
 }
 
 extern const struct attribute_group omnia_mcu_gpio_group;
+extern const struct attribute_group omnia_mcu_poweroff_group;
 
 int omnia_mcu_register_gpiochip(struct omnia_mcu *mcu);
+int omnia_mcu_register_sys_off_and_wakeup(struct omnia_mcu *mcu);
 
 #endif /* __TURRIS_OMNIA_MCU_H */
Signature · 1 line
2.44.2
Reviewed-by on v11 4/8
#8 lore raw

Re: [PATCH v11 4/8] platform: cznic: turris-omnia-mcu: Add support for poweroff and wakeup

Quoted 4 lines · Marek Behún

Add support for true board poweroff (MCU can disable all unnecessary voltage regulators) and wakeup at a specified time, implemented via a RTC driver so that the rtcwake utility can be used to configure it.

...

drivers/platform/cznic/turris-omnia-mcu-sys-off-wakeup.c line 15

Quoted 2 lines
drivers/platform/cznic/turris-omnia-mcu-sys-off-wakeup.c new file +2 -0
+#include <linux/crc32.h>
+#include <linux/delay.h>

+ device.h
+ err.h

Quoted 1 line

+#include <linux/i2c.h>

+ kstrtox.h

drivers/platform/cznic/turris-omnia-mcu-sys-off-wakeup.c line 20

Quoted 5 lines
drivers/platform/cznic/turris-omnia-mcu-sys-off-wakeup.c new file +4 -0
+#include <linux/reboot.h>
+#include <linux/rtc.h>
+#include <linux/sysfs.h>
 
+#include <linux/turris-omnia-mcu-interface.h>

As per other patches.

Quoted 3 lines
drivers/platform/cznic/turris-omnia-mcu-sys-off-wakeup.c new file +3 -0
+#include <linux/types.h>
+
+#include "turris-omnia-mcu.h"

...

Quoted 1 line

+ struct device *dev = kobj_to_dev(kobj);

Is this declared in device.h or elsewhere?

...

Quoted 1 line

+#include <linux/rtc.h>

I don't see you need it.
Just

struct rtc_device;

should suffice.

Quoted 4 lines

#include <linux/types.h>
#include <linux/workqueue.h>
#include <asm/byteorder.h>
+#include <asm/unaligned.h>

...

With the above being addressed, LGTM, FWIW,

Signature · 2 lines
With Best Regards,
Andy Shevchenko
author maintainer
#9 lore raw

Re: [PATCH v11 4/8] platform: cznic: turris-omnia-mcu: Add support for poweroff and wakeup

Quoted 3 lines · On Wed, 5 Jun 2024 21:41:04 +0300 Andy Shevchenko <[email protected]>…
Quoted 1 line

+ struct device *dev = kobj_to_dev(kobj);

Is this declared in device.h or elsewhere?

It is in device.h.

author maintainer
#10 lore raw

PATCH v11 5/8 platform: cznic: turris-omnia-mcu: Add support for MCU watchdog

In reply to Marek Behún

Add support for the watchdog mechanism provided by the MCU.

---
 drivers/platform/cznic/Kconfig                |   2 +
 drivers/platform/cznic/Makefile               |   1 +
 .../platform/cznic/turris-omnia-mcu-base.c    |   4 +
 .../cznic/turris-omnia-mcu-watchdog.c         | 128 ++++++++++++++++++
 drivers/platform/cznic/turris-omnia-mcu.h     |  24 ++++
 5 files changed, 159 insertions(+)
 create mode 100644 drivers/platform/cznic/turris-omnia-mcu-watchdog.c
drivers/platform/cznic/Kconfig +2 -0
index c1e719235517..e262930b3faf 100644
@@ -19,6 +19,7 @@ config TURRIS_OMNIA_MCU
 	select GPIOLIB
 	select GPIOLIB_IRQCHIP
 	select RTC_CLASS
+	select WATCHDOG_CORE
 	help
 	  Say Y here to add support for the features implemented by the
 	  microcontroller on the CZ.NIC's Turris Omnia SOHO router.
@@ -26,6 +27,7 @@ config TURRIS_OMNIA_MCU
 	  - board poweroff into true low power mode (with voltage regulators
 	    disabled) and the ability to configure wake up from this mode (via
 	    rtcwake)
+	  - MCU watchdog
 	  - GPIO pins
 	    - to get front button press events (the front button can be
 	      configured either to generate press events to the CPU or to change
drivers/platform/cznic/Makefile +1 -0
index a185ef882e44..687f7718c0a1 100644
@@ -4,3 +4,4 @@ obj-$(CONFIG_TURRIS_OMNIA_MCU)	+= turris-omnia-mcu.o
 turris-omnia-mcu-y		:= turris-omnia-mcu-base.o
 turris-omnia-mcu-y		+= turris-omnia-mcu-gpio.o
 turris-omnia-mcu-y		+= turris-omnia-mcu-sys-off-wakeup.o
+turris-omnia-mcu-y		+= turris-omnia-mcu-watchdog.o
drivers/platform/cznic/turris-omnia-mcu-base.c +4 -0
index 479f355f730a..f44996588d38 100644
@@ -376,6 +376,10 @@ static int omnia_mcu_probe(struct i2c_client *client)
 	if (err)
 		return err;
 
+	err = omnia_mcu_register_watchdog(mcu);
+	if (err)
+		return err;
+
 	return omnia_mcu_register_gpiochip(mcu);
 }
 
drivers/platform/cznic/turris-omnia-mcu-watchdog.c new file +128 -0

128 lines not on this page · raw message

drivers/platform/cznic/turris-omnia-mcu.h +24 -0
index 5df421b03878..5f846909934f 100644
@@ -14,6 +14,7 @@
 #include <linux/mutex.h>
 #include <linux/rtc.h>
 #include <linux/types.h>
+#include <linux/watchdog.h>
 #include <linux/workqueue.h>
 #include <asm/byteorder.h>
 #include <asm/unaligned.h>
@@ -43,6 +44,9 @@ struct omnia_mcu {
 	struct rtc_device *rtcdev;
 	u32 rtc_alarm;
 	bool front_button_poweron;
+
+	/* MCU watchdog */
+	struct watchdog_device wdt;
 };
 
 int omnia_cmd_write_read(const struct i2c_client *client,
@@ -55,6 +59,25 @@ static inline int omnia_cmd_write(const struct i2c_client *client, void *cmd,
 	return omnia_cmd_write_read(client, cmd, len, NULL, 0);
 }
 
+static inline int omnia_cmd_write_u8(const struct i2c_client *client, u8 cmd,
+				     u8 val)
+{
+	u8 buf[2] = { cmd, val };
+
+	return omnia_cmd_write(client, buf, sizeof(buf));
+}
+
+static inline int omnia_cmd_write_u16(const struct i2c_client *client, u8 cmd,
+				      u16 val)
+{
+	u8 buf[3];
+
+	buf[0] = cmd;
+	put_unaligned_le16(val, &buf[1]);
+
+	return omnia_cmd_write(client, buf, sizeof(buf));
+}
+
 static inline int omnia_cmd_write_u32(const struct i2c_client *client, u8 cmd,
 				      u32 val)
 {
@@ -158,5 +181,6 @@ extern const struct attribute_group omnia_mcu_poweroff_group;
 
 int omnia_mcu_register_gpiochip(struct omnia_mcu *mcu);
 int omnia_mcu_register_sys_off_and_wakeup(struct omnia_mcu *mcu);
+int omnia_mcu_register_watchdog(struct omnia_mcu *mcu);
 
 #endif /* __TURRIS_OMNIA_MCU_H */
Signature · 1 line
2.44.2
Reviewed-by on v11 5/8
#11 lore raw

Re: [PATCH v11 5/8] platform: cznic: turris-omnia-mcu: Add support for MCU watchdog

Quoted 2 lines · Marek Behún

Add support for the watchdog mechanism provided by the MCU.

...

+ bitops.h
+ dev_printk.h

drivers/platform/cznic/turris-omnia-mcu-watchdog.c line 10

Quoted 4 lines
drivers/platform/cznic/turris-omnia-mcu-watchdog.c new file +3 -0
+#include <linux/i2c.h>
+#include <linux/moduleparam.h>
 
+#include <linux/turris-omnia-mcu-interface.h>

As per other patches.

drivers/platform/cznic/turris-omnia-mcu-watchdog.c line 15

Quoted 5 lines
drivers/platform/cznic/turris-omnia-mcu-watchdog.c new file +5 -0
+#include <linux/types.h>
+#include <linux/units.h>
+#include <linux/watchdog.h>
+
+#include "turris-omnia-mcu.h"

struct device;

Alternatively instead of dev_printk.h + struct device forward declaration --> device.h.

...

With the above being addressed, LGTM, FWIW,

Signature · 2 lines
With Best Regards,
Andy Shevchenko
author maintainer
#12 lore raw

PATCH v11 6/8 platform: cznic: turris-omnia-mcu: Add support for MCU provided TRNG

In reply to Marek Behún

Add support for true random number generator provided by the MCU. New Omnia boards come without the Atmel SHA204-A chip. Instead the crypto functionality is provided by new microcontroller, which has a TRNG peripheral.

---
 drivers/platform/cznic/Kconfig                |   2 +
 drivers/platform/cznic/Makefile               |   1 +
 .../platform/cznic/turris-omnia-mcu-base.c    |   6 +-
 .../platform/cznic/turris-omnia-mcu-gpio.c    |   2 +-
 .../platform/cznic/turris-omnia-mcu-trng.c    | 103 ++++++++++++++++++
 drivers/platform/cznic/turris-omnia-mcu.h     |   8 ++
 6 files changed, 120 insertions(+), 2 deletions(-)
 create mode 100644 drivers/platform/cznic/turris-omnia-mcu-trng.c
drivers/platform/cznic/Kconfig +2 -0
index e262930b3faf..6edac80d5fa3 100644
@@ -18,6 +18,7 @@ config TURRIS_OMNIA_MCU
 	depends on I2C
 	select GPIOLIB
 	select GPIOLIB_IRQCHIP
+	select HW_RANDOM
 	select RTC_CLASS
 	select WATCHDOG_CORE
 	help
@@ -27,6 +28,7 @@ config TURRIS_OMNIA_MCU
 	  - board poweroff into true low power mode (with voltage regulators
 	    disabled) and the ability to configure wake up from this mode (via
 	    rtcwake)
+	  - true random number generator (if available on the MCU)
 	  - MCU watchdog
 	  - GPIO pins
 	    - to get front button press events (the front button can be
drivers/platform/cznic/Makefile +1 -0
index 687f7718c0a1..eae4c6b341ff 100644
@@ -4,4 +4,5 @@ obj-$(CONFIG_TURRIS_OMNIA_MCU)	+= turris-omnia-mcu.o
 turris-omnia-mcu-y		:= turris-omnia-mcu-base.o
 turris-omnia-mcu-y		+= turris-omnia-mcu-gpio.o
 turris-omnia-mcu-y		+= turris-omnia-mcu-sys-off-wakeup.o
+turris-omnia-mcu-y		+= turris-omnia-mcu-trng.o
 turris-omnia-mcu-y		+= turris-omnia-mcu-watchdog.o
drivers/platform/cznic/turris-omnia-mcu-base.c +5 -1
index f44996588d38..1d4153a96526 100644
@@ -380,7 +380,11 @@ static int omnia_mcu_probe(struct i2c_client *client)
 	if (err)
 		return err;
 
-	return omnia_mcu_register_gpiochip(mcu);
+	err = omnia_mcu_register_gpiochip(mcu);
+	if (err)
+		return err;
+
+	return omnia_mcu_register_trng(mcu);
 }
 
 static const struct of_device_id of_omnia_mcu_match[] = {
drivers/platform/cznic/turris-omnia-mcu-gpio.c +1 -1
index bc7965e6c879..972364d3d223 100644
@@ -174,7 +174,7 @@ static const struct omnia_gpio omnia_gpios[64] = {
 };
 
 /* mapping from interrupts to indexes of GPIOs in the omnia_gpios array */
-static const u8 omnia_int_to_gpio_idx[32] = {
+const u8 omnia_int_to_gpio_idx[32] = {
 	[__bf_shf(OMNIA_INT_CARD_DET)]			= 4,
 	[__bf_shf(OMNIA_INT_MSATA_IND)]			= 5,
 	[__bf_shf(OMNIA_INT_USB30_OVC)]			= 6,
drivers/platform/cznic/turris-omnia-mcu-trng.c new file +103 -0

103 lines not on this page · raw message

drivers/platform/cznic/turris-omnia-mcu.h +8 -0
index 5f846909934f..ee8d58516156 100644
@@ -9,7 +9,9 @@
 #define __TURRIS_OMNIA_MCU_H
 
 #include <linux/bitops.h>
+#include <linux/completion.h>
 #include <linux/gpio/driver.h>
+#include <linux/hw_random.h>
 #include <linux/if_ether.h>
 #include <linux/mutex.h>
 #include <linux/rtc.h>
@@ -47,6 +49,10 @@ struct omnia_mcu {
 
 	/* MCU watchdog */
 	struct watchdog_device wdt;
+
+	/* true random number generator */
+	struct hwrng trng;
+	struct completion trng_completion;
 };
 
 int omnia_cmd_write_read(const struct i2c_client *client,
@@ -176,11 +182,13 @@ static inline int omnia_cmd_read_u8(const struct i2c_client *client, u8 cmd,
 	return omnia_cmd_read(client, cmd, reply, sizeof(*reply));
 }
 
+extern const u8 omnia_int_to_gpio_idx[32];
 extern const struct attribute_group omnia_mcu_gpio_group;
 extern const struct attribute_group omnia_mcu_poweroff_group;
 
 int omnia_mcu_register_gpiochip(struct omnia_mcu *mcu);
 int omnia_mcu_register_sys_off_and_wakeup(struct omnia_mcu *mcu);
+int omnia_mcu_register_trng(struct omnia_mcu *mcu);
 int omnia_mcu_register_watchdog(struct omnia_mcu *mcu);
 
 #endif /* __TURRIS_OMNIA_MCU_H */
Signature · 1 line
2.44.2
#13 lore raw

Re: [PATCH v11 6/8] platform: cznic: turris-omnia-mcu: Add support for MCU provided TRNG

Quoted 5 lines · Marek Behún

Add support for true random number generator provided by the MCU. New Omnia boards come without the Atmel SHA204-A chip. Instead the crypto functionality is provided by new microcontroller, which has a TRNG peripheral.

+Cc: Bart for gpiochip_get_desc() usage.

...

drivers/platform/cznic/turris-omnia-mcu-trng.c line 9

Quoted 2 lines
drivers/platform/cznic/turris-omnia-mcu-trng.c new file +2 -0
+#include <linux/bitfield.h>
+#include <linux/completion.h>

+ errno.h

drivers/platform/cznic/turris-omnia-mcu-trng.c line 18

Quoted 10 lines
drivers/platform/cznic/turris-omnia-mcu-trng.c new file +9 -0
+#include <linux/gpio/consumer.h>
+#include <linux/gpio/driver.h>
+#include <linux/hw_random.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/minmax.h>
+#include <linux/module.h>
+#include <linux/string.h>
 
+#include <linux/turris-omnia-mcu-interface.h>

As per other patches.

Quoted 3 lines
drivers/platform/cznic/turris-omnia-mcu-trng.c new file +3 -0
+#include <linux/types.h>
+
+#include "turris-omnia-mcu.h"

...

drivers/platform/cznic/turris-omnia-mcu-trng.c line 73

Quoted 4 lines
drivers/platform/cznic/turris-omnia-mcu-trng.c new file +4 -0
+       irq_idx = omnia_int_to_gpio_idx[__bf_shf(OMNIA_INT_TRNG)];
+       irq = gpiod_to_irq(gpiochip_get_desc(&mcu->gc, irq_idx));
+       if (irq < 0)
+               return dev_err_probe(dev, irq, "Cannot get TRNG IRQ\n");

Okay, it's a bit more complicated than that. The gpiochip_get_desc() shouldn't be used. Bart, what can you suggest to do here? Opencoding it doesn't sound to me a (fully) correct approach in a long term.

--
With Best Regards,
Andy Shevchenko

author maintainer
#14 lore raw

Re: [PATCH v11 6/8] platform: cznic: turris-omnia-mcu: Add support for MCU provided TRNG

Quoted 8 lines · On Wed, 5 Jun 2024 22:00:20 +0300 Andy Shevchenko <[email protected]>…

drivers/platform/cznic/turris-omnia-mcu-trng.c line 73

Quoted 4 lines
drivers/platform/cznic/turris-omnia-mcu-trng.c new file +4 -0
+       irq_idx = omnia_int_to_gpio_idx[__bf_shf(OMNIA_INT_TRNG)];
+       irq = gpiod_to_irq(gpiochip_get_desc(&mcu->gc, irq_idx));
+       if (irq < 0)
+               return dev_err_probe(dev, irq, "Cannot get TRNG IRQ\n");  

Okay, it's a bit more complicated than that. The gpiochip_get_desc() shouldn't be used. Bart, what can you suggest to do here? Opencoding it doesn't sound to me a (fully) correct approach in a long term.

Note that I can't use gpiochip_request_own_desc(), nor any other function that calls gpio_request_commit() (like gpiod_get()), because that checks for gpiochip_line_is_valid(), and this returns false for the TRNG line, cause that line is not a GPIO line, but interrupt only line.

That is why I used
irq = irq_create_mapping(dev, mcu->gc.irq.domain, irq_idx);
until v7, with no reference to gpio descriptors, since this line is not a GPIO line.

We have discussed this back in April, in the thread
https://lore.kernel.org/soc/[email protected]/
where we concluded that
irq = gpiod_to_irq(gpiochip_get_desc(gc, irq_idx));
is better...

Marek

#15 lore raw

Re: [PATCH v11 6/8] platform: cznic: turris-omnia-mcu: Add support for MCU provided TRNG

Quoted 23 lines · Marek Behún
Quoted 8 lines · On Wed, 5 Jun 2024 22:00:20 +0300 Andy Shevchenko <[email protected]>…

drivers/platform/cznic/turris-omnia-mcu-trng.c line 73

Quoted 4 lines
drivers/platform/cznic/turris-omnia-mcu-trng.c new file +4 -0
+       irq_idx = omnia_int_to_gpio_idx[__bf_shf(OMNIA_INT_TRNG)];
+       irq = gpiod_to_irq(gpiochip_get_desc(&mcu->gc, irq_idx));
+       if (irq < 0)
+               return dev_err_probe(dev, irq, "Cannot get TRNG IRQ\n");  

Okay, it's a bit more complicated than that. The gpiochip_get_desc() shouldn't be used. Bart, what can you suggest to do here? Opencoding it doesn't sound to me a (fully) correct approach in a long term.

Note that I can't use gpiochip_request_own_desc(), nor any other function that calls gpio_request_commit() (like gpiod_get()), because that checks for gpiochip_line_is_valid(), and this returns false for the TRNG line, cause that line is not a GPIO line, but interrupt only line.

That is why I used
irq = irq_create_mapping(dev, mcu->gc.irq.domain, irq_idx);
until v7, with no reference to gpio descriptors, since this line is not a GPIO line.

Quoted 5 lines

We have discussed this back in April, in the thread
https://lore.kernel.org/soc/[email protected]/
where we concluded that
irq = gpiod_to_irq(gpiochip_get_desc(gc, irq_idx));
is better...

That's fine to not use other APIs, the problem here is with reference counting on the GPIO device. The API you could use is gpio_device_get_desc(). But you need to have a GPIO device pointer somewhere in your driver being available.

Signature · 2 lines
With Best Regards,
Andy Shevchenko
author maintainer
#16 lore raw

Re: [PATCH v11 6/8] platform: cznic: turris-omnia-mcu: Add support for MCU provided TRNG

Quoted 30 lines · On Thu, 6 Jun 2024 13:11:09 +0300 Andy Shevchenko <[email protected]>…
Quoted 23 lines · Marek Behún
Quoted 8 lines · On Wed, 5 Jun 2024 22:00:20 +0300 Andy Shevchenko <[email protected]>…

drivers/platform/cznic/turris-omnia-mcu-trng.c line 73

Quoted 4 lines
drivers/platform/cznic/turris-omnia-mcu-trng.c new file +4 -0
+       irq_idx = omnia_int_to_gpio_idx[__bf_shf(OMNIA_INT_TRNG)];
+       irq = gpiod_to_irq(gpiochip_get_desc(&mcu->gc, irq_idx));
+       if (irq < 0)
+               return dev_err_probe(dev, irq, "Cannot get TRNG IRQ\n");    

Okay, it's a bit more complicated than that. The gpiochip_get_desc() shouldn't be used. Bart, what can you suggest to do here? Opencoding it doesn't sound to me a (fully) correct approach in a long term.

Note that I can't use gpiochip_request_own_desc(), nor any other function that calls gpio_request_commit() (like gpiod_get()), because that checks for gpiochip_line_is_valid(), and this returns false for the TRNG line, cause that line is not a GPIO line, but interrupt only line.

That is why I used
irq = irq_create_mapping(dev, mcu->gc.irq.domain, irq_idx);
until v7, with no reference to gpio descriptors, since this line is not a GPIO line.

Quoted 5 lines

We have discussed this back in April, in the thread
https://lore.kernel.org/soc/[email protected]/
where we concluded that
irq = gpiod_to_irq(gpiochip_get_desc(gc, irq_idx));
is better...

Quoted 3 lines

That's fine to not use other APIs, the problem here is with reference counting on the GPIO device. The API you could use is gpio_device_get_desc(). But you need to have a GPIO device pointer somewhere in your driver being available.

Rewriting to gpio_device_get_desc() is simple, since
gpiochip_get_desc(gc, hwnum)
is equivalent to
gpio_device_get_desc(gc->gpiodev, hwnum)

Obviously neither of these take care of reference counting. But what reference counting are you talking about?
Is it the
try_module_get(desc->gdev->owner)
in gpiod_request()?
Or are we talking only about the FLAG_REQUESTED flag on the descriptor flags? (This one should not be needed since the GPIO line cannot be requested, becuase it is not a valid GPIO line.)

Since the line is not a valid GPIO line, I thought that we don't need to refcount in GPIO code. gpiod_to_irq() will call the gpiochip's .to_irq() method, which will call gpiochip_to_irq(), which will call irq_create_mapping()
gpiod_to_irq()
gpiochip_to_irq()
irq_create_mapping()

Then on gpiochip removal, the gpiochip_irqchip_remove() manually disposes all IRQ mappings with irq_dispose_mapping().

Marek

author maintainer
#17 lore raw

Re: [PATCH v11 6/8] platform: cznic: turris-omnia-mcu: Add support for MCU provided TRNG

In reply to Andy Shevchenko
Quoted 4 lines · On Wed, 5 Jun 2024 22:00:20 +0300 Andy Shevchenko <[email protected]>…

drivers/platform/cznic/turris-omnia-mcu-trng.c line 9

Quoted 2 lines
drivers/platform/cznic/turris-omnia-mcu-trng.c new file +2 -0
+#include <linux/bitfield.h>
+#include <linux/completion.h>  

+ errno.h

I use -EIO, -EINVAL and -ENOMEM in turris-omnia-mcu-base.c, -EINVAL, -ENOTSUPP in turris-omnia-mcu-gpio.c.

Should I include errno.h in those also? Or is this only needed for -ERESTARTSYS?

Marek

#18 lore raw

Re: [PATCH v11 6/8] platform: cznic: turris-omnia-mcu: Add support for MCU provided TRNG

Quoted 8 lines · Marek Behún
Quoted 4 lines · On Wed, 5 Jun 2024 22:00:20 +0300 Andy Shevchenko <[email protected]>…

drivers/platform/cznic/turris-omnia-mcu-trng.c line 9

Quoted 2 lines
drivers/platform/cznic/turris-omnia-mcu-trng.c new file +2 -0
+#include <linux/bitfield.h>
+#include <linux/completion.h>

+ errno.h

Quoted 4 lines

I use -EIO, -EINVAL and -ENOMEM in turris-omnia-mcu-base.c, -EINVAL, -ENOTSUPP in turris-omnia-mcu-gpio.c.

Should I include errno.h in those also?

If you have err.h, then no (it includes asm/errno.h), otherwise, yes.

Quoted 1 line

Or is this only needed for -ERESTARTSYS?

Definitely yes for Linux internal error codes (>= 512). Note, that ENOTSUPP is also Linux internal code.

Signature · 2 lines
With Best Regards,
Andy Shevchenko
#19 lore raw

Re: [PATCH v11 6/8] platform: cznic: turris-omnia-mcu: Add support for MCU provided TRNG

In reply to Andy Shevchenko
Quoted 36 lines · Andy Shevchenko
Quoted 5 lines · Marek Behún

Add support for true random number generator provided by the MCU. New Omnia boards come without the Atmel SHA204-A chip. Instead the crypto functionality is provided by new microcontroller, which has a TRNG peripheral.

+Cc: Bart for gpiochip_get_desc() usage.

...

drivers/platform/cznic/turris-omnia-mcu-trng.c line 9

Quoted 2 lines
drivers/platform/cznic/turris-omnia-mcu-trng.c new file +2 -0
+#include <linux/bitfield.h>
+#include <linux/completion.h>

+ errno.h

drivers/platform/cznic/turris-omnia-mcu-trng.c line 18

Quoted 10 lines
drivers/platform/cznic/turris-omnia-mcu-trng.c new file +9 -0
+#include <linux/gpio/consumer.h>
+#include <linux/gpio/driver.h>
+#include <linux/hw_random.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/minmax.h>
+#include <linux/module.h>
+#include <linux/string.h>
 
+#include <linux/turris-omnia-mcu-interface.h>

As per other patches.

Quoted 3 lines
drivers/platform/cznic/turris-omnia-mcu-trng.c new file +3 -0
+#include <linux/types.h>
+
+#include "turris-omnia-mcu.h"

...

Quoted 9 lines

drivers/platform/cznic/turris-omnia-mcu-trng.c line 73

Quoted 4 lines
drivers/platform/cznic/turris-omnia-mcu-trng.c new file +4 -0
+       irq_idx = omnia_int_to_gpio_idx[__bf_shf(OMNIA_INT_TRNG)];
+       irq = gpiod_to_irq(gpiochip_get_desc(&mcu->gc, irq_idx));
+       if (irq < 0)
+               return dev_err_probe(dev, irq, "Cannot get TRNG IRQ\n");

Okay, it's a bit more complicated than that. The gpiochip_get_desc() shouldn't be used. Bart, what can you suggest to do here? Opencoding it doesn't sound to me a (fully) correct approach in a long term.

Andy's worried about reference counting of the GPIO device. Maybe you should just ref the GPIO device in irq_request_resources() and unref it in irq_release_resources()? Then you could use gpiochip_get_desc() just fine.

Bart

author maintainer
#20 lore raw

Re: [PATCH v11 6/8] platform: cznic: turris-omnia-mcu: Add support for MCU provided TRNG

Quoted 48 lines · On Mon, 17 Jun 2024 10:38:31 +0200 Bartosz Golaszewski <[email protected]> wrote:
Quoted 36 lines · Andy Shevchenko
Quoted 5 lines · Marek Behún

Add support for true random number generator provided by the MCU. New Omnia boards come without the Atmel SHA204-A chip. Instead the crypto functionality is provided by new microcontroller, which has a TRNG peripheral.

+Cc: Bart for gpiochip_get_desc() usage.

...

drivers/platform/cznic/turris-omnia-mcu-trng.c line 9

Quoted 2 lines
drivers/platform/cznic/turris-omnia-mcu-trng.c new file +2 -0
+#include <linux/bitfield.h>
+#include <linux/completion.h>  

+ errno.h

drivers/platform/cznic/turris-omnia-mcu-trng.c line 18

Quoted 10 lines
drivers/platform/cznic/turris-omnia-mcu-trng.c new file +9 -0
+#include <linux/gpio/consumer.h>
+#include <linux/gpio/driver.h>
+#include <linux/hw_random.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/minmax.h>
+#include <linux/module.h>
+#include <linux/string.h>  
 
+#include <linux/turris-omnia-mcu-interface.h>  

As per other patches.

Quoted 3 lines
drivers/platform/cznic/turris-omnia-mcu-trng.c new file +3 -0
+#include <linux/types.h>
+
+#include "turris-omnia-mcu.h"  

...

Quoted 9 lines

drivers/platform/cznic/turris-omnia-mcu-trng.c line 73

Quoted 4 lines
drivers/platform/cznic/turris-omnia-mcu-trng.c new file +4 -0
+       irq_idx = omnia_int_to_gpio_idx[__bf_shf(OMNIA_INT_TRNG)];
+       irq = gpiod_to_irq(gpiochip_get_desc(&mcu->gc, irq_idx));
+       if (irq < 0)
+               return dev_err_probe(dev, irq, "Cannot get TRNG IRQ\n");  

Okay, it's a bit more complicated than that. The gpiochip_get_desc() shouldn't be used. Bart, what can you suggest to do here? Opencoding it doesn't sound to me a (fully) correct approach in a long term.

Quoted 4 lines

Andy's worried about reference counting of the GPIO device. Maybe you should just ref the GPIO device in irq_request_resources() and unref it in irq_release_resources()? Then you could use gpiochip_get_desc() just fine.

But this is already being done.

The irqchip uses GPIOCHIP_IRQ_RESOURCE_HELPERS macro in its definition:

  static const struct irq_chip omnia_mcu_irq_chip = {
    ...
    GPIOCHIP_IRQ_RESOURCE_HELPERS,
  };

This means that gpiochip_irq_reqres() and gpiochip_irq_relres() are used as irq_request_resources() and irq_release_resources().

The gpiochip_reqres_irq() code increases the module refcount and even locks the line as IRQ:

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/gpio/gpiolib.c?h=v6.10-rc4#n3732

Marek

#21 lore raw

Re: [PATCH v11 6/8] platform: cznic: turris-omnia-mcu: Add support for MCU provided TRNG

Quoted 69 lines · Marek Behún
Quoted 48 lines · On Mon, 17 Jun 2024 10:38:31 +0200 Bartosz Golaszewski <[email protected]> wrote:
Quoted 36 lines · Andy Shevchenko
Quoted 5 lines · Marek Behún

Add support for true random number generator provided by the MCU. New Omnia boards come without the Atmel SHA204-A chip. Instead the crypto functionality is provided by new microcontroller, which has a TRNG peripheral.

+Cc: Bart for gpiochip_get_desc() usage.

...

drivers/platform/cznic/turris-omnia-mcu-trng.c line 9

Quoted 2 lines
drivers/platform/cznic/turris-omnia-mcu-trng.c new file +2 -0
+#include <linux/bitfield.h>
+#include <linux/completion.h>

+ errno.h

drivers/platform/cznic/turris-omnia-mcu-trng.c line 18

Quoted 10 lines
drivers/platform/cznic/turris-omnia-mcu-trng.c new file +9 -0
+#include <linux/gpio/consumer.h>
+#include <linux/gpio/driver.h>
+#include <linux/hw_random.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/minmax.h>
+#include <linux/module.h>
+#include <linux/string.h>
 
+#include <linux/turris-omnia-mcu-interface.h>

As per other patches.

Quoted 3 lines
drivers/platform/cznic/turris-omnia-mcu-trng.c new file +3 -0
+#include <linux/types.h>
+
+#include "turris-omnia-mcu.h"

...

Quoted 9 lines

drivers/platform/cznic/turris-omnia-mcu-trng.c line 73

Quoted 4 lines
drivers/platform/cznic/turris-omnia-mcu-trng.c new file +4 -0
+       irq_idx = omnia_int_to_gpio_idx[__bf_shf(OMNIA_INT_TRNG)];
+       irq = gpiod_to_irq(gpiochip_get_desc(&mcu->gc, irq_idx));
+       if (irq < 0)
+               return dev_err_probe(dev, irq, "Cannot get TRNG IRQ\n");

Okay, it's a bit more complicated than that. The gpiochip_get_desc() shouldn't be used. Bart, what can you suggest to do here? Opencoding it doesn't sound to me a (fully) correct approach in a long term.

Quoted 4 lines

Andy's worried about reference counting of the GPIO device. Maybe you should just ref the GPIO device in irq_request_resources() and unref it in irq_release_resources()? Then you could use gpiochip_get_desc() just fine.

But this is already being done.

The irqchip uses GPIOCHIP_IRQ_RESOURCE_HELPERS macro in its definition:

  static const struct irq_chip omnia_mcu_irq_chip = {
    ...
    GPIOCHIP_IRQ_RESOURCE_HELPERS,
  };

This means that gpiochip_irq_reqres() and gpiochip_irq_relres() are used as irq_request_resources() and irq_release_resources().

Quoted 6 lines

The gpiochip_reqres_irq() code increases the module refcount and even locks the line as IRQ:

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/gpio/gpiolib.c?h=v6.10-rc4#n3732

Marek

Andy: what is the issue here then exactly?

Bart

#22 lore raw

Re: [PATCH v11 6/8] platform: cznic: turris-omnia-mcu: Add support for MCU provided TRNG

Quoted 13 lines · Bartosz Golaszewski
Quoted 12 lines · Marek Behún
Quoted 10 lines · On Mon, 17 Jun 2024 10:38:31 +0200 Bartosz Golaszewski <[email protected]> wrote:
Quoted 8 lines · Andy Shevchenko
Quoted 5 lines · Marek Behún

Add support for true random number generator provided by the MCU. New Omnia boards come without the Atmel SHA204-A chip. Instead the crypto functionality is provided by new microcontroller, which has a TRNG peripheral.

+Cc: Bart for gpiochip_get_desc() usage.

...

Quoted 26 lines
Quoted 26 lines
Quoted 5 lines
Quoted 5 lines
Quoted 4 lines
drivers/platform/cznic/turris-omnia-mcu-trng.c new file +4 -0
+       irq_idx = omnia_int_to_gpio_idx[__bf_shf(OMNIA_INT_TRNG)];
+       irq = gpiod_to_irq(gpiochip_get_desc(&mcu->gc, irq_idx));
+       if (irq < 0)
+               return dev_err_probe(dev, irq, "Cannot get TRNG IRQ\n");
Quoted 8 lines
Quoted 3 lines

Okay, it's a bit more complicated than that. The gpiochip_get_desc() shouldn't be used. Bart, what can you suggest to do here? Opencoding it doesn't sound to me a (fully) correct approach in a long term.

Andy's worried about reference counting of the GPIO device. Maybe you should just ref the GPIO device in irq_request_resources() and unref it in irq_release_resources()? Then you could use gpiochip_get_desc() just fine.

But this is already being done.

The irqchip uses GPIOCHIP_IRQ_RESOURCE_HELPERS macro in its definition:

  static const struct irq_chip omnia_mcu_irq_chip = {
    ...
    GPIOCHIP_IRQ_RESOURCE_HELPERS,
  };

This means that gpiochip_irq_reqres() and gpiochip_irq_relres() are used as irq_request_resources() and irq_release_resources().

Quoted 6 lines
Quoted 4 lines

The gpiochip_reqres_irq() code increases the module refcount and even locks the line as IRQ:

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/gpio/gpiolib.c?h=v6.10-rc4#n3732

Andy: what is the issue here then exactly?

The function in use is marked as DEPRECATED. If you are fine with its usage in this case, I have no issues with it.
If you want it to be replaced with the respective gpio_device_get_desc(), it's fine, but then the question is how properly get a pointer to GPIO device object.

Signature · 2 lines
With Best Regards,
Andy Shevchenko
author maintainer
#23 lore raw

Re: [PATCH v11 6/8] platform: cznic: turris-omnia-mcu: Add support for MCU provided TRNG

Quoted 48 lines · On Mon, 17 Jun 2024 12:42:41 +0200 Andy Shevchenko <[email protected]>…
Quoted 13 lines · Bartosz Golaszewski
Quoted 12 lines · Marek Behún
Quoted 10 lines · On Mon, 17 Jun 2024 10:38:31 +0200 Bartosz Golaszewski <[email protected]> wrote:
Quoted 8 lines · Andy Shevchenko
Quoted 5 lines · Marek Behún

Add support for true random number generator provided by the MCU. New Omnia boards come without the Atmel SHA204-A chip. Instead the crypto functionality is provided by new microcontroller, which has a TRNG peripheral.

+Cc: Bart for gpiochip_get_desc() usage.

...

Quoted 31 lines
Quoted 30 lines
Quoted 5 lines
Quoted 5 lines
Quoted 4 lines
drivers/platform/cznic/turris-omnia-mcu-trng.c new file +4 -0
+       irq_idx = omnia_int_to_gpio_idx[__bf_shf(OMNIA_INT_TRNG)];
+       irq = gpiod_to_irq(gpiochip_get_desc(&mcu->gc, irq_idx));
+       if (irq < 0)
+               return dev_err_probe(dev, irq, "Cannot get TRNG IRQ\n");  
Quoted 8 lines
Quoted 3 lines

Okay, it's a bit more complicated than that. The gpiochip_get_desc() shouldn't be used. Bart, what can you suggest to do here? Opencoding it doesn't sound to me a (fully) correct approach in a long term.

Andy's worried about reference counting of the GPIO device. Maybe you should just ref the GPIO device in irq_request_resources() and unref it in irq_release_resources()? Then you could use gpiochip_get_desc() just fine.

But this is already being done.

The irqchip uses GPIOCHIP_IRQ_RESOURCE_HELPERS macro in its definition:

  static const struct irq_chip omnia_mcu_irq_chip = {
    ...
    GPIOCHIP_IRQ_RESOURCE_HELPERS,
  };

This means that gpiochip_irq_reqres() and gpiochip_irq_relres() are used as irq_request_resources() and irq_release_resources().

The gpiochip_reqres_irq() code increases the module refcount and even locks the line as IRQ:

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/gpio/gpiolib.c?h=v6.10-rc4#n3732

Quoted 8 lines
Quoted 1 line

Andy: what is the issue here then exactly?

The function in use is marked as DEPRECATED. If you are fine with its usage in this case, I have no issues with it.
If you want it to be replaced with the respective gpio_device_get_desc(), it's fine, but then the question is how properly get a pointer to GPIO device object.

Aha, I did not notice that the function is deprecated.

What about

  irq = gpiod_to_irq(gpio_device_get_desc(mcu->gc.gpiodev, irq_idx));

?

Note: I would prefer
irq_create_mapping(mcu->gc.irq.domain, irq_idx)
since the irq_idx line is not a valid GPIO line and at this part of the driver the fact that the IRQs are provided through a gpiochip are semantically irrelevant (we are interested in "an IRQ", not "an IRQ from a GPIO").

Marek

#24 lore raw

Re: [PATCH v11 6/8] platform: cznic: turris-omnia-mcu: Add support for MCU provided TRNG

Quoted 69 lines · Marek Behún
Quoted 48 lines · On Mon, 17 Jun 2024 12:42:41 +0200 Andy Shevchenko <[email protected]>…
Quoted 13 lines · Bartosz Golaszewski
Quoted 12 lines · Marek Behún
Quoted 10 lines · On Mon, 17 Jun 2024 10:38:31 +0200 Bartosz Golaszewski <[email protected]> wrote:
Quoted 8 lines · Andy Shevchenko
Quoted 5 lines · Marek Behún

Add support for true random number generator provided by the MCU. New Omnia boards come without the Atmel SHA204-A chip. Instead the crypto functionality is provided by new microcontroller, which has a TRNG peripheral.

+Cc: Bart for gpiochip_get_desc() usage.

...

Quoted 31 lines
Quoted 30 lines
Quoted 5 lines
Quoted 5 lines
Quoted 4 lines
(quoted diff) +4 -0
+       irq_idx = omnia_int_to_gpio_idx[__bf_shf(OMNIA_INT_TRNG)];
+       irq = gpiod_to_irq(gpiochip_get_desc(&mcu->gc, irq_idx));
+       if (irq < 0)
+               return dev_err_probe(dev, irq, "Cannot get TRNG IRQ\n");
Quoted 8 lines
Quoted 3 lines

Okay, it's a bit more complicated than that. The gpiochip_get_desc() shouldn't be used. Bart, what can you suggest to do here? Opencoding it doesn't sound to me a (fully) correct approach in a long term.

Andy's worried about reference counting of the GPIO device. Maybe you should just ref the GPIO device in irq_request_resources() and unref it in irq_release_resources()? Then you could use gpiochip_get_desc() just fine.

But this is already being done.

The irqchip uses GPIOCHIP_IRQ_RESOURCE_HELPERS macro in its definition:

  static const struct irq_chip omnia_mcu_irq_chip = {
    ...
    GPIOCHIP_IRQ_RESOURCE_HELPERS,
  };

This means that gpiochip_irq_reqres() and gpiochip_irq_relres() are used as irq_request_resources() and irq_release_resources().

The gpiochip_reqres_irq() code increases the module refcount and even locks the line as IRQ:

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/gpio/gpiolib.c?h=v6.10-rc4#n3732

Quoted 8 lines
Quoted 1 line

Andy: what is the issue here then exactly?

The function in use is marked as DEPRECATED. If you are fine with its usage in this case, I have no issues with it.
If you want it to be replaced with the respective gpio_device_get_desc(), it's fine, but then the question is how properly get a pointer to GPIO device object.

Aha, I did not notice that the function is deprecated.

What about

  irq = gpiod_to_irq(gpio_device_get_desc(mcu->gc.gpiodev, irq_idx));

?

Quoted 8 lines

Note: I would prefer
irq_create_mapping(mcu->gc.irq.domain, irq_idx)
since the irq_idx line is not a valid GPIO line and at this part of the driver the fact that the IRQs are provided through a gpiochip are semantically irrelevant (we are interested in "an IRQ", not "an IRQ from a GPIO").

Marek

The reason to deprecate it was the fact that it's dangerous to use from outside of the GPIO provider code. I actually plan to soon make this function private to gpiolib, there's just one pinctrl driver left to convert.

So maybe it's better to not use it here. Please keep in mind that gpio_device_get_desc() doesn't increase the reference count of gpio_device so you need to make sure it stays alive. But it seems to be the case here as you're within the driver code still.

Bart

maintainer
#25 lore raw

Re: [PATCH v11 6/8] platform: cznic: turris-omnia-mcu: Add support for MCU provided TRNG

In reply to Marek Behún

drivers/platform/cznic/turris-omnia-mcu-trng.c line 36

Quoted 4 lines · Marek Behún
drivers/platform/cznic/turris-omnia-mcu-trng.c new file +3 -0
+static int omnia_trng_read(struct hwrng *rng, void *data, size_t max, bool wait)
+{
+	struct omnia_mcu *mcu = (struct omnia_mcu *)rng->priv;

Please don't cast rng->priv in this manner. Please take a look at drivers/char/hw_random/bcm2835-rng.c for how it should be done.

Thanks,

Signature · 3 lines
Email: Herbert Xu <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
author maintainer
#26 lore raw

Re: [PATCH v11 6/8] platform: cznic: turris-omnia-mcu: Add support for MCU provided TRNG

Quoted 10 lines · On Fri, 7 Jun 2024 18:30:24 +0800 Herbert Xu <[email protected]>…

drivers/platform/cznic/turris-omnia-mcu-trng.c line 36

Quoted 4 lines · Marek Behún
drivers/platform/cznic/turris-omnia-mcu-trng.c new file +3 -0
+static int omnia_trng_read(struct hwrng *rng, void *data, size_t max, bool wait)
+{
+	struct omnia_mcu *mcu = (struct omnia_mcu *)rng->priv;  

Please don't cast rng->priv in this manner. Please take a look at drivers/char/hw_random/bcm2835-rng.c for how it should be done.

Thanks,

THX, prepared for next version.

author maintainer
#27 lore raw

PATCH v11 7/8 ARM: dts: turris-omnia: Add MCU system-controller node

In reply to Marek Behún

Turris Omnia's MCU provides various features that can be configured over I2C at address 0x2a. Add device-tree node.

This does not carry a Fixes tag - we do not want this to get backported to stable kernels for the following reason: U-Boot since v2022.10 inserts a phy-reset-gpio property into the WAN ethernet node pointing to the MCU node if it finds the MCU node with a cznic,turris-omnia-mcu compatible. Thus if this change got backported to a stable kernel, the WAN interface driver would defer probe indefinitely (since it would wait for the turris-omnia-mcu driver which would not be present).

---
 .../dts/marvell/armada-385-turris-omnia.dts   | 22 ++++++++++++++++++-
 1 file changed, 21 insertions(+), 1 deletion(-)
arch/arm/boot/dts/marvell/armada-385-turris-omnia.dts +21 -1
index 7b755bb4e4e7..59079d63fe27 100644
@@ -218,7 +218,22 @@ i2c@0 {
 			#size-cells = <0>;
 			reg = <0>;
 
-			/* STM32F0 command interface at address 0x2a */
+			mcu: system-controller@2a {
+				compatible = "cznic,turris-omnia-mcu";
+				reg = <0x2a>;
+
+				pinctrl-names = "default";
+				pinctrl-0 = <&mcu_pins>;
+
+				interrupt-parent = <&gpio1>;
+				interrupts = <11 IRQ_TYPE_NONE>;
+
+				gpio-controller;
+				#gpio-cells = <3>;
+
+				interrupt-controller;
+				#interrupt-cells = <2>;
+			};
 
 			led-controller@2b {
 				compatible = "cznic,turris-omnia-leds";
@@ -501,6 +516,11 @@ fixed-link {
 };
 
 &pinctrl {
+	mcu_pins: mcu-pins {
+		marvell,pins = "mpp43";
+		marvell,function = "gpio";
+	};
+
 	pcawan_pins: pcawan-pins {
 		marvell,pins = "mpp46";
 		marvell,function = "gpio";
Signature · 1 line
2.44.2
author maintainer
#28 lore raw

PATCH v11 8/8 ARM: dts: turris-omnia: Add GPIO key node for front button

In reply to Marek Behún

Now that we have the MCU device-tree node, which acts as a GPIO controller, add GPIO key node for the front button.

---
 .../boot/dts/marvell/armada-385-turris-omnia.dts    | 13 +++++++++++++
 1 file changed, 13 insertions(+)
arch/arm/boot/dts/marvell/armada-385-turris-omnia.dts +13 -0
index 59079d63fe27..43202890c959 100644
@@ -112,6 +112,19 @@ sfp: sfp {
 		status = "disabled";
 	};
 
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		front-button {
+			label = "Front Button";
+			linux,code = <KEY_VENDOR>;
+			linux,can-disable;
+			gpios = <&mcu 0 12 GPIO_ACTIVE_HIGH>;
+			/* debouncing is done by the microcontroller */
+			debounce-interval = <0>;
+		};
+	};
+
 	sound {
 		compatible = "simple-audio-card";
 		simple-audio-card,name = "SPDIF";
Signature · 1 line
2.44.2
#29 lore raw
In reply to Marek Behún
Quoted 4 lines · Marek Behún

Hello Andy, Hans, Ilpo, Arnd, Gregory, and others,

this is v11 of the series adding Turris Omnia MCU driver.

Thank you!
There are a few small issues here and there, but overall LGTM. The only one main question is what to do with gpiochip_get_desc(). I Cc'ed Bart for this.

Signature · 2 lines
With Best Regards,
Andy Shevchenko
author maintainer
#30 lore raw
Quoted 10 lines · On Wed, 5 Jun 2024 22:05:37 +0300 Andy Shevchenko <[email protected]>…
Quoted 4 lines · Marek Behún

Hello Andy, Hans, Ilpo, Arnd, Gregory, and others,

this is v11 of the series adding Turris Omnia MCU driver.

Thank you!
There are a few small issues here and there, but overall LGTM. The only one main question is what to do with gpiochip_get_desc(). I Cc'ed Bart for this.

Thank you for the review, I am going to apply the changes you requested and wait for Bart, and we'll see what to do with the gpiochip_get_desc().

Marek