platform: cznic: Add preliminary support for Turris Omnia MCU

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>
Reviewed-by: Andy Shevchenko <andy@kernel.org>
Acked-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Link: https://lore.kernel.org/r/20240701113010.16447-3-kabel@kernel.org
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
Marek Behún 2024-07-01 13:30:04 +02:00 committed by Arnd Bergmann
parent f5e6f47f2a
commit 992f1a3d4e
No known key found for this signature in database
GPG key ID: 60AB47FFC9095227
9 changed files with 833 additions and 0 deletions

View file

@ -0,0 +1,81 @@
What: /sys/bus/i2c/devices/<mcu_device>/board_revision
Date: September 2024
KernelVersion: 6.11
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: September 2024
KernelVersion: 6.11
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: September 2024
KernelVersion: 6.11
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: September 2024
KernelVersion: 6.11
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: September 2024
KernelVersion: 6.11
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: September 2024
KernelVersion: 6.11
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: September 2024
KernelVersion: 6.11
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: September 2024
KernelVersion: 6.11
Contact: Marek Behún <kabel@kernel.org>
Description: (RO) Contains the 64-bit board serial number in hexadecimal
format.
Only available if board information is burned in the MCU (older
revisions have board information burned in the ATSHA204-A chip).
Format: %016X.

View file

@ -2206,6 +2206,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/bus/moxtet.txt
@ -2219,10 +2220,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>

View file

@ -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"

View file

@ -10,5 +10,6 @@ obj-$(CONFIG_MIPS) += mips/
obj-$(CONFIG_OLPC_EC) += olpc/
obj-$(CONFIG_GOLDFISH) += goldfish/
obj-$(CONFIG_CHROME_PLATFORMS) += chrome/
obj-$(CONFIG_CZNIC_PLATFORMS) += cznic/
obj-$(CONFIG_SURFACE_PLATFORMS) += surface/
obj-$(CONFIG_ARM64) += arm64/

View file

@ -0,0 +1,25 @@
# SPDX-License-Identifier: GPL-2.0-only
#
# For a description of the syntax of this configuration file,
# see Documentation/kbuild/kconfig-language.rst.
#
menuconfig CZNIC_PLATFORMS
bool "Platform support for CZ.NIC's Turris hardware"
help
Say Y here to be able to choose driver support for CZ.NIC's Turris
devices. This option alone does not add any kernel code.
if CZNIC_PLATFORMS
config TURRIS_OMNIA_MCU
tristate "Turris Omnia MCU driver"
depends on MACH_ARMADA_38X || COMPILE_TEST
depends on I2C
help
Say Y here to add support for the features implemented by the
microcontroller on the CZ.NIC's Turris Omnia SOHO router.
To compile this driver as a module, choose M here; the module will be
called turris-omnia-mcu.
endif # CZNIC_PLATFORMS

View file

@ -0,0 +1,4 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_TURRIS_OMNIA_MCU) += turris-omnia-mcu.o
turris-omnia-mcu-y := turris-omnia-mcu-base.o

View file

