linux-watchdog.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v5 00/11] Turris Omnia MCU driver
@ 2024-03-23 16:43 Marek Behún
  2024-03-23 16:43 ` [PATCH v5 02/11] platform: cznic: Add preliminary support for Turris Omnia MCU Marek Behún
  2024-03-23 16:43 ` [PATCH v5 05/11] platform: cznic: turris-omnia-mcu: Add support for MCU watchdog Marek Behún
  0 siblings, 2 replies; 8+ messages in thread
From: Marek Behún @ 2024-03-23 16:43 UTC (permalink / raw)
  To: Arnd Bergmann, Gregory CLEMENT, soc, arm, Alessandro Zummo,
	Alexandre Belloni, Andy Shevchenko, Bartosz Golaszewski,
	devicetree, Greg Kroah-Hartman, Guenter Roeck, Herbert Xu,
	Krzysztof Kozlowski, Linus Walleij, linux-crypto, linux-gpio,
	linux-rtc, linux-watchdog, Rob Herring, Wim Van Sebroeck,
	Hans de Goede, Matti Vaittinen
  Cc: Marek Behún

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/20230823161012.6986-1-kabel@kernel.org/
  https://patchwork.kernel.org/project/linux-soc/cover/20230919103815.16818-1-kabel@kernel.org/
  https://patchwork.kernel.org/project/linux-soc/cover/20231023143130.11602-1-kabel@kernel.org/
  https://patchwork.kernel.org/project/linux-soc/cover/20231026161803.16750-1-kabel@kernel.org/

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

-- 
2.43.2


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH v5 02/11] platform: cznic: Add preliminary support for Turris Omnia MCU
  2024-03-23 16:43 [PATCH v5 00/11] Turris Omnia MCU driver Marek Behún
