Turris Omnia MCU driver
Subsystems (16)
Marek Behún
maintainerv5 cover Turris Omnia MCU driver
Hello Andy, Linus, Arnd, Gregory, and others,
I am sending v5 of the series adding Turris Omnia MCU driver. See the cover letters for v1, v2, v3 and v4:
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 v4:
- added new patches
06/11 devm-helpers: Add resource managed version of irq_create_mapping() 07/11 platform: cznic: turris-omnia-mcu: Add support for MCU provided TRNG 08/11 devm-helpers: Add resource managed version of debugfs directory create
function
09/11 platform: cznic: turris-omnia-mcu: Add support for digital message
signing via debugfs
- for changes specific to patches which were also sent in previous versions see the notes in those patches
Marek Behún (11):
dt-bindings: arm: 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
devm-helpers: Add resource managed version of irq_create_mapping()
platform: cznic: turris-omnia-mcu: Add support for MCU provided TRNG
devm-helpers: Add resource managed version of debugfs directory create
function
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 ++ .../bindings/arm/cznic,turris-omnia-mcu.yaml | 86 ++ MAINTAINERS | 5 + .../dts/marvell/armada-385-turris-omnia.dts | 35 +- drivers/crypto/caam/ctrl.c | 16 +- drivers/crypto/caam/jr.c | 8 +- drivers/gpio/gpio-mockup.c | 11 +- drivers/gpu/drm/bridge/ti-sn65dsi86.c | 13 +- drivers/hwmon/hp-wmi-sensors.c | 15 +- drivers/hwmon/mr75203.c | 15 +- drivers/hwmon/pmbus/pmbus_core.c | 16 +- drivers/platform/Kconfig | 2 + drivers/platform/Makefile | 1 + drivers/platform/cznic/Kconfig | 51 + drivers/platform/cznic/Makefile | 10 + .../platform/cznic/turris-omnia-mcu-base.c | 406 +++++++ .../platform/cznic/turris-omnia-mcu-debugfs.c | 216 ++++ .../platform/cznic/turris-omnia-mcu-gpio.c | 1056 +++++++++++++++++ .../cznic/turris-omnia-mcu-sys-off-wakeup.c | 258 ++++ .../platform/cznic/turris-omnia-mcu-trng.c | 89 ++ .../cznic/turris-omnia-mcu-watchdog.c | 122 ++ drivers/platform/cznic/turris-omnia-mcu.h | 214 ++++ include/linux/devm-helpers.h | 94 ++ include/linux/turris-omnia-mcu-interface.h | 238 ++++ 25 files changed, 3044 insertions(+), 72 deletions(-) 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/arm/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 v5 1/11 dt-bindings: arm: 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.
---
Changes from v4:
- #gpio-cells changed from 2 (pin number, flags) to 3 (bank, pin number, flags). This is because two years ago we added device-tree fixing code into U-Boot [1] which adds reset-gpios to PCIe controller nodes if these GPIOs are controllable via MCU, and the code adds the gpio specifiers to have 3 cells. Implementing this driver with twocell specifier breaks PCIe functionality for users which have upgraded U-Boot
- added documentation for #interrupt-cells and #gpio-cells
[1] https://source.denx.de/u-boot/u-boot/-/commit/1da53ae26afc
--- .../bindings/arm/cznic,turris-omnia-mcu.yaml | 86 +++++++++++++++++++ MAINTAINERS | 1 + 2 files changed, 87 insertions(+) create mode 100644 Documentation/devicetree/bindings/arm/cznic,turris-omnia-mcu.yaml
Documentation/devicetree/bindings/arm/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/arm/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
@@ -2141,6 +2141,7 @@ W: https://www.turris.cz/ F: Documentation/ABI/testing/debugfs-moxtet F: Documentation/ABI/testing/sysfs-bus-moxtet-devices F: Documentation/ABI/testing/sysfs-firmware-turris-mox-rwtm +F: Documentation/devicetree/bindings/arm/cznic,turris-omnia-mcu.yaml F: Documentation/devicetree/bindings/bus/moxtet.txt F: Documentation/devicetree/bindings/firmware/cznic,turris-mox-rwtm.txt F: Documentation/devicetree/bindings/gpio/gpio-moxtet.txt
Signature · 1 line
2.43.2
Re: [PATCH v5 01/11] dt-bindings: arm: add cznic,turris-omnia-mcu binding
Quoted 6 lines · Marek Behún
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.
Signed-off-by Marek Behún <[email protected]>Reviewed-by Krzysztof Kozlowski <[email protected]>
Quoted 10 lines
---
Changes from v4:
- #gpio-cells changed from 2 (pin number, flags) to 3 (bank, pin number, flags). This is because two years ago we added device-tree fixing code into U-Boot [1] which adds reset-gpios to PCIe controller nodes if these GPIOs are controllable via MCU, and the code adds the gpio specifiers to have 3 cells. Implementing this driver with twocell specifier breaks PCIe functionality for users which have upgraded U-Boot
- added documentation for #interrupt-cells and #gpio-cells
Please use scripts/get_maintainers.pl to get a list of necessary people and lists to CC. It might happen, that command when run on an older kernel, gives you outdated entries. Therefore please be sure you base your patches on recent Linux kernel.
Tools like b4 or scripts/get_maintainer.pl provide you proper list of people, so fix your workflow. Tools might also fail if you work on some ancient tree (don't, instead use mainline), work on fork of kernel (don't, instead use mainline) or you ignore some maintainers (really don't). Just use b4 and everything should be fine, although remember about b4 prep --auto-to-cc if you added new patches to the patchset.
You missed at least devicetree list (maybe more), so this won't be tested by automated tooling. Performing review on untested code might be a waste of time, thus I will skip this patch entirely till you follow the process allowing the patch to be tested.
Please kindly resend and include all necessary To/Cc entries.
Best regards,
Krzysztof
Marek Behún
maintainerRe: [PATCH v5 01/11] dt-bindings: arm: add cznic,turris-omnia-mcu binding
Quoted 35 lines · On Tue, 26 Mar 2024 09:45:00 +0100 Krzysztof Kozlowski <[email protected]> wrote:
Quoted 6 lines · Marek Behún
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.
Signed-off-by Marek Behún <[email protected]>Reviewed-by Krzysztof Kozlowski <[email protected]>Quoted 10 lines
---
Changes from v4:
- #gpio-cells changed from 2 (pin number, flags) to 3 (bank, pin number, flags). This is because two years ago we added device-tree fixing code into U-Boot [1] which adds reset-gpios to PCIe controller nodes if these GPIOs are controllable via MCU, and the code adds the gpio specifiers to have 3 cells. Implementing this driver with twocell specifier breaks PCIe functionality for users which have upgraded U-Boot
- added documentation for #interrupt-cells and #gpio-cellsPlease use
scripts/get_maintainers.plto get a list of necessary people and lists to CC. It might happen, that command when run on an older kernel, gives you outdated entries. Therefore please be sure you base your patches on recent Linux kernel.Tools like b4 or
scripts/get_maintainer.plprovide you proper list of people, so fix your workflow. Tools might also fail if you work on some ancient tree (don't, instead use mainline), work on fork of kernel (don't, instead use mainline) or you ignore some maintainers (really don't). Just use b4 and everything should be fine, although remember aboutb4 prep --auto-to-ccif you added new patches to the patchset.You missed at least devicetree list (maybe more), so this won't be tested by automated tooling. Performing review on untested code might be a waste of time, thus I will skip this patch entirely till you follow the process allowing the patch to be tested.
Quoted 5 lines
Please kindly resend and include all necessary To/Cc entries.
Best regards,
Krzysztof
Will do in v5.
Marek
Marek Behún
maintainerPATCH v5 2/11 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.
---
Changes since v4:
- added board information reading code and new sysfs files: board_revision, first_mac_address and serial_number. These are present if the MCU firmware supports the FEAT_BOARD_INFO feature, which is a new feature implemented for boards where MCU is also responsible for board information
--- .../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 | 349 ++++++++++++++++++ drivers/platform/cznic/turris-omnia-mcu.h | 71 ++++ include/linux/turris-omnia-mcu-interface.h | 238 ++++++++++++ 9 files changed, 775 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/arm/cznic,turris-omnia-mcu.yaml
@@ -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-objs := turris-omnia-mcu-base.o
drivers/platform/cznic/turris-omnia-mcu-base.c new file +349 -0
349 lines not on this page · raw message
drivers/platform/cznic/turris-omnia-mcu.h new file +71 -0
71 lines not on this page · raw message
include/linux/turris-omnia-mcu-interface.h new file +238 -0
238 lines not on this page · raw message
Signature · 1 line
2.43.2
Re: [PATCH v5 02/11] platform: cznic: Add preliminary support for Turris Omnia MCU
Sat, Mar 23, 2024 at 05:43:50PM +0100, Marek Behún kirjoitti:
Quoted 2 lines
Add the basic skeleton for a new platform driver for the microcontroller found on the Turris Omnia board.
...
drivers/platform/cznic/Makefile line 4
Quoted 6 lines
+++ b/drivers/platform/cznic/Makefile
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-objs := turris-omnia-mcu-base.o
'objs' is for user space. You need to use 'y'. Same applies to the entire series.
...
+ array_size.h
+ bits.h
drivers/platform/cznic/turris-omnia-mcu-base.c line 13
Quoted 6 lines
drivers/platform/cznic/turris-omnia-mcu-base.c new file +6
-0+#include <linux/device.h> +#include <linux/hex.h> +#include <linux/i2c.h> +#include <linux/module.h> +#include <linux/turris-omnia-mcu-interface.h> +#include <linux/types.h>
+ string.h
Quoted 1 line
+#include <
linux/sysfs.h>
...
drivers/platform/cznic/turris-omnia-mcu-base.c line 30
Quoted 3 lines
drivers/platform/cznic/turris-omnia-mcu-base.c new file +3
-0+ err =omnia_cmd_read (mcu->client, bootloader ?CMD_GET_FW_VERSION_BOOT : +CMD_GET_FW_VERSION_APP , + reply,sizeof (reply));
Wouldn't be better to have a logical split?
err = omnia_cmd_read(mcu->client, bootloader ? CMD_GET_FW_VERSION_BOOT : CMD_GET_FW_VERSION_APP, reply, sizeof(reply));
?
...
Review
Quoted 1 line
(quoted diff) +1
-0+ struct omnia_mcu *mcu = i2c_get_clientdata(to_i2c_client(dev));
What's wrong with dev_get_drvdata()?
...
Review
Quoted 2 lines
(quoted diff) +2
-0+static ssize_t fw_features_show(struct device *dev, struct device_attribute *a, + char *buf)
One line?
...
Review
Quoted 1 line
(quoted diff) +1
-0+ struct omnia_mcu *mcu = i2c_get_clientdata(to_i2c_client(dev));
Use direct call (see above). Same applies to all such constructions in your code.
...
drivers/platform/cznic/turris-omnia-mcu-base.c line 164
Quoted 9 lines
drivers/platform/cznic/turris-omnia-mcu-base.c new file +9
-0+static const struct attribute_group omnia_mcu_base_group = { + .attrs = omnia_mcu_base_attrs, + .is_visible = omnia_mcu_base_attrs_visible, +}; + +static const struct attribute_group *omnia_mcu_groups[] = { + &omnia_mcu_base_group, +NULL +};
__ATTRIBUTE_GROUPS()
...
drivers/platform/cznic/turris-omnia-mcu-base.c line 344
Quoted 10 lines
drivers/platform/cznic/turris-omnia-mcu-base.c new file +9
-0+static struct i2c_driver omnia_mcu_driver = { + .probe = omnia_mcu_probe, + .driver = { + .name ="turris-omnia-mcu" , + .of_match_table = of_omnia_mcu_match, + .dev_groups = omnia_mcu_groups, + }, +}; +
Redundant blank line.
Quoted 1 line
+module_i2c_driver(omnia_mcu_driver);
...
drivers/platform/cznic/turris-omnia-mcu.h line 9
Quoted 2 lines
drivers/platform/cznic/turris-omnia-mcu.h new file +2
-0+#ifndef __TURRIS_OMNIA_MCU_H +#define __TURRIS_OMNIA_MCU_H
+ array_size.h
Quoted 4 lines
drivers/platform/cznic/turris-omnia-mcu.h new file +4
-0+#include <linux/i2c.h> +#include <linux/if_ether.h> +#include <linux/types.h> +#include <asm/byteorder.h>
...
drivers/platform/cznic/turris-omnia-mcu.h line 29
Quoted 3 lines
drivers/platform/cznic/turris-omnia-mcu.h new file +3
-0+static inline int omnia_cmd_read (const struct i2c_client *client,u8 cmd, +void *reply,unsigned int len) +{
Why is this in the header?
Quoted 20 lines
drivers/platform/cznic/turris-omnia-mcu.h new file +20
-0+struct i2c_msg msgs[2 ]; +int ret; + + 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)); +if (ret <0 ) +return ret; +if (ret !=ARRAY_SIZE (msgs)) +return -EIO ; + +return 0 ; +}
...
include/linux/turris-omnia-mcu-interface.h line 11
Quoted 4 lines
include/linux/turris-omnia-mcu-interface.h new file +4
-0+#ifndef __TURRIS_OMNIA_MCU_INTERFACE_H +#define __TURRIS_OMNIA_MCU_INTERFACE_H + +#include <linux/bits.h>
+ bitfield.h
Quoted 1 line
+#endif /*
__TURRIS_OMNIA_MCU_INTERFACE_H*/
Signature · 2 lines
With Best Regards, Andy Shevchenko
Marek Behún
maintainerRe: [PATCH v5 02/11] platform: cznic: Add preliminary support for Turris Omnia MCU
Hi Andy,
thank you very much for the review. I have some notes and some questions, see below.
Quoted 6 lines · On Sun, 24 Mar 2024 13:01:55 +0200 Andy Shevchenko <[email protected]>…
Sat, Mar 23, 2024 at 05:43:50PM +0100, Marek Behún kirjoitti:
Quoted 2 lines
Add the basic skeleton for a new platform driver for the microcontroller found on the Turris Omnia board.
...
Quoted 9 lines
drivers/platform/cznic/Makefile line 4
Quoted 6 lines
+++ b/drivers/platform/cznic/Makefile
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-objs := turris-omnia-mcu-base.o'objs' is for user space. You need to use 'y'. Same applies to the entire series.
Fixed for v6.
Quoted 3 lines
+
array_size.h
+bits.h
Fixed for v6. Is there some tool for this?
Quoted 1 line
+
string.h
Fixed for v6.
Quoted 11 lines
Quoted 2 lines
+#include <
linux/sysfs.h>...
drivers/platform/cznic/turris-omnia-mcu-base.c line 30
Quoted 3 lines
drivers/platform/cznic/turris-omnia-mcu-base.c new file +3
-0+ err =omnia_cmd_read (mcu->client, bootloader ?CMD_GET_FW_VERSION_BOOT : +CMD_GET_FW_VERSION_APP , + reply,sizeof (reply));Wouldn't be better to have a logical split?
Quoted 3 lines
err = omnia_cmd_read(mcu->client, bootloader ? CMD_GET_FW_VERSION_BOOT : CMD_GET_FW_VERSION_APP, reply, sizeof(reply));
Changed for v6 to
Quoted 4 lines
err = omnia_cmd_read(mcu->client, bootloader ? CMD_GET_FW_VERSION_BOOT : CMD_GET_FW_VERSION_APP, reply, sizeof(reply));
There are still some people wanting only 80 columns, and the whole driver is written that way.
Quoted 8 lines
?
...
Review
Quoted 1 line
(quoted diff) +1
-0+ struct omnia_mcu *mcu = i2c_get_clientdata(to_i2c_client(dev));What's wrong with
dev_get_drvdata()?
Fixed for v6.
Quoted 6 lines
...
Review
Quoted 2 lines
(quoted diff) +2
-0+static ssize_t fw_features_show(struct device *dev, struct device_attribute *a, + char *buf)One line?
80 columns...
...
Quoted 11 lines
drivers/platform/cznic/turris-omnia-mcu-base.c line 164
Quoted 9 lines
drivers/platform/cznic/turris-omnia-mcu-base.c new file +9
-0+static const struct attribute_group omnia_mcu_base_group = { + .attrs = omnia_mcu_base_attrs, + .is_visible = omnia_mcu_base_attrs_visible, +}; + +static const struct attribute_group *omnia_mcu_groups[] = { + &omnia_mcu_base_group, +NULL +};
__ATTRIBUTE_GROUPS()
The next patches add more groups into this array, after the whole series it looks like this:
static const struct attribute_group *omnia_mcu_groups[] = {
&omnia_mcu_base_group, &omnia_mcu_gpio_group, &omnia_mcu_poweroff_group,
NULL
};
There is no macro for that. Should I still use __ATTRIBUTE_GROUPS() in the first patch and than change it in the next one?
Quoted 12 lines
...
Quoted 8 lines
drivers/platform/cznic/turris-omnia-mcu-base.c new file +8
-0+static struct i2c_driver omnia_mcu_driver = { + .probe = omnia_mcu_probe, + .driver = { + .name ="turris-omnia-mcu" , + .of_match_table = of_omnia_mcu_match, + .dev_groups = omnia_mcu_groups, + }, +};
Quoted 4 lines
Quoted 1 line
+
Redundant blank line.
Fixed for v6.
Quoted 8 lines
Quoted 1 line
+module_i2c_driver(omnia_mcu_driver);
...
drivers/platform/cznic/turris-omnia-mcu.h line 9
Quoted 2 lines
drivers/platform/cznic/turris-omnia-mcu.h new file +2
-0+#ifndef __TURRIS_OMNIA_MCU_H +#define __TURRIS_OMNIA_MCU_H+
array_size.h
Fixed for v6.
Quoted 8 lines
Quoted 5 lines
drivers/platform/cznic/turris-omnia-mcu.h new file +4
-0+#include <linux/i2c.h> +#include <linux/if_ether.h> +#include <linux/types.h> +#include <asm/byteorder.h> ...
Quoted 5 lines
drivers/platform/cznic/turris-omnia-mcu.h line 29
Quoted 3 lines
drivers/platform/cznic/turris-omnia-mcu.h new file +3
-0+static inline int omnia_cmd_read (const struct i2c_client *client,u8 cmd, +void *reply,unsigned int len) +{Why is this in the header?
I considered it a helper function that should be defined in the header file, like the rest of the cmd helpers in this file. If you disagree, I will put it into the -base.c file.
Quoted 24 lines
Quoted 21 lines
drivers/platform/cznic/turris-omnia-mcu.h new file +20
-0+struct i2c_msg msgs[2 ]; +int ret; + + 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)); +if (ret <0 ) +return ret; +if (ret !=ARRAY_SIZE (msgs)) +return -EIO ; + +return 0 ; +}...
Quoted 6 lines
include/linux/turris-omnia-mcu-interface.h line 11
Quoted 4 lines
include/linux/turris-omnia-mcu-interface.h new file +4
-0+#ifndef __TURRIS_OMNIA_MCU_INTERFACE_H +#define __TURRIS_OMNIA_MCU_INTERFACE_H + +#include <linux/bits.h> +
bitfield.h
Fixed for v6.
Quoted 3 lines
Quoted 2 lines
+#endif /*
__TURRIS_OMNIA_MCU_INTERFACE_H*/
Re: [PATCH v5 02/11] platform: cznic: Add preliminary support for Turris Omnia MCU
Quoted 5 lines · Marek Behún
Hi Andy,
thank you very much for the review. I have some notes and some questions, see below.
Btw, I'll look into other patches next week.
Quoted 3 lines
Quoted 1 line · On Sun, 24 Mar 2024 13:01:55 +0200 Andy Shevchenko <[email protected]>…
Sat, Mar 23, 2024 at 05:43:50PM +0100, Marek Behún kirjoitti:
...
Quoted 12 lines
Quoted 9 lines
drivers/platform/cznic/turris-omnia-mcu-base.c line 30
Quoted 3 lines
drivers/platform/cznic/turris-omnia-mcu-base.c new file +3
-0+ err =omnia_cmd_read (mcu->client, bootloader ?CMD_GET_FW_VERSION_BOOT : +CMD_GET_FW_VERSION_APP , + reply,sizeof (reply));Wouldn't be better to have a logical split?
err = omnia_cmd_read(mcu->client, bootloader ? CMD_GET_FW_VERSION_BOOT : CMD_GET_FW_VERSION_APP, reply, sizeof(reply));Changed for v6 to
Quoted 7 lines
Quoted 4 lines
err = omnia_cmd_read(mcu->client, bootloader ? CMD_GET_FW_VERSION_BOOT : CMD_GET_FW_VERSION_APP, reply, sizeof(reply));There are still some people wanting only 80 columns, and the whole driver is written that way.
Hmm... Is it still a hard limit for drivers/platform/cznic for the _new_ code?
Quoted 1 line
Quoted 1 line
?
...
Quoted 6 lines
Quoted 4 lines
Review
Quoted 2 lines
(quoted diff) +2
-0+static ssize_t fw_features_show(struct device *dev, struct device_attribute *a, + char *buf)One line?
80 columns...
Ditto.
...
Quoted 10 lines
Quoted 6 lines
drivers/platform/cznic/turris-omnia-mcu-base.c line 164
Quoted 4 lines
drivers/platform/cznic/turris-omnia-mcu-base.c new file +4
-0+static const struct attribute_group *omnia_mcu_groups[] = { + &omnia_mcu_base_group, +NULL +};
__ATTRIBUTE_GROUPS()The next patches add more groups into this array, after the whole series it looks like this:
Quoted 8 lines
static const struct
attribute_group*omnia_mcu_groups[] = {
&omnia_mcu_base_group,&omnia_mcu_gpio_group,&omnia_mcu_poweroff_group,
NULL
};There is no macro for that.
Good point.
Quoted 2 lines
Should I still use
__ATTRIBUTE_GROUPS()in the first patch and than change it in the next one?
...
Quoted 9 lines
Quoted 5 lines
drivers/platform/cznic/turris-omnia-mcu.h line 29
Quoted 3 lines
drivers/platform/cznic/turris-omnia-mcu.h new file +3
-0+static inline int omnia_cmd_read (const struct i2c_client *client,u8 cmd, +void *reply,unsigned int len) +{Why is this in the header?
I considered it a helper function that should be defined in the header file, like the rest of the cmd helpers in this file. If you disagree, I will put it into the
-base.cfile.
I don't see the technical justification to hold it in the *.h rather than *.c. To me this one is big enough in C and likely in assembly to be copied to each user. Besides that aspect, it slows down the build a lot (mostly due to i2c.h inclusion which otherwise is not needed).
Quoted 20 lines
Quoted 20 lines
Quoted 20 lines
drivers/platform/cznic/turris-omnia-mcu.h new file +20
-0+struct i2c_msg msgs[2 ]; +int ret; + + 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)); +if (ret <0 ) +return ret; +if (ret !=ARRAY_SIZE (msgs)) +return -EIO ; + +return 0 ; +}
Signature · 2 lines
With Best Regards, Andy Shevchenko
Marek Behún
maintainerRe: [PATCH v5 02/11] platform: cznic: Add preliminary support for Turris Omnia MCU
Quoted 8 lines · On Sun, 24 Mar 2024 17:30:39 +0200 Andy Shevchenko <[email protected]>…
Quoted 5 lines · Marek Behún
Hi Andy,
thank you very much for the review. I have some notes and some questions, see below.
Btw, I'll look into other patches next week.
Thx.
...
Quoted 5 lines
Quoted 3 lines
There are still some people wanting only 80 columns, and the whole driver is written that way.
Hmm... Is it still a hard limit for
drivers/platform/cznicfor the _new_ code?
I don't think so, but I personally would also prefer leaving this at 80 columns. Is this a problem?
Quoted 8 lines
Quoted 3 lines
I considered it a helper function that should be defined in the header file, like the rest of the cmd helpers in this file. If you disagree, I will put it into the
-base.cfile.I don't see the technical justification to hold it in the *.h rather than *.c. To me this one is big enough in C and likely in assembly to be copied to each user. Besides that aspect, it slows down the build a lot (mostly due to
i2c.hinclusion which otherwise is not needed).
OK, I moved it into -base.c.
Marek
Re: [PATCH v5 02/11] platform: cznic: Add preliminary support for Turris Omnia MCU
In reply to Andy ShevchenkoQuoted 8 lines · Andy Shevchenko
Quoted 5 lines · Marek Behún
Hi Andy,
thank you very much for the review. I have some notes and some questions, see below.
Btw, I'll look into other patches next week.
Hello Andy,
did you have a chance to look at the other patches?
Marek
Marek Behún
maintainerPATCH v5 3/11 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
---
Changes since v4:
- added definitions of TRNG and MESSAGE_SIGNED interrupts into the omnia_gpios array. These interrupts are for features supported in versions of MCU firmware
- changed OF gpio translation from default (twocell) to driver specific (threecell), for more information see the changes note in patch 01/11
--- .../sysfs-bus-i2c-devices-turris-omnia-mcu | 16 + drivers/platform/cznic/Kconfig | 15 + drivers/platform/cznic/Makefile | 1 + .../platform/cznic/turris-omnia-mcu-base.c | 3 +- .../platform/cznic/turris-omnia-mcu-gpio.c | 1056 +++++++++++++++++ drivers/platform/cznic/turris-omnia-mcu.h | 61 + 6 files changed, 1151 insertions(+), 1 deletion(-) create mode 100644 drivers/platform/cznic/turris-omnia-mcu-gpio.c
Documentation/ABI/testing/sysfs-bus-i2c-devices-turris-omnia-mcu +16 -0
@@ -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-objs := turris-omnia-mcu-base.o +turris-omnia-mcu-objs += turris-omnia-mcu-gpio.o
drivers/platform/cznic/turris-omnia-mcu-base.c +2 -1
@@ -160,6 +160,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 };
@@ -325,7 +326,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 +1056 -0
1,056 lines not on this page · raw message
drivers/platform/cznic/turris-omnia-mcu.h +61 -0
88 lines not on this page · raw message
Signature · 1 line
2.43.2
Matti Vaittinen
reviewerRe: [PATCH v5 03/11] platform: cznic: turris-omnia-mcu: Add support for MCU connected GPIOs
Hi Marek,
I can't say I did a proper review but browsing through the code without proper understanding of the platform raised one small question :)
Quoted 11 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 pinSigned-off-by Marek Behún <[email protected]>
...
Quoted 7 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
+ *
+ * Interleaves the little-endian bytes from @rising and @falling words.
This means the 'rising' and 'falling' should always be little-endian? Should the parameter types reflect this? Or should we see some cpu_to_le() calls? (Or, is this code just guaranteed to be always running on a le-machine?).
Quoted 26 lines
+ * 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
+ * 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 new file +14
-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); + } +} + +/** +* omnia_mask_deinterleave - Deinterleaves the bytes into @rising and @falling +* @src: the source u8 array containing the interleaved bytes +* @rising: pointer where to store the rising mask gathered from @src +* @falling: pointer where to store the falling mask gathered from @src +*
drivers/platform/cznic/turris-omnia-mcu-gpio.c line 621
Quoted 10 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +10
-0+* This is the inverse function to omnia_mask_interleave. +*/ +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); + }
Also here I could expect seeing le_to_cpu() unless I am (again :]) missing something.
Quoted 1 line
+}
Yours,
-- Matti
Signature · 5 lines
Matti Vaittinen Linux kernel developer at ROHM Semiconductors Oulu Finland ~~ When things go utterly wrong vim users can always type :help! ~~
Marek Behún
maintainerRe: [PATCH v5 03/11] platform: cznic: turris-omnia-mcu: Add support for MCU connected GPIOs
Quoted 63 lines · On Mon, 25 Mar 2024 11:10:04 +0200 Matti Vaittinen <[email protected]>…
Hi Marek,
I can't say I did a proper review but browsing through the code without proper understanding of the platform raised one small question :)
Quoted 11 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 pinSigned-off-by Marek Behún <[email protected]>...
Quoted 7 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
+ *
+ * Interleaves the little-endian bytes from @rising and @falling words.This means the 'rising' and 'falling' should always be little-endian? Should the parameter types reflect this? Or should we see some
cpu_to_le()calls? (Or, is this code just guaranteed to be always running on a le-machine?).Quoted 31 lines
+ * 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
+ * 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 new file +19
-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); + } +} + +/** +* omnia_mask_deinterleave - Deinterleaves the bytes into @rising and @falling +* @src: the source u8 array containing the interleaved bytes +* @rising: pointer where to store the rising mask gathered from @src +* @falling: pointer where to store the falling mask gathered from @src +* +* This is the inverse function to omnia_mask_interleave. +*/ +static void omnia_mask_deinterleave (const u8 *src,u32 *rising,u32 *falling) +{ + *rising = *falling =0 ;
Quoted 8 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c line 621
Quoted 5 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +5
-0+ +for (int i =0 ; i <sizeof (u32); ++i) { + *rising |= src[2 * i] << (8 * i); + *falling |= src[2 * i +1 ] << (8 * i); + }Also here I could expect seeing
le_to_cpu()unless I am (again :]) missing something.
I don't understand. The rising and falling variables have native endiannes, as they should have.
And the src and dst are u8 arrays, which contain two LE32 unsigned integers, but these integers are interleaved. I am converting then to two native unsigned integers byte by byte, so I am basically doing what a theoretical le32_interleaved_le32_to_cpu() would have done if it did exist. Putting another le*_to_cpu() would only break things.
Marek
Matti Vaittinen
reviewerRe: [PATCH v5 03/11] platform: cznic: turris-omnia-mcu: Add support for MCU connected GPIOs
Quoted 75 lines · Marek Behún
Quoted 63 lines · On Mon, 25 Mar 2024 11:10:04 +0200 Matti Vaittinen <[email protected]>…
Hi Marek,
I can't say I did a proper review but browsing through the code without proper understanding of the platform raised one small question :)
Quoted 11 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 pinSigned-off-by Marek Behún <[email protected]>...
Quoted 7 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
+ *
+ * Interleaves the little-endian bytes from @rising and @falling words.This means the 'rising' and 'falling' should always be little-endian? Should the parameter types reflect this? Or should we see some
cpu_to_le()calls? (Or, is this code just guaranteed to be always running on a le-machine?).Quoted 31 lines
+ * 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
+ * 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 new file +19
-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); + } +} + +/** +* omnia_mask_deinterleave - Deinterleaves the bytes into @rising and @falling +* @src: the source u8 array containing the interleaved bytes +* @rising: pointer where to store the rising mask gathered from @src +* @falling: pointer where to store the falling mask gathered from @src +* +* This is the inverse function to omnia_mask_interleave. +*/ +static void omnia_mask_deinterleave (const u8 *src,u32 *rising,u32 *falling) +{ + *rising = *falling =0 ;Quoted 8 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c line 621
Quoted 5 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +5
-0+ +for (int i =0 ; i <sizeof (u32); ++i) { + *rising |= src[2 * i] << (8 * i); + *falling |= src[2 * i +1 ] << (8 * i); + }Also here I could expect seeing
le_to_cpu()unless I am (again :]) missing something.
Quoted 2 lines
I don't understand. The rising and falling variables have native endiannes, as they should have.
So, it was the last option then :) I was missing something.
Quoted 5 lines
And the src and dst are u8 arrays, which contain two LE32 unsigned integers, but these integers are interleaved. I am converting then to two native unsigned integers byte by byte, so I am basically doing what a theoretical
le32_interleaved_le32_to_cpu()would have done if it did exist. Putting another le*_to_cpu() would only break things.
Thank you for the explanation. I commented way too hastily after a glance - missing the point you used shift and not u8 pointer to go through the 'rising' and 'falling' in interleave() - and the point that the result of deinterleave() was u8s. Very sorry for the noise.
Thanks for the patience!
Yours,
-- Matti
Signature · 5 lines
Matti Vaittinen Linux kernel developer at ROHM Semiconductors Oulu Finland ~~ When things go utterly wrong vim users can always type :help! ~~
Re: [PATCH v5 03/11] platform: cznic: turris-omnia-mcu: Add support for MCU connected GPIOs
In reply to Marek Behúndrivers/platform/cznic/turris-omnia-mcu-gpio.c line 929
Quoted 9 lines · Marek Behún
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +9
-0+static ssize_t front_button_mode_store (struct device *dev, +struct device_attribute *a, +const char *buf,size_t count) +{ +struct omnia_mcu *mcu =i2c_get_clientdata (to_i2c_client (dev)); +u8 mask, val; +int err, i; + + mask =CTL_BUTTON_MODE ;
No need for the mask variable. Just use CTL_BUTTON_MODE directly.
regards,
dan carpenter
Quoted 13 lines
drivers/platform/cznic/turris-omnia-mcu-gpio.c new file +13
-0+ + i =sysfs_match_string (front_button_modes, buf); +if (i <0 ) +return i; + + val = i ? mask :0 ; + err =omnia_ctl_cmd_locked (mcu,CMD_GENERAL_CONTROL , val, mask); +if (err) +return err; + +return count; +} +static DEVICE_ATTR_RW (front_button_mode);
Marek Behún
maintainerPATCH v5 4/11 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.
---
Changes since v4:
- the driver now registers the RTC with feature bit RTC_FEATURE_ALARM_WAKEUP_ONLY, as requested by Alexandre Belloni (see commit e99653afeb95 for explanation)
--- .../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-objs := turris-omnia-mcu-base.o turris-omnia-mcu-objs += turris-omnia-mcu-gpio.o +turris-omnia-mcu-objs += turris-omnia-mcu-sys-off-wakeup.o
drivers/platform/cznic/turris-omnia-mcu-base.c +5 -0
@@ -161,6 +161,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 };
@@ -326,6 +327,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
@@ -13,9 +13,11 @@#include <linux/i2c.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;
@@ -35,6 +37,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; }; static inline int omnia_cmd_write(const struct i2c_client *client, void *cmd,
@@ -47,6 +54,17 @@ static inline int omnia_cmd_write(const struct i2c_client *client, void *cmd,return ret <0 ? ret :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) {
@@ -126,7 +144,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 v5 5/11 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 | 122 ++++++++++++++++++ drivers/platform/cznic/turris-omnia-mcu.h | 24 ++++ 5 files changed, 153 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-objs := turris-omnia-mcu-base.o turris-omnia-mcu-objs += turris-omnia-mcu-gpio.o turris-omnia-mcu-objs += turris-omnia-mcu-sys-off-wakeup.o +turris-omnia-mcu-objs += turris-omnia-mcu-watchdog.o
drivers/platform/cznic/turris-omnia-mcu-base.c +4 -0
@@ -331,6 +331,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 +122 -0
122 lines not on this page · raw message
drivers/platform/cznic/turris-omnia-mcu.h +24 -0
@@ -15,6 +15,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>
@@ -42,6 +43,9 @@ struct omnia_mcu {struct rtc_device *rtcdev;u32 rtc_alarm;bool front_button_poweron; + +/* MCU watchdog */ +struct watchdog_device wdt; }; static inline int omnia_cmd_write(const struct i2c_client *client, void *cmd,
@@ -54,6 +58,25 @@ static inline int omnia_cmd_write(const struct i2c_client *client, void *cmd,return ret <0 ? ret :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) {
@@ -148,5 +171,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 v5 6/11 devm-helpers: Add resource managed version of irq_create_mapping()
In reply to Marek BehúnAdd resource managed version of irq_create_mapping(), to help drivers automatically dispose a linux irq mapping when driver is detached.
The new function devm_irq_create_mapping() is not yet used, but the action function can be used in the FSL CAAM driver.
--- drivers/crypto/caam/jr.c | 8 ++---- include/linux/devm-helpers.h | 54 ++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 6 deletions(-)
drivers/crypto/caam/jr.c +2 -6
@@ -7,6 +7,7 @@* Copyright 2019, 2023 NXP */ +#include <linux/devm-helpers.h> #include <linux/of_irq.h> #include <linux/of_address.h> #include <linux/platform_device.h>
@@ -576,11 +577,6 @@ static int caam_jr_init(struct device *dev)return error; } -static void caam_jr_irq_dispose_mapping (void *data) -{ -irq_dispose_mapping ((unsigned long )data); -} -/* * Probe routine for each detected JobR subsystem. */
@@ -656,7 +652,7 @@ static int caam_jr_probe(struct platform_device *pdev)return -EINVAL ; } - error =devm_add_action_or_reset (jrdev, caam_jr_irq_dispose_mapping, + error =devm_add_action_or_reset (jrdev, devm_irq_mapping_drop, (void *)(unsigned long )jrpriv->irq);if (error)return error;
include/linux/devm-helpers.h +54 -0
64 lines not on this page · raw message
Signature · 1 line
2.43.2
Matti Vaittinen
reviewerRe: [PATCH v5 06/11] devm-helpers: Add resource managed version of irq_create_mapping()
Quoted 50 lines · Marek Behún
Add resource managed version of
irq_create_mapping(), to help drivers automatically dispose a linux irq mapping when driver is detached.The new function
devm_irq_create_mapping()is not yet used, but the action function can be used in the FSL CAAM driver.Signed-off-by Marek Behún <[email protected]>--- drivers/crypto/caam/jr.c | 8 ++---- include/linux/devm-helpers.h | 54 ++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 6 deletions(-)drivers/crypto/caam/jr.c +2
-6@@ -7,6 +7,7 @@* Copyright 2019, 2023 NXP */ +#include <linux/devm-helpers.h> #include <linux/of_irq.h> #include <linux/of_address.h> #include <linux/platform_device.h> @@ -576,11 +577,6 @@ static int caam_jr_init(struct device *dev)return error; } -static void caam_jr_irq_dispose_mapping (void *data) -{ -irq_dispose_mapping ((unsigned long )data); -} -/* * Probe routine for each detected JobR subsystem. */ @@ -656,7 +652,7 @@ static int caam_jr_probe(struct platform_device *pdev)return -EINVAL ; } - error =devm_add_action_or_reset (jrdev, caam_jr_irq_dispose_mapping, + error =devm_add_action_or_reset (jrdev, devm_irq_mapping_drop, (void *)(unsigned long )jrpriv->irq);if (error)return error;include/linux/devm-helpers.h +0
-0
include/linux/devm-helpers.h line 29
Quoted 6 lines
include/linux/devm-helpers.h +2
-0@@ -24,6 +24,8 @@*/ #include <linux/device.h> +#include <linux/kconfig.h> +#include <linux/irqdomain.h> #include <linux/workqueue.h>
My confidence level is not terribly high today, so I am likely to accept just about any counter arguments :) But ... More I think of this whole header, less convinced I am that this (the header) is a great idea. I wonder who has authored a concept like this... :rolleyes:
Pulling punch of unrelated APIs (or, unrelated except the devm-usage) in one header has potential to be including a lot of unneeded stuff to the users. I am under impression this can be bad for example for the build times.
I think that ideally the devm-APIs should live close to their non-devm counterparts, and this header should be just used as a last resort, when all the other options fail :) May I assume all other options have failed for the IRQ stuff?
Well, I will leave the big picture to the bigger minds. When just looking at the important things like the function names and coding style - this change looks Ok to me ;)
Quoted 58 lines
include/linux/devm-helpers.h +52
-0static inline void devm_delayed_work_drop (void *res)@@ -76,4 +78,56 @@ static inline int devm_work_autocancel(struct device *dev, return devm_add_action(dev, devm_work_drop, w); } +/** +* devm_irq_mapping_drop - devm action for disposing an irq mapping +* @res: linux irq number cast to the void * type +* +* devm_irq_mapping_drop() can be used as an action parameter for the +* devm_add_action_or_reset() function in order to automatically dispose +* a linux irq mapping when a device driver is detached. +*/ +static inline void devm_irq_mapping_drop (void *res) +{ +irq_dispose_mapping ((unsigned int )(unsigned long )res); +} + +/** +* devm_irq_create_mapping - Resource managed version of irq_create_mapping() +* @dev: Device which lifetime the mapping is bound to +* @domain: domain owning this hardware interrupt or NULL for default domain +* @hwirq: hardware irq number in that domain space +* +* Create an irq mapping to linux irq space which is automatically disposed when +* the driver is detached. +* devm_irq_create_mapping() can be used to omit the explicit +* irq_dispose_mapping() call when driver is detached. +* +* Returns a linux irq number on success, 0 if mapping could not be created, or +* a negative error number if devm action could not be added. +*/ +static inline int devm_irq_create_mapping (struct device *dev, +struct irq_domain *domain, +irq_hw_number_t hwirq) +{ +unsigned int virq =irq_create_mapping (domain, hwirq); + +if (!virq) +return 0 ; + +/* +* irq_dispose_mapping() is an empty function if CONFIG_IRQ_DOMAIN is +* disabled. No need to register an action in that case. +*/ +if (IS_ENABLED (CONFIG_IRQ_DOMAIN )) { +int err; + + err =devm_add_action_or_reset (dev, devm_irq_mapping_drop, + (void *)(unsigned long )virq); +if (err) +return err; + } + +return virq; +} +#endif
Signature · 5 lines
Matti Vaittinen Linux kernel developer at ROHM Semiconductors Oulu Finland ~~ When things go utterly wrong vim users can always type :help! ~~
Marek Behún
maintainerRe: [PATCH v5 06/11] devm-helpers: Add resource managed version of irq_create_mapping()
Quoted 68 lines · On Mon, 25 Mar 2024 11:40:20 +0200 Matti Vaittinen <[email protected]>…
Quoted 50 lines · Marek Behún
Add resource managed version of
irq_create_mapping(), to help drivers automatically dispose a linux irq mapping when driver is detached.The new function
devm_irq_create_mapping()is not yet used, but the action function can be used in the FSL CAAM driver.Signed-off-by Marek Behún <[email protected]>--- drivers/crypto/caam/jr.c | 8 ++---- include/linux/devm-helpers.h | 54 ++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 6 deletions(-)drivers/crypto/caam/jr.c +2
-6@@ -7,6 +7,7 @@* Copyright 2019, 2023 NXP */ +#include <linux/devm-helpers.h> #include <linux/of_irq.h> #include <linux/of_address.h> #include <linux/platform_device.h> @@ -576,11 +577,6 @@ static int caam_jr_init(struct device *dev)return error; } -static void caam_jr_irq_dispose_mapping (void *data) -{ -irq_dispose_mapping ((unsigned long )data); -} -/* * Probe routine for each detected JobR subsystem. */ @@ -656,7 +652,7 @@ static int caam_jr_probe(struct platform_device *pdev)return -EINVAL ; } - error =devm_add_action_or_reset (jrdev, caam_jr_irq_dispose_mapping, + error =devm_add_action_or_reset (jrdev, devm_irq_mapping_drop, (void *)(unsigned long )jrpriv->irq);if (error)return error;include/linux/devm-helpers.h +0
-0include/linux/devm-helpers.h line 29
Quoted 6 lines
include/linux/devm-helpers.h +2
-0@@ -24,6 +24,8 @@*/ #include <linux/device.h> +#include <linux/kconfig.h> +#include <linux/irqdomain.h> #include <linux/workqueue.h> My confidence level is not terribly high today, so I am likely to accept just about any counter arguments :) But ... More I think of this whole header, less convinced I am that this (the header) is a great idea. I wonder who has authored a concept like this... :rolleyes:
Pulling punch of unrelated APIs (or, unrelated except the devm-usage) in one header has potential to be including a lot of unneeded stuff to the users. I am under impression this can be bad for example for the build times.
Quoted 8 lines
I think that ideally the devm-APIs should live close to their non-devm counterparts, and this header should be just used as a last resort, when all the other options fail :) May I assume all other options have failed for the IRQ stuff?
Well, I will leave the big picture to the bigger minds. When just looking at the important things like the function names and coding style
- this change looks Ok to me ;)
If the authors of devm-helpers or someone else decide it should not exist (due for example of long build times), I am OK with that.
But currently this seems to me to be the proper place to put this into.
Marek
Re: [PATCH v5 06/11] devm-helpers: Add resource managed version of irq_create_mapping()
In reply to Marek BehúnQuoted 4 lines · Marek Behún
+/**
+ *devm_irq_create_mapping- Resource managed version ofirq_create_mapping()
+ * @dev: Device which lifetime the mapping is bound to
+ * @domain: domain owning this hardware interrupt or NULL for default domain
Quoted 8 lines
+ * @hwirq: hardware irq number in that domain space
+ *
+ * Create an irq mapping to linux irq space which is automatically disposed when
+ * the driver is detached.
+ *devm_irq_create_mapping()can be used to omit the explicit
+ *irq_dispose_mapping()call when driver is detached.
+ *
+ * Returns a linux irq number on success, 0 if mapping could not be created, or
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
include/linux/devm-helpers.h static inline int devm_work_autocancel(struct device *dev, · line 115
Quoted 10 lines
+ * a negative error number if devm action could not be added.
+ */include/linux/devm-helpers.h +8
-0+static inline int devm_irq_create_mapping (struct device *dev, +struct irq_domain *domain, +irq_hw_number_t hwirq) +{ +unsigned int virq =irq_create_mapping (domain, hwirq); + +if (!virq) +return 0 ;
What is the point of returning zero instead of an error code? Neither of the callers that are introduced later in the patchset use this.
I understand that it matches some of the other legacy irq function behaviors, but I think we are trying to move away from that because it just leads to bugs.
Since we don't need the zero now, let's wait until we have a user before introducing this behavior. Then we can add a new function that returns zero, but we'll still encourage people to use the standard error code function where possible. And at the same time, when we do introduce the zero is an error code, function you should contact [email protected] so someone an write a static checker rule to detect the bugs that result from it.
regards,
dan carpenter
Quoted 21 lines
include/linux/devm-helpers.h +17
-0+ +/* +* irq_dispose_mapping() is an empty function if CONFIG_IRQ_DOMAIN is +* disabled. No need to register an action in that case. +*/ +if (IS_ENABLED (CONFIG_IRQ_DOMAIN )) { +int err; + + err =devm_add_action_or_reset (dev, devm_irq_mapping_drop, + (void *)(unsigned long )virq); +if (err) +return err; + } + + return virq; +} +#endif Signature · 1 line
2.43.2
Marek Behún
maintainerRe: [PATCH v5 06/11] devm-helpers: Add resource managed version of irq_create_mapping()
Quoted 33 lines · On Tue, 26 Mar 2024 12:00:25 +0300 Dan Carpenter <[email protected]>…
Quoted 4 lines · Marek Behún
+/**
+ *devm_irq_create_mapping- Resource managed version ofirq_create_mapping()
+ * @dev: Device which lifetime the mapping is bound to
+ * @domain: domain owning this hardware interrupt or NULL for default domainQuoted 8 lines
+ * @hwirq: hardware irq number in that domain space
+ *
+ * Create an irq mapping to linux irq space which is automatically disposed when
+ * the driver is detached.
+ *devm_irq_create_mapping()can be used to omit the explicit
+ *irq_dispose_mapping()call when driver is detached.
+ *
+ * Returns a linux irq number on success, 0 if mapping could not be created, or^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^include/linux/devm-helpers.h static inline int devm_work_autocancel(struct device *dev, · line 115
Quoted 10 lines
+ * a negative error number if devm action could not be added.
+ */include/linux/devm-helpers.h +8
-0+static inline int devm_irq_create_mapping (struct device *dev, +struct irq_domain *domain, +irq_hw_number_t hwirq) +{ +unsigned int virq =irq_create_mapping (domain, hwirq); + +if (!virq) +return 0 ;What is the point of returning zero instead of an error code? Neither of the callers that are introduced later in the patchset use this.
I understand that it matches some of the other legacy irq function behaviors, but I think we are trying to move away from that because it just leads to bugs.
Quoted 7 lines
Since we don't need the zero now, let's wait until we have a user before introducing this behavior. Then we can add a new function that returns zero, but we'll still encourage people to use the standard error code function where possible. And at the same time, when we do introduce the zero is an error code, function you should contact [email protected] so someone an write a static checker rule to detect the bugs that result from it.
Hi Dan,
the first user of this function is the very next patch of this series, and it does this:
+ irq = devm_irq_create_mapping(dev, mcu->gc.irq.domain, irq_idx);
+ if (irq <= 0)
+ return dev_err_probe(dev, irq ?: -ENXIO,
+ "Cannot map MESSAGE_SIGNED IRQ\n");
So it handles !irq as -ENXIO.
I looked into several users who do
virq = irq_create_mapping()
and then reutrn errno if !virq:
git grep -A 3 'virq = irq_create_mapping'
Some return -ENOMEM, some -ENXIO, some -EINVAL.
What do you think?
Or should I send this driver without introducing this helper for now?
Marek
Re: [PATCH v5 06/11] devm-helpers: Add resource managed version of irq_create_mapping()
Quoted 54 lines · Marek Behún
Quoted 33 lines · On Tue, 26 Mar 2024 12:00:25 +0300 Dan Carpenter <[email protected]>…
Quoted 4 lines · Marek Behún
+/**
+ *devm_irq_create_mapping- Resource managed version ofirq_create_mapping()
+ * @dev: Device which lifetime the mapping is bound to
+ * @domain: domain owning this hardware interrupt or NULL for default domainQuoted 8 lines
+ * @hwirq: hardware irq number in that domain space
+ *
+ * Create an irq mapping to linux irq space which is automatically disposed when
+ * the driver is detached.
+ *devm_irq_create_mapping()can be used to omit the explicit
+ *irq_dispose_mapping()call when driver is detached.
+ *
+ * Returns a linux irq number on success, 0 if mapping could not be created, or^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^include/linux/devm-helpers.h static inline int devm_work_autocancel(struct device *dev, · line 115
Quoted 10 lines
+ * a negative error number if devm action could not be added.
+ */include/linux/devm-helpers.h +8
-0+static inline int devm_irq_create_mapping (struct device *dev, +struct irq_domain *domain, +irq_hw_number_t hwirq) +{ +unsigned int virq =irq_create_mapping (domain, hwirq); + +if (!virq) +return 0 ;What is the point of returning zero instead of an error code? Neither of the callers that are introduced later in the patchset use this.
I understand that it matches some of the other legacy irq function behaviors, but I think we are trying to move away from that because it just leads to bugs.
Quoted 7 lines
Since we don't need the zero now, let's wait until we have a user before introducing this behavior. Then we can add a new function that returns zero, but we'll still encourage people to use the standard error code function where possible. And at the same time, when we do introduce the zero is an error code, function you should contact [email protected] so someone an write a static checker rule to detect the bugs that result from it.
Hi Dan,
the first user of this function is the very next patch of this series, and it does this:
(quoted diff) +4
-0+ irq = devm_irq_create_mapping(dev, mcu->gc.irq.domain, irq_idx); + if (irq <= 0) + return dev_err_probe(dev, irq ?: -ENXIO, + "Cannot map MESSAGE_SIGNED IRQ\n");
Quoted 1 line
So it handles !irq as
-ENXIO.
Yeah. But imagine how much easier it would be if devm_irq_create_mapping() returned -ENXIO directly.
irq = devm_irq_create_mapping(); if (irq < 0) return dev_err_probe(dev, irq, "Cannot map MESSAGE_SIGNED IRQ\n");
Quoted 10 lines
I looked into several users who do
virq =irq_create_mapping()
and then reutrn errno if !virq:git grep -A 3 'virq =
irq_create_mapping'Some return
-ENOMEM, some-ENXIO, some-EINVAL.What do you think?
-ENXIO is fine.
regards,
dan carpenter
Marek Behún
maintainerPATCH v5 7/11 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 | 89 +++++++++++++++++++ drivers/platform/cznic/turris-omnia-mcu.h | 8 ++ 6 files changed, 106 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-objs := turris-omnia-mcu-base.o turris-omnia-mcu-objs += turris-omnia-mcu-gpio.o turris-omnia-mcu-objs += turris-omnia-mcu-sys-off-wakeup.o +turris-omnia-mcu-objs += turris-omnia-mcu-trng.o turris-omnia-mcu-objs += turris-omnia-mcu-watchdog.o
drivers/platform/cznic/turris-omnia-mcu-base.c +5 -1
@@ -335,7 +335,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
@@ -161,7 +161,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 +89 -0
89 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/i2c.h> #include <linux/if_ether.h> #include <linux/mutex.h>
@@ -46,6 +48,10 @@ struct omnia_mcu {/* MCU watchdog */ struct watchdog_device wdt; + +/* true random number generator */ +struct hwrng trng; +struct completion trng_completion; }; static inline int omnia_cmd_write(const struct i2c_client *client, void *cmd,
@@ -166,11 +172,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 v5 8/11 devm-helpers: Add resource managed version of debugfs directory create function
In reply to Marek BehúnA few drivers register a devm action to remove a debugfs directory, implementing a one-liner function that calls debufs_remove_recursive(). Help drivers avoid this repeated implementations by adding managed version of debugfs directory create function.
Use the new function devm_debugfs_create_dir() in the following drivers:
drivers/crypto/caam/ctrl.c drivers/gpu/drm/bridge/ti-sn65dsi86.c drivers/hwmon/hp-wmi-sensors.c drivers/hwmon/mr75203.c drivers/hwmon/pmbus/pmbus_core.c
Also use the action function devm_debugfs_dir_recursive_drop() in driver
drivers/gpio/gpio-mockup.c
As per Dan Williams' request [1], do not touch the driver
drivers/cxl/mem.c
--- drivers/crypto/caam/ctrl.c | 16 +++-------- drivers/gpio/gpio-mockup.c | 11 ++------ drivers/gpu/drm/bridge/ti-sn65dsi86.c | 13 ++------- drivers/hwmon/hp-wmi-sensors.c | 15 ++-------- drivers/hwmon/mr75203.c | 15 ++++------ drivers/hwmon/pmbus/pmbus_core.c | 16 ++++------- include/linux/devm-helpers.h | 40 +++++++++++++++++++++++++++ 7 files changed, 61 insertions(+), 65 deletions(-)
drivers/crypto/caam/ctrl.c +4 -12
@@ -7,6 +7,7 @@*/ #include <linux/device.h> +#include <linux/devm-helpers.h> #include <linux/of_address.h> #include <linux/of_irq.h> #include <linux/platform_device.h>
@@ -604,11 +605,6 @@ static int init_clocks(struct device *dev, const struct caam_imx_data *data)return devm_add_action_or_reset (dev, disable_clocks, ctrlpriv); } -static void caam_remove_debugfs (void *root) -{ -debugfs_remove_recursive (root); -} -#ifdef CONFIG_FSL_MC_BUS static bool check_version (struct fsl_mc_version *mc_version,u32 major,u32 minor,u32 revision)
@@ -1058,13 +1054,9 @@ static int caam_probe(struct platform_device *pdev) ctrlpriv->era =caam_get_era (perfmon); ctrlpriv->domain =iommu_get_domain_for_dev (dev); - dfs_root =debugfs_create_dir (dev_name (dev),NULL ); -if (IS_ENABLED (CONFIG_DEBUG_FS )) { - ret =devm_add_action_or_reset (dev, caam_remove_debugfs, - dfs_root); -if (ret) -return ret; - } + dfs_root =devm_debugfs_create_dir (dev,dev_name (dev),NULL ); +if (IS_ERR (dfs_root)) +return PTR_ERR (dfs_root);caam_debugfs_init (ctrlpriv, perfmon, dfs_root);
drivers/gpio/gpio-mockup.c +3 -8
@@ -12,6 +12,7 @@#include <linux/cleanup.h> #include <linux/debugfs.h> #include <linux/device.h> +#include <linux/devm-helpers.h> #include <linux/gpio/driver.h> #include <linux/interrupt.h> #include <linux/irq.h>
@@ -390,13 +391,6 @@ static void gpio_mockup_debugfs_setup(struct device *dev, } } -static void gpio_mockup_debugfs_cleanup (void *data) -{ -struct gpio_mockup_chip *chip = data; - -debugfs_remove_recursive (chip->dbg_dir); -} -static void gpio_mockup_dispose_mappings (void *data) {struct gpio_mockup_chip *chip = data;
@@ -480,7 +474,8 @@ static int gpio_mockup_probe(struct platform_device *pdev)gpio_mockup_debugfs_setup (dev, chip); -return devm_add_action_or_reset (dev, gpio_mockup_debugfs_cleanup, chip); +return devm_add_action_or_reset (dev, devm_debugfs_dir_recursive_drop, + chip->dbg_dir); }static const struct of_device_id gpio_mockup_of_match[] = {
drivers/gpu/drm/bridge/ti-sn65dsi86.c +2 -11
@@ -10,6 +10,7 @@#include <linux/bits.h> #include <linux/clk.h> #include <linux/debugfs.h> +#include <linux/devm-helpers.h> #include <linux/gpio/consumer.h> #include <linux/gpio/driver.h> #include <linux/i2c.h>
@@ -427,18 +428,12 @@ static int status_show(struct seq_file *s, void *data)DEFINE_SHOW_ATTRIBUTE (status); -static void ti_sn65dsi86_debugfs_remove (void *data) -{ -debugfs_remove_recursive (data); -} -static void ti_sn65dsi86_debugfs_init (struct ti_sn65dsi86 *pdata) {struct device *dev = pdata->dev;struct dentry *debugfs; -int ret; - debugfs =debugfs_create_dir (dev_name (dev),NULL ); + debugfs =devm_debugfs_create_dir (dev,dev_name (dev),NULL );/* * We might get an error back if debugfs wasn't enabled in the kernel
@@ -447,10 +442,6 @@ static void ti_sn65dsi86_debugfs_init(struct ti_sn65dsi86 *pdata)if (IS_ERR_OR_NULL (debugfs))return ; - ret =devm_add_action_or_reset (dev, ti_sn65dsi86_debugfs_remove, debugfs); -if (ret) -return ; -debugfs_create_file ("status" ,0600 , debugfs, pdata, &status_fops); }
drivers/hwmon/hp-wmi-sensors.c +2 -13
@@ -23,6 +23,7 @@#include <linux/acpi.h> #include <linux/debugfs.h> +#include <linux/devm-helpers.h> #include <linux/hwmon.h> #include <linux/jiffies.h> #include <linux/mutex.h>
@@ -1304,12 +1305,6 @@ static int current_reading_show(struct seq_file *seqf, void *ignored) }DEFINE_SHOW_ATTRIBUTE (current_reading); -/* hp_wmi_devm_debugfs_remove - devm callback for debugfs cleanup */ -static void hp_wmi_devm_debugfs_remove (void *res) -{ -debugfs_remove_recursive (res); -} -/* hp_wmi_debugfs_init - create and populate debugfs directory tree */ static void hp_wmi_debugfs_init(struct device *dev, struct hp_wmi_info *info, struct hp_wmi_platform_events *pevents,
@@ -1320,21 +1315,15 @@ static void hp_wmi_debugfs_init(struct device *dev, struct hp_wmi_info *info,struct dentry *debugfs;struct dentry *entries;struct dentry *dir; -int err;u8 i;/* dev_name() gives a not-very-friendly GUID for WMI devices. */ scnprintf (buf,sizeof (buf),"hp-wmi-sensors-%u" , dev->id); - debugfs =debugfs_create_dir (buf,NULL ); + debugfs =devm_debugfs_create_dir (dev, buf,NULL );if (IS_ERR (debugfs))return ; - err =devm_add_action_or_reset (dev, hp_wmi_devm_debugfs_remove, - debugfs); -if (err) -return ; - entries =debugfs_create_dir ("sensor" , debugfs);for (i =0 ; i < icount; i++, info++) {
drivers/hwmon/mr75203.c +5 -10
@@ -10,6 +10,7 @@#include <linux/bits.h> #include <linux/clk.h> #include <linux/debugfs.h> +#include <linux/devm-helpers.h> #include <linux/hwmon.h> #include <linux/kstrtox.h> #include <linux/module.h>
@@ -216,17 +217,11 @@ static const struct file_operations pvt_ts_coeff_j_fops = { .llseek = default_llseek, }; -static void devm_pvt_ts_dbgfs_remove (void *data) -{ -struct pvt_device *pvt = (struct pvt_device *)data; - -debugfs_remove_recursive (pvt->dbgfs_dir); - pvt->dbgfs_dir =NULL ; -} -static int pvt_ts_dbgfs_create (struct pvt_device *pvt,struct device *dev) { - pvt->dbgfs_dir =debugfs_create_dir (dev_name (dev),NULL ); + pvt->dbgfs_dir =devm_debugfs_create_dir (dev,dev_name (dev),NULL ); +if (IS_ERR (pvt->dbgfs_dir)) +return PTR_ERR (pvt->dbgfs_dir);debugfs_create_u32 ("ts_coeff_h" ,0644 , pvt->dbgfs_dir, &pvt->ts_coeff.h);
@@ -237,7 +232,7 @@ static int pvt_ts_dbgfs_create(struct pvt_device *pvt, struct device *dev)debugfs_create_file ("ts_coeff_j" ,0644 , pvt->dbgfs_dir, pvt, &pvt_ts_coeff_j_fops); -return devm_add_action_or_reset (dev, devm_pvt_ts_dbgfs_remove, pvt); +return 0 ; } static umode_t pvt_is_visible(const void *data, enum hwmon_sensor_types type,
drivers/hwmon/pmbus/pmbus_core.c +5 -11
@@ -7,6 +7,7 @@*/ #include <linux/debugfs.h> +#include <linux/devm-helpers.h> #include <linux/kernel.h> #include <linux/math64.h> #include <linux/module.h>
@@ -3336,13 +3337,6 @@ static const struct file_operations pmbus_debugfs_ops_mfr = { .open = simple_open, }; -static void pmbus_remove_debugfs (void *data) -{ -struct dentry *entry = data; - -debugfs_remove_recursive (entry); -} -static int pmbus_init_debugfs (struct i2c_client *client,struct pmbus_data *data) {
@@ -3357,8 +3351,9 @@ static int pmbus_init_debugfs(struct i2c_client *client,* Create the debugfs directory for this device. Use the hwmon device * name to avoid conflicts (hwmon numbers are globally unique). */ - data->debugfs =debugfs_create_dir (dev_name (data->hwmon_dev), - pmbus_debugfs_dir); + data->debugfs =devm_debugfs_create_dir (data->dev, +dev_name (data->hwmon_dev), + pmbus_debugfs_dir);if (IS_ERR_OR_NULL (data->debugfs)) { data->debugfs =NULL ;return -ENODEV ;
@@ -3542,8 +3537,7 @@ static int pmbus_init_debugfs(struct i2c_client *client, } } -return devm_add_action_or_reset (data->dev, - pmbus_remove_debugfs, data->debugfs); +return 0 ; }#else static int pmbus_init_debugfs(struct i2c_client *client,
include/linux/devm-helpers.h +40 -0
@@ -23,6 +23,7 @@* already ran. */ +#include <linux/debugfs.h> #include <linux/device.h> #include <linux/kconfig.h> #include <linux/irqdomain.h>
@@ -130,4 +131,43 @@ static inline int devm_irq_create_mapping(struct device *dev, return virq; } +static inline void devm_debugfs_dir_recursive_drop (void *res) +{ +debugfs_remove_recursive (res); +} + +/** +* devm_debugfs_create_dir - Resource managed debugfs directory creation +* @dev: Device which lifetime the directory is bound to +* @name: a pointer to a string containing the name of the directory to +* create +* @parent: a pointer to the parent dentry for this file. This should be a +* directory dentry if set. If this parameter is NULL, then the +* directory will be created in the root of the debugfs filesystem. +* +* Create a debugfs directory which is automatically recursively removed when +* the driver is detached. A few drivers create debugfs directories which they +* want removed before driver is detached. +* devm_debugfs_create_dir() can be used to omit the explicit +* debugfs_remove_recursive() call when driver is detached. +*/ +static inline struct dentry * +devm_debugfs_create_dir (struct device *dev,const char *name, +struct dentry *parent) +{ +struct dentry *dentry; +int err; + + dentry =debugfs_create_dir (name, parent); +if (IS_ERR (dentry)) +return dentry; + + err =devm_add_action_or_reset (dev, devm_debugfs_dir_recursive_drop, + dentry); +if (err <0 ) +return ERR_PTR (err); + +return dentry; +} +#endif
Signature · 1 line
2.43.2
Guenter Roeck
maintainerRe: [PATCH v5 08/11] devm-helpers: Add resource managed version of debugfs directory create function
Quoted 5 lines · Marek Behún
A few drivers register a devm action to remove a debugfs directory, implementing a one-liner function that calls
debufs_remove_recursive(). Help drivers avoid this repeated implementations by adding managed version of debugfs directory create function.
Quoted 8 lines
Use the new function
devm_debugfs_create_dir()in the following drivers:drivers/crypto/caam/ctrl.c drivers/gpu/drm/bridge/ti-sn65dsi86.c drivers/hwmon/hp-wmi-sensors.c drivers/hwmon/mr75203.c drivers/hwmon/pmbus/pmbus_core.c
Please split this up into multiple patches, at least separating out the hwmon patches.
Guenter
Marek Behún
maintainerPATCH v5 9/11 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 | 12 +- .../platform/cznic/turris-omnia-mcu-base.c | 45 +++- .../platform/cznic/turris-omnia-mcu-debugfs.c | 216 ++++++++++++++++++ drivers/platform/cznic/turris-omnia-mcu.h | 40 +++- 8 files changed, 331 insertions(+), 11 deletions(-) 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 +7 -5
@@ -1,8 +1,10 @@ # SPDX-License-Identifier: GPL-2.0-only obj-$(CONFIG_TURRIS_OMNIA_MCU) += turris-omnia-mcu.o -turris-omnia-mcu-objs := turris-omnia-mcu-base.o -turris-omnia-mcu-objs += turris-omnia-mcu-gpio.o -turris-omnia-mcu-objs += turris-omnia-mcu-sys-off-wakeup.o -turris-omnia-mcu-objs += turris-omnia-mcu-trng.o -turris-omnia-mcu-objs += turris-omnia-mcu-watchdog.o +turris-omnia-mcu-objs-y := turris-omnia-mcu-base.o +turris-omnia-mcu-objs-y += turris-omnia-mcu-gpio.o +turris-omnia-mcu-objs-y += turris-omnia-mcu-sys-off-wakeup.o +turris-omnia-mcu-objs-y += turris-omnia-mcu-trng.o +turris-omnia-mcu-objs-y += turris-omnia-mcu-watchdog.o +turris-omnia-mcu-objs-$(CONFIG_DEBUG_FS) += turris-omnia-mcu-debugfs.o +turris-omnia-mcu-objs := $(turris-omnia-mcu-objs-y)
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 +216 -0
216 lines not on this page · raw message
drivers/platform/cznic/turris-omnia-mcu.h +35 -5
@@ -22,6 +22,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;
@@ -31,6 +34,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;
@@ -52,6 +56,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 }; static inline int omnia_cmd_write(const struct i2c_client *client, void *cmd,
@@ -94,19 +108,20 @@ static inline int omnia_cmd_write_u32(const struct i2c_client *client, u8 cmd,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) +static inline 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; msgs[0 ].addr = client->addr; msgs[0 ].flags =0 ; - msgs[0 ].len =1 ; - msgs[0 ].buf = &cmd; + msgs[0 ].len = cmd_len; + msgs[0 ].buf = cmd; msgs[1 ].addr = client->addr; msgs[1 ].flags =I2C_M_RD ; - msgs[1 ].len = len; + msgs[1 ].len = reply_len; msgs[1 ].buf = reply; ret =i2c_transfer (client->adapter, msgs,ARRAY_SIZE (msgs));
@@ -118,6 +133,12 @@ static inline int omnia_cmd_read(const struct i2c_client *client, u8 cmd,return 0 ; } +static inline int omnia_cmd_read (const struct i2c_client *client,u8 cmd, +void *reply,unsigned int len) +{ +return omnia_cmd_write_read (client, &cmd,1 , reply, len); +} +/* Returns 0 on success */ static inline int omnia_cmd_read_bits (const struct i2c_client *client,u8 cmd,u32 bits,u32 *dst)
@@ -181,4 +202,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 v5 10/11 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.
---
Changes since v4:
- #gpio-cells set to 3 instead of 2, see patch 01/11
--- .../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 v5 11/11 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.
---
Changes since v4:
- gpio specifier has 3 args instead of 2, see patch 01/11
--- .../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
A message that is not in the archive (sent off-list or not yet received): 20240323164359.21642-9-kabel__6885.49310886941$1711212291$gmane$org@kernel.org
Re: [PATCH v5 08/11] devm-helpers: Add resource managed version of debugfs directory create function
Le 23/03/2024 à 17:43, Marek Behún a écrit :
Quoted 32 lines
A few drivers register a devm action to remove a debugfs directory, implementing a one-liner function that calls
debufs_remove_recursive(). Help drivers avoid this repeated implementations by adding managed version of debugfs directory create function.Use the new function
devm_debugfs_create_dir()in the following drivers:drivers/crypto/caam/ctrl.c drivers/gpu/drm/bridge/ti-sn65dsi86.c drivers/hwmon/hp-wmi-sensors.c drivers/hwmon/mr75203.c drivers/hwmon/pmbus/pmbus_core.cAlso use the action function
devm_debugfs_dir_recursive_drop()in driver
drivers/gpio/gpio-mockup.cAs per Dan Williams' request [1], do not touch the driver
drivers/cxl/mem.cSigned-off-by Marek Behún <[email protected]>--- drivers/crypto/caam/ctrl.c | 16 +++-------- drivers/gpio/gpio-mockup.c | 11 ++------ drivers/gpu/drm/bridge/ti-sn65dsi86.c | 13 ++------- drivers/hwmon/hp-wmi-sensors.c | 15 ++-------- drivers/hwmon/mr75203.c | 15 ++++------ drivers/hwmon/pmbus/pmbus_core.c | 16 ++++------- include/linux/devm-helpers.h | 40 +++++++++++++++++++++++++++ 7 files changed, 61 insertions(+), 65 deletions(-)
...
Quoted 27 lines
drivers/gpio/gpio-mockup.c +1
-7@@ -12,6 +12,7 @@#include <linux/cleanup.h> #include <linux/debugfs.h> #include <linux/device.h> +#include <linux/devm-helpers.h> #include <linux/gpio/driver.h> #include <linux/interrupt.h> #include <linux/irq.h> @@ -390,13 +391,6 @@ static void gpio_mockup_debugfs_setup(struct device *dev, } } -static void gpio_mockup_debugfs_cleanup (void *data) -{ -struct gpio_mockup_chip *chip = data; - -debugfs_remove_recursive (chip->dbg_dir); -} -static void gpio_mockup_dispose_mappings (void *data) {struct gpio_mockup_chip *chip = data;
drivers/gpio/gpio-mockup.c static int gpio_mockup_probe(struct platform_device *pdev) · line 478
Quoted 6 lines
drivers/gpio/gpio-mockup.c +2
-1@@ -480,7 +474,8 @@ static int gpio_mockup_probe(struct platform_device *pdev)gpio_mockup_debugfs_setup (dev, chip); -return devm_add_action_or_reset (dev, gpio_mockup_debugfs_cleanup, chip); +return devm_add_action_or_reset (dev, devm_debugfs_dir_recursive_drop, + chip->dbg_dir);
This look strange. Shouldn't the debugfs_create_dir() call in gpio_mockup_debugfs_setup() be changed, instead?
(I've not look in the previous version if something was said about it, so apologies if already discussed)
Quoted 3 lines
drivers/gpio/gpio-mockup.c +0
-0}static const struct of_device_id gpio_mockup_of_match[] = {
...
Quoted 20 lines
drivers/hwmon/mr75203.c +1
-4@@ -10,6 +10,7 @@#include <linux/bits.h> #include <linux/clk.h> #include <linux/debugfs.h> +#include <linux/devm-helpers.h> #include <linux/hwmon.h> #include <linux/kstrtox.h> #include <linux/module.h> @@ -216,17 +217,11 @@ static const struct file_operations pvt_ts_coeff_j_fops = { .llseek = default_llseek, }; -static void devm_pvt_ts_dbgfs_remove (void *data) -{ -struct pvt_device *pvt = (struct pvt_device *)data; -
drivers/hwmon/mr75203.c static const struct file_operations pvt_ts_coeff_j_fops = { · line 224
Quoted 10 lines
drivers/hwmon/mr75203.c +3
-5-debugfs_remove_recursive (pvt->dbgfs_dir); - pvt->dbgfs_dir =NULL ; -} -static int pvt_ts_dbgfs_create (struct pvt_device *pvt,struct device *dev) { - pvt->dbgfs_dir =debugfs_create_dir (dev_name (dev),NULL ); + pvt->dbgfs_dir =devm_debugfs_create_dir (dev,dev_name (dev),NULL ); +if (IS_ERR (pvt->dbgfs_dir)) +return PTR_ERR (pvt->dbgfs_dir);
Not sure if the test and error handling should be added here.
*If I'm correct*, functions related to debugfs already handle this case and just do nothing. And failure in debugfs related code is not considered as something that need to be reported and abort a probe function.
Maybe the same other (already existing) tests in this patch should be removed as well, in a separated patch.
just my 2c
CJ
Quoted 10 lines
drivers/hwmon/mr75203.c +1
-1debugfs_create_u32 ("ts_coeff_h" ,0644 , pvt->dbgfs_dir, &pvt->ts_coeff.h);@@ -237,7 +232,7 @@ static int pvt_ts_dbgfs_create(struct pvt_device *pvt, struct device *dev)debugfs_create_file ("ts_coeff_j" ,0644 , pvt->dbgfs_dir, pvt, &pvt_ts_coeff_j_fops); -return devm_add_action_or_reset (dev, devm_pvt_ts_dbgfs_remove, pvt); +return 0 ; }
...
Marek Behún
maintainerRe: [PATCH v5 08/11] devm-helpers: Add resource managed version of debugfs directory create function
Quoted 9 lines · On Sat, 23 Mar 2024 22:10:40 +0100 Christophe JAILLET…
Review
Quoted 3 lines
(quoted diff) +2
-1- return devm_add_action_or_reset(dev, gpio_mockup_debugfs_cleanup, chip); + return devm_add_action_or_reset(dev, devm_debugfs_dir_recursive_drop, + chip->dbg_dir);This look strange. Shouldn't the
debugfs_create_dir()call ingpio_mockup_debugfs_setup()be changed, instead?(I've not look in the previous version if something was said about it, so apologies if already discussed)
Yeah, this specific user needs a more complicated refactoring.
I was reluctant to do more complicated refactors in the patch that also introduces these helpers.
But Guenter asked me to split the patch anyway...
Quoted 12 lines
Review
Quoted 6 lines
static int pvt_ts_dbgfs_create(struct pvt_device *pvt, struct device *dev) {(quoted diff) +3
-1- pvt->dbgfs_dir = debugfs_create_dir(dev_name(dev), NULL); + pvt->dbgfs_dir = devm_debugfs_create_dir(dev, dev_name(dev), NULL); + if (IS_ERR(pvt->dbgfs_dir)) + return PTR_ERR(pvt->dbgfs_dir);Not sure if the test and error handling should be added here. *If I'm correct*, functions related to debugfs already handle this case and just do nothing. And failure in debugfs related code is not considered as something that need to be reported and abort a probe function.
Quoted 2 lines
Maybe the same other (already existing) tests in this patch should be removed as well, in a separated patch.
Functions related to debugfs maybe do, but devm_ resource management functions may fail to allocate release structure, and those errors need to be handled, AFAIK.
Marek
Re: [PATCH v5 08/11] devm-helpers: Add resource managed version of debugfs directory create function
Le 23/03/2024 à 22:25, Marek Behún a écrit :
Quoted 3 lines
On Sat, 23 Mar 2024 22:10:40 +0100
Christophe JAILLET <[email protected]> wrote:
...
Quoted 12 lines
Quoted 12 lines
Review
Quoted 6 lines
static int pvt_ts_dbgfs_create(struct pvt_device *pvt, struct device *dev) {(quoted diff) +3
-1- pvt->dbgfs_dir = debugfs_create_dir(dev_name(dev), NULL); + pvt->dbgfs_dir = devm_debugfs_create_dir(dev, dev_name(dev), NULL); + if (IS_ERR(pvt->dbgfs_dir)) + return PTR_ERR(pvt->dbgfs_dir);Not sure if the test and error handling should be added here. *If I'm correct*, functions related to debugfs already handle this case and just do nothing. And failure in debugfs related code is not considered as something that need to be reported and abort a probe function.
Quoted 6 lines
Quoted 2 lines
Maybe the same other (already existing) tests in this patch should be removed as well, in a separated patch.
Functions related to debugfs maybe do, but
devm_resource management functions may fail to allocate release structure, and those errors need to be handled, AFAIK.
I would say no.
If this memory allocation fails, then debugfs_create_dir() will not be called, but that's not a really big deal if the driver itself can still run normally without it.
Up to you to leave it as-is or remove what I think is a useless error handling.
At least, maybe it could be said in the commit log, so that maintainers can comment on it, if they don't spot the error handling you introduce.
CJ
Quoted 3 lines
Marek
Marek Behún
maintainerRe: [PATCH v5 08/11] devm-helpers: Add resource managed version of debugfs directory create function
Quoted 22 lines · On Sun, 24 Mar 2024 10:21:28 +0100 Christophe JAILLET…
Le 23/03/2024 à 22:25, Marek Behún a écrit :
Quoted 3 lines
On Sat, 23 Mar 2024 22:10:40 +0100
Christophe JAILLET <[email protected]> wrote:...
Quoted 15 lines
Quoted 14 lines
Review
Quoted 6 lines
static int pvt_ts_dbgfs_create(struct pvt_device *pvt, struct device *dev) {(quoted diff) +3
-1- pvt->dbgfs_dir = debugfs_create_dir(dev_name(dev), NULL); + pvt->dbgfs_dir = devm_debugfs_create_dir(dev, dev_name(dev), NULL); + if (IS_ERR(pvt->dbgfs_dir)) + return PTR_ERR(pvt->dbgfs_dir);Not sure if the test and error handling should be added here. *If I'm correct*, functions related to debugfs already handle this case and just do nothing. And failure in debugfs related code is not considered as something that need to be reported and abort a probe function.
Maybe the same other (already existing) tests in this patch should be removed as well, in a separated patch.
Quoted 8 lines
Quoted 3 lines
Functions related to debugfs maybe do, but
devm_resource management functions may fail to allocate release structure, and those errors need to be handled, AFAIK.I would say no.
If this memory allocation fails, thendebugfs_create_dir()will not be called, but that's not a really big deal if the driver itself can still run normally without it.
debugfs_create_dir() will always be called. Resource allocation is done afterwards, and if it fails, then the created dir will be removed.
But now I don't know what to do, because yes, it seems that the debugfs errors are being ignored at many places...
Quoted 12 lines
Up to you to leave it as-is or remove what I think is a useless error handling.
At least, maybe it could be said in the commit log, so that maintainers can comment on it, if they don't spot the error handling you introduce.CJ
Quoted 3 lines
Marek
Re: [PATCH v5 08/11] devm-helpers: Add resource managed version of debugfs directory create function
In reply to Christophe JAILLETQuoted 8 lines · Christophe JAILLET
Review
Quoted 6 lines
static int pvt_ts_dbgfs_create(struct pvt_device *pvt, struct device *dev) {(quoted diff) +3
-1- pvt->dbgfs_dir = debugfs_create_dir(dev_name(dev), NULL); + pvt->dbgfs_dir = devm_debugfs_create_dir(dev, dev_name(dev), NULL); + if (IS_ERR(pvt->dbgfs_dir)) + return PTR_ERR(pvt->dbgfs_dir);Not sure if the test and error handling should be added here.
Yep. debugfs_create_dir() is not supposed to be checked here. It breaks the driver if CONFIG_DEBUGFS is disabled. I have written a blog about this:
https://staticthinking.wordpress.com/2023/07/24/debugfs-functions-are-not-supposed-to-be-checked/
regards,
dan carpenter