Turris Omnia MCU driver
Subsystems (7)
Marek Behún
maintainerv8 cover Turris Omnia MCU driver
Hello Andy, Hans, Ilpo, Arnd, Gregory, and others,
this is v8 of the series adding Turris Omnia MCU driver.
This series depends on the immutable branch between LEDs and locking, introducing devm_mutex_init(), see the PR
https://lore.kernel.org/linux-leds/[email protected]/
See also cover letters for v1, v2, v3, v4, v5, v6 and v7:
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]/
Changes since v7:
- fixed wrong $id path in DT binding (patch 1)
- removed resource managed IRQ mapping disposal, which is not needed, as pointed out by Andy (patches 6, 7)
- added some more #includes (for linux/device.h, linux/interrupt.h, linux/hw_random.h) (patches 3, 6, 7)
- dropped the Fixes tags from the DT changes (patches 8, 9), with an explanation of this added into the commit message of patch 8, as suggested by Andrew
Marek Behún (9):
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
platform: cznic: turris-omnia-mcu: Add support for digital message
signing via debugfs
ARM: dts: turris-omnia: Add MCU system-controller node
ARM: dts: turris-omnia: Add GPIO key node for front button
.../ABI/testing/debugfs-turris-omnia-mcu | 13 + .../sysfs-bus-i2c-devices-turris-omnia-mcu | 126 ++ .../firmware/cznic,turris-omnia-mcu.yaml | 86 ++ MAINTAINERS | 5 + .../dts/marvell/armada-385-turris-omnia.dts | 35 +- drivers/platform/Kconfig | 2 + drivers/platform/Makefile | 1 + drivers/platform/cznic/Kconfig | 51 + drivers/platform/cznic/Makefile | 9 + .../platform/cznic/turris-omnia-mcu-base.c | 439 +++++++ .../platform/cznic/turris-omnia-mcu-debugfs.c | 207 ++++ .../platform/cznic/turris-omnia-mcu-gpio.c | 1048 +++++++++++++++++ .../cznic/turris-omnia-mcu-sys-off-wakeup.c | 258 ++++ .../platform/cznic/turris-omnia-mcu-trng.c | 101 ++ .../cznic/turris-omnia-mcu-watchdog.c | 123 ++ drivers/platform/cznic/turris-omnia-mcu.h | 188 +++ include/linux/turris-omnia-mcu-interface.h | 249 ++++ 17 files changed, 2940 insertions(+), 1 deletion(-) create mode 100644 Documentation/ABI/testing/debugfs-turris-omnia-mcu 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-debugfs.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.43.2
Marek Behún
maintainerPATCH v8 1/9 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
@@ -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
@@ -2143,6 +2143,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.43.2
Marek Behún
maintainerPATCH v8 2/9 platform: cznic: Add preliminary support for Turris Omnia MCU
In reply to Marek BehúnAdd 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 | 26 ++ drivers/platform/cznic/Makefile | 4 + .../platform/cznic/turris-omnia-mcu-base.c | 376 ++++++++++++++++++ drivers/platform/cznic/turris-omnia-mcu.h | 50 +++ include/linux/turris-omnia-mcu-interface.h | 249 ++++++++++++ 9 files changed, 792 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
@@ -0,0 +1,81 @@ +What: /sys/bus/i2c/devices/<mcu_device>/board_revision +Date: July 2024 +KernelVersion: 6.10 +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: July 2024 +KernelVersion: 6.10 +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: July 2024 +KernelVersion: 6.10 +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: July 2024 +KernelVersion: 6.10 +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: July 2024 +KernelVersion: 6.10 +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: July 2024 +KernelVersion: 6.10 +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: July 2024 +KernelVersion: 6.10 +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: July 2024 +KernelVersion: 6.10 +Contact: Marek Behún <[email protected]> +Description: (RO) Contains the 64 bit long 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
@@ -2139,6 +2139,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
@@ -2152,10 +2153,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
@@ -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
@@ -10,4 +10,5 @@ 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/
drivers/platform/cznic/Kconfig new file +26 -0
@@ -0,0 +1,26 @@ +# 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" + depends on MACH_ARMADA_38X || COMPILE_TEST + 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
@@ -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 +376 -0
376 lines not on this page · raw message
drivers/platform/cznic/turris-omnia-mcu.h new file +50 -0
50 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.43.2
Re: [PATCH v8 2/9] 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.
...
Documentation/ABI/testing/sysfs-bus-i2c-devices-turris-omnia-mcu line 75
Quoted 5 lines
Documentation/ABI/testing/sysfs-bus-i2c-devices-turris-omnia-mcu new file +5
-0+What: /sys/bus/i2c/devices/<mcu_device>/serial_number +Date: July 2024 +KernelVersion: 6.10 +Contact: Marek Behún <[email protected]> +Description: (RO) Contains the 64 bit long board serial number in hexadecimal
64 bit long --> 64-bit
Documentation/ABI/testing/sysfs-bus-i2c-devices-turris-omnia-mcu line 81
Quoted 6 lines
Documentation/ABI/testing/sysfs-bus-i2c-devices-turris-omnia-mcu new file +6
-0+ format. + + Only available if board information is burned in the MCU (older + revisions have board information burned in the ATSHA204-A chip). + + Format: %016X.
It's strange to use capitalized hexadecimal here and not in other files, but maybe it's something special about "serial number"? Dunno.
...
drivers/platform/cznic/Kconfig line 9
Quoted 4 lines
drivers/platform/cznic/Kconfig new file +3
-0+menuconfig CZNIC_PLATFORMS + bool "Platform support for CZ.NIC's Turris hardware" + depends on MACH_ARMADA_38X || COMPILE_TEST
This...
drivers/platform/cznic/Kconfig line 18
Quoted 10 lines
drivers/platform/cznic/Kconfig new file +9
-0+ 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
...or this dependency is redundant. I think one would expect that these platforms will not be always based on the same platform, hence I would drop the former and leave the latter. But you should know better than me.
Quoted 6 lines
drivers/platform/cznic/Kconfig new file +6
-0+ 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.
...
drivers/platform/cznic/turris-omnia-mcu-base.c line 50
Quoted 2 lines
drivers/platform/cznic/turris-omnia-mcu-base.c new file +2
-0+static int omnia_get_version_hash (struct omnia_mcu *mcu,bool bootloader, +u8 version[static OMNIA_FW_VERSION_HEX_LEN ])
Interesting format of the last parameter. Does it make any difference to the compiler if you use u8 *version?
drivers/platform/cznic/turris-omnia-mcu-base.c line 63
Quoted 13 lines
drivers/platform/cznic/turris-omnia-mcu-base.c new file +12
-0+{ +u8 reply[OMNIA_FW_VERSION_LEN ]; +int err; + + err =omnia_cmd_read (mcu->client, + bootloader ?CMD_GET_FW_VERSION_BOOT + :CMD_GET_FW_VERSION_APP , + reply,sizeof (reply)); +if (err) +return err; + version[OMNIA_FW_VERSION_HEX_LEN -1 ] ='\0' ; +bin2hex (version, reply,OMNIA_FW_VERSION_LEN );
Hmm... I would rather use returned value
char *p;
p = bin2hex(...);
*p = '\0';
return 0;
Quoted 2 lines
(quoted diff) +2
-0+ return 0; +}
...
drivers/platform/cznic/turris-omnia-mcu-base.c line 173
Quoted 7 lines
drivers/platform/cznic/turris-omnia-mcu-base.c new file +6
-0+static umode_t omnia_mcu_base_attrs_visible (struct kobject *kobj, +struct attribute *a,int n) +{ +struct device *dev =kobj_to_dev (kobj); +struct omnia_mcu *mcu =dev_get_drvdata (dev); +umode_t mode = a->mode;
Do you need this?
drivers/platform/cznic/turris-omnia-mcu-base.c line 179
Quoted 6 lines
drivers/platform/cznic/turris-omnia-mcu-base.c new file +5
-0+if ((a == &dev_attr_serial_number.attr || + a == &dev_attr_first_mac_address.attr || + a == &dev_attr_board_revision.attr) && + !(mcu->features &FEAT_BOARD_INFO )) + mode =0 ;
return 0; ?
Quoted 1 line
+ return mode;
return a->mode; ?
Quoted 1 line
+}
...
drivers/platform/cznic/turris-omnia-mcu-base.c line 204
Quoted 11 lines
drivers/platform/cznic/turris-omnia-mcu-base.c new file +11
-0+static void omnia_mcu_print_version_hash (struct omnia_mcu *mcu,bool bootloader) +{ +const char *type = bootloader ?"bootloader" :"application" ; +struct device *dev = &mcu->client->dev; +u8 version[OMNIA_FW_VERSION_HEX_LEN ]; +int err; + + err =omnia_get_version_hash (mcu, bootloader, version); +if (err) { +dev_err (dev,"Cannot read MCU %s firmware version: %d\n" , type, + err);
One line?
Quoted 5 lines
drivers/platform/cznic/turris-omnia-mcu-base.c new file +5
-0+return ; + } + +dev_info (dev,"MCU %s firmware version hash: %s\n" , type, version); +}
...
Quoted 1 line
+static const char *omnia_status_to_mcu_type(uint16_t status)
Why out of a sudden uint16_t instead of u16?
Quoted 12 lines
drivers/platform/cznic/turris-omnia-mcu-base.c new file +12
-0+{ +switch (status &STS_MCU_TYPE_MASK ) { +case STS_MCU_TYPE_STM32 : +return "STM32" ; +case STS_MCU_TYPE_GD32 : +return "GD32" ; +case STS_MCU_TYPE_MKL : +return "MKL" ; +default : +return "unknown" ; + } +}
...
drivers/platform/cznic/turris-omnia-mcu-base.c line 235
Quoted 2 lines
drivers/platform/cznic/turris-omnia-mcu-base.c new file +2
-0+ static const struct { + uint16_t mask;
Ditto.
Quoted 9 lines
drivers/platform/cznic/turris-omnia-mcu-base.c new file +9
-0+const char *name; + } features[] = { + { FEAT_EXT_CMDS, "extended control and status" }, + { FEAT_WDT_PING, "watchdog pinging" }, + { FEAT_LED_STATE_EXT_MASK, "peripheral LED pins reading" }, + { FEAT_NEW_INT_API, "new interrupt API" }, + { FEAT_POWEROFF_WAKEUP, "poweroff and wakeup" }, + { FEAT_TRNG, "true random number generator" }, + };
...
Quoted 1 line
+
omnia_info_missing_feature(dev, "feature reading");
Tautology. Read the final message. I believe you wanted to pass just "reading" here.
...
Quoted 1 line
+
memcpy(mcu->board_first_mac, &reply[9], ETH_ALEN);
There is an API ether_copy_addr() or so, don't remember by heart. You also need an include for ETH_ALEN definition.
...
Quoted 1 line
+#include <
linux/i2c.h>
No users of this, you may replace with
struct i2c_client;
Am I right?
...
Quoted 1 line
+
CMD_GET_FW_VERSION_BOOT=0x0E, /* 20B git hash number */
Git
...
Quoted 1 line
+ /* available only at address
0x2b(led-controller) */
LED-controller
...
include/linux/turris-omnia-mcu-interface.h line 124
Quoted 9 lines
include/linux/turris-omnia-mcu-interface.h new file +9
-0+enum omnia_ctl_byte_e { +CTL_LIGHT_RST =BIT (0 ), +CTL_HARD_RST =BIT (1 ), +/* BIT(2) is currently reserved */ +CTL_USB30_PWRON =BIT (3 ), +CTL_USB31_PWRON =BIT (4 ), +CTL_ENABLE_4V5 =BIT (5 ), +CTL_BUTTON_MODE =BIT (6 ), +CTL_BOOTLOADER =BIT (7 )
Keep trailing comma as it might be extended (theoretically). And you do the similar in other enums anyway.
Quoted 1 line
+};
--
With Best Regards,
Andy Shevchenko
Marek Behún
maintainerRe: [PATCH v8 2/9] platform: cznic: Add preliminary support for Turris Omnia MCU
Quoted 7 lines · On Tue, 30 Apr 2024 15:53:51 +0300 Andy Shevchenko <[email protected]>…
Quoted 3 lines · Marek Behún
Add the basic skeleton for a new platform driver for the microcontroller found on the Turris Omnia board.
...
Quoted 7 lines
Documentation/ABI/testing/sysfs-bus-i2c-devices-turris-omnia-mcu line 75
Quoted 5 lines
Documentation/ABI/testing/sysfs-bus-i2c-devices-turris-omnia-mcu new file +5
-0+What: /sys/bus/i2c/devices/<mcu_device>/serial_number +Date: July 2024 +KernelVersion: 6.10 +Contact: Marek Behún <[email protected]> +Description: (RO) Contains the 64 bit long board serial number in hexadecimal64 bit long --> 64-bit
ok
Quoted 10 lines
Documentation/ABI/testing/sysfs-bus-i2c-devices-turris-omnia-mcu line 81
Quoted 7 lines
Documentation/ABI/testing/sysfs-bus-i2c-devices-turris-omnia-mcu new file +6
-0+ format. + + Only available if board information is burned in the MCU (older + revisions have board information burned in the ATSHA204-A chip). + + Format: %016X.It's strange to use capitalized hexadecimal here and not in other files, but maybe it's something special about "serial number"? Dunno.
Yes, the serial number is printed with captial hex letters.
Quoted 16 lines
drivers/platform/cznic/Kconfig line 9
Quoted 4 lines
drivers/platform/cznic/Kconfig new file +3
-0+menuconfig CZNIC_PLATFORMS + bool "Platform support for CZ.NIC's Turris hardware" + depends on MACH_ARMADA_38X || COMPILE_TESTThis...
Quoted 8 lines
drivers/platform/cznic/Kconfig new file +8
-0+ 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"
Quoted 6 lines
Quoted 1 line
+ depends on
MACH_ARMADA_38X||COMPILE_TEST...or this dependency is redundant. I think one would expect that these platforms will not be always based on the same platform, hence I would drop the former and leave the latter. But you should know better than me.
ok
Quoted 8 lines
drivers/platform/cznic/Kconfig line 24
Quoted 7 lines
drivers/platform/cznic/Kconfig new file +6
-0+ 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.
Quoted 7 lines
...
drivers/platform/cznic/turris-omnia-mcu-base.c line 50
Quoted 2 lines
drivers/platform/cznic/turris-omnia-mcu-base.c new file +2
-0+static int omnia_get_version_hash (struct omnia_mcu *mcu,bool bootloader, +u8 version[static OMNIA_FW_VERSION_HEX_LEN ])Interesting format of the last parameter. Does it make any difference to the compiler if you use u8 *version?
The compiler will warn if an array with not enough space is passed as argument.
Quoted 15 lines
Quoted 4 lines
drivers/platform/cznic/turris-omnia-mcu-base.c new file +3
-0+{ +u8 reply[OMNIA_FW_VERSION_LEN ]; +int err;drivers/platform/cznic/turris-omnia-mcu-base.c line 63
Quoted 10 lines
drivers/platform/cznic/turris-omnia-mcu-base.c new file +9
-0+ + err =omnia_cmd_read (mcu->client, + bootloader ?CMD_GET_FW_VERSION_BOOT + :CMD_GET_FW_VERSION_APP , + reply,sizeof (reply)); +if (err) +return err; + version[OMNIA_FW_VERSION_HEX_LEN -1 ] ='\0' ; +bin2hex (version, reply,OMNIA_FW_VERSION_LEN );
Quoted 8 lines
Hmm... I would rather use returned value
char *p;
p = bin2hex(...);
*p = '\0';return 0;
OK. I guess
*bin2hex(version, reply, OMNIA_FW_VERSION_LEN) = '\0';
would be too crazy, right?
Quoted 21 lines
Quoted 3 lines
(quoted diff) +2
-0+ return 0; +}...
drivers/platform/cznic/turris-omnia-mcu-base.c line 173
Quoted 7 lines
drivers/platform/cznic/turris-omnia-mcu-base.c new file +6
-0+static umode_t omnia_mcu_base_attrs_visible (struct kobject *kobj, +struct attribute *a,int n) +{ +struct device *dev =kobj_to_dev (kobj); +struct omnia_mcu *mcu =dev_get_drvdata (dev); +umode_t mode = a->mode;Do you need this?
Quoted 4 lines
drivers/platform/cznic/turris-omnia-mcu-base.c new file +4
-0+if ((a == &dev_attr_serial_number.attr || + a == &dev_attr_first_mac_address.attr || + a == &dev_attr_board_revision.attr) && + !(mcu->features &FEAT_BOARD_INFO ))
Quoted 7 lines
Quoted 1 line
+ mode = 0;
return 0; ?
Quoted 1 line
+ return mode;
return
a->mode; ?
ok
Quoted 5 lines
Quoted 2 lines
+}
...
Quoted 13 lines
drivers/platform/cznic/turris-omnia-mcu-base.c line 204
Quoted 11 lines
drivers/platform/cznic/turris-omnia-mcu-base.c new file +11
-0+static void omnia_mcu_print_version_hash (struct omnia_mcu *mcu,bool bootloader) +{ +const char *type = bootloader ?"bootloader" :"application" ; +struct device *dev = &mcu->client->dev; +u8 version[OMNIA_FW_VERSION_HEX_LEN ]; +int err; + + err =omnia_get_version_hash (mcu, bootloader, version); +if (err) { +dev_err (dev,"Cannot read MCU %s firmware version: %d\n" , type, + err);One line?
I'd like to keep this driver to 80 columns.
Quoted 9 lines
Quoted 6 lines
drivers/platform/cznic/turris-omnia-mcu-base.c new file +5
-0+return ; + } + +dev_info (dev,"MCU %s firmware version hash: %s\n" , type, version); +}...
Quoted 3 lines
Quoted 1 line
+static const char *omnia_status_to_mcu_type(uint16_t status)
Why out of a sudden
uint16_tinstead of u16?
This was a mistake, thanks.
Quoted 30 lines
Quoted 12 lines
drivers/platform/cznic/turris-omnia-mcu-base.c new file +12
-0+{ +switch (status &STS_MCU_TYPE_MASK ) { +case STS_MCU_TYPE_STM32 : +return "STM32" ; +case STS_MCU_TYPE_GD32 : +return "GD32" ; +case STS_MCU_TYPE_MKL : +return "MKL" ; +default : +return "unknown" ; + } +}...
drivers/platform/cznic/turris-omnia-mcu-base.c line 235
Quoted 2 lines
drivers/platform/cznic/turris-omnia-mcu-base.c new file +2
-0+ static const struct { + uint16_t mask;Ditto.
drivers/platform/cznic/turris-omnia-mcu-base.c line 244
Quoted 9 lines
drivers/platform/cznic/turris-omnia-mcu-base.c new file +9
-0+const char *name; + } features[] = { + { FEAT_EXT_CMDS, "extended control and status" }, + { FEAT_WDT_PING, "watchdog pinging" }, + { FEAT_LED_STATE_EXT_MASK, "peripheral LED pins reading" }, + { FEAT_NEW_INT_API, "new interrupt API" }, + { FEAT_POWEROFF_WAKEUP, "poweroff and wakeup" }, + { FEAT_TRNG, "true random number generator" }, + };
Quoted 6 lines
...
Quoted 1 line
+
omnia_info_missing_feature(dev, "feature reading");Tautology. Read the final message. I believe you wanted to pass just "reading" here.
No, I actually wanted it to print
Your board's MCU firmware does not support the feature reading feature.
as in the feature "feature reading" is not supported.
I guess I could change it to
Your board's MCU firmware does not support the feature reading.
but that would complicate the code: either I would need to add " feature" suffix to all the features[].name, or duplicate the info string from the omnia_info_missing_feature() function.
Quoted 6 lines
...
Quoted 1 line
+
memcpy(mcu->board_first_mac, &reply[9], ETH_ALEN);There is an API
ether_copy_addr()or so, don't remember by heart. You also need an include forETH_ALENdefinition.
Doc for ether_addr_copy says:
Please note: dst & src must both be aligned to u16.
since the code does:
u16 *a = (u16 *)dst;
const u16 *b = (const u16 *)src;
a[0] = b[0]; a[1] = b[1]; a[2] = b[2]
Since I am copying from &reply[9], which is not u16-aligned, this won't work.
Quoted 9 lines
...
Quoted 1 line
+#include <
linux/i2c.h>No users of this, you may replace with
struct
i2c_client;Am I right?
OK.
Quoted 7 lines
...
Quoted 2 lines
+
CMD_GET_FW_VERSION_BOOT=0x0E, /* 20B git hash
number */Git
OK.
Quoted 5 lines
...
Quoted 1 line
+ /* available only at address
0x2b(led-controller) */LED-controller
OK
Quoted 13 lines
...
include/linux/turris-omnia-mcu-interface.h line 124
Quoted 9 lines
include/linux/turris-omnia-mcu-interface.h new file +9
-0+enum omnia_ctl_byte_e { +CTL_LIGHT_RST =BIT (0 ), +CTL_HARD_RST =BIT (1 ), +/* BIT(2) is currently reserved */ +CTL_USB30_PWRON =BIT (3 ), +CTL_USB31_PWRON =BIT (4 ), +CTL_ENABLE_4V5 =BIT (5 ), +CTL_BUTTON_MODE =BIT (6 ), +CTL_BOOTLOADER =BIT (7 )
Quoted 2 lines
Keep trailing comma as it might be extended (theoretically). And you do the similar in other enums anyway.
ctl_byt is 8-bit, so this enum really can't be extended. In fact I need to drop the last comma from omnia_ext_sts_dword_e and omnia_int_e.
Thanks, Andy.
Re: [PATCH v8 2/9] platform: cznic: Add preliminary support for Turris Omnia MCU
Quoted 21 lines · Marek Behún
Quoted 21 lines
drivers/platform/cznic/turris-omnia-mcu-base.c line 63
Quoted 13 lines
drivers/platform/cznic/turris-omnia-mcu-base.c new file +12
-0+{ +u8 reply[OMNIA_FW_VERSION_LEN ]; +int err; + + err =omnia_cmd_read (mcu->client, + bootloader ?CMD_GET_FW_VERSION_BOOT + :CMD_GET_FW_VERSION_APP , + reply,sizeof (reply)); +if (err) +return err; + version[OMNIA_FW_VERSION_HEX_LEN -1 ] ='\0' ; +bin2hex (version, reply,OMNIA_FW_VERSION_LEN );Hmm... I would rather use returned value
char *p;
p = bin2hex(...);
*p = '\0';
Quoted 7 lines
Quoted 1 line
return 0;
OK. I guess
*bin2hex(version, reply, OMNIA_FW_VERSION_LEN) = '\0';would be too crazy, right?
Indeed. Please don't do that. 0_0
regards,
dan carpenter
Re: [PATCH v8 2/9] platform: cznic: Add preliminary support for Turris Omnia MCU
In reply to Marek BehúnQuoted 3 lines · Marek Behún
Quoted 1 line · On Tue, 30 Apr 2024 15:53:51 +0300 Andy Shevchenko <[email protected]>…
On Tue, Apr 30, 2024 at 2:51 PM Marek Behún <[email protected]> wrote:
...
Quoted 8 lines
Quoted 5 lines
drivers/platform/cznic/turris-omnia-mcu-base.c line 50
Quoted 2 lines
drivers/platform/cznic/turris-omnia-mcu-base.c new file +2
-0+static int omnia_get_version_hash (struct omnia_mcu *mcu,bool bootloader, +u8 version[static OMNIA_FW_VERSION_HEX_LEN ])Interesting format of the last parameter. Does it make any difference to the compiler if you use u8 *version?
The compiler will warn if an array with not enough space is passed as argument.
Really?
Quoted 21 lines
Quoted 21 lines
drivers/platform/cznic/turris-omnia-mcu-base.c line 63
Quoted 13 lines
drivers/platform/cznic/turris-omnia-mcu-base.c new file +12
-0+{ +u8 reply[OMNIA_FW_VERSION_LEN ]; +int err; + + err =omnia_cmd_read (mcu->client, + bootloader ?CMD_GET_FW_VERSION_BOOT + :CMD_GET_FW_VERSION_APP , + reply,sizeof (reply)); +if (err) +return err; + version[OMNIA_FW_VERSION_HEX_LEN -1 ] ='\0' ; +bin2hex (version, reply,OMNIA_FW_VERSION_LEN );Hmm... I would rather use returned value
char *p;
p = bin2hex(...);
*p = '\0';
Quoted 7 lines
Quoted 1 line
return 0;
OK. I guess
*bin2hex(version, reply, OMNIA_FW_VERSION_LEN) = '\0';would be too crazy, right?
Yes, it's not a Python :-)
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
(quoted diff) +2
-0+ return 0; +}
...
Quoted 6 lines
Quoted 4 lines
drivers/platform/cznic/turris-omnia-mcu-base.c line 204
Quoted 2 lines
drivers/platform/cznic/turris-omnia-mcu-base.c new file +2
-0+dev_err (dev,"Cannot read MCU %s firmware version: %d\n" , type, + err);One line?
I'd like to keep this driver to 80 columns.
Then better to have a logical split then?
dev_err(dev, "Cannot read MCU %s firmware version: %d\n", type, err);
...
Quoted 5 lines
Quoted 4 lines
Quoted 1 line
+
omnia_info_missing_feature(dev, "feature reading");Tautology. Read the final message. I believe you wanted to pass just "reading" here.
Quoted 9 lines
No, I actually wanted it to print
Your board's MCU firmware does not support the feature reading feature.
as in the feature "feature reading" is not supported.
I guess I could change it to
Your board's MCU firmware does not support the feature reading.
but that would complicate the code: either I would need to add " feature" suffix to all the features[].name, or duplicate the info string from theomnia_info_missing_feature()function.
From point of a mere user (as I am towards this driver) I consider the tautology confusing.
...the 'reading' feature
may be a good compromise.
...
Quoted 11 lines
Quoted 4 lines
Quoted 1 line
+
memcpy(mcu->board_first_mac, &reply[9], ETH_ALEN);There is an API
ether_copy_addr()or so, don't remember by heart. You also need an include forETH_ALENdefinition.Doc for
ether_addr_copysays:
Please note: dst & src must both be aligned to u16.
since the code does:
u16 *a = (u16 *)dst;
const u16 *b = (const u16 *)src;
Quoted 6 lines
a[0] = b[0]; a[1] = b[1]; a[2] = b[2]Since I am copying from &reply[9], which is not u16-aligned, this won't work.
It would work on architectures that support misaligned accesses, but in general you are right. Perhaps a comment on top to avoid "cleanup" patches like this?
...
Quoted 10 lines
Quoted 10 lines
Quoted 9 lines
include/linux/turris-omnia-mcu-interface.h new file +9
-0+enum omnia_ctl_byte_e { +CTL_LIGHT_RST =BIT (0 ), +CTL_HARD_RST =BIT (1 ), +/* BIT(2) is currently reserved */ +CTL_USB30_PWRON =BIT (3 ), +CTL_USB31_PWRON =BIT (4 ), +CTL_ENABLE_4V5 =BIT (5 ), +CTL_BUTTON_MODE =BIT (6 ), +CTL_BOOTLOADER =BIT (7 )
Quoted 4 lines
Quoted 2 lines
Keep trailing comma as it might be extended (theoretically). And you do the similar in other enums anyway.
ctl_bytis 8-bit, so this enum really can't be extended.
I understand that (even before writing the previous reply).
Quoted 2 lines
In fact I need
to drop the last comma fromomnia_ext_sts_dword_eandomnia_int_e.
Who prevents from having in a new firmware let's say
BIT(31) | BIT(1)
as a new value?
From Linux perspective these are not terminating lines.
Signature · 2 lines
With Best Regards, Andy Shevchenko
Marek Behún
maintainerRe: [PATCH v8 2/9] platform: cznic: Add preliminary support for Turris Omnia MCU
Quoted 10 lines · Andy Shevchenko
Quoted 3 lines · Marek Behún
Quoted 1 line · On Tue, 30 Apr 2024 15:53:51 +0300 Andy Shevchenko <[email protected]>…
On Tue, Apr 30, 2024 at 2:51 PM Marek Behún <[email protected]> wrote:
...
Quoted 3 lines
Quoted 3 lines
Quoted 2 lines
drivers/platform/cznic/turris-omnia-mcu-base.c new file +2
-0+static int omnia_get_version_hash (struct omnia_mcu *mcu,bool bootloader, +u8 version[static OMNIA_FW_VERSION_HEX_LEN ])
Quoted 7 lines
Quoted 5 lines
Quoted 2 lines
Interesting format of the last parameter. Does it make any difference to the compiler if you use u8 *version?
The compiler will warn if an array with not enough space is passed as argument.
Really?
Indeed:
extern void a(char *x);
static void b(char x[static 10]) {
a(x);
}
void c(void) {
char x[5] = "abcd";
b(x);
}says:
test.c: In function ‘c’:
test.c:9:9: warning: ‘b’ accessing 10 bytes in a region of size 5 [-Wstringop-overflow=]
9 | b(x);
| ^~~~
test.c:9:9: note: referencing argument 1 of type ‘char[10]’
test.c:3:13: note: in a call to function ‘b’
3 | static void b(char x[static 10]) {
|...
Quoted 11 lines
Quoted 6 lines
Quoted 4 lines
drivers/platform/cznic/turris-omnia-mcu-base.c line 204
Quoted 2 lines
drivers/platform/cznic/turris-omnia-mcu-base.c new file +2
-0+dev_err (dev,"Cannot read MCU %s firmware version: %d\n" , type, + err);One line?
I'd like to keep this driver to 80 columns.
Then better to have a logical split then?
dev_err(dev, "Cannot read MCU %s firmware version: %d\n", type, err);
OK
Quoted 15 lines
Quoted 5 lines
Quoted 4 lines
Quoted 1 line
+
omnia_info_missing_feature(dev, "feature reading");Tautology. Read the final message. I believe you wanted to pass just "reading" here.
Quoted 9 lines
No, I actually wanted it to print
Your board's MCU firmware does not support the feature reading feature.
as in the feature "feature reading" is not supported.
I guess I could change it to
Your board's MCU firmware does not support the feature reading.
but that would complicate the code: either I would need to add " feature" suffix to all the features[].name, or duplicate the info string from theomnia_info_missing_feature()function.
Quoted 6 lines
From point of a mere user (as I am towards this driver) I consider the tautology confusing.
...the 'reading' feature
may be a good compromise.
I have rewritten it to use another dev_info:
dev_info(dev,
"Your board's MCU firmware does not support feature reading.\n");
Quoted 18 lines
...
Quoted 15 lines
Quoted 4 lines
Quoted 1 line
+
memcpy(mcu->board_first_mac, &reply[9], ETH_ALEN);There is an API
ether_copy_addr()or so, don't remember by heart. You also need an include forETH_ALENdefinition.Doc for
ether_addr_copysays:
Please note: dst & src must both be aligned to u16.
since the code does:
u16 *a = (u16 *)dst;
const u16 *b = (const u16 *)src;a[0] = b[0]; a[1] = b[1]; a[2] = b[2]
Quoted 5 lines
Quoted 2 lines
Since I am copying from &reply[9], which is not u16-aligned, this won't work.
It would work on architectures that support misaligned accesses, but in general you are right. Perhaps a comment on top to avoid "cleanup" patches like this?
OK
Quoted 20 lines
Quoted 10 lines
Quoted 10 lines
Quoted 9 lines
include/linux/turris-omnia-mcu-interface.h new file +9
-0+enum omnia_ctl_byte_e { +CTL_LIGHT_RST =BIT (0 ), +CTL_HARD_RST =BIT (1 ), +/* BIT(2) is currently reserved */ +CTL_USB30_PWRON =BIT (3 ), +CTL_USB31_PWRON =BIT (4 ), +CTL_ENABLE_4V5 =BIT (5 ), +CTL_BUTTON_MODE =BIT (6 ), +CTL_BOOTLOADER =BIT (7 )Quoted 4 lines
Quoted 2 lines
Keep trailing comma as it might be extended (theoretically). And you do the similar in other enums anyway.
ctl_bytis 8-bit, so this enum really can't be extended.I understand that (even before writing the previous reply).
Quoted 2 lines
In fact I need
to drop the last comma fromomnia_ext_sts_dword_eandomnia_int_e.
Quoted 7 lines
Who prevents from having in a new firmware let's say
BIT(31) | BIT(1)
as a new value?
From Linux perspective these are not terminating lines.
OK
Re: [PATCH v8 2/9] platform: cznic: Add preliminary support for Turris Omnia MCU
Quoted 5 lines · Marek Behún
Quoted 4 lines · Andy Shevchenko
Quoted 3 lines · Marek Behún
Quoted 1 line · On Tue, 30 Apr 2024 15:53:51 +0300 Andy Shevchenko <[email protected]>…
On Tue, Apr 30, 2024 at 2:51 PM Marek Behún <[email protected]> wrote:
...
Quoted 22 lines
Quoted 10 lines
Quoted 8 lines
Quoted 5 lines
drivers/platform/cznic/turris-omnia-mcu-base.c line 50
Quoted 2 lines
drivers/platform/cznic/turris-omnia-mcu-base.c new file +2
-0+static int omnia_get_version_hash (struct omnia_mcu *mcu,bool bootloader, +u8 version[static OMNIA_FW_VERSION_HEX_LEN ])Interesting format of the last parameter. Does it make any difference to the compiler if you use u8 *version?
The compiler will warn if an array with not enough space is passed as argument.
Really?
Indeed:
extern void a(char *x); static void b(char x[static 10]) { a(x); } void c(void) { char x[5] = "abcd";
Quoted 1 line
b(x);
It's not the example I was talking about. Here should be a(x).
Quoted 11 lines
}says:
test.c: In function ‘c’:
test.c:9:9: warning: ‘b’ accessing 10 bytes in a region of size 5 [-Wstringop-overflow=]9 | b(x); | ^~~~ test.c:9:9: note: referencing argument 1 of type ‘char[10]’ test.c:3:13: note: in a call to function ‘b’ 3 | static void b(char x[static 10]) { |
...
Quoted 18 lines
Quoted 18 lines
Quoted 5 lines
Quoted 4 lines
Quoted 1 line
+
omnia_info_missing_feature(dev, "feature reading");Tautology. Read the final message. I believe you wanted to pass just "reading" here.
Quoted 9 lines
No, I actually wanted it to print
Your board's MCU firmware does not support the feature reading feature.
as in the feature "feature reading" is not supported.
I guess I could change it to
Your board's MCU firmware does not support the feature reading.
but that would complicate the code: either I would need to add " feature" suffix to all the features[].name, or duplicate the info string from theomnia_info_missing_feature()function.From point of a mere user (as I am towards this driver) I consider the tautology confusing.
Quoted 7 lines
Quoted 3 lines
...the 'reading' feature
may be a good compromise.
I have rewritten it to use another
dev_info:
dev_info(dev,"Your board's MCU firmware does not support feature reading.\n");
OK! As long as there are no two messages in a row for the same error.
Signature · 2 lines
With Best Regards, Andy Shevchenko
Marek Behún
maintainerRe: [PATCH v8 2/9] platform: cznic: Add preliminary support for Turris Omnia MCU
Quoted 28 lines · Andy Shevchenko
Quoted 5 lines · Marek Behún
Quoted 4 lines · Andy Shevchenko
Quoted 3 lines · Marek Behún
Quoted 1 line · On Tue, 30 Apr 2024 15:53:51 +0300 Andy Shevchenko <[email protected]>…
On Tue, Apr 30, 2024 at 2:51 PM Marek Behún <[email protected]> wrote:
...
Quoted 19 lines
Quoted 10 lines
Quoted 8 lines
Quoted 5 lines
drivers/platform/cznic/turris-omnia-mcu-base.c line 50
Quoted 2 lines
drivers/platform/cznic/turris-omnia-mcu-base.c new file +2
-0+static int omnia_get_version_hash (struct omnia_mcu *mcu,bool bootloader, +u8 version[static OMNIA_FW_VERSION_HEX_LEN ])Interesting format of the last parameter. Does it make any difference to the compiler if you use u8 *version?
The compiler will warn if an array with not enough space is passed as argument.
Really?
Indeed:
extern void a(char *x); static void b(char x[static 10]) { a(x); }
Quoted 6 lines
Quoted 4 lines
void c(void) { char x[5] = "abcd";b(x);It's not the example I was talking about. Here should be a(x).
Somehow I got lost. Let's return to my function, where I have
int omnia_get_version_hash(..., u8 version[static 40]);
and then I use this function:
u8 version[40]; omnia_get_version_hash(..., version);
If somehow I made a mistake and declared the version array shorter:
u8 version[20];
omnia_get_version_hash(..., version);
I would get a warning.
So the purpose is to get warned if the compiler can prove that there is not enough space in the destination buffer.
Marek
Re: [PATCH v8 2/9] platform: cznic: Add preliminary support for Turris Omnia MCU
Quoted 7 lines · Marek Behún
Quoted 6 lines · Andy Shevchenko
Quoted 5 lines · Marek Behún
Quoted 4 lines · Andy Shevchenko
Quoted 3 lines · Marek Behún
Quoted 1 line · On Tue, 30 Apr 2024 15:53:51 +0300 Andy Shevchenko <[email protected]>…
On Tue, Apr 30, 2024 at 2:51 PM Marek Behún <[email protected]> wrote:
...
Quoted 31 lines
Quoted 19 lines
Quoted 19 lines
Quoted 10 lines
Quoted 8 lines
Quoted 5 lines
Review
Quoted 2 lines
(quoted diff) +2
-0+static int omnia_get_version_hash(struct omnia_mcu *mcu, bool bootloader, + u8 version[static OMNIA_FW_VERSION_HEX_LEN])Interesting format of the last parameter. Does it make any difference to the compiler if you use u8 *version?
The compiler will warn if an array with not enough space is passed as argument.
Really?
Indeed:
extern void a(char *x); static void b(char x[static 10]) { a(x); }Quoted 6 lines
Quoted 4 lines
void c(void) { char x[5] = "abcd";b(x);It's not the example I was talking about. Here should be a(x).
Somehow I got lost. Let's return to my function, where I have
intomnia_get_version_hash(..., u8 version[static 40]);and then I use this function:
Quoted 7 lines
u8 version[40]; omnia_get_version_hash(..., version);If somehow I made a mistake and declared the version array shorter:
u8 version[20];
omnia_get_version_hash(..., version);
I would get a warning.
Yes. Would you get the same warning if you replace the parameter to a pointer?
Quoted 2 lines
So the purpose is to get warned if the compiler can prove that there is not enough space in the destination buffer.
Signature · 2 lines
With Best Regards, Andy Shevchenko
Marek Behún
maintainerRe: [PATCH v8 2/9] platform: cznic: Add preliminary support for Turris Omnia MCU
Quoted 45 lines · Andy Shevchenko
Quoted 7 lines · Marek Behún
Quoted 6 lines · Andy Shevchenko
Quoted 5 lines · Marek Behún
Quoted 4 lines · Andy Shevchenko
Quoted 3 lines · Marek Behún
Quoted 1 line · On Tue, 30 Apr 2024 15:53:51 +0300 Andy Shevchenko <[email protected]>…
On Tue, Apr 30, 2024 at 2:51 PM Marek Behún <[email protected]> wrote:
...
Quoted 34 lines
Quoted 19 lines
Quoted 19 lines
Quoted 10 lines
Quoted 8 lines
Quoted 5 lines
Review
Quoted 2 lines
(quoted diff) +2
-0+static int omnia_get_version_hash(struct omnia_mcu *mcu, bool bootloader, + u8 version[static OMNIA_FW_VERSION_HEX_LEN])Interesting format of the last parameter. Does it make any difference to the compiler if you use u8 *version?
The compiler will warn if an array with not enough space is passed as argument.
Really?
Indeed:
extern void a(char *x); static void b(char x[static 10]) { a(x); }Quoted 6 lines
Quoted 4 lines
void c(void) { char x[5] = "abcd";b(x);It's not the example I was talking about. Here should be a(x).
Somehow I got lost. Let's return to my function, where I have
intomnia_get_version_hash(..., u8 version[static 40]);and then I use this function:
u8 version[40]; omnia_get_version_hash(..., version);
Quoted 6 lines
Quoted 4 lines
If somehow I made a mistake and declared the version array shorter:
u8 version[20];
omnia_get_version_hash(..., version);
I would get a warning.Yes. Would you get the same warning if you replace the parameter to a pointer?
If you mean instead of declaring
u8 version[20];
if I did
u8 *version;
omnia_get_version_hash(..., version);
then I will get a different warning:
version is used uninitialized
And if you mean that instead of the
char version[static 40]
in the argument list of the function I used
char *version,
then no, GCC spits no warning.
Marek
Re: [PATCH v8 2/9] platform: cznic: Add preliminary support for Turris Omnia MCU
In reply to Marek BehúnQuoted 5 lines · Marek Behún
Add the basic skeleton for a new platform driver for the microcontroller found on the Turris Omnia board.
Signed-off-by Marek Behún <[email protected]>
drivers/platform/cznic/turris-omnia-mcu-base.c line 254
Quoted 10 lines
drivers/platform/cznic/turris-omnia-mcu-base.c new file +10
-0+struct device *dev = &mcu->client->dev; +bool suggest_fw_upgrade = false; +int status; + +/* status word holds MCU type, which we need below */ + status =omnia_cmd_read_u16 (mcu->client,CMD_GET_STATUS_WORD ); +if (status <0 ) +return status; + +/* check whether MCU firmware supports the CMD_GET_FEAUTRES command */
FEATURES
Quoted 10 lines
drivers/platform/cznic/turris-omnia-mcu-base.c new file +10
-0+if (status &STS_FEATURES_SUPPORTED ) { +__le32 reply; +int ret; + +/* try read 32-bit features */ + ret =omnia_cmd_read (mcu->client,CMD_GET_FEATURES , &reply, +sizeof (reply)); +if (ret) { +/* try read 16-bit features */ + ret =omnia_cmd_read_u16 (mcu->client,CMD_GET_FEATURES );
drivers/platform/cznic/turris-omnia-mcu-base.c line 274
Quoted 10 lines
drivers/platform/cznic/turris-omnia-mcu-base.c new file +10
-0+if (ret <0 ) +return ret; + + mcu->features = ret; + }else { + mcu->features =le32_to_cpu (reply); + +if (mcu->features &FEAT_FROM_BIT_16_INVALID ) + mcu->features &=GENMASK (15 ,0 ); + }
I'm not a big fan of the inconsistency here when it comes to who handles the endianness, perhaps there is a good reason for that but it looks a bit odd to have it done in a different way for 32-bit and 16-bit.
Quoted 150 lines
drivers/platform/cznic/turris-omnia-mcu-base.c new file +56
-0+ } else { +omnia_info_missing_feature (dev,"feature reading" ); + suggest_fw_upgrade = true; + } + + mcu->type =omnia_status_to_mcu_type (status); +dev_info (dev,"MCU type %s%s\n" , mcu->type, + (mcu->features &FEAT_PERIPH_MCU ) ? +", with peripheral resets wired" :"" ); + +omnia_mcu_print_version_hash (mcu, true); + +if (mcu->features &FEAT_BOOTLOADER ) +dev_warn (dev, +"MCU is running bootloader firmware. Was firmware upgrade interrupted?\n" ); +else +omnia_mcu_print_version_hash (mcu, false); + +for (unsigned int i =0 ; i <ARRAY_SIZE (features); i++) { +if (mcu->features & features[i].mask) +continue ; + +omnia_info_missing_feature (dev, features[i].name); + suggest_fw_upgrade = true; + } + +if (suggest_fw_upgrade) +dev_info (dev, +"Consider upgrading MCU firmware with the omnia-mcutool utility.\n" ); + +return 0 ; +} +int omnia_cmd_read (const struct i2c_client *client,u8 cmd,void *reply, +unsigned int len); + +static inline int omnia_cmd_read_u16 (const struct i2c_client *client,u8 cmd) +{ +__le16 reply; +int err; + + err =omnia_cmd_read (client, cmd, &reply,sizeof (reply)); + +return err ?:le16_to_cpu (reply); +} + +static inline int omnia_cmd_read_u8 (const struct i2c_client *client,u8 cmd) +{ +u8 reply; +int err; + + err =omnia_cmd_read (client, cmd, &reply,sizeof (reply)); + +return err ?: reply; +} + +#endif /* __TURRIS_OMNIA_MCU_H */ include/linux/turris-omnia-mcu-interface.h new file +85
-0@@ -0,0 +1,249 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* +* CZ.NIC's Turris Omnia MCU I2C interface commands definitions +* +* 2024 by Marek Behún <[email protected]> +*/ + +#ifndef __TURRIS_OMNIA_MCU_INTERFACE_H +#define __TURRIS_OMNIA_MCU_INTERFACE_H + +#include <linux/bitfield.h> +#include <linux/bits.h> + +enum omnia_commands_e { +CMD_GET_STATUS_WORD =0x01 ,/* slave sends status word back */ +CMD_GENERAL_CONTROL =0x02 , +CMD_LED_MODE =0x03 ,/* default/user */ +CMD_LED_STATE =0x04 ,/* LED on/off */ +CMD_LED_COLOR =0x05 ,/* LED number + RED + GREEN + BLUE */ +CMD_USER_VOLTAGE =0x06 , +CMD_SET_BRIGHTNESS =0x07 , +CMD_GET_BRIGHTNESS =0x08 , +CMD_GET_RESET =0x09 , +CMD_GET_FW_VERSION_APP =0x0A ,/* 20B git hash number */ +CMD_SET_WATCHDOG_STATE =0x0B ,/* 0 - disable +* 1 - enable / ping +* after boot watchdog is started +* with 2 minutes timeout +*/ + +/* CMD_WATCHDOG_STATUS = 0x0C, not implemented anymore */ + +CMD_GET_WATCHDOG_STATE =0x0D , +CMD_GET_FW_VERSION_BOOT =0x0E ,/* 20B git hash number */ +CMD_GET_FW_CHECKSUM =0x0F ,/* 4B length, 4B checksum */ + +/* available if FEATURES_SUPPORTED bit set in status word */ +CMD_GET_FEATURES =0x10 , + +/* available if EXT_CMD bit set in features */ +CMD_GET_EXT_STATUS_DWORD =0x11 , +CMD_EXT_CONTROL =0x12 , +CMD_GET_EXT_CONTROL_STATUS =0x13 , + +/* available if NEW_INT_API bit set in features */ +CMD_GET_INT_AND_CLEAR =0x14 , +CMD_GET_INT_MASK =0x15 , +CMD_SET_INT_MASK =0x16 , + +/* available if FLASHING bit set in features */ +CMD_FLASH =0x19 , + +/* available if WDT_PING bit set in features */ +CMD_SET_WDT_TIMEOUT =0x20 , +CMD_GET_WDT_TIMELEFT =0x21 , + +/* available if POWEROFF_WAKEUP bit set in features */ +CMD_SET_WAKEUP =0x22 , +CMD_GET_UPTIME_AND_WAKEUP =0x23 , +CMD_POWER_OFF =0x24 , + +/* available if USB_OVC_PROT_SETTING bit set in features */ +CMD_SET_USB_OVC_PROT =0x25 , +CMD_GET_USB_OVC_PROT =0x26 , + +/* available if TRNG bit set in features */ +CMD_TRNG_COLLECT_ENTROPY =0x28 , + +/* available if CRYPTO bit set in features */ +CMD_CRYPTO_GET_PUBLIC_KEY =0x29 , +CMD_CRYPTO_SIGN_MESSAGE =0x2A , +CMD_CRYPTO_COLLECT_SIGNATURE =0x2B , + +/* available if BOARD_INFO it set in features */ +CMD_BOARD_INFO_GET =0x2C , +CMD_BOARD_INFO_BURN =0x2D , + +/* available only at address 0x2b (led-controller) */ +/* available only if LED_GAMMA_CORRECTION bit set in features */ +CMD_SET_GAMMA_CORRECTION =0x30 , +CMD_GET_GAMMA_CORRECTION =0x31 , + +/* available only at address 0x2b (led-controller) */ +/* available only if PER_LED_CORRECTION bit set in features */ + /* available only if FROM_BIT_16_INVALID bit NOT set in features */
include/linux/turris-omnia-mcu-interface.h line 95
Quoted 10 lines
include/linux/turris-omnia-mcu-interface.h new file +10
-0+CMD_SET_LED_CORRECTIONS =0x32 , + CMD_GET_LED_CORRECTIONS = 0x33, +}; + +enum omnia_flashing_commands_e { +FLASH_CMD_UNLOCK =0x01 , +FLASH_CMD_SIZE_AND_CSUM =0x02 , +FLASH_CMD_PROGRAM =0x03 , +FLASH_CMD_RESET =0x04 , +};
I'm bit worried about many items above, they seem generic enough they could trigger name conflict at some point. Could these all defines be prefixed so there's no risk of collisions.
include/linux/turris-omnia-mcu-interface.h line 101
Quoted 5 lines
include/linux/turris-omnia-mcu-interface.h new file +5
-0+enum omnia_sts_word_e { +STS_MCU_TYPE_MASK =GENMASK (1 ,0 ), +STS_MCU_TYPE_STM32 =0 <<0 , +STS_MCU_TYPE_GD32 =1 <<0 , +STS_MCU_TYPE_MKL =2 <<0 ,
These are FIELD_PREP(STS_MCU_TYPE_MASK, x), although I suspect you need to use FIELD_PREP_CONST() in this context. If neither ends up working in this context, then leave it as is.
Quoted 22 lines
include/linux/turris-omnia-mcu-interface.h new file +22
-0+STS_FEATURES_SUPPORTED =BIT (2 ), +STS_USER_REGULATOR_NOT_SUPPORTED =BIT (3 ), +STS_CARD_DET =BIT (4 ), +STS_MSATA_IND =BIT (5 ), +STS_USB30_OVC =BIT (6 ), +STS_USB31_OVC =BIT (7 ), +STS_USB30_PWRON =BIT (8 ), +STS_USB31_PWRON =BIT (9 ), +STS_ENABLE_4V5 =BIT (10 ), +STS_BUTTON_MODE =BIT (11 ), +STS_BUTTON_PRESSED =BIT (12 ), +STS_BUTTON_COUNTER_MASK =GENMASK (15 ,13 ) +}; + +enum omnia_ctl_byte_e { +CTL_LIGHT_RST =BIT (0 ), +CTL_HARD_RST =BIT (1 ), +/* BIT(2) is currently reserved */ +CTL_USB30_PWRON =BIT (3 ), +CTL_USB31_PWRON =BIT (4 ), +CTL_ENABLE_4V5 =BIT (5 ), + CTL_BUTTON_MODE = BIT(6),
include/linux/turris-omnia-mcu-interface.h line 133
Quoted 10 lines
include/linux/turris-omnia-mcu-interface.h new file +10
-0+CTL_BOOTLOADER =BIT (7 ) +}; + +enum omnia_features_e { +FEAT_PERIPH_MCU =BIT (0 ), +FEAT_EXT_CMDS =BIT (1 ), +FEAT_WDT_PING =BIT (2 ), +FEAT_LED_STATE_EXT_MASK =GENMASK (4 ,3 ), +FEAT_LED_STATE_EXT =1 <<3 , +FEAT_LED_STATE_EXT_V32 =2 <<3 ,
Ditto.
Quoted 14 lines
include/linux/turris-omnia-mcu-interface.h new file +14
-0+FEAT_LED_GAMMA_CORRECTION =BIT (5 ), +FEAT_NEW_INT_API =BIT (6 ), +FEAT_BOOTLOADER =BIT (7 ), +FEAT_FLASHING =BIT (8 ), +FEAT_NEW_MESSAGE_API =BIT (9 ), +FEAT_BRIGHTNESS_INT =BIT (10 ), +FEAT_POWEROFF_WAKEUP =BIT (11 ), +FEAT_CAN_OLD_MESSAGE_API =BIT (12 ), +FEAT_TRNG =BIT (13 ), +FEAT_CRYPTO =BIT (14 ), +FEAT_BOARD_INFO =BIT (15 ), + +/* +* Orginally the features command replied only 16 bits. If more were
include/linux/turris-omnia-mcu-interface.h line 157
Quoted 10 lines
include/linux/turris-omnia-mcu-interface.h new file +10
-0+* read, either the I2C transaction failed or 0xff bytes were sent. +* Therefore to consider bits 16 - 31 valid, one bit (20) was reserved +* to be zero. +*/ + +/* Bits 16 - 19 correspond to bits 0 - 3 of status word */ +FEAT_MCU_TYPE_MASK =GENMASK (17 ,16 ), +FEAT_MCU_TYPE_STM32 =0 <<16 , +FEAT_MCU_TYPE_GD32 =1 <<16 , + FEAT_MCU_TYPE_MKL = 2 << 16,
Ditto.
Signature · 1 line
i.
Marek Behún
maintainerRe: [PATCH v8 2/9] platform: cznic: Add preliminary support for Turris Omnia MCU
Thanks, Ilpo, I've applied all your suggestions.
Marek Behún
maintainerPATCH v8 3/9 platform: cznic: turris-omnia-mcu: Add support for MCU connected GPIOs
In reply to Marek BehúnAdd 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 | 33 +- .../platform/cznic/turris-omnia-mcu-gpio.c | 1048 +++++++++++++++++ drivers/platform/cznic/turris-omnia-mcu.h | 69 +- 6 files changed, 1166 insertions(+), 16 deletions(-) create mode 100644 drivers/platform/cznic/turris-omnia-mcu-gpio.c
Documentation/ABI/testing/sysfs-bus-i2c-devices-turris-omnia-mcu +16 -0
@@ -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: July 2024 +KernelVersion: 6.10 +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: July 2024 KernelVersion: 6.10
drivers/platform/cznic/Kconfig +15 -0
@@ -17,9 +17,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
@@ -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 +20 -13
@@ -22,25 +22,31 @@#define OMNIA_FW_VERSION_HEX_LEN (2 * OMNIA_FW_VERSION_LEN + 1)#define OMNIA_BOARD_INFO_LEN 16 -int omnia_cmd_read (const struct i2c_client *client,u8 cmd,void *reply, -unsigned int len) +int omnia_cmd_write_read (const struct i2c_client *client, +void *cmd,unsigned int cmd_len, +void *reply,unsigned int reply_len) {struct i2c_msg msgs[2 ]; -int ret; +int ret, num; msgs[0 ].addr = client->addr; msgs[0 ].flags =0 ; - msgs[0 ].len =1 ; - msgs[0 ].buf = &cmd; - msgs[1 ].addr = client->addr; - msgs[1 ].flags =I2C_M_RD ; - msgs[1 ].len = len; - msgs[1 ].buf = reply; - - ret =i2c_transfer (client->adapter, msgs,ARRAY_SIZE (msgs)); + msgs[0 ].len = cmd_len; + msgs[0 ].buf = cmd; + num =1 ; + +if (reply_len) { + msgs[1 ].addr = client->addr; + msgs[1 ].flags =I2C_M_RD ; + msgs[1 ].len = reply_len; + msgs[1 ].buf = reply; + num++; + } + + ret =i2c_transfer (client->adapter, msgs, num);if (ret <0 )return ret; -if (ret !=ARRAY_SIZE (msgs)) +if (ret != num)return -EIO ;return 0 ;
@@ -188,6 +194,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 };
@@ -353,7 +360,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 +1048 -0
1,048 lines not on this page · raw message
drivers/platform/cznic/turris-omnia-mcu.h +66 -3
89 lines not on this page · raw message
Signature · 1 line
2.43.2
Re: [PATCH v8 3/9] 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 30 lines
drivers/platform/cznic/turris-omnia-mcu-base.c +14
-11-int omnia_cmd_read (const struct i2c_client *client,u8 cmd,void *reply, -unsigned int len) +int omnia_cmd_write_read (const struct i2c_client *client, +void *cmd,unsigned int cmd_len, +void *reply,unsigned int reply_len) {struct i2c_msg msgs[2 ]; -int ret; +int ret, num; msgs[0 ].addr = client->addr; msgs[0 ].flags =0 ; - msgs[0 ].len =1 ; - msgs[0 ].buf = &cmd; - msgs[1 ].addr = client->addr; - msgs[1 ].flags =I2C_M_RD ; - msgs[1 ].len = len; - msgs[1 ].buf = reply; - - ret =i2c_transfer (client->adapter, msgs,ARRAY_SIZE (msgs)); + msgs[0 ].len = cmd_len; + msgs[0 ].buf = cmd; + num =1 ; + +if (reply_len) { + msgs[1 ].addr = client->addr; + msgs[1 ].flags =I2C_M_RD ; + msgs[1 ].len = reply_len; + msgs[1 ].buf = reply; + num++;
drivers/platform/cznic/turris-omnia-mcu-base.c line 52
Quoted 10 lines
drivers/platform/cznic/turris-omnia-mcu-base.c +4
-1+ } + + ret =i2c_transfer (client->adapter, msgs, num);if (ret <0 )return ret; -if (ret !=ARRAY_SIZE (msgs)) +if (ret != num)return -EIO ;return 0 ;
Hold on, you are "patching" the code you just brought by the previous patch?! No, just do from the beginning how it should be at the end.
...
Quoted 1 line
+#include <
linux/devm-helpers.h>
Do you still need this?
...
Quoted 1 line
+#define
FRONT_BUTTON_RELEASE_DELAY50 /* ms */
Use proper unit suffix instead of a comment like many others do.
_MS here.
...
Quoted 32 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +32
-0+static const char *const omnia_mcu_gpio_templates[64 ] = { +/* GPIOs with value read from the 16-bit wide status */ + [4 ] ="gpio%u.MiniPCIe0 Card Detect" , + [5 ] ="gpio%u.MiniPCIe0 mSATA Indicator" , + [6 ] ="gpio%u.Front USB3 port over-current" , + [7 ] ="gpio%u.Rear USB3 port over-current" , + [8 ] ="gpio%u.Front USB3 port power" , + [9 ] ="gpio%u.Rear USB3 port power" , + [12 ] ="gpio%u.Front Button" , + +/* GPIOs with value read from the 32-bit wide extended status */ + [16 ] ="gpio%u.SFP nDET" , + [28 ] ="gpio%u.MiniPCIe0 LED" , + [29 ] ="gpio%u.MiniPCIe1 LED" , + [30 ] ="gpio%u.MiniPCIe2 LED" , + [31 ] ="gpio%u.MiniPCIe0 PAN LED" , + [32 ] ="gpio%u.MiniPCIe1 PAN LED" , + [33 ] ="gpio%u.MiniPCIe2 PAN LED" , + [34 ] ="gpio%u.WAN PHY LED0" , + [35 ] ="gpio%u.WAN PHY LED1" , + [36 ] ="gpio%u.LAN switch p0 LED0" , + [37 ] ="gpio%u.LAN switch p0 LED1" , + [38 ] ="gpio%u.LAN switch p1 LED0" , + [39 ] ="gpio%u.LAN switch p1 LED1" , + [40 ] ="gpio%u.LAN switch p2 LED0" , + [41 ] ="gpio%u.LAN switch p2 LED1" , + [42 ] ="gpio%u.LAN switch p3 LED0" , + [43 ] ="gpio%u.LAN switch p3 LED1" , + [44 ] ="gpio%u.LAN switch p4 LED0" , + [45 ] ="gpio%u.LAN switch p4 LED1" , + [46 ] ="gpio%u.LAN switch p5 LED0" , + [47 ] ="gpio%u.LAN switch p5 LED1" ,
drivers/platform/cznic/turris-omnia-mcu-gpio.c line 71
Quoted 10 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +10
-0+ +/* GPIOs with value read from the 16-bit wide extended control status */ + [48] = "gpio%u.eMMC nRESET", + [49] = "gpio%u.LAN switch nRESET", + [50] = "gpio%u.WAN PHY nRESET", + [51] = "gpio%u.MiniPCIe0 nPERST", + [52] = "gpio%u.MiniPCIe1 nPERST", + [53] = "gpio%u.MiniPCIe2 nPERST", + [54] = "gpio%u.WAN PHY SFP mux", +};
You may reduce the memory footprint of these just by doing "gpio%u." part(s) outside. Here compiler won't compress this (as in the case of repetitive string literals),
...
drivers/platform/cznic/turris-omnia-mcu-gpio.c line 112
Quoted 6 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +6
-0+static const struct omnia_gpio { +u8 cmd, ctl_cmd; +u32 bit, ctl_bit; +u32 int_bit; +u16 feat, feat_mask; +} omnia_gpios[64 ] = {
It's much better to decouple definition and assignment and put definition _before_ the macros that fill it.
Quoted 1 line
+};
...
drivers/platform/cznic/turris-omnia-mcu-gpio.c line 257
Quoted 7 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +7
-0+scoped_guard (mutex, &mcu->lock) + val = omnia_cmd_read_bit(mcu->client, +CMD_GET_EXT_CONTROL_STATUS , +EXT_CTL_PHY_SFP_AUTO ); + +if (val <0 ) +return val;
I would move that under guard for the sake of better readability (usual pattern in place). It's anyway a slow path and one branch under the mutex won't affect anything.
Quoted 4 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +4
-0+if (val) +return GPIO_LINE_DIRECTION_IN ; + +return GPIO_LINE_DIRECTION_OUT ;
...
drivers/platform/cznic/turris-omnia-mcu-gpio.c line 342
Quoted 7 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +6
-0+struct omnia_mcu *mcu =gpiochip_get_data (gc); +u32 sts_bits, ext_sts_bits, ext_ctl_bits; +int err, i; + sts_bits =0 ; + ext_sts_bits =0 ; + ext_ctl_bits =0 ;
Why not assign these inside the definition line?
...
drivers/platform/cznic/turris-omnia-mcu-gpio.c line 388
Quoted 6 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +6
-0+for_each_set_bit (i, mask,ARRAY_SIZE (omnia_gpios)) { +if (omnia_gpios[i].cmd ==CMD_GET_STATUS_WORD ) +__assign_bit (i, bits, sts_bits & omnia_gpios[i].bit); +else if (omnia_gpios[i].cmd ==CMD_GET_EXT_STATUS_DWORD ) +__assign_bit (i, bits, ext_sts_bits & + omnia_gpios[i].bit);
One line?
drivers/platform/cznic/turris-omnia-mcu-gpio.c line 391
Quoted 3 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +3
-0+else if (omnia_gpios[i].cmd ==CMD_GET_EXT_CONTROL_STATUS ) +__assign_bit (i, bits, ext_ctl_bits & + omnia_gpios[i].bit);
Ditto?
Quoted 1 line
+ }
...
drivers/platform/cznic/turris-omnia-mcu-gpio.c line 423
Quoted 9 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +9
-0+struct omnia_mcu *mcu =gpiochip_get_data (gc); +u16 ext_ctl, ext_ctl_mask; +u8 ctl, ctl_mask; +int i; + + ctl =0 ; + ctl_mask =0 ; + ext_ctl =0 ; + ext_ctl_mask =0 ;
Assignments in the definition line?
...
Quoted 11 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +11
-0+for_each_set_bit (i, mask,ARRAY_SIZE (omnia_gpios)) { +if (omnia_gpios[i].ctl_cmd ==CMD_GENERAL_CONTROL ) { + ctl_mask |= omnia_gpios[i].ctl_bit; +if (test_bit (i, bits)) + ctl |= omnia_gpios[i].ctl_bit; + }else if (omnia_gpios[i].ctl_cmd ==CMD_EXT_CONTROL ) { + ext_ctl_mask |= omnia_gpios[i].ctl_bit; +if (test_bit (i, bits)) + ext_ctl |= omnia_gpios[i].ctl_bit; + } + }
...
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
Quoted 7 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 interrupt mask and reports pending interrupt bitmap int this
an interrupt
a pending
int --> in ?
Quoted 8 lines
+ * interleaved format. The rationale behind it 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 605
Quoted 6 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +6
-0+static void omnia_mask_interleave (u8 *dst,u32 rising,u32 falling) +{ +for (int i =0 ; i <sizeof (u32); ++i) { + dst[2 * i] = rising >> (8 * i); + dst[2 * i +1 ] = falling >> (8 * i); + }
I will look at this later on,
drivers/platform/cznic/turris-omnia-mcu-gpio.c line 624
Quoted 11 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +10
-0+} +static void omnia_mask_deinterleave (const u8 *src,u32 *rising,u32 *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); + } +}
and into this.
...
drivers/platform/cznic/turris-omnia-mcu-gpio.c line 722
Quoted 12 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +12
-0+static size_t omnia_irq_compute_pending_length (u32 rising,u32 falling) +{ +size_t rlen =0 , flen =0 ; + +if (rising) + rlen = ((__fls (rising) >>3 ) <<1 ) +1 ; + +if (falling) + flen = ((__fls (falling) >>3 ) <<1 ) +2 ; + +return max (rlen, flen); +}
I am not sure why you need this, but it can be done easily
x = ((__fls(falling | rising) >> 3) << 1) + 1;
if (falling)
return x + 1;
return x;
and most likely you can drop minmax.h.
...
Quoted 1 line
+static const char * const front_button_modes[2] = { "mcu", "cpu" };
2 is not needed.
...
Quoted 1 line
-#include <
linux/i2c.h>
??? That is exactly the point to have things done from the beginning.
Quoted 7 lines
drivers/platform/cznic/turris-omnia-mcu.h +4
-0+#include <linux/bitops.h> +#include <linux/gpio/driver.h> #include <linux/if_ether.h> +#include <linux/mutex.h> #include <linux/types.h> +#include <linux/workqueue.h> #include <asm/byteorder.h>
...
Quoted 1 line
+ err =
omnia_cmd_read(client, cmd, &reply, (__fls(bits) >> 3) + 1);
Perhaps a helper for this (__fls(x) >> 3 + (y)) ? It seems it's used in a few places.
Review
Quoted 2 lines
(quoted diff) +2
-0+ if (err) + return err;
--
With Best Regards,
Andy Shevchenko
Marek Behún
maintainerRe: [PATCH v8 3/9] platform: cznic: turris-omnia-mcu: Add support for MCU connected GPIOs
Quoted 53 lines · Andy Shevchenko
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 39 lines
drivers/platform/cznic/turris-omnia-mcu-base.c +18
-12-int omnia_cmd_read (const struct i2c_client *client,u8 cmd,void *reply, -unsigned int len) +int omnia_cmd_write_read (const struct i2c_client *client, +void *cmd,unsigned int cmd_len, +void *reply,unsigned int reply_len) {struct i2c_msg msgs[2 ]; -int ret; +int ret, num; msgs[0 ].addr = client->addr; msgs[0 ].flags =0 ; - msgs[0 ].len =1 ; - msgs[0 ].buf = &cmd; - msgs[1 ].addr = client->addr; - msgs[1 ].flags =I2C_M_RD ; - msgs[1 ].len = len; - msgs[1 ].buf = reply; - - ret =i2c_transfer (client->adapter, msgs,ARRAY_SIZE (msgs)); + msgs[0 ].len = cmd_len; + msgs[0 ].buf = cmd; + num =1 ; + +if (reply_len) { + msgs[1 ].addr = client->addr; + msgs[1 ].flags =I2C_M_RD ; + msgs[1 ].len = reply_len; + msgs[1 ].buf = reply; + num++; + } + + ret =i2c_transfer (client->adapter, msgs, num);if (ret <0 )return ret; -if (ret !=ARRAY_SIZE (msgs)) +if (ret != num)return -EIO ;
Quoted 4 lines
Quoted 1 line
return 0;Hold on, you are "patching" the code you just brought by the previous patch?! No, just do from the beginning how it should be at the end.
Fixed.
Quoted 3 lines
Quoted 1 line
+#include <
linux/devm-helpers.h>Do you still need this?
Yes, for devm_delayed_work_drop().
Quoted 7 lines
...
Quoted 1 line
+#define
FRONT_BUTTON_RELEASE_DELAY50 /* ms */Use proper unit suffix instead of a comment like many others do.
_MShere.
Fixed.
Quoted 38 lines
Quoted 38 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +38
-0+static const char *const omnia_mcu_gpio_templates[64 ] = { +/* GPIOs with value read from the 16-bit wide status */ + [4 ] ="gpio%u.MiniPCIe0 Card Detect" , + [5 ] ="gpio%u.MiniPCIe0 mSATA Indicator" , + [6 ] ="gpio%u.Front USB3 port over-current" , + [7 ] ="gpio%u.Rear USB3 port over-current" , + [8 ] ="gpio%u.Front USB3 port power" , + [9 ] ="gpio%u.Rear USB3 port power" , + [12 ] ="gpio%u.Front Button" , + +/* GPIOs with value read from the 32-bit wide extended status */ + [16 ] ="gpio%u.SFP nDET" , + [28 ] ="gpio%u.MiniPCIe0 LED" , + [29 ] ="gpio%u.MiniPCIe1 LED" , + [30 ] ="gpio%u.MiniPCIe2 LED" , + [31 ] ="gpio%u.MiniPCIe0 PAN LED" , + [32 ] ="gpio%u.MiniPCIe1 PAN LED" , + [33 ] ="gpio%u.MiniPCIe2 PAN LED" , + [34 ] ="gpio%u.WAN PHY LED0" , + [35 ] ="gpio%u.WAN PHY LED1" , + [36 ] ="gpio%u.LAN switch p0 LED0" , + [37 ] ="gpio%u.LAN switch p0 LED1" , + [38 ] ="gpio%u.LAN switch p1 LED0" , + [39 ] ="gpio%u.LAN switch p1 LED1" , + [40 ] ="gpio%u.LAN switch p2 LED0" , + [41 ] ="gpio%u.LAN switch p2 LED1" , + [42 ] ="gpio%u.LAN switch p3 LED0" , + [43 ] ="gpio%u.LAN switch p3 LED1" , + [44 ] ="gpio%u.LAN switch p4 LED0" , + [45 ] ="gpio%u.LAN switch p4 LED1" , + [46 ] ="gpio%u.LAN switch p5 LED0" , + [47 ] ="gpio%u.LAN switch p5 LED1" , + +/* GPIOs with value read from the 16-bit wide extended control status */ + [48 ] ="gpio%u.eMMC nRESET" , + [49 ] ="gpio%u.LAN switch nRESET" , + [50 ] ="gpio%u.WAN PHY nRESET" , + [51 ] ="gpio%u.MiniPCIe0 nPERST" ,
Quoted 8 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c line 71
Quoted 4 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +4
-0+ [52] = "gpio%u.MiniPCIe1 nPERST", + [53] = "gpio%u.MiniPCIe2 nPERST", + [54] = "gpio%u.WAN PHY SFP mux", +};You may reduce the memory footprint of these just by doing "gpio%u." part(s) outside. Here compiler won't compress this (as in the case of repetitive string literals),
Are you saying that I should dynamically create another array just to pass it to the gpiochip's names pointer?
Quoted 9 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c line 112
Quoted 6 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +6
-0+static const struct omnia_gpio { +u8 cmd, ctl_cmd; +u32 bit, ctl_bit; +u32 int_bit; +u16 feat, feat_mask; +} omnia_gpios[64 ] = {It's much better to decouple definition and assignment and put definition _before_ the macros that fill it.
Fixed.
Quoted 11 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c line 257
Quoted 7 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +7
-0+scoped_guard (mutex, &mcu->lock) + val = omnia_cmd_read_bit(mcu->client, +CMD_GET_EXT_CONTROL_STATUS , +EXT_CTL_PHY_SFP_AUTO ); + +if (val <0 ) +return val;I would move that under guard for the sake of better readability (usual pattern in place). It's anyway a slow path and one branch under the mutex won't affect anything.
OK.
Quoted 11 lines
Quoted 4 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +4
-0+if (val) +return GPIO_LINE_DIRECTION_IN ; + +return GPIO_LINE_DIRECTION_OUT ;...
Quoted 3 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +3
-0+struct omnia_mcu *mcu =gpiochip_get_data (gc); +u32 sts_bits, ext_sts_bits, ext_ctl_bits; +int err, i;
Quoted 5 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c line 342
Quoted 3 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +3
-0+ sts_bits =0 ; + ext_sts_bits =0 ; + ext_ctl_bits =0 ;Why not assign these inside the definition line?
OK.
Quoted 8 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c line 388
Quoted 6 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +6
-0+for_each_set_bit (i, mask,ARRAY_SIZE (omnia_gpios)) { +if (omnia_gpios[i].cmd ==CMD_GET_STATUS_WORD ) +__assign_bit (i, bits, sts_bits & omnia_gpios[i].bit); +else if (omnia_gpios[i].cmd ==CMD_GET_EXT_STATUS_DWORD ) +__assign_bit (i, bits, ext_sts_bits & + omnia_gpios[i].bit);One line?
That would be 81 columns, which I would like to avoid.
I can remove the _bits suffix from these variables, though. What do you think?
Quoted 20 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c line 391
Quoted 3 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +3
-0+else if (omnia_gpios[i].cmd ==CMD_GET_EXT_CONTROL_STATUS ) +__assign_bit (i, bits, ext_ctl_bits & + omnia_gpios[i].bit);Ditto?
Quoted 1 line
+ }
...
drivers/platform/cznic/turris-omnia-mcu-gpio.c line 423
Quoted 9 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +9
-0+struct omnia_mcu *mcu =gpiochip_get_data (gc); +u16 ext_ctl, ext_ctl_mask; +u8 ctl, ctl_mask; +int i; + + ctl =0 ; + ctl_mask =0 ; + ext_ctl =0 ; + ext_ctl_mask =0 ;
Quoted 1 line
Assignments in the definition line?
OK
Quoted 27 lines
Quoted 11 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +11
-0+for_each_set_bit (i, mask,ARRAY_SIZE (omnia_gpios)) { +if (omnia_gpios[i].ctl_cmd ==CMD_GENERAL_CONTROL ) { + ctl_mask |= omnia_gpios[i].ctl_bit; +if (test_bit (i, bits)) + ctl |= omnia_gpios[i].ctl_bit; + }else if (omnia_gpios[i].ctl_cmd ==CMD_EXT_CONTROL ) { + ext_ctl_mask |= omnia_gpios[i].ctl_bit; +if (test_bit (i, bits)) + ext_ctl |= omnia_gpios[i].ctl_bit; + } + }...
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 maskQuoted 7 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 interrupt mask and reports pending interrupt bitmap int this
Quoted 3 lines
an interrupt
a pending
int --> in ?
Thx.
Quoted 48 lines
Quoted 8 lines
+ * interleaved format. The rationale behind it 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 605
Quoted 6 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +6
-0+static void omnia_mask_interleave (u8 *dst,u32 rising,u32 falling) +{ +for (int i =0 ; i <sizeof (u32); ++i) { + dst[2 * i] = rising >> (8 * i); + dst[2 * i +1 ] = falling >> (8 * i); + }I will look at this later on,
drivers/platform/cznic/turris-omnia-mcu-gpio.c line 624
Quoted 11 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +10
-0+} +static void omnia_mask_deinterleave (const u8 *src,u32 *rising,u32 *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); + } +}and into this.
...
drivers/platform/cznic/turris-omnia-mcu-gpio.c line 722
Quoted 12 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +12
-0+static size_t omnia_irq_compute_pending_length (u32 rising,u32 falling) +{ +size_t rlen =0 , flen =0 ; + +if (rising) + rlen = ((__fls (rising) >>3 ) <<1 ) +1 ; + +if (falling) + flen = ((__fls (falling) >>3 ) <<1 ) +2 ; + +return max (rlen, flen); +}I am not sure why you need this, but it can be done easily
Quoted 6 lines
x = ((
__fls(falling | rising)>> 3) << 1) + 1;
if (falling)
return x + 1;
return x;and most likely you can drop
minmax.h.
This will return different results for for example when
rising = 0x100
falling = 0x10
where we need to read only 3 bytes, but your version will say that we need 4 bytes.
Quoted 3 lines
Quoted 1 line
+static const char * const front_button_modes[2] = { "mcu", "cpu" };
2 is not needed.
OK
Quoted 3 lines
Quoted 1 line
-#include <
linux/i2c.h>??? That is exactly the point to have things done from the beginning.
I must have somehow missed this before sending, I see that I've already fixed it in my working branch.
Quoted 22 lines
Quoted 7 lines
drivers/platform/cznic/turris-omnia-mcu.h +4
-0+#include <linux/bitops.h> +#include <linux/gpio/driver.h> #include <linux/if_ether.h> +#include <linux/mutex.h> #include <linux/types.h> +#include <linux/workqueue.h> #include <asm/byteorder.h> ...
Quoted 1 line
+ err =
omnia_cmd_read(client, cmd, &reply, (__fls(bits) >> 3) + 1);Perhaps a helper for this (
__fls(x)>> 3 + (y)) ? It seems it's used in a few places.Review
Quoted 2 lines
(quoted diff) +2
-0+ if (err) + return err;--
With Best Regards,
Andy Shevchenko
Re: [PATCH v8 3/9] platform: cznic: turris-omnia-mcu: Add support for MCU connected GPIOs
Quoted 2 lines · Marek Behún
Quoted 1 line · Andy Shevchenko
On Tue, Apr 30, 2024 at 2:51 PM Marek Behún <[email protected]> wrote:
...
Quoted 47 lines
Quoted 38 lines
Quoted 38 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +38
-0+static const char *const omnia_mcu_gpio_templates[64 ] = { +/* GPIOs with value read from the 16-bit wide status */ + [4 ] ="gpio%u.MiniPCIe0 Card Detect" , + [5 ] ="gpio%u.MiniPCIe0 mSATA Indicator" , + [6 ] ="gpio%u.Front USB3 port over-current" , + [7 ] ="gpio%u.Rear USB3 port over-current" , + [8 ] ="gpio%u.Front USB3 port power" , + [9 ] ="gpio%u.Rear USB3 port power" , + [12 ] ="gpio%u.Front Button" , + +/* GPIOs with value read from the 32-bit wide extended status */ + [16 ] ="gpio%u.SFP nDET" , + [28 ] ="gpio%u.MiniPCIe0 LED" , + [29 ] ="gpio%u.MiniPCIe1 LED" , + [30 ] ="gpio%u.MiniPCIe2 LED" , + [31 ] ="gpio%u.MiniPCIe0 PAN LED" , + [32 ] ="gpio%u.MiniPCIe1 PAN LED" , + [33 ] ="gpio%u.MiniPCIe2 PAN LED" , + [34 ] ="gpio%u.WAN PHY LED0" , + [35 ] ="gpio%u.WAN PHY LED1" , + [36 ] ="gpio%u.LAN switch p0 LED0" , + [37 ] ="gpio%u.LAN switch p0 LED1" , + [38 ] ="gpio%u.LAN switch p1 LED0" , + [39 ] ="gpio%u.LAN switch p1 LED1" , + [40 ] ="gpio%u.LAN switch p2 LED0" , + [41 ] ="gpio%u.LAN switch p2 LED1" , + [42 ] ="gpio%u.LAN switch p3 LED0" , + [43 ] ="gpio%u.LAN switch p3 LED1" , + [44 ] ="gpio%u.LAN switch p4 LED0" , + [45 ] ="gpio%u.LAN switch p4 LED1" , + [46 ] ="gpio%u.LAN switch p5 LED0" , + [47 ] ="gpio%u.LAN switch p5 LED1" , + +/* GPIOs with value read from the 16-bit wide extended control status */ + [48 ] ="gpio%u.eMMC nRESET" , + [49 ] ="gpio%u.LAN switch nRESET" , + [50 ] ="gpio%u.WAN PHY nRESET" , + [51 ] ="gpio%u.MiniPCIe0 nPERST" ,Quoted 8 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c line 71
Quoted 4 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +4
-0+ [52] = "gpio%u.MiniPCIe1 nPERST", + [53] = "gpio%u.MiniPCIe2 nPERST", + [54] = "gpio%u.WAN PHY SFP mux", +};You may reduce the memory footprint of these just by doing "gpio%u." part(s) outside. Here compiler won't compress this (as in the case of repetitive string literals),
Quoted 2 lines
Are you saying that I should dynamically create another array just to pass it to the gpiochip's names pointer?
I have looked into this again and now I'm puzzled how you tested this. To me it seems that those gpio%u will go as a fixed string to the user space, there is no %u --> number substitution happens. Moreover, this data anyway is redundant. Userspace and debugfs all have line numbers being printed.
...
Quoted 10 lines
Quoted 8 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c line 388
Quoted 6 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +6
-0+for_each_set_bit (i, mask,ARRAY_SIZE (omnia_gpios)) { +if (omnia_gpios[i].cmd ==CMD_GET_STATUS_WORD ) +__assign_bit (i, bits, sts_bits & omnia_gpios[i].bit); +else if (omnia_gpios[i].cmd ==CMD_GET_EXT_STATUS_DWORD ) +__assign_bit (i, bits, ext_sts_bits & + omnia_gpios[i].bit);One line?
That would be 81 columns, which I would like to avoid.
81?! It's fine! Even documentation allows that for the readability.
Quoted 2 lines
I can remove the
_bitssuffix from these variables, though. What do you think?
Make sense as well.
Quoted 7 lines
Quoted 7 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c line 391
Quoted 3 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +3
-0+else if (omnia_gpios[i].cmd ==CMD_GET_EXT_CONTROL_STATUS ) +__assign_bit (i, bits, ext_ctl_bits & + omnia_gpios[i].bit);Ditto?
Quoted 1 line
+ }
Signature · 2 lines
With Best Regards, Andy Shevchenko
Marek Behún
maintainerRe: [PATCH v8 3/9] platform: cznic: turris-omnia-mcu: Add support for MCU connected GPIOs
Quoted 53 lines · Andy Shevchenko
Quoted 2 lines · Marek Behún
Quoted 1 line · Andy Shevchenko
On Tue, Apr 30, 2024 at 2:51 PM Marek Behún <[email protected]> wrote:
...
Quoted 47 lines
Quoted 46 lines
Quoted 32 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +32
-0+static const char *const omnia_mcu_gpio_templates[64 ] = { +/* GPIOs with value read from the 16-bit wide status */ + [4 ] ="gpio%u.MiniPCIe0 Card Detect" , + [5 ] ="gpio%u.MiniPCIe0 mSATA Indicator" , + [6 ] ="gpio%u.Front USB3 port over-current" , + [7 ] ="gpio%u.Rear USB3 port over-current" , + [8 ] ="gpio%u.Front USB3 port power" , + [9 ] ="gpio%u.Rear USB3 port power" , + [12 ] ="gpio%u.Front Button" , + +/* GPIOs with value read from the 32-bit wide extended status */ + [16 ] ="gpio%u.SFP nDET" , + [28 ] ="gpio%u.MiniPCIe0 LED" , + [29 ] ="gpio%u.MiniPCIe1 LED" , + [30 ] ="gpio%u.MiniPCIe2 LED" , + [31 ] ="gpio%u.MiniPCIe0 PAN LED" , + [32 ] ="gpio%u.MiniPCIe1 PAN LED" , + [33 ] ="gpio%u.MiniPCIe2 PAN LED" , + [34 ] ="gpio%u.WAN PHY LED0" , + [35 ] ="gpio%u.WAN PHY LED1" , + [36 ] ="gpio%u.LAN switch p0 LED0" , + [37 ] ="gpio%u.LAN switch p0 LED1" , + [38 ] ="gpio%u.LAN switch p1 LED0" , + [39 ] ="gpio%u.LAN switch p1 LED1" , + [40 ] ="gpio%u.LAN switch p2 LED0" , + [41 ] ="gpio%u.LAN switch p2 LED1" , + [42 ] ="gpio%u.LAN switch p3 LED0" , + [43 ] ="gpio%u.LAN switch p3 LED1" , + [44 ] ="gpio%u.LAN switch p4 LED0" , + [45 ] ="gpio%u.LAN switch p4 LED1" , + [46 ] ="gpio%u.LAN switch p5 LED0" , + [47 ] ="gpio%u.LAN switch p5 LED1" ,drivers/platform/cznic/turris-omnia-mcu-gpio.c line 71
Quoted 10 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +10
-0+ +/* GPIOs with value read from the 16-bit wide extended control status */ + [48] = "gpio%u.eMMC nRESET", + [49] = "gpio%u.LAN switch nRESET", + [50] = "gpio%u.WAN PHY nRESET", + [51] = "gpio%u.MiniPCIe0 nPERST", + [52] = "gpio%u.MiniPCIe1 nPERST", + [53] = "gpio%u.MiniPCIe2 nPERST", + [54] = "gpio%u.WAN PHY SFP mux", +};You may reduce the memory footprint of these just by doing "gpio%u." part(s) outside. Here compiler won't compress this (as in the case of repetitive string literals),
Quoted 8 lines
Quoted 2 lines
Are you saying that I should dynamically create another array just to pass it to the gpiochip's names pointer?
I have looked into this again and now I'm puzzled how you tested this. To me it seems that those gpio%u will go as a fixed string to the user space, there is no %u --> number substitution happens. Moreover, this data anyway is redundant. Userspace and debugfs all have line numbers being printed.
It gets substituted in drivers/gpio/gpiolib-sysfs.c, function gpiod_export():
dev = device_create_with_groups(&gpio_class, &gdev->dev,
MKDEV(0, 0), data, gpio_groups, ioname ? ioname : "gpio%u", desc_to_gpio(desc));
The ioname variable contains the string.
This is then visible in sysfs:
$ cd /sys/class/gpio $ echo 560 >export $ ls ... gpio560.eMMC nRESET ...
Quoted 9 lines
...
Quoted 7 lines
Quoted 7 lines
Quoted 6 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +6
-0+for_each_set_bit (i, mask,ARRAY_SIZE (omnia_gpios)) { +if (omnia_gpios[i].cmd ==CMD_GET_STATUS_WORD ) +__assign_bit (i, bits, sts_bits & omnia_gpios[i].bit); +else if (omnia_gpios[i].cmd ==CMD_GET_EXT_STATUS_DWORD ) +__assign_bit (i, bits, ext_sts_bits & + omnia_gpios[i].bit);
Quoted 5 lines
Quoted 3 lines
Quoted 1 line
One line?
That would be 81 columns, which I would like to avoid.
81?! It's fine! Even documentation allows that for the readability.
OK
Quoted 18 lines
Quoted 2 lines
I can remove the
_bitssuffix from these variables, though. What do you think?Make sense as well.
Quoted 7 lines
Quoted 7 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c line 391
Quoted 3 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +3
-0+else if (omnia_gpios[i].cmd ==CMD_GET_EXT_CONTROL_STATUS ) +__assign_bit (i, bits, ext_ctl_bits & + omnia_gpios[i].bit);Ditto?
Quoted 1 line
+ }
Signature · 2 lines
With Best Regards, Andy Shevchenko
Re: [PATCH v8 3/9] platform: cznic: turris-omnia-mcu: Add support for MCU connected GPIOs
Quoted 4 lines · Marek Behún
Quoted 3 lines · Andy Shevchenko
Quoted 2 lines · Marek Behún
Quoted 1 line · Andy Shevchenko
On Tue, Apr 30, 2024 at 2:51 PM Marek Behún <[email protected]> wrote:
...
Quoted 66 lines
Quoted 47 lines
Quoted 47 lines
Quoted 46 lines
Quoted 32 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +32
-0+static const char *const omnia_mcu_gpio_templates[64 ] = { +/* GPIOs with value read from the 16-bit wide status */ + [4 ] ="gpio%u.MiniPCIe0 Card Detect" , + [5 ] ="gpio%u.MiniPCIe0 mSATA Indicator" , + [6 ] ="gpio%u.Front USB3 port over-current" , + [7 ] ="gpio%u.Rear USB3 port over-current" , + [8 ] ="gpio%u.Front USB3 port power" , + [9 ] ="gpio%u.Rear USB3 port power" , + [12 ] ="gpio%u.Front Button" , + +/* GPIOs with value read from the 32-bit wide extended status */ + [16 ] ="gpio%u.SFP nDET" , + [28 ] ="gpio%u.MiniPCIe0 LED" , + [29 ] ="gpio%u.MiniPCIe1 LED" , + [30 ] ="gpio%u.MiniPCIe2 LED" , + [31 ] ="gpio%u.MiniPCIe0 PAN LED" , + [32 ] ="gpio%u.MiniPCIe1 PAN LED" , + [33 ] ="gpio%u.MiniPCIe2 PAN LED" , + [34 ] ="gpio%u.WAN PHY LED0" , + [35 ] ="gpio%u.WAN PHY LED1" , + [36 ] ="gpio%u.LAN switch p0 LED0" , + [37 ] ="gpio%u.LAN switch p0 LED1" , + [38 ] ="gpio%u.LAN switch p1 LED0" , + [39 ] ="gpio%u.LAN switch p1 LED1" , + [40 ] ="gpio%u.LAN switch p2 LED0" , + [41 ] ="gpio%u.LAN switch p2 LED1" , + [42 ] ="gpio%u.LAN switch p3 LED0" , + [43 ] ="gpio%u.LAN switch p3 LED1" , + [44 ] ="gpio%u.LAN switch p4 LED0" , + [45 ] ="gpio%u.LAN switch p4 LED1" , + [46 ] ="gpio%u.LAN switch p5 LED0" , + [47 ] ="gpio%u.LAN switch p5 LED1" ,drivers/platform/cznic/turris-omnia-mcu-gpio.c line 71
Quoted 10 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +10
-0+ +/* GPIOs with value read from the 16-bit wide extended control status */ + [48] = "gpio%u.eMMC nRESET", + [49] = "gpio%u.LAN switch nRESET", + [50] = "gpio%u.WAN PHY nRESET", + [51] = "gpio%u.MiniPCIe0 nPERST", + [52] = "gpio%u.MiniPCIe1 nPERST", + [53] = "gpio%u.MiniPCIe2 nPERST", + [54] = "gpio%u.WAN PHY SFP mux", +};You may reduce the memory footprint of these just by doing "gpio%u." part(s) outside. Here compiler won't compress this (as in the case of repetitive string literals),
Quoted 8 lines
Quoted 2 lines
Are you saying that I should dynamically create another array just to pass it to the gpiochip's names pointer?
I have looked into this again and now I'm puzzled how you tested this. To me it seems that those gpio%u will go as a fixed string to the user space, there is no %u --> number substitution happens. Moreover, this data anyway is redundant. Userspace and debugfs all have line numbers being printed.
It gets substituted in
drivers/gpio/gpiolib-sysfs.c, functiongpiod_export():dev = device_create_with_groups(&gpio_class,
&gdev->dev,MKDEV(0, 0), data, gpio_groups, ioname ? ioname : "gpio%u", desc_to_gpio(desc));The ioname variable contains the string.
Quoted 8 lines
This is then visible in sysfs:
$ cd /sys/class/gpio $ echo 560 >export $ ls ... gpio560.eMMC nRESET ...
Interesting. But before giving my conclusion on this, what is the output of /sys/kernel/debug/gpio and gpioinfo (the latter from libgpiod)?
Signature · 2 lines
With Best Regards, Andy Shevchenko
Marek Behún
maintainerRe: [PATCH v8 3/9] platform: cznic: turris-omnia-mcu: Add support for MCU connected GPIOs
Quoted 83 lines · Andy Shevchenko
Quoted 4 lines · Marek Behún
Quoted 3 lines · Andy Shevchenko
Quoted 2 lines · Marek Behún
Quoted 1 line · Andy Shevchenko
On Tue, Apr 30, 2024 at 2:51 PM Marek Behún <[email protected]> wrote:
...
Quoted 66 lines
Quoted 47 lines
Quoted 47 lines
Quoted 46 lines
Quoted 32 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +32
-0+static const char *const omnia_mcu_gpio_templates[64 ] = { +/* GPIOs with value read from the 16-bit wide status */ + [4 ] ="gpio%u.MiniPCIe0 Card Detect" , + [5 ] ="gpio%u.MiniPCIe0 mSATA Indicator" , + [6 ] ="gpio%u.Front USB3 port over-current" , + [7 ] ="gpio%u.Rear USB3 port over-current" , + [8 ] ="gpio%u.Front USB3 port power" , + [9 ] ="gpio%u.Rear USB3 port power" , + [12 ] ="gpio%u.Front Button" , + +/* GPIOs with value read from the 32-bit wide extended status */ + [16 ] ="gpio%u.SFP nDET" , + [28 ] ="gpio%u.MiniPCIe0 LED" , + [29 ] ="gpio%u.MiniPCIe1 LED" , + [30 ] ="gpio%u.MiniPCIe2 LED" , + [31 ] ="gpio%u.MiniPCIe0 PAN LED" , + [32 ] ="gpio%u.MiniPCIe1 PAN LED" , + [33 ] ="gpio%u.MiniPCIe2 PAN LED" , + [34 ] ="gpio%u.WAN PHY LED0" , + [35 ] ="gpio%u.WAN PHY LED1" , + [36 ] ="gpio%u.LAN switch p0 LED0" , + [37 ] ="gpio%u.LAN switch p0 LED1" , + [38 ] ="gpio%u.LAN switch p1 LED0" , + [39 ] ="gpio%u.LAN switch p1 LED1" , + [40 ] ="gpio%u.LAN switch p2 LED0" , + [41 ] ="gpio%u.LAN switch p2 LED1" , + [42 ] ="gpio%u.LAN switch p3 LED0" , + [43 ] ="gpio%u.LAN switch p3 LED1" , + [44 ] ="gpio%u.LAN switch p4 LED0" , + [45 ] ="gpio%u.LAN switch p4 LED1" , + [46 ] ="gpio%u.LAN switch p5 LED0" , + [47 ] ="gpio%u.LAN switch p5 LED1" ,drivers/platform/cznic/turris-omnia-mcu-gpio.c line 71
Quoted 10 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +10
-0+ +/* GPIOs with value read from the 16-bit wide extended control status */ + [48] = "gpio%u.eMMC nRESET", + [49] = "gpio%u.LAN switch nRESET", + [50] = "gpio%u.WAN PHY nRESET", + [51] = "gpio%u.MiniPCIe0 nPERST", + [52] = "gpio%u.MiniPCIe1 nPERST", + [53] = "gpio%u.MiniPCIe2 nPERST", + [54] = "gpio%u.WAN PHY SFP mux", +};You may reduce the memory footprint of these just by doing "gpio%u." part(s) outside. Here compiler won't compress this (as in the case of repetitive string literals),
Quoted 8 lines
Quoted 2 lines
Are you saying that I should dynamically create another array just to pass it to the gpiochip's names pointer?
I have looked into this again and now I'm puzzled how you tested this. To me it seems that those gpio%u will go as a fixed string to the user space, there is no %u --> number substitution happens. Moreover, this data anyway is redundant. Userspace and debugfs all have line numbers being printed.
It gets substituted in
drivers/gpio/gpiolib-sysfs.c, functiongpiod_export():dev = device_create_with_groups(&gpio_class,
&gdev->dev,MKDEV(0, 0), data, gpio_groups, ioname ? ioname : "gpio%u", desc_to_gpio(desc));The ioname variable contains the string.
Quoted 8 lines
This is then visible in sysfs:
$ cd /sys/class/gpio $ echo 560 >export $ ls ... gpio560.eMMC nRESET ...
Quoted 3 lines
Interesting. But before giving my conclusion on this, what is the output of
/sys/kernel/debug/gpioandgpioinfo(the latter from libgpiod)?
It prints %u, as you suspected and I see you already posted patch to avoid this. I'm dropping the "gpio%u." prefixes from GPIO line names.
Marek
Marek Behún
maintainerRe: [PATCH v8 3/9] platform: cznic: turris-omnia-mcu: Add support for MCU connected GPIOs
In reply to Andy ShevchenkoOn Fri, May 03, 2024 at 07:05:34AM +0300, Andy Shevchenko wrote:
...
Quoted 4 lines
Quoted 1 line
+ err =
omnia_cmd_read(client, cmd, &reply, (__fls(bits) >> 3) + 1);Perhaps a helper for this (
__fls(x)>> 3 + (y)) ? It seems it's used in a few places.
It is used 3 times:
rlen = ((__fls(rising) >> 3) << 1) + 1;
flen = ((__fls(falling) >> 3) << 1) + 2;
err = omnia_cmd_read(client, cmd, &reply, (__fls(bits) >> 3) + 1);
The last one is not compatible with the first two (because of the "<< 1").
The first two instances are contained within a function that is dedicated to "computing needed reply length".
I could probably do something like
static inline unsigned int
omnia_compute_reply_len(uin32_t mask, bool interleaved, unsigned int offset)
{
return ((__fls(mask) >> 3) << interleaved) + 1 + offset;
}Then the 3 instances would become
rlen = omnia_compute_reply_len(rising, true, 0);
flen = omnia_compute_reply_len(falling, true, 1);
err = omnia_cmd_read(client, cmd, &reply,
omnia_compute_reply_len(bits, false, 0));What do you think?
Re: [PATCH v8 3/9] platform: cznic: turris-omnia-mcu: Add support for MCU connected GPIOs
Quoted 1 line · Marek Behún
On Fri, May 03, 2024 at 07:05:34AM +0300, Andy Shevchenko wrote:
...
Quoted 23 lines
Quoted 4 lines
Quoted 1 line
+ err =
omnia_cmd_read(client, cmd, &reply, (__fls(bits) >> 3) + 1);Perhaps a helper for this (
__fls(x)>> 3 + (y)) ? It seems it's used in a few places.It is used 3 times:
rlen = ((__fls(rising)>> 3) << 1) + 1;
flen = ((__fls(falling)>> 3) << 1) + 2;
err =omnia_cmd_read(client, cmd, &reply, (__fls(bits) >> 3) + 1);The last one is not compatible with the first two (because of the "<< 1").
The first two instances are contained within a function that is dedicated to "computing needed reply length".
I could probably do something like
static inline unsigned int omnia_compute_reply_len(uin32_t mask, bool interleaved, unsigned int offset) { return ((__fls(mask) >> 3) << interleaved) + 1 + offset; }
Quoted 8 lines
Then the 3 instances would become
rlen = omnia_compute_reply_len(rising, true, 0); flen = omnia_compute_reply_len(falling, true, 1); err = omnia_cmd_read(client, cmd, &reply, omnia_compute_reply_len(bits, false, 0));What do you think?
Fine, but think about these bit operations, I believe it can be optimised.
Signature · 2 lines
With Best Regards, Andy Shevchenko
Marek Behún
maintainerRe: [PATCH v8 3/9] platform: cznic: turris-omnia-mcu: Add support for MCU connected GPIOs
Quoted 30 lines · Andy Shevchenko
Quoted 1 line · Marek Behún
On Fri, May 03, 2024 at 07:05:34AM +0300, Andy Shevchenko wrote:
...
Quoted 25 lines
Quoted 4 lines
Quoted 1 line
+ err =
omnia_cmd_read(client, cmd, &reply, (__fls(bits) >> 3) + 1);Perhaps a helper for this (
__fls(x)>> 3 + (y)) ? It seems it's used in a few places.It is used 3 times:
rlen = ((__fls(rising)>> 3) << 1) + 1;
flen = ((__fls(falling)>> 3) << 1) + 2;
err =omnia_cmd_read(client, cmd, &reply, (__fls(bits) >> 3) + 1);The last one is not compatible with the first two (because of the "<< 1").
The first two instances are contained within a function that is dedicated to "computing needed reply length".
I could probably do something like
static inline unsigned int omnia_compute_reply_len(uin32_t mask, bool interleaved, unsigned int offset) { return ((__fls(mask) >> 3) << interleaved) + 1 + offset; }Then the 3 instances would become
Quoted 8 lines
Quoted 6 lines
rlen = omnia_compute_reply_len(rising, true, 0); flen = omnia_compute_reply_len(falling, true, 1); err = omnia_cmd_read(client, cmd, &reply, omnia_compute_reply_len(bits, false, 0));What do you think?
Fine, but think about these bit operations, I believe it can be optimised.
I will try something, altough I fear it might need 64-bit operations, which may be even more suboptimal since the driver is supposed to run on armv7.
Also, isn't this premature optimization? Since the computed length is then passed as a parameter to I2C reading, and the I2C bus is orders of magnitudes slower and the handling of I2C requests in Marvell I2C driver will kill any optimization I do here...
Marek Behún
maintainerPATCH v8 4/9 platform: cznic: turris-omnia-mcu: Add support for poweroff and wakeup
In reply to Marek BehúnAdd 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 | 258 ++++++++++++++++++ drivers/platform/cznic/turris-omnia-mcu.h | 20 ++ 6 files changed, 304 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
@@ -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: July 2024 +KernelVersion: 6.10 +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: July 2024 KernelVersion: 6.10
drivers/platform/cznic/Kconfig +4 -0
@@ -19,10 +19,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
@@ -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
@@ -195,6 +195,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 };
@@ -360,6 +361,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 +258 -0
258 lines not on this page · raw message
drivers/platform/cznic/turris-omnia-mcu.h +20 -0
@@ -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 omnia_mcu {struct i2c_client *client;
@@ -34,6 +36,11 @@ struct omnia_mcu {struct delayed_work button_release_emul_work;u16 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,
@@ -46,6 +53,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) {
@@ -107,7 +125,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.43.2
Marek Behún
maintainerPATCH v8 5/9 platform: cznic: turris-omnia-mcu: Add support for MCU watchdog
In reply to Marek BehúnAdd 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 | 123 ++++++++++++++++++ drivers/platform/cznic/turris-omnia-mcu.h | 24 ++++ 5 files changed, 154 insertions(+) create mode 100644 drivers/platform/cznic/turris-omnia-mcu-watchdog.c
drivers/platform/cznic/Kconfig +2 -0
@@ -20,6 +20,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.
@@ -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) + - 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
@@ -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
@@ -365,6 +365,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 +123 -0
123 lines not on this page · raw message
drivers/platform/cznic/turris-omnia-mcu.h +24 -0
@@ -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>
@@ -41,6 +42,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,
@@ -53,6 +57,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) {
@@ -129,5 +152,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.43.2
Marek Behún
maintainerPATCH v8 6/9 platform: cznic: turris-omnia-mcu: Add support for MCU provided TRNG
In reply to Marek BehúnAdd 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 | 101 ++++++++++++++++++ drivers/platform/cznic/turris-omnia-mcu.h | 8 ++ 6 files changed, 118 insertions(+), 2 deletions(-) create mode 100644 drivers/platform/cznic/turris-omnia-mcu-trng.c
drivers/platform/cznic/Kconfig +2 -0
@@ -19,6 +19,7 @@ config TURRIS_OMNIA_MCU depends on I2C select GPIOLIB select GPIOLIB_IRQCHIP + select HW_RANDOM select RTC_CLASS select WATCHDOG_CORE help
@@ -28,6 +29,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
@@ -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
@@ -369,7 +369,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
@@ -163,7 +163,7 @@ static const struct omnia_gpio { };/* 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 (INT_CARD_DET )] =4 , [__bf_shf (INT_MSATA_IND )] =5 , [__bf_shf (INT_USB30_OVC )] =6 ,
drivers/platform/cznic/turris-omnia-mcu-trng.c new file +101 -0
101 lines not on this page · raw message
drivers/platform/cznic/turris-omnia-mcu.h +8 -0
@@ -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>
@@ -45,6 +47,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,
@@ -147,11 +153,13 @@ static inline int omnia_cmd_read_u8(const struct i2c_client *client, u8 cmd) return err ?: 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.43.2
Marek Behún
maintainerPATCH v8 7/9 platform: cznic: turris-omnia-mcu: Add support for digital message signing via debugfs
In reply to Marek BehúnAdd support for digital message signing with private key stored in the MCU. Boards with MKL MCUs have a NIST256p ECDSA private key created when manufactured. The private key is not readable from the MCU, but MCU allows for signing messages with it and retrieving the public key.
As described in a similar commit 50524d787de3 ("firmware:
turris-mox-rwtm: support ECDSA signatures via debugfs"):
The optimal solution would be to register an akcipher provider via kernel's crypto API, but crypto API does not yet support accessing akcipher API from userspace (and probably won't for some time, see
https://www.spinics.net/lists/linux-crypto/msg38388.html).
Therefore we add support for accessing this signature generation mechanism via debugfs for now, so that userspace can access it.
--- .../ABI/testing/debugfs-turris-omnia-mcu | 13 ++ .../sysfs-bus-i2c-devices-turris-omnia-mcu | 13 ++ MAINTAINERS | 1 + drivers/platform/cznic/Kconfig | 2 + drivers/platform/cznic/Makefile | 1 + .../platform/cznic/turris-omnia-mcu-base.c | 45 +++- .../platform/cznic/turris-omnia-mcu-debugfs.c | 207 ++++++++++++++++++ drivers/platform/cznic/turris-omnia-mcu.h | 23 ++ 8 files changed, 304 insertions(+), 1 deletion(-) create mode 100644 Documentation/ABI/testing/debugfs-turris-omnia-mcu create mode 100644 drivers/platform/cznic/turris-omnia-mcu-debugfs.c
Documentation/ABI/testing/debugfs-turris-omnia-mcu new file +13 -0
@@ -0,0 +1,13 @@ +What: /sys/kernel/debug/turris-omnia-mcu/do_sign +Date: July 2024 +KernelVersion: 6.10 +Contact: Marek Behún <[email protected]> +Description: + + ======= =========================================================== + (Write) Message to sign with the ECDSA private key stored in MCU. + The message must be exactly 32 bytes long (since this is + intended to be a SHA-256 hash). + (Read) The resulting signature, 64 bytes. This contains the R and + S values of the ECDSA signature, both in big-endian format. + ======= ===========================================================
Documentation/ABI/testing/sysfs-bus-i2c-devices-turris-omnia-mcu +13 -0
@@ -90,6 +90,19 @@ Description: (RO) Contains the microcontroller type (STM32, GD32, MKL). Format: %s. +What: /sys/bus/i2c/devices/<mcu_device>/public_key +Date: July 2024 +KernelVersion: 6.10 +Contact: Marek Behún <[email protected]> +Description: (RO) Contains board ECDSA public key. + + Only available if MCU supports signing messages with the ECDSA + algorithm. If so, the board has a private key stored in the MCU + that was generated during manufacture and cannot be retrieved + from the MCU. + + Format: %s. + What: /sys/bus/i2c/devices/<mcu_device>/reset_selector Date: July 2024 KernelVersion: 6.10
MAINTAINERS +1 -0
@@ -2139,6 +2139,7 @@ M: Marek Behún <[email protected]> S: Maintained W: https://www.turris.cz/ F: Documentation/ABI/testing/debugfs-moxtet +F: Documentation/ABI/testing/debugfs-turris-omnia-mcu 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
drivers/platform/cznic/Kconfig +2 -0
@@ -30,6 +30,8 @@ config TURRIS_OMNIA_MCU disabled) and the ability to configure wake up from this mode (via rtcwake) - true random number generator (if available on the MCU) + - ECDSA message signing with board private key (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
@@ -6,3 +6,4 @@ 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 +turris-omnia-mcu-$(CONFIG_DEBUG_FS) += turris-omnia-mcu-debugfs.o
drivers/platform/cznic/turris-omnia-mcu-base.c +44 -1
81 lines not on this page · raw message
drivers/platform/cznic/turris-omnia-mcu-debugfs.c new file +207 -0
207 lines not on this page · raw message
drivers/platform/cznic/turris-omnia-mcu.h +23 -0
@@ -21,6 +21,9 @@#include <asm/byteorder.h> #include <asm/unaligned.h> +#define OMNIA_MCU_CRYPTO_PUBLIC_KEY_LEN 33 +#define OMNIA_MCU_CRYPTO_SIGNATURE_LEN 64 +struct omnia_mcu {struct i2c_client *client;const char *type;
@@ -30,6 +33,7 @@ struct omnia_mcu {u64 board_serial_number;u8 board_first_mac[ETH_ALEN ];u8 board_revision; +u8 board_public_key[OMNIA_MCU_CRYPTO_PUBLIC_KEY_LEN ];/* GPIO chip */ struct gpio_chip gc;
@@ -51,6 +55,16 @@ struct omnia_mcu {/* true random number generator */ struct hwrng trng;struct completion trng_completion; + +#ifdef CONFIG_DEBUG_FS +/* MCU ECDSA message signing via debugfs */ +struct dentry *debugfs_root; +struct completion msg_signed_completion; +struct mutex sign_lock; +unsigned int sign_state; +u8 signature[OMNIA_MCU_CRYPTO_SIGNATURE_LEN ]; +int sign_err; +#endif }; int omnia_cmd_write_read(const struct i2c_client *client,
@@ -162,4 +176,13 @@ 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); +#ifdef CONFIG_DEBUG_FS +int omnia_mcu_register_debugfs (struct omnia_mcu *mcu); +#else +static inline int omnia_mcu_register_debugfs (struct omnia_mcu *mcu) +{ +return 0 ; +} +#endif +#endif /* __TURRIS_OMNIA_MCU_H */
Signature · 1 line
2.43.2
Marek Behún
maintainerPATCH v8 8/9 ARM: dts: turris-omnia: Add MCU system-controller node
In reply to Marek BehúnTurris 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
@@ -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.43.2
Marek Behún
maintainerPATCH v8 9/9 ARM: dts: turris-omnia: Add GPIO key node for front button
In reply to Marek BehúnNow 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
@@ -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.43.2