@ 2024-03-23 16:43 ` Marek Behún
  2024-03-24 11:01   ` Andy Shevchenko
  2024-03-23 16:43 ` [PATCH v5 05/11] platform: cznic: turris-omnia-mcu: Add support for MCU watchdog Marek Behún
  1 sibling, 1 reply; 8+ messages in thread
From: Marek Behún @ 2024-03-23 16:43 UTC (permalink / raw)
  To: Arnd Bergmann, Gregory CLEMENT, soc, arm, Linus Walleij,
	Bartosz Golaszewski, Andy Shevchenko, linux-gpio,
	Alessandro Zummo, Alexandre Belloni, linux-rtc, Wim Van Sebroeck,
	Guenter Roeck, linux-watchdog
  Cc: Marek Behún

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

Signed-off-by: Marek Behún <kabel@kernel.org>
---
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

diff --git a/Documentation/ABI/testing/sysfs-bus-i2c-devices-turris-omnia-mcu b/Documentation/ABI/testing/sysfs-bus-i2c-devices-turris-omnia-mcu
new file mode 100644
index 000000000000..ff5e7cb00206
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-bus-i2c-devices-turris-omnia-mcu
@@ -0,0 +1,81 @@
+What:		/sys/bus/i2c/devices/<mcu_device>/board_revision
+Date:		July 2024
+KernelVersion:	6.10
+Contact:	Marek Behún <kabel@kernel.org>
+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 <kabel@kernel.org>
+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 <kabel@kernel.org>
+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 <kabel@kernel.org>
+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 <kabel@kernel.org>
+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 <kabel@kernel.org>
+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 <kabel@kernel.org>
+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 <kabel@kernel.org>
+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.
diff --git a/MAINTAINERS b/MAINTAINERS
index 89edfc2b875b..529e16d386e8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2139,6 +2139,7 @@ M:	Marek Behún <kabel@kernel.org>
 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 <ulli.kroll@googlemail.com>
diff --git a/drivers/platform/Kconfig b/drivers/platform/Kconfig
index 868b20361769..fef907a94001 100644
--- a/drivers/platform/Kconfig
+++ b/drivers/platform/Kconfig
@@ -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"
diff --git a/drivers/platform/Makefile b/drivers/platform/Makefile
index 41640172975a..8bf189264374 100644
--- a/drivers/platform/Makefile
+++ b/drivers/platform/Makefile
@@ -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/
diff --git a/drivers/platform/cznic/Kconfig b/drivers/platform/cznic/Kconfig
new file mode 100644
index 000000000000..f8560ff9c1af
--- /dev/null
+++ b/drivers/platform/cznic/Kconfig
@@ -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
diff --git a/drivers/platform/cznic/Makefile b/drivers/platform/cznic/Makefile
new file mode 100644
index 000000000000..4d0a9586538c
--- /dev/null
+++ b/drivers/platform/cznic/Makefile
@@ -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
diff --git a/drivers/platform/cznic/turris-omnia-mcu-base.c b/drivers/platform/cznic/turris-omnia-mcu-base.c
new file mode 100644
index 000000000000..27f08ce8f368
--- /dev/null
+++ b/drivers/platform/cznic/turris-omnia-mcu-base.c
@@ -0,0 +1,349 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * CZ.NIC's Turris Omnia MCU driver
+ *
+ * 2024 by Marek Behún <kabel@kernel.org>
+ */
+
+#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>
+#include <linux/sysfs.h>
+
+#include "turris-omnia-mcu.h"
+
+#define OMNIA_FW_VERSION_LEN		20
+#define OMNIA_FW_VERSION_HEX_LEN	(2 * OMNIA_FW_VERSION_LEN + 1)
+#define OMNIA_BOARD_INFO_LEN		16
+
+static int omnia_get_version_hash(struct omnia_mcu *mcu, bool bootloader,
+				  u8 version[static OMNIA_FW_VERSION_HEX_LEN])
+{
+	u8 reply[OMNIA_FW_VERSION_LEN];
+	int err;
+
+	err = omnia_cmd_read(mcu->client, bootloader ? CMD_GET_FW_VERSION_BOOT :
+						       CMD_GET_FW_VERSION_APP,
+			     reply, sizeof(reply));
+	if (err)
+		return err;
+
+	version[OMNIA_FW_VERSION_HEX_LEN - 1] = '\0';
+	bin2hex(version, reply, OMNIA_FW_VERSION_LEN);
+
+	return 0;
+}
+
+static ssize_t fw_version_hash_show(struct device *dev, char *buf,
+				    bool bootloader)
+{
+	struct omnia_mcu *mcu = i2c_get_clientdata(to_i2c_client(dev));
+	u8 version[OMNIA_FW_VERSION_HEX_LEN];
+	int err;
+
+	err = omnia_get_version_hash(mcu, bootloader, version);
+	if (err)
+		return err;
+
+	return sysfs_emit(buf, "%s\n", version);
+}
+
+static ssize_t fw_version_hash_application_show(struct device *dev,
+						struct device_attribute *a,
+						char *buf)
+{
+	return fw_version_hash_show(dev, buf, false);
+}
+static DEVICE_ATTR_RO(fw_version_hash_application);
+
+static ssize_t fw_version_hash_bootloader_show(struct device *dev,
+					       struct device_attribute *a,
+					       char *buf)
+{
+	return fw_version_hash_show(dev, buf, true);
+}
+static DEVICE_ATTR_RO(fw_version_hash_bootloader);
+
+static ssize_t fw_features_show(struct device *dev, struct device_attribute *a,
+				char *buf)
+{
+	struct omnia_mcu *mcu = i2c_get_clientdata(to_i2c_client(dev));
+
+	return sysfs_emit(buf, "0x%x\n", mcu->features);
+}
+static DEVICE_ATTR_RO(fw_features);
+
+static ssize_t mcu_type_show(struct device *dev, struct device_attribute *a,
+			     char *buf)
+{
+	struct omnia_mcu *mcu = i2c_get_clientdata(to_i2c_client(dev));
+
+	return sysfs_emit(buf, "%s\n", mcu->type);
+}
+static DEVICE_ATTR_RO(mcu_type);
+
+static ssize_t reset_selector_show(struct device *dev,
+				   struct device_attribute *a, char *buf)
+{
+	int ret;
+
+	ret = omnia_cmd_read_u8(to_i2c_client(dev), CMD_GET_RESET);
+	if (ret < 0)
+		return ret;
+
+	return sysfs_emit(buf, "%d\n", ret);
+}
+static DEVICE_ATTR_RO(reset_selector);
+
+static ssize_t serial_number_show(struct device *dev,
+				  struct device_attribute *a, char *buf)
+{
+	struct omnia_mcu *mcu = i2c_get_clientdata(to_i2c_client(dev));
+
+	return sysfs_emit(buf, "%016llX\n", mcu->board_serial_number);
+}
+static DEVICE_ATTR_RO(serial_number);
+
+static ssize_t first_mac_address_show(struct device *dev,
+				      struct device_attribute *a, char *buf)
+{
+	struct omnia_mcu *mcu = i2c_get_clientdata(to_i2c_client(dev));
+
+	return sysfs_emit(buf, "%pM\n", mcu->board_first_mac);
+}
+static DEVICE_ATTR_RO(first_mac_address);
+
+static ssize_t board_revision_show(struct device *dev,
+				   struct device_attribute *a, char *buf)
+{
+	struct omnia_mcu *mcu = i2c_get_clientdata(to_i2c_client(dev));
+
+	return sysfs_emit(buf, "%u\n", mcu->board_revision);
+}
+static DEVICE_ATTR_RO(board_revision);
+
+static struct attribute *omnia_mcu_base_attrs[] = {
+	&dev_attr_fw_version_hash_application.attr,
+	&dev_attr_fw_version_hash_bootloader.attr,
+	&dev_attr_fw_features.attr,
+	&dev_attr_mcu_type.attr,
+	&dev_attr_reset_selector.attr,
+	&dev_attr_serial_number.attr,
+	&dev_attr_first_mac_address.attr,
+	&dev_attr_board_revision.attr,
+	NULL
+};
+
+static umode_t omnia_mcu_base_attrs_visible(struct kobject *kobj,
+					    struct attribute *a, int n)
+{
+	struct device *dev = kobj_to_dev(kobj);
+	struct omnia_mcu *mcu = i2c_get_clientdata(to_i2c_client(dev));
+	umode_t mode = a->mode;
+
+	if ((a == &dev_attr_serial_number.attr ||
+	     a == &dev_attr_first_mac_address.attr ||
+	     a == &dev_attr_board_revision.attr) &&
+	    !(mcu->features & FEAT_BOARD_INFO))
+		mode = 0;
+
+	return mode;
+}
+
+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
+};
+
+static void omnia_mcu_print_version_hash(struct omnia_mcu *mcu, bool bootloader)
+{
+	const char *type = bootloader ? "bootloader" : "application";
+	struct device *dev = &mcu->client->dev;
+	u8 version[OMNIA_FW_VERSION_HEX_LEN];
+	int err;
+
+	err = omnia_get_version_hash(mcu, bootloader, version);
+	if (err) {
+		dev_err(dev, "Cannot read MCU %s firmware version: %d\n", type,
+			err);
+		return;
+	}
+
+	dev_info(dev, "MCU %s firmware version hash: %s\n", type, version);
+}
+
+static const char *omnia_status_to_mcu_type(uint16_t status)
+{
+	switch (status & STS_MCU_TYPE_MASK) {
+	case STS_MCU_TYPE_STM32:
+		return "STM32";
+	case STS_MCU_TYPE_GD32:
+		return "GD32";
+	case STS_MCU_TYPE_MKL:
+		return "MKL";
+	default:
+		return "unknown";
+	}
+}
+
+static void omnia_info_missing_feature(struct device *dev, const char *feature)
+{
+	dev_info(dev,
+		 "Your board's MCU firmware does not support the %s feature.\n",
+		 feature);
+}
+
+static int omnia_mcu_read_features(struct omnia_mcu *mcu)
+{
+	static const struct {
+		uint16_t mask;
+		const char *name;
+	} features[] = {
+		{ FEAT_EXT_CMDS,	   "extended control and status" },
+		{ FEAT_WDT_PING,	   "watchdog pinging" },
+		{ FEAT_LED_STATE_EXT_MASK, "peripheral LED pins reading" },
+		{ FEAT_NEW_INT_API,	   "new interrupt API" },
+		{ FEAT_POWEROFF_WAKEUP,	   "poweroff and wakeup" },
+		{ FEAT_TRNG,		   "true random number generator" },
+	};
+	struct device *dev = &mcu->client->dev;
+	bool suggest_fw_upgrade = false;
+	int status;
+
+	/* status word holds MCU type, which we need below */
+	status = omnia_cmd_read_u16(mcu->client, CMD_GET_STATUS_WORD);
+	if (status < 0)
+		return status;
+
+	/* check whether MCU firmware supports the CMD_GET_FEAUTRES command */
+	if (status & STS_FEATURES_SUPPORTED) {
+		__le32 reply;
+		int ret;
+
+		/* try read 32-bit features */
+		ret = omnia_cmd_read(mcu->client, CMD_GET_FEATURES, &reply,
+				     sizeof(reply));
+		if (ret) {
+			/* try read 16-bit features */
+			ret = omnia_cmd_read_u16(mcu->client, CMD_GET_FEATURES);
+			if (ret < 0)
+				return ret;
+
+			mcu->features = features;
+		} else {
+			mcu->features = le32_to_cpu(reply);
+
+			if (mcu->features & FEAT_FROM_BIT_16_INVALID)
+				mcu->features &= GENMASK(15, 0);
+		}
+	} else {
+		omnia_info_missing_feature(dev, "feature reading");
+		suggest_fw_upgrade = true;
+	}
+
+	mcu->type = omnia_status_to_mcu_type(status);
+	dev_info(dev, "MCU type %s%s\n", mcu->type,
+		 (mcu->features & FEAT_PERIPH_MCU) ?
+			", with peripheral resets wired" : "");
+
+	omnia_mcu_print_version_hash(mcu, true);
+
+	if (mcu->features & FEAT_BOOTLOADER)
+		dev_warn(dev,
+			 "MCU is running bootloader firmware. Was firmware upgrade interrupted?\n");
+	else
+		omnia_mcu_print_version_hash(mcu, false);
+
+	for (unsigned int i = 0; i < ARRAY_SIZE(features); i++) {
+		if (mcu->features & features[i].mask)
+			continue;
+
+		omnia_info_missing_feature(dev, features[i].name);
+		suggest_fw_upgrade = true;
+	}
+
+	if (suggest_fw_upgrade)
+		dev_info(dev,
+			 "Consider upgrading MCU firmware with the omnia-mcutool utility.\n");
+
+	return 0;
+}
+
+static int omnia_mcu_read_board_info(struct omnia_mcu *mcu)
+{
+	u8 reply[1 + OMNIA_BOARD_INFO_LEN];
+	int err;
+
+	err = omnia_cmd_read(mcu->client, CMD_BOARD_INFO_GET, reply,
+			     sizeof(reply));
+	if (err)
+		return err;
+
+	if (reply[0] != OMNIA_BOARD_INFO_LEN)
+		return -EIO;
+
+	mcu->board_serial_number = get_unaligned_le64(&reply[1]);
+	memcpy(mcu->board_first_mac, &reply[9], ETH_ALEN);
+	mcu->board_revision = reply[15];
+
+	return 0;
+}
+
+static int omnia_mcu_probe(struct i2c_client *client)
+{
+	struct device *dev = &client->dev;
+	struct omnia_mcu *mcu;
+	int err;
+
+	if (!client->irq)
+		return dev_err_probe(dev, -EINVAL, "IRQ resource not found\n");
+
+	mcu = devm_kzalloc(dev, sizeof(*mcu), GFP_KERNEL);
+	if (!mcu)
+		return -ENOMEM;
+
+	mcu->client = client;
+	i2c_set_clientdata(client, mcu);
+
+	err = omnia_mcu_read_features(mcu);
+	if (err)
+		return dev_err_probe(dev, err,
+				     "Cannot determine MCU supported features\n");
+
+	if (mcu->features & FEAT_BOARD_INFO) {
+		err = omnia_mcu_read_board_info(mcu);
+		if (err)
+			return dev_err_probe(dev, err,
+					     "Cannot read board info\n");
+	}
+
+	return 0;
+}
+
+static const struct of_device_id of_omnia_mcu_match[] = {
+	{ .compatible = "cznic,turris-omnia-mcu" },
+	{}
+};
+
+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,
+	},
+};
+
+module_i2c_driver(omnia_mcu_driver);
+
+MODULE_AUTHOR("Marek Behun <kabel@kernel.org>");
+MODULE_DESCRIPTION("CZ.NIC's Turris Omnia MCU");
+MODULE_LICENSE("GPL");
diff --git a/drivers/platform/cznic/turris-omnia-mcu.h b/drivers/platform/cznic/turris-omnia-mcu.h
new file mode 100644
index 000000000000..0662626c6007
--- /dev/null
+++ b/drivers/platform/cznic/turris-omnia-mcu.h
@@ -0,0 +1,71 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * CZ.NIC's Turris Omnia MCU driver
+ *
+ * 2024 by Marek Behún <kabel@kernel.org>
+ */
+
+#ifndef __TURRIS_OMNIA_MCU_H
+#define __TURRIS_OMNIA_MCU_H
+
+#include <linux/i2c.h>
+#include <linux/if_ether.h>
+#include <linux/types.h>
+#include <asm/byteorder.h>
+
+struct omnia_mcu {
+	struct i2c_client *client;
+	const char *type;
+	u32 features;
+
+	/* board information */
+	u64 board_serial_number;
+	u8 board_first_mac[ETH_ALEN];
+	u8 board_revision;
+};
+
+static inline int omnia_cmd_read(const struct i2c_client *client, u8 cmd,
+				 void *reply, unsigned int 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[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;
+}
+
+static inline int omnia_cmd_read_u16(const struct i2c_client *client, u8 cmd)
+{
+	__le16 reply;
+	int err;
+
+	err = omnia_cmd_read(client, cmd, &reply, sizeof(reply));
+
+	return err ?: le16_to_cpu(reply);
+}
+
+static inline int omnia_cmd_read_u8(const struct i2c_client *client, u8 cmd)
+{
+	u8 reply;
+	int err;
+
+	err = omnia_cmd_read(client, cmd, &reply, sizeof(reply));
+
+	return err ?: reply;
+}
+
+#endif /* __TURRIS_OMNIA_MCU_H */
diff --git a/include/linux/turris-omnia-mcu-interface.h b/include/linux/turris-omnia-mcu-interface.h
new file mode 100644
index 000000000000..84bb47786147
--- /dev/null
+++ b/include/linux/turris-omnia-mcu-interface.h
@@ -0,0 +1,238 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * CZ.NIC's Turris Omnia MCU I2C interface commands definitions
+ *
+ * 2023 by Marek Behún <kabel@kernel.org>
+ */
+
+#ifndef __TURRIS_OMNIA_MCU_INTERFACE_H
+#define __TURRIS_OMNIA_MCU_INTERFACE_H
+
+#include <linux/bits.h>
+
+enum omnia_commands_e {
+	CMD_GET_STATUS_WORD		= 0x01, /* slave sends status word back */
+	CMD_GENERAL_CONTROL		= 0x02,
+	CMD_LED_MODE			= 0x03, /* default/user */
+	CMD_LED_STATE			= 0x04, /* LED on/off */
+	CMD_LED_COLOR			= 0x05, /* LED number + RED + GREEN + BLUE */
+	CMD_USER_VOLTAGE		= 0x06,
+	CMD_SET_BRIGHTNESS		= 0x07,
+	CMD_GET_BRIGHTNESS		= 0x08,
+	CMD_GET_RESET			= 0x09,
+	CMD_GET_FW_VERSION_APP		= 0x0A, /* 20B git hash number */
+	CMD_SET_WATCHDOG_STATE		= 0x0B, /* 0 - disable
+						 * 1 - enable / ping
+						 * after boot watchdog is started
+						 * with 2 minutes timeout
+						 */
+
+	/* CMD_WATCHDOG_STATUS		= 0x0C, not implemented anymore */
+
+	CMD_GET_WATCHDOG_STATE		= 0x0D,
+	CMD_GET_FW_VERSION_BOOT		= 0x0E, /* 20B git hash number */
+	CMD_GET_FW_CHECKSUM		= 0x0F, /* 4B length, 4B checksum */
+
+	/* available if FEATURES_SUPPORTED bit set in status word */
+	CMD_GET_FEATURES		= 0x10,
+
+	/* available if EXT_CMD bit set in features */
+	CMD_GET_EXT_STATUS_DWORD	= 0x11,
+	CMD_EXT_CONTROL			= 0x12,
+	CMD_GET_EXT_CONTROL_STATUS	= 0x13,
+
+	/* available if NEW_INT_API bit set in features */
+	CMD_GET_INT_AND_CLEAR		= 0x14,
+	CMD_GET_INT_MASK		= 0x15,
+	CMD_SET_INT_MASK		= 0x16,
+
+	/* available if FLASHING bit set in features */
+	CMD_FLASH			= 0x19,
+
+	/* available if WDT_PING bit set in features */
+	CMD_SET_WDT_TIMEOUT		= 0x20,
+	CMD_GET_WDT_TIMELEFT		= 0x21,
+
+	/* available if POWEROFF_WAKEUP bit set in features */
+	CMD_SET_WAKEUP			= 0x22,
+	CMD_GET_UPTIME_AND_WAKEUP	= 0x23,
+	CMD_POWER_OFF			= 0x24,
+
+	/* available if TRNG bit set in features */
+	CMD_TRNG_COLLECT_ENTROPY	= 0x28,
+
+	/* available if CRYPTO bit set in features */
+	CMD_CRYPTO_GET_PUBLIC_KEY	= 0x29,
+	CMD_CRYPTO_SIGN_MESSAGE		= 0x2A,
+	CMD_CRYPTO_COLLECT_SIGNATURE	= 0x2B,
+
+	/* available if BOARD_INFO it set in features */
+	CMD_BOARD_INFO_GET		= 0x2C,
+	CMD_BOARD_INFO_BURN		= 0x2D,
+
+	/* available only at address 0x2b (led-controller) */
+	/* available only if LED_GAMMA_CORRECTION bit set in features */
+	CMD_SET_GAMMA_CORRECTION	= 0x30,
+	CMD_GET_GAMMA_CORRECTION	= 0x31,
+
+	/* available only at address 0x2b (led-controller) */
+	/* available only if PER_LED_CORRECTION bit set in features */
+	/* available only if FROM_BIT_16_INVALID bit NOT set in features */
+	CMD_SET_LED_CORRECTIONS		= 0x32,
+	CMD_GET_LED_CORRECTIONS		= 0x33,
+};
+
+enum omnia_flashing_commands_e {
+	FLASH_CMD_UNLOCK		= 0x01,
+	FLASH_CMD_SIZE_AND_CSUM		= 0x02,
+	FLASH_CMD_PROGRAM		= 0x03,
+	FLASH_CMD_RESET			= 0x04,
+};
+
+enum omnia_sts_word_e {
+	STS_MCU_TYPE_MASK			= GENMASK(1, 0),
+	STS_MCU_TYPE_STM32			= 0 << 0,
+	STS_MCU_TYPE_GD32			= 1 << 0,
+	STS_MCU_TYPE_MKL			= 2 << 0,
+	STS_FEATURES_SUPPORTED			= BIT(2),
+	STS_USER_REGULATOR_NOT_SUPPORTED	= BIT(3),
+	STS_CARD_DET				= BIT(4),
+	STS_MSATA_IND				= BIT(5),
+	STS_USB30_OVC				= BIT(6),
+	STS_USB31_OVC				= BIT(7),
+	STS_USB30_PWRON				= BIT(8),
+	STS_USB31_PWRON				= BIT(9),
+	STS_ENABLE_4V5				= BIT(10),
+	STS_BUTTON_MODE				= BIT(11),
+	STS_BUTTON_PRESSED			= BIT(12),
+	STS_BUTTON_COUNTER_MASK			= GENMASK(15, 13)
+};
+
+enum omnia_ctl_byte_e {
+	CTL_LIGHT_RST		= BIT(0),
+	CTL_HARD_RST		= BIT(1),
+	/* BIT(2) is currently reserved */
+	CTL_USB30_PWRON		= BIT(3),
+	CTL_USB31_PWRON		= BIT(4),
+	CTL_ENABLE_4V5		= BIT(5),
+	CTL_BUTTON_MODE		= BIT(6),
+	CTL_BOOTLOADER		= BIT(7)
+};
+
+enum omnia_features_e {
+	FEAT_PERIPH_MCU			= BIT(0),
+	FEAT_EXT_CMDS			= BIT(1),
+	FEAT_WDT_PING			= BIT(2),
+	FEAT_LED_STATE_EXT_MASK		= GENMASK(4, 3),
+	FEAT_LED_STATE_EXT		= 1 << 3,
+	FEAT_LED_STATE_EXT_V32		= 2 << 3,
+	FEAT_LED_GAMMA_CORRECTION	= BIT(5),
+	FEAT_NEW_INT_API		= BIT(6),
+	FEAT_BOOTLOADER			= BIT(7),
+	FEAT_FLASHING			= BIT(8),
+	FEAT_NEW_MESSAGE_API		= BIT(9),
+	FEAT_BRIGHTNESS_INT		= BIT(10),
+	FEAT_POWEROFF_WAKEUP		= BIT(11),
+	FEAT_CAN_OLD_MESSAGE_API	= BIT(12),
+	FEAT_TRNG			= BIT(13),
+	FEAT_CRYPTO			= BIT(14),
+	FEAT_BOARD_INFO			= BIT(15),
+
+	/*
+	 * Orginally the features command replied only 16 bits. If more were
+	 * read, either the I2C transaction failed or 0xff bytes were sent.
+	 * Therefore to consider bits 16 - 31 valid, one bit (20) was reserved
+	 * to be zero.
+	 */
+
+	/* Bits 16 - 19 correspond to bits 0 - 3 of status word */
+	FEAT_MCU_TYPE_MASK		= GENMASK(17, 16),
+	FEAT_MCU_TYPE_STM32		= FIELD_PREP(FEAT_MCU_TYPE_MASK, 0),
+	FEAT_MCU_TYPE_GD32		= FIELD_PREP(FEAT_MCU_TYPE_MASK, 1),
+	FEAT_MCU_TYPE_MKL		= FIELD_PREP(FEAT_MCU_TYPE_MASK, 2),
+	FEAT_FEATURES_SUPPORTED		= BIT(18),
+	FEAT_USER_REGULATOR_NOT_SUPPORTED = BIT(19),
+
+	/* must not be set */
+	FEAT_FROM_BIT_16_INVALID	= BIT(20),
+
+	FEAT_PER_LED_CORRECTION		= BIT(21),
+};
+
+enum omnia_ext_sts_dword_e {
+	EXT_STS_SFP_nDET		= BIT(0),
+	EXT_STS_LED_STATES_MASK		= GENMASK(31, 12),
+	EXT_STS_WLAN0_MSATA_LED		= BIT(12),
+	EXT_STS_WLAN1_LED		= BIT(13),
+	EXT_STS_WLAN2_LED		= BIT(14),
+	EXT_STS_WPAN0_LED		= BIT(15),
+	EXT_STS_WPAN1_LED		= BIT(16),
+	EXT_STS_WPAN2_LED		= BIT(17),
+	EXT_STS_WAN_LED0		= BIT(18),
+	EXT_STS_WAN_LED1		= BIT(19),
+	EXT_STS_LAN0_LED0		= BIT(20),
+	EXT_STS_LAN0_LED1		= BIT(21),
+	EXT_STS_LAN1_LED0		= BIT(22),
+	EXT_STS_LAN1_LED1		= BIT(23),
+	EXT_STS_LAN2_LED0		= BIT(24),
+	EXT_STS_LAN2_LED1		= BIT(25),
+	EXT_STS_LAN3_LED0		= BIT(26),
+	EXT_STS_LAN3_LED1		= BIT(27),
+	EXT_STS_LAN4_LED0		= BIT(28),
+	EXT_STS_LAN4_LED1		= BIT(29),
+	EXT_STS_LAN5_LED0		= BIT(30),
+	EXT_STS_LAN5_LED1		= BIT(31),
+};
+
+enum omnia_ext_ctl_e {
+	EXT_CTL_nRES_MMC		= BIT(0),
+	EXT_CTL_nRES_LAN		= BIT(1),
+	EXT_CTL_nRES_PHY		= BIT(2),
+	EXT_CTL_nPERST0			= BIT(3),
+	EXT_CTL_nPERST1			= BIT(4),
+	EXT_CTL_nPERST2			= BIT(5),
+	EXT_CTL_PHY_SFP			= BIT(6),
+	EXT_CTL_PHY_SFP_AUTO		= BIT(7),
+	EXT_CTL_nVHV_CTRL		= BIT(8),
+};
+
+enum omnia_int_e {
+	INT_CARD_DET		= BIT(0),
+	INT_MSATA_IND		= BIT(1),
+	INT_USB30_OVC		= BIT(2),
+	INT_USB31_OVC		= BIT(3),
+	INT_BUTTON_PRESSED	= BIT(4),
+	INT_SFP_nDET		= BIT(5),
+	INT_BRIGHTNESS_CHANGED	= BIT(6),
+	INT_TRNG		= BIT(7),
+	INT_MESSAGE_SIGNED	= BIT(8),
+
+	INT_LED_STATES_MASK	= GENMASK(31, 12),
+	INT_WLAN0_MSATA_LED	= BIT(12),
+	INT_WLAN1_LED		= BIT(13),
+	INT_WLAN2_LED		= BIT(14),
+	INT_WPAN0_LED		= BIT(15),
+	INT_WPAN1_LED		= BIT(16),
+	INT_WPAN2_LED		= BIT(17),
+	INT_WAN_LED0		= BIT(18),
+	INT_WAN_LED1		= BIT(19),
+	INT_LAN0_LED0		= BIT(20),
+	INT_LAN0_LED1		= BIT(21),
+	INT_LAN1_LED0		= BIT(22),
+	INT_LAN1_LED1		= BIT(23),
+	INT_LAN2_LED0		= BIT(24),
+	INT_LAN2_LED1		= BIT(25),
+	INT_LAN3_LED0		= BIT(26),
+	INT_LAN3_LED1		= BIT(27),
+	INT_LAN4_LED0		= BIT(28),
+	INT_LAN4_LED1		= BIT(29),
+	INT_LAN5_LED0		= BIT(30),
+	INT_LAN5_LED1		= BIT(31),
+};
+
+enum omnia_cmd_poweroff_e {
+	CMD_POWER_OFF_POWERON_BUTTON	= BIT(0),
+	CMD_POWER_OFF_MAGIC		= 0xdead,
+};
+
+#endif /* __TURRIS_OMNIA_MCU_INTERFACE_H */
-- 
2.43.2


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v5 05/11] platform: cznic: turris-omnia-mcu: Add support for MCU watchdog
  2024-03-23 16:43 [PATCH v5 00/11] Turris Omnia MCU driver Marek Behún
  2024-03-23 16:43 ` [PATCH v5 02/11] platform: cznic: Add preliminary support for Turris Omnia MCU Marek Behún