@ -0,0 +1,394 @@
// SPDX-License-Identifier: GPL-2.0
/*
* CZ.NIC's Turris Omnia MCU driver
*
* 2024 by Marek Behún <kabel@kernel.org>
*/
#include <linux/array_size.h>
#include <linux/bits.h>
#include <linux/device.h>
#include <linux/errno.h>
#include <linux/hex.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/string.h>
#include <linux/sysfs.h>
#include <linux/types.h>
#include <linux/turris-omnia-mcu-interface.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
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, num;
msgs[0].addr = client->addr;
msgs[0].flags = 0;
msgs[0].len = cmd_len;
msgs[0].buf = cmd;
num = 1;
if (reply_len) {
msgs[1].addr = client->addr;
msgs[1].flags = I2C_M_RD;
msgs[1].len = reply_len;
msgs[1].buf = reply;
num++;
}
ret = i2c_transfer(client->adapter, msgs, num);
if (ret < 0)
return ret;
if (ret != num)
return -EIO;
return 0;
}
static int omnia_get_version_hash(struct omnia_mcu *mcu, bool bootloader,
char version[static OMNIA_FW_VERSION_HEX_LEN])
{
u8 reply[OMNIA_FW_VERSION_LEN];
char *p;
int err;
err = omnia_cmd_read(mcu->client,
bootloader ? OMNIA_CMD_GET_FW_VERSION_BOOT
: OMNIA_CMD_GET_FW_VERSION_APP,
reply, sizeof(reply));
if (err)
return err;
p = bin2hex(version, reply, OMNIA_FW_VERSION_LEN);
*p = '\0';
return 0;
}
static ssize_t fw_version_hash_show(struct device *dev, char *buf,
bool bootloader)
{
struct omnia_mcu *mcu = dev_get_drvdata(dev);
char 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 = dev_get_drvdata(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 = dev_get_drvdata(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)
{
u8 reply;
int err;
err = omnia_cmd_read_u8(to_i2c_client(dev), OMNIA_CMD_GET_RESET,
&reply);
if (err)
return err;
return sysfs_emit(buf, "%d\n", reply);
}
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 = dev_get_drvdata(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 = dev_get_drvdata(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 = dev_get_drvdata(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 = dev_get_drvdata(dev);
if ((a == &dev_attr_serial_number.attr ||
a == &dev_attr_first_mac_address.attr ||
a == &dev_attr_board_revision.attr) &&
!(mcu->features & OMNIA_FEAT_BOARD_INFO))
return 0;
return a->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;
char 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(u16 status)
{
switch (status & OMNIA_STS_MCU_TYPE_MASK) {
case OMNIA_STS_MCU_TYPE_STM32:
return "STM32";
case OMNIA_STS_MCU_TYPE_GD32:
return "GD32";
case OMNIA_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 {
u16 mask;
const char *name;
} features[] = {
#define _DEF_FEAT(_n, _m) { OMNIA_FEAT_ ## _n, _m }
_DEF_FEAT(EXT_CMDS, "extended control and status"),
_DEF_FEAT(WDT_PING, "watchdog pinging"),
_DEF_FEAT(LED_STATE_EXT_MASK, "peripheral LED pins reading"),
_DEF_FEAT(NEW_INT_API, "new interrupt API"),
_DEF_FEAT(POWEROFF_WAKEUP, "poweroff and wakeup"),
_DEF_FEAT(TRNG, "true random number generator"),
#undef _DEF_FEAT
};
struct i2c_client *client = mcu->client;
struct device *dev = &client->dev;
bool suggest_fw_upgrade = false;
u16 status;
int err;
/* status word holds MCU type, which we need below */
err = omnia_cmd_read_u16(client, OMNIA_CMD_GET_STATUS_WORD, &status);
if (err)
return err;
/*
* Check whether MCU firmware supports the OMNIA_CMD_GET_FEATURES
* command.
*/
if (status & OMNIA_STS_FEATURES_SUPPORTED) {
/* try read 32-bit features */
err = omnia_cmd_read_u32(client, OMNIA_CMD_GET_FEATURES,
&mcu->features);
if (err) {
/* try read 16-bit features */
u16 features16;
err = omnia_cmd_read_u16(client, OMNIA_CMD_GET_FEATURES,
&features16);
if (err)
return err;
mcu->features = features16;
} else {
if (mcu->features & OMNIA_FEAT_FROM_BIT_16_INVALID)
mcu->features &= GENMASK(15, 0);
}
} else {
dev_info(dev,
"Your board's MCU firmware does not support feature reading.\n");
suggest_fw_upgrade = true;
}
mcu->type = omnia_status_to_mcu_type(status);
dev_info(dev, "MCU type %s%s\n", mcu->type,
(mcu->features & OMNIA_FEAT_PERIPH_MCU) ?
", with peripheral resets wired" : "");
omnia_mcu_print_version_hash(mcu, true);
if (mcu->features & OMNIA_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, OMNIA_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]);
/* we can't use ether_addr_copy() because reply is not u16-aligned */
memcpy(mcu->board_first_mac, &reply[9], sizeof(mcu->board_first_mac));
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 & OMNIA_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");

View file

@ -0,0 +1,74 @@
/* 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/if_ether.h>
#include <linux/types.h>
#include <asm/byteorder.h>
struct i2c_client;
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;
};
int omnia_cmd_write_read(const struct i2c_client *client,
void *cmd, unsigned int cmd_len,
void *reply, unsigned int reply_len);
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);
}
static inline int omnia_cmd_read_u32(const struct i2c_client *client, u8 cmd,
u32 *dst)
{
__le32 reply;
int err;
err = omnia_cmd_read(client, cmd, &reply, sizeof(reply));
if (err)
return err;
*dst = le32_to_cpu(reply);
return 0;
}
static inline int omnia_cmd_read_u16(const struct i2c_client *client, u8 cmd,
u16 *dst)
{
__le16 reply;
int err;
err = omnia_cmd_read(client, cmd, &reply, sizeof(reply));
if (err)
return err;
*dst = le16_to_cpu(reply);
return 0;
}
static inline int omnia_cmd_read_u8(const struct i2c_client *client, u8 cmd,
u8 *reply)
{
return omnia_cmd_read(client, cmd, reply, sizeof(*reply));
}
#endif /* __TURRIS_OMNIA_MCU_H */

View file

@ -0,0 +1,249 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* CZ.NIC's Turris Omnia MCU I2C interface commands definitions
*
* 2024 by Marek Behún <kabel@kernel.org>
*/
#ifndef __TURRIS_OMNIA_MCU_INTERFACE_H
#define __TURRIS_OMNIA_MCU_INTERFACE_H
#include <linux/bitfield.h>
#include <linux/bits.h>
enum omnia_commands_e {
OMNIA_CMD_GET_STATUS_WORD = 0x01, /* slave sends status word back */
OMNIA_CMD_GENERAL_CONTROL = 0x02,
OMNIA_CMD_LED_MODE = 0x03, /* default/user */
OMNIA_CMD_LED_STATE = 0x04, /* LED on/off */
OMNIA_CMD_LED_COLOR = 0x05, /* LED number + RED + GREEN + BLUE */
OMNIA_CMD_USER_VOLTAGE = 0x06,
OMNIA_CMD_SET_BRIGHTNESS = 0x07,
OMNIA_CMD_GET_BRIGHTNESS = 0x08,
OMNIA_CMD_GET_RESET = 0x09,
OMNIA_CMD_GET_FW_VERSION_APP = 0x0A, /* 20B git hash number */
OMNIA_CMD_SET_WATCHDOG_STATE = 0x0B, /* 0 - disable
* 1 - enable / ping
* after boot watchdog is started
* with 2 minutes timeout
*/
/* OMNIA_CMD_WATCHDOG_STATUS = 0x0C, not implemented anymore */
OMNIA_CMD_GET_WATCHDOG_STATE = 0x0D,
OMNIA_CMD_GET_FW_VERSION_BOOT = 0x0E, /* 20B Git hash number */
OMNIA_CMD_GET_FW_CHECKSUM = 0x0F, /* 4B length, 4B checksum */
/* available if FEATURES_SUPPORTED bit set in status word */
OMNIA_CMD_GET_FEATURES = 0x10,
/* available if EXT_CMD bit set in features */
OMNIA_CMD_GET_EXT_STATUS_DWORD = 0x11,
OMNIA_CMD_EXT_CONTROL = 0x12,
OMNIA_CMD_GET_EXT_CONTROL_STATUS = 0x13,
/* available if NEW_INT_API bit set in features */
OMNIA_CMD_GET_INT_AND_CLEAR = 0x14,
OMNIA_CMD_GET_INT_MASK = 0x15,
OMNIA_CMD_SET_INT_MASK = 0x16,
/* available if FLASHING bit set in features */
OMNIA_CMD_FLASH = 0x19,
/* available if WDT_PING bit set in features */
OMNIA_CMD_SET_WDT_TIMEOUT = 0x20,
OMNIA_CMD_GET_WDT_TIMELEFT = 0x21,
/* available if POWEROFF_WAKEUP bit set in features */
OMNIA_CMD_SET_WAKEUP = 0x22,
OMNIA_CMD_GET_UPTIME_AND_WAKEUP = 0x23,
OMNIA_CMD_POWER_OFF = 0x24,
/* available if USB_OVC_PROT_SETTING bit set in features */
OMNIA_CMD_SET_USB_OVC_PROT = 0x25,
OMNIA_CMD_GET_USB_OVC_PROT = 0x26,
/* available if TRNG bit set in features */
OMNIA_CMD_TRNG_COLLECT_ENTROPY = 0x28,
/* available if CRYPTO bit set in features */
OMNIA_CMD_CRYPTO_GET_PUBLIC_KEY = 0x29,
OMNIA_CMD_CRYPTO_SIGN_MESSAGE = 0x2A,
OMNIA_CMD_CRYPTO_COLLECT_SIGNATURE = 0x2B,
/* available if BOARD_INFO it set in features */
OMNIA_CMD_BOARD_INFO_GET = 0x2C,
OMNIA_CMD_BOARD_INFO_BURN = 0x2D,
/* available only at address 0x2b (LED-controller) */
/* available only if LED_GAMMA_CORRECTION bit set in features */
OMNIA_CMD_SET_GAMMA_CORRECTION = 0x30,
OMNIA_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 */
OMNIA_CMD_SET_LED_CORRECTIONS = 0x32,
OMNIA_CMD_GET_LED_CORRECTIONS = 0x33,
};
enum omnia_flashing_commands_e {
OMNIA_FLASH_CMD_UNLOCK = 0x01,
OMNIA_FLASH_CMD_SIZE_AND_CSUM = 0x02,
OMNIA_FLASH_CMD_PROGRAM = 0x03,
OMNIA_FLASH_CMD_RESET = 0x04,
};
enum omnia_sts_word_e {
OMNIA_STS_MCU_TYPE_MASK = GENMASK(1, 0),
OMNIA_STS_MCU_TYPE_STM32 = FIELD_PREP_CONST(OMNIA_STS_MCU_TYPE_MASK, 0),
OMNIA_STS_MCU_TYPE_GD32 = FIELD_PREP_CONST(OMNIA_STS_MCU_TYPE_MASK, 1),
OMNIA_STS_MCU_TYPE_MKL = FIELD_PREP_CONST(OMNIA_STS_MCU_TYPE_MASK, 2),
OMNIA_STS_FEATURES_SUPPORTED = BIT(2),
OMNIA_STS_USER_REGULATOR_NOT_SUPPORTED = BIT(3),
OMNIA_STS_CARD_DET = BIT(4),
OMNIA_STS_MSATA_IND = BIT(5),
OMNIA_STS_USB30_OVC = BIT(6),
OMNIA_STS_USB31_OVC = BIT(7),
OMNIA_STS_USB30_PWRON = BIT(8),
OMNIA_STS_USB31_PWRON = BIT(9),
OMNIA_STS_ENABLE_4V5 = BIT(10),
OMNIA_STS_BUTTON_MODE = BIT(11),
OMNIA_STS_BUTTON_PRESSED = BIT(12),
OMNIA_STS_BUTTON_COUNTER_MASK = GENMASK(15, 13),
};
enum omnia_ctl_byte_e {
OMNIA_CTL_LIGHT_RST = BIT(0),
OMNIA_CTL_HARD_RST = BIT(1),
/* BIT(2) is currently reserved */
OMNIA_CTL_USB30_PWRON = BIT(3),
OMNIA_CTL_USB31_PWRON = BIT(4),
OMNIA_CTL_ENABLE_4V5 = BIT(5),
OMNIA_CTL_BUTTON_MODE = BIT(6),
OMNIA_CTL_BOOTLOADER = BIT(7),
};
enum omnia_features_e {
OMNIA_FEAT_PERIPH_MCU = BIT(0),
OMNIA_FEAT_EXT_CMDS = BIT(1),
OMNIA_FEAT_WDT_PING = BIT(2),
OMNIA_FEAT_LED_STATE_EXT_MASK = GENMASK(4, 3),
OMNIA_FEAT_LED_STATE_EXT = FIELD_PREP_CONST(OMNIA_FEAT_LED_STATE_EXT_MASK, 1),
OMNIA_FEAT_LED_STATE_EXT_V32 = FIELD_PREP_CONST(OMNIA_FEAT_LED_STATE_EXT_MASK, 2),
OMNIA_FEAT_LED_GAMMA_CORRECTION = BIT(5),
OMNIA_FEAT_NEW_INT_API = BIT(6),
OMNIA_FEAT_BOOTLOADER = BIT(7),
OMNIA_FEAT_FLASHING = BIT(8),
OMNIA_FEAT_NEW_MESSAGE_API = BIT(9),
OMNIA_FEAT_BRIGHTNESS_INT = BIT(10),
OMNIA_FEAT_POWEROFF_WAKEUP = BIT(11),
OMNIA_FEAT_CAN_OLD_MESSAGE_API = BIT(12),
OMNIA_FEAT_TRNG = BIT(13),
OMNIA_FEAT_CRYPTO = BIT(14),
OMNIA_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 */
OMNIA_FEAT_MCU_TYPE_MASK = GENMASK(17, 16),
OMNIA_FEAT_MCU_TYPE_STM32 = FIELD_PREP_CONST(OMNIA_FEAT_MCU_TYPE_MASK, 0),
OMNIA_FEAT_MCU_TYPE_GD32 = FIELD_PREP_CONST(OMNIA_FEAT_MCU_TYPE_MASK, 1),
OMNIA_FEAT_MCU_TYPE_MKL = FIELD_PREP_CONST(OMNIA_FEAT_MCU_TYPE_MASK, 2),
OMNIA_FEAT_FEATURES_SUPPORTED = BIT(18),
OMNIA_FEAT_USER_REGULATOR_NOT_SUPPORTED = BIT(19),
/* must not be set */
OMNIA_FEAT_FROM_BIT_16_INVALID = BIT(20),
OMNIA_FEAT_PER_LED_CORRECTION = BIT(21),
OMNIA_FEAT_USB_OVC_PROT_SETTING = BIT(22),
};
enum omnia_ext_sts_dword_e {
OMNIA_EXT_STS_SFP_nDET = BIT(0),
OMNIA_EXT_STS_LED_STATES_MASK = GENMASK(31, 12),
OMNIA_EXT_STS_WLAN0_MSATA_LED = BIT(12),
OMNIA_EXT_STS_WLAN1_LED = BIT(13),
OMNIA_EXT_STS_WLAN2_LED = BIT(14),
OMNIA_EXT_STS_WPAN0_LED = BIT(15),
OMNIA_EXT_STS_WPAN1_LED = BIT(16),
OMNIA_EXT_STS_WPAN2_LED = BIT(17),
OMNIA_EXT_STS_WAN_LED0 = BIT(18),
OMNIA_EXT_STS_WAN_LED1 = BIT(19),
OMNIA_EXT_STS_LAN0_LED0 = BIT(20),
OMNIA_EXT_STS_LAN0_LED1 = BIT(21),
OMNIA_EXT_STS_LAN1_LED0 = BIT(22),
OMNIA_EXT_STS_LAN1_LED1 = BIT(23),
OMNIA_EXT_STS_LAN2_LED0 = BIT(24),
OMNIA_EXT_STS_LAN2_LED1 = BIT(25),
OMNIA_EXT_STS_LAN3_LED0 = BIT(26),
OMNIA_EXT_STS_LAN3_LED1 = BIT(27),
OMNIA_EXT_STS_LAN4_LED0 = BIT(28),
OMNIA_EXT_STS_LAN4_LED1 = BIT(29),
OMNIA_EXT_STS_LAN5_LED0 = BIT(30),
OMNIA_EXT_STS_LAN5_LED1 = BIT(31),
};
enum omnia_ext_ctl_e {
OMNIA_EXT_CTL_nRES_MMC = BIT(0),
OMNIA_EXT_CTL_nRES_LAN = BIT(1),
OMNIA_EXT_CTL_nRES_PHY = BIT(2),
OMNIA_EXT_CTL_nPERST0 = BIT(3),
OMNIA_EXT_CTL_nPERST1 = BIT(4),
OMNIA_EXT_CTL_nPERST2 = BIT(5),
OMNIA_EXT_CTL_PHY_SFP = BIT(6),
OMNIA_EXT_CTL_PHY_SFP_AUTO = BIT(7),
OMNIA_EXT_CTL_nVHV_CTRL = BIT(8),
};
enum omnia_int_e {
OMNIA_INT_CARD_DET = BIT(0),
OMNIA_INT_MSATA_IND = BIT(1),
OMNIA_INT_USB30_OVC = BIT(2),
OMNIA_INT_USB31_OVC = BIT(3),
OMNIA_INT_BUTTON_PRESSED = BIT(4),
OMNIA_INT_SFP_nDET = BIT(5),
OMNIA_INT_BRIGHTNESS_CHANGED = BIT(6),
OMNIA_INT_TRNG = BIT(7),
OMNIA_INT_MESSAGE_SIGNED = BIT(8),
OMNIA_INT_LED_STATES_MASK = GENMASK(31, 12),
OMNIA_INT_WLAN0_MSATA_LED = BIT(12),
OMNIA_INT_WLAN1_LED = BIT(13),
OMNIA_INT_WLAN2_LED = BIT(14),
OMNIA_INT_WPAN0_LED = BIT(15),
OMNIA_INT_WPAN1_LED = BIT(16),
OMNIA_INT_WPAN2_LED = BIT(17),
OMNIA_INT_WAN_LED0 = BIT(18),
OMNIA_INT_WAN_LED1 = BIT(19),
OMNIA_INT_LAN0_LED0 = BIT(20),
OMNIA_INT_LAN0_LED1 = BIT(21),
OMNIA_INT_LAN1_LED0 = BIT(22),
OMNIA_INT_LAN1_LED1 = BIT(23),
OMNIA_INT_LAN2_LED0 = BIT(24),
OMNIA_INT_LAN2_LED1 = BIT(25),
OMNIA_INT_LAN3_LED0 = BIT(26),
OMNIA_INT_LAN3_LED1 = BIT(27),
OMNIA_INT_LAN4_LED0 = BIT(28),
OMNIA_INT_LAN4_LED1 = BIT(29),
OMNIA_INT_LAN5_LED0 = BIT(30),
OMNIA_INT_LAN5_LED1 = BIT(31),
};
enum omnia_cmd_poweroff_e {
OMNIA_CMD_POWER_OFF_POWERON_BUTTON = BIT(0),
OMNIA_CMD_POWER_OFF_MAGIC = 0xdead,
};
enum omnia_cmd_usb_ovc_prot_e {
OMNIA_CMD_xET_USB_OVC_PROT_PORT_MASK = GENMASK(3, 0),
OMNIA_CMD_xET_USB_OVC_PROT_ENABLE = BIT(4),
};
#endif /* __TURRIS_OMNIA_MCU_INTERFACE_H */