@ 2024-03-23 16:43 ` Marek Behún
  1 sibling, 0 replies; 8+ messages in thread
From: Marek Behún @ 2024-03-23 16:43 UTC (permalink / raw)
  To: Arnd Bergmann, Gregory CLEMENT, soc, arm, Andy Shevchenko,
	Bartosz Golaszewski, Guenter Roeck, Linus Walleij,
	linux-watchdog, Wim Van Sebroeck
  Cc: Marek Behún

Add support for the watchdog mechanism provided by the MCU.

Signed-off-by: Marek Behún <kabel@kernel.org>
---
 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

diff --git a/drivers/platform/cznic/Kconfig b/drivers/platform/cznic/Kconfig
index 0a752aa654fa..e2649cdecc38 100644
--- a/drivers/platform/cznic/Kconfig
+++ b/drivers/platform/cznic/Kconfig
@@ -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
diff --git a/drivers/platform/cznic/Makefile b/drivers/platform/cznic/Makefile
index 6f1470d1f673..a43997a12d74 100644
--- a/drivers/platform/cznic/Makefile
+++ b/drivers/platform/cznic/Makefile
@@ -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
diff --git a/drivers/platform/cznic/turris-omnia-mcu-base.c b/drivers/platform/cznic/turris-omnia-mcu-base.c
index 6ab4494335ca..5a45834003cd 100644
--- a/drivers/platform/cznic/turris-omnia-mcu-base.c
+++ b/drivers/platform/cznic/turris-omnia-mcu-base.c
@@ -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);
 }
 
diff --git a/drivers/platform/cznic/turris-omnia-mcu-watchdog.c b/drivers/platform/cznic/turris-omnia-mcu-watchdog.c
new file mode 100644
index 000000000000..94cdd6eea4c8
--- /dev/null
+++ b/drivers/platform/cznic/turris-omnia-mcu-watchdog.c
@@ -0,0 +1,122 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * CZ.NIC's Turris Omnia MCU watchdog driver
+ *
+ * 2024 by Marek Behún <kabel@kernel.org>
+ */
+
+#include <linux/moduleparam.h>
+#include <linux/turris-omnia-mcu-interface.h>
+#include <linux/types.h>
+#include <linux/watchdog.h>
+
+#include "turris-omnia-mcu.h"
+
+#define WATCHDOG_TIMEOUT		120
+
+static unsigned int timeout;
+module_param(timeout, int, 0);
+MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds");
+
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
+			   __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
+static int omnia_wdt_start(struct watchdog_device *wdt)
+{
+	struct omnia_mcu *mcu = watchdog_get_drvdata(wdt);
+
+	return omnia_cmd_write_u8(mcu->client, CMD_SET_WATCHDOG_STATE, 1);
+}
+
+static int omnia_wdt_stop(struct watchdog_device *wdt)
+{
+	struct omnia_mcu *mcu = watchdog_get_drvdata(wdt);
+
+	return omnia_cmd_write_u8(mcu->client, CMD_SET_WATCHDOG_STATE, 0);
+}
+
+static int omnia_wdt_ping(struct watchdog_device *wdt)
+{
+	struct omnia_mcu *mcu = watchdog_get_drvdata(wdt);
+
+	return omnia_cmd_write_u8(mcu->client, CMD_SET_WATCHDOG_STATE, 1);
+}
+
+static int omnia_wdt_set_timeout(struct watchdog_device *wdt,
+				 unsigned int timeout)
+{
+	struct omnia_mcu *mcu = watchdog_get_drvdata(wdt);
+
+	return omnia_cmd_write_u16(mcu->client, CMD_SET_WDT_TIMEOUT,
+				   timeout * 10);
+}
+
+static unsigned int omnia_wdt_get_timeleft(struct watchdog_device *wdt)
+{
+	struct omnia_mcu *mcu = watchdog_get_drvdata(wdt);
+	int ret;
+
+	ret = omnia_cmd_read_u16(mcu->client, CMD_GET_WDT_TIMELEFT);
+	if (ret < 0) {
+		dev_err(&mcu->client->dev, "Cannot get watchdog timeleft: %d\n",
+			ret);
+		return 0;
+	}
+
+	return ret / 10;
+}
+
+static const struct watchdog_info omnia_wdt_info = {
+	.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
+	.identity = "Turris Omnia MCU Watchdog",
+};
+
+static const struct watchdog_ops omnia_wdt_ops = {
+	.owner		= THIS_MODULE,
+	.start		= omnia_wdt_start,
+	.stop		= omnia_wdt_stop,
+	.ping		= omnia_wdt_ping,
+	.set_timeout	= omnia_wdt_set_timeout,
+	.get_timeleft	= omnia_wdt_get_timeleft,
+};
+
+int omnia_mcu_register_watchdog(struct omnia_mcu *mcu)
+{
+	struct device *dev = &mcu->client->dev;
+	int ret;
+
+	if (!(mcu->features & FEAT_WDT_PING))
+		return 0;
+
+	mcu->wdt.info = &omnia_wdt_info;
+	mcu->wdt.ops = &omnia_wdt_ops;
+	mcu->wdt.parent = dev;
+	mcu->wdt.min_timeout = 1;
+	mcu->wdt.max_timeout = 6553; /* 65535 deciseconds */
+
+	mcu->wdt.timeout = WATCHDOG_TIMEOUT;
+	watchdog_init_timeout(&mcu->wdt, timeout, dev);
+
+	watchdog_set_drvdata(&mcu->wdt, mcu);
+
+	omnia_wdt_set_timeout(&mcu->wdt, mcu->wdt.timeout);
+
+	ret = omnia_cmd_read_u8(mcu->client, CMD_GET_WATCHDOG_STATE);
+	if (ret < 0)
+		return dev_err_probe(dev, ret,
+				     "Cannot get MCU watchdog state\n");
+
+	if (ret)
+		set_bit(WDOG_HW_RUNNING, &mcu->wdt.status);
+
+	watchdog_set_nowayout(&mcu->wdt, nowayout);
+	watchdog_stop_on_reboot(&mcu->wdt);
+	ret = devm_watchdog_register_device(dev, &mcu->wdt);
+	if (ret)
+		return dev_err_probe(dev, ret,
+				     "Cannot register MCU watchdog\n");
+
+	return 0;
+}
diff --git a/drivers/platform/cznic/turris-omnia-mcu.h b/drivers/platform/cznic/turris-omnia-mcu.h
index af9845d1c6d2..3e2c96079e64 100644
--- a/drivers/platform/cznic/turris-omnia-mcu.h
+++ b/drivers/platform/cznic/turris-omnia-mcu.h
@@ -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 */
-- 
2.43.2


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH v5 02/11] platform: cznic: Add preliminary support for Turris Omnia MCU
  2024-03-23 16:43 ` [PATCH v5 02/11] platform: cznic: Add preliminary support for Turris Omnia MCU Marek Behún
@ 2024-03-24 11:01   ` Andy Shevchenko
  2024-03-24 15:04     ` Marek Behún
  0 siblings, 1 reply; 8+ messages in thread
From: Andy Shevchenko @ 2024-03-24 11:01 UTC (permalink / raw)
  To: Marek Behún
  Cc: Arnd Bergmann, Gregory CLEMENT, soc, arm, Linus Walleij,
	Bartosz Golaszewski, Andy Shevchenko, linux-gpio,
	Alessandro Zummo, Alexandre Belloni, linux-rtc, Wim Van Sebroeck,
	Guenter Roeck, linux-watchdog

Sat, Mar 23, 2024 at 05:43:50PM +0100, Marek Behún kirjoitti:
> Add the basic skeleton for a new platform driver for the microcontroller
> found on the Turris Omnia board.

...

> +++ b/drivers/platform/cznic/Makefile
> @@ -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

> +#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

> +#include <linux/sysfs.h>

...

> +	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));

?

...

> +	struct omnia_mcu *mcu = i2c_get_clientdata(to_i2c_client(dev));

What's wrong with dev_get_drvdata()?

...

> +static ssize_t fw_features_show(struct device *dev, struct device_attribute *a,
> +				char *buf)

One line?

...

> +	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.

...

> +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()

...

> +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.

> +module_i2c_driver(omnia_mcu_driver);

...

> +#ifndef __TURRIS_OMNIA_MCU_H
> +#define __TURRIS_OMNIA_MCU_H

+ array_size.h

> +#include <linux/i2c.h>
> +#include <linux/if_ether.h>
> +#include <linux/types.h>
> +#include <asm/byteorder.h>

...

> +static inline int omnia_cmd_read(const struct i2c_client *client, u8 cmd,
> +				 void *reply, unsigned int len)
> +{

Why is this in the header?

> +	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;
> +}

...

> +#ifndef __TURRIS_OMNIA_MCU_INTERFACE_H
> +#define __TURRIS_OMNIA_MCU_INTERFACE_H
> +
> +#include <linux/bits.h>

+ bitfield.h

> +#endif /* __TURRIS_OMNIA_MCU_INTERFACE_H */

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v5 02/11] platform: cznic: Add preliminary support for Turris Omnia MCU
  2024-03-24 11:01   ` Andy Shevchenko
@ 2024-03-24 15:04     ` Marek Behún
  2024-03-24 15:30       ` Andy Shevchenko
  0 siblings, 1 reply; 8+ messages in thread
From: Marek Behún @ 2024-03-24 15:04 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Arnd Bergmann, Gregory CLEMENT, soc, arm, Linus Walleij,
	Bartosz Golaszewski, Andy Shevchenko, linux-gpio,
	Alessandro Zummo, Alexandre Belloni, linux-rtc, Wim Van Sebroeck,
	Guenter Roeck, linux-watchdog

Hi Andy,

thank you very much for the review. I have some notes and some
questions, see below.

On Sun, 24 Mar 2024 13:01:55 +0200
Andy Shevchenko <andy.shevchenko@gmail.com> wrote:

> Sat, Mar 23, 2024 at 05:43:50PM +0100, Marek Behún kirjoitti:
> > Add the basic skeleton for a new platform driver for the microcontroller
> > found on the Turris Omnia board.  
> 
> ...
> 
> > +++ b/drivers/platform/cznic/Makefile
> > @@ -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.

> 
> + array_size.h
> + bits.h

Fixed for v6. Is there some tool for this?

> + string.h

Fixed for v6.
> 
> > +#include <linux/sysfs.h>  
> 
> ...
> 
> > +	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

> 	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.

> 
> ?
> 
> ...
> 
> > +	struct omnia_mcu *mcu = i2c_get_clientdata(to_i2c_client(dev));  
> 
> What's wrong with dev_get_drvdata()?

Fixed for v6.

> ...
> 
> > +static ssize_t fw_features_show(struct device *dev, struct device_attribute *a,
> > +				char *buf)  
> 
> One line?

80 columns...

...

> > +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?

> 
> ...
> 
> > +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.
> 

Fixed for v6.

> > +module_i2c_driver(omnia_mcu_driver);  
> 
> ...
> 
> > +#ifndef __TURRIS_OMNIA_MCU_H
> > +#define __TURRIS_OMNIA_MCU_H  
> 
> + array_size.h

Fixed for v6.

> 
> > +#include <linux/i2c.h>
> > +#include <linux/if_ether.h>
> > +#include <linux/types.h>
> > +#include <asm/byteorder.h>  
> 
> ...
> 
> > +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.

> 
> > +	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;
> > +}  
> 
> ...
> 
> > +#ifndef __TURRIS_OMNIA_MCU_INTERFACE_H
> > +#define __TURRIS_OMNIA_MCU_INTERFACE_H
> > +
> > +#include <linux/bits.h>  
> 
> + bitfield.h

Fixed for v6.

> 
> > +#endif /* __TURRIS_OMNIA_MCU_INTERFACE_H */  
> 


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v5 02/11] platform: cznic: Add preliminary support for Turris Omnia MCU
  2024-03-24 15:04     ` Marek Behún
@ 2024-03-24 15:30       ` Andy Shevchenko
  2024-03-25 10:39         ` Marek Behún
  2024-04-02 16:41         ` Marek Behún
  0 siblings, 2 replies; 8+ messages in thread
From: Andy Shevchenko @ 2024-03-24 15:30 UTC (permalink / raw)
  To: Marek Behún
  Cc: Arnd Bergmann, Gregory CLEMENT, soc, arm, Linus Walleij,
	Bartosz Golaszewski, Andy Shevchenko, linux-gpio,
	Alessandro Zummo, Alexandre Belloni, linux-rtc, Wim Van Sebroeck,
	Guenter Roeck, linux-watchdog

On Sun, Mar 24, 2024 at 5:04 PM Marek Behún <kabel@kernel.org> wrote:
>
> 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.

> On Sun, 24 Mar 2024 13:01:55 +0200
> Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > Sat, Mar 23, 2024 at 05:43:50PM +0100, Marek Behún kirjoitti:

...

> > > +   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
>
> >       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?

> > ?

...

> > > +static ssize_t fw_features_show(struct device *dev, struct device_attribute *a,
> > > +                           char *buf)
> >
> > One line?
>
> 80 columns...

Ditto.

...

> > > +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.

Good point.

> Should I still use __ATTRIBUTE_GROUPS() in
> the first patch and than change it in the next one?

...

> > > +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.

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).

> > > +   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;
> > > +}

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v5 02/11] platform: cznic: Add preliminary support for Turris Omnia MCU
  2024-03-24 15:30       ` Andy Shevchenko
@ 2024-03-25 10:39         ` Marek Behún
  2024-04-02 16:41         ` Marek Behún
  1 sibling, 0 replies; 8+ messages in thread
From: Marek Behún @ 2024-03-25 10:39 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Arnd Bergmann, Gregory CLEMENT, soc, arm, Linus Walleij,
	Bartosz Golaszewski, Andy Shevchenko, linux-gpio,
	Alessandro Zummo, Alexandre Belloni, linux-rtc, Wim Van Sebroeck,
	Guenter Roeck, linux-watchdog

On Sun, 24 Mar 2024 17:30:39 +0200
Andy Shevchenko <andy.shevchenko@gmail.com> wrote:

> On Sun, Mar 24, 2024 at 5:04 PM Marek Behún <kabel@kernel.org> wrote:
> >
> > 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.

...

> >
> > 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?

I don't think so, but I personally would also prefer leaving this at 80
columns. Is this a problem?

> > 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.  
> 
> 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).

OK, I moved it into -base.c.

Marek

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v5 02/11] platform: cznic: Add preliminary support for Turris Omnia MCU
  2024-03-24 15:30       ` Andy Shevchenko
  2024-03-25 10:39         ` Marek Behún
@ 2024-04-02 16:41         ` Marek Behún
  1 sibling, 0 replies; 8+ messages in thread
From: Marek Behún @ 2024-04-02 16:41 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Marek Behún, Arnd Bergmann, Gregory CLEMENT, soc, arm,
	Linus Walleij, Bartosz Golaszewski, Andy Shevchenko, linux-gpio,
	Alessandro Zummo, Alexandre Belloni, linux-rtc, Wim Van Sebroeck,
	Guenter Roeck, linux-watchdog

On Sun, Mar 24, 2024 at 05:30:39PM +0200, Andy Shevchenko wrote:
> On Sun, Mar 24, 2024 at 5:04 PM Marek Behún <kabel@kernel.org> wrote:
> >
> > 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

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2024-04-02 16:51 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-03-23 16:43 [PATCH v5 00/11] Turris Omnia MCU driver Marek Behún
2024-03-23 16:43 ` [PATCH v5 02/11] platform: cznic: Add preliminary support for Turris Omnia MCU Marek Behún
2024-03-24 11:01   ` Andy Shevchenko
2024-03-24 15:04     ` Marek Behún
2024-03-24 15:30       ` Andy Shevchenko
2024-03-25 10:39         ` Marek Behún
2024-04-02 16:41         ` Marek Behún
2024-03-23 16:43 ` [PATCH v5 05/11] platform: cznic: turris-omnia-mcu: Add support for MCU watchdog Marek Behún

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).