[PATCH 1/2] board: traverse: add Ten64 board controller driver

Priyanka Jain (OSS) priyanka.jain at oss.nxp.com
Tue Nov 9 12:59:18 CET 2021



>-----Original Message-----
>From: U-Boot <u-boot-bounces at lists.denx.de> On Behalf Of Mathew McBride
>Sent: Wednesday, November 3, 2021 10:59 AM
>To: u-boot at lists.denx.de; Priyanka Jain <priyanka.jain at nxp.com>
>Cc: Mathew McBride <matt at traverse.com.au>
>Subject: [PATCH 1/2] board: traverse: add Ten64 board controller driver
>
>Traverse Technologies Ten64 family boards use a microcontroller to control low
>level board functions like startup and reset, as well as holding details such as the
>board MAC address.
>
>Communication between the CPU and microcontroller is via I2C.
>
>To keep the driver structure clean between the Ten64 board file, DM_I2C, and a
>future utility command, this driver has been implemented as a misc uclass device.
>
>Signed-off-by: Mathew McBride <matt at traverse.com.au>
>---
> board/traverse/common/Kconfig            |   6 +
> board/traverse/common/Makefile           |   1 +
> board/traverse/common/ten64-controller.h |  28 +++
>board/traverse/common/ten64_controller.c | 238 +++++++++++++++++++++++
> 4 files changed, 273 insertions(+)
> create mode 100644 board/traverse/common/Kconfig  create mode 100644
>board/traverse/common/Makefile  create mode 100644
>board/traverse/common/ten64-controller.h
> create mode 100644 board/traverse/common/ten64_controller.c
>
>diff --git a/board/traverse/common/Kconfig b/board/traverse/common/Kconfig
>new file mode 100644 index 0000000000..d34832bd0d
>--- /dev/null
>+++ b/board/traverse/common/Kconfig
>@@ -0,0 +1,6 @@
>+config TEN64_CONTROLLER
>+	bool "Enable Ten64 board controller driver"
>+	depends on TARGET_TEN64
>+	help
>+		Support for the board microcontroller on the Traverse
>+		Ten64 family of boards.
>diff --git a/board/traverse/common/Makefile
>b/board/traverse/common/Makefile new file mode 100644 index
>0000000000..d31e3535b9
>--- /dev/null
>+++ b/board/traverse/common/Makefile
>@@ -0,0 +1 @@
>+obj-$(CONFIG_TEN64_CONTROLLER) += ten64_controller.o
>diff --git a/board/traverse/common/ten64-controller.h
>b/board/traverse/common/ten64-controller.h
>new file mode 100644
>index 0000000000..fed6af470d
>--- /dev/null
>+++ b/board/traverse/common/ten64-controller.h
>@@ -0,0 +1,28 @@
>+/* SPDX-License-Identifier: GPL-2.0+ */ #ifndef TEN64_CNTRL_H #define
>+TEN64_CNTRL_H
>+
>+/**
>+ * struct t64uc_board_info - Board Information Structure
>+ * @mac: Base MAC address
>+ * @cpuId: Microcontroller unique serial number
>+ * @fwversion_major: Microcontroller version number (Major)
>+ * @fwversion_minor: Microcontroller version number (Minor)
>+ * @fwversion_patch: Microcontroller version number (Patch)  */ struct
>+t64uc_board_info {
>+	u8 mac[6];
>+	u32 cpuId[4];
>+	u8 fwversion_major;
>+	u8 fwversion_minor;
>+	u8 fwversion_patch;
>+} __packed;
>+
>+enum {
>+	TEN64_CNTRL_GET_BOARD_INFO,
>+	TEN64_CNTRL_10G_OFF,
>+	TEN64_CNTRL_10G_ON,
>+	TEN64_CNTRL_SET_NEXT_BOOTSRC
>+};
>+
>+#endif
>diff --git a/board/traverse/common/ten64_controller.c
>b/board/traverse/common/ten64_controller.c
>new file mode 100644
>index 0000000000..11e068f94f
>--- /dev/null
>+++ b/board/traverse/common/ten64_controller.c
>@@ -0,0 +1,238 @@
>+// SPDX-License-Identifier: GPL-2.0+
>+
>+/* Ten64 Board Microcontroller Driver
>+ * Copyright 2021 Traverse Technologies Australia
>+ *
>+ */
>+
>+#include <common.h>
>+#include <dm.h>
>+#include <misc.h>
>+#include <i2c.h>
>+#include <hexdump.h>
>+#include <dm/device_compat.h>
>+#include <inttypes.h>
>+#include <linux/delay.h>
>+
>+#include "ten64-controller.h"
>+
>+/* Microcontroller command set and structure
>+ * These should not be used outside this file  */
>+
>+#define T64_UC_DATA_MAX_SIZE            128U
>+#define T64_UC_API_MSG_HEADER_SIZE      4U
>+#define T64_UC_API_HEADER_PREAMB        0xcabe
>+
>+#define TEN64_UC_CMD_SET_BOARD_MAC		0x10
>+#define TEN64_UC_CMD_GET_BOARD_INFO		0x11
>+
>+#define TEN64_UC_CMD_GET_STATE			0x20
>+#define TEN64_UC_CMD_SET_RESET_BTN_HOLD_TIME	0x21
>+#define TEN64_UC_CMD_ENABLE_RESET_BUTTON	0x22
>+#define TEN64_UC_CMD_SET_NEXT_BOOTSRC		0x23
>+#define TEN64_UC_CMD_ENABLE_10G 		0x24
>+
>+#define TEN64_UC_CMD_FWUP_GET_INFO		0xA0
>+#define TEN64_UC_CMD_FWUP_INIT			0xA1
>+#define TEN64_UC_CMD_FWUP_XFER			0xA2
>+#define TEN64_UC_CMD_FWUP_CHECK 		0xA3
>+#define TEN64_UC_CMD_FWUPBOOT			0xA
>+
>+/** struct t64uc_message - Wire Format for microcontroller messages
>+ * @preamb: Message preamble (always 0xcabe)
>+ * @cmd: Command to invoke
>+ * @len: Length of data
>+ * @data: Command data, up to 128 bytes  */ struct t64uc_message {
>+	u16 preamb;
>+	u8 cmd;
>+	u8 len;
>+	u8 data[T64_UC_DATA_MAX_SIZE];
>+}  __packed;
>+
>+#define	T64_CTRL_IO_SET		1U
>+#define	T64_CTRL_IO_CLEAR	2U
>+#define	T64_CTRL_IO_TOGGLE	3U
>+#define	T64_CTRL_IO_RESET	4U
>+#define	T64_CTRL_IO_UNKNOWN	5U
>+
>+/** struct t64uc_board_10g_enable - Wrapper for 10G enable command
>+ * @control: state to set the 10G retimer - either
>+ *	     T64_CTRL_IO_CLEAR (0x02) for off or
>+ *	     T64_CTRL_IO_SET (0x01) for on.
>+ *
>+ * This struct exists to simplify the wrapping of the
>+ * command value into a microcontroller message and passing into
>+ * functions.
>+ */
>+struct t64uc_board_10g_enable {
>+	u8 control;
>+} __packed;
>+
>+/** ten64_controller_send_recv_command() - Wrapper function to
>+ * send a command to the microcontroller.
>+ * @uc_chip: the DM I2C chip handle for the microcontroller
>+ * @uc_cmd: the microcontroller API command code
>+ * @uc_cmd_data: pointer to the data struct for this command
>+ * @uc_data_len: size of command data struct
>+ * @return_data: place to store response from microcontroller, NULL if
>+not expected
>+ * @expected_return_len: expected size of microcontroller command
>+response
>+ * @return_message_wait: wait this long (in us) before reading the
>+response
>+ *
>+ * Invoke a microcontroller command and receive a response.
>+ * This function includes communicating with the microcontroller over
>+ * I2C and encoding a message in the wire format.
>+ *
>+ * Return: 0 if successful, error code otherwise.
>+ * Returns -EBADMSG if the microcontroller response could not be
>+validated,
>+ * other error codes may be passed from dm_i2c_xfer()  */ static int
>+ten64_controller_send_recv_command(struct udevice *ucdev, u8 uc_cmd,
>+					      void *uc_cmd_data, u8
>cmd_data_len,
>+					      void *return_data, u8
>expected_return_len,
>+					      u16 return_message_wait)
>+{
>+	int ret;
>+	struct t64uc_message send, recv;
>+	struct i2c_msg command_message, return_message;
>+	struct dm_i2c_chip *chip = dev_get_parent_plat(ucdev);
>+
>+	dev_dbg(ucdev, "%s sending cmd %02X len %d\n", __func__, uc_cmd,
>+cmd_data_len);
>+
>+	send.preamb = T64_UC_API_HEADER_PREAMB;
>+	send.cmd = uc_cmd;
>+	send.len = cmd_data_len;
>+	if (uc_cmd_data && cmd_data_len > 0)
>+		memcpy(send.data, uc_cmd_data, cmd_data_len);
>+
>+	command_message.addr = chip->chip_addr;
>+	command_message.len = T64_UC_API_MSG_HEADER_SIZE + send.len;
>+	command_message.buf = (void *)&send;
>+	command_message.flags = I2C_M_STOP;
>+
>+	ret = dm_i2c_xfer(ucdev, &command_message, 1);
>+	if (!return_data)
>+		return ret;
>+
>+	udelay(return_message_wait);
>+
>+	return_message.addr = chip->chip_addr;
>+	return_message.len = T64_UC_API_MSG_HEADER_SIZE +
>expected_return_len;
>+	return_message.buf = (void *)&recv;
>+	return_message.flags = I2C_M_RD;
>+
>+	ret = dm_i2c_xfer(ucdev, &return_message, 1);
>+	if (ret)
>+		return ret;
>+
>+	if (recv.preamb != T64_UC_API_HEADER_PREAMB) {
>+		dev_err(ucdev, "%s: No preamble received in microcontroller
>response\n",
>+			__func__);
>+		return -EBADMSG;
>+	}
>+	if (recv.cmd != uc_cmd) {
>+		dev_err(ucdev, "%s: command response mismatch, got %02X
>expecting %02X\n",
>+			__func__, recv.cmd, uc_cmd);
>+		return -EBADMSG;
>+	}
>+	if (recv.len != expected_return_len) {
>+		dev_err(ucdev, "%s: received message has unexpected length,
>got %d expected %d\n",
>+			__func__, recv.len, expected_return_len);
>+		return -EBADMSG;
>+	}
>+	memcpy(return_data, recv.data, expected_return_len);
>+	return ret;
>+}
>+
>+/** ten64_controller_send_command() - Send command to microcontroller
>+without
>+ * expecting a response (for example, invoking a control command)
>+ * @uc_chip: the DM I2C chip handle for the microcontroller
>+ * @uc_cmd: the microcontroller API command code
>+ * @uc_cmd_data: pointer to the data struct for this command
>+ * @uc_data_len: size of command data struct  */ static int
>+ten64_controller_send_command(struct udevice *ucdev, u8 uc_cmd,
>+					 void *uc_cmd_data, u8 cmd_data_len)
>{
>+	return ten64_controller_send_recv_command(ucdev, uc_cmd,
>+						  uc_cmd_data, cmd_data_len,
>+						  NULL, 0, 0);
>+}
>+
>+/** ten64_controller_get_board_info() - Get board information from
>+microcontroller
>+ * @dev: The microcontroller device handle
>+ * @out: Pointer to a t64uc_board_info struct that has been allocated
>+by the caller  */ static int ten64_controller_get_board_info(struct
>+udevice *dev, struct t64uc_board_info *out) {
>+	int ret;
>+
>+	ret = ten64_controller_send_recv_command(dev,
>TEN64_UC_CMD_GET_BOARD_INFO,
>+						 NULL, 0, out,
>+						 sizeof(struct t64uc_board_info),
>+						 10000);
>+	if (ret) {
>+		dev_err(dev, "%s unable to send board info command: %d\n",
>+			__func__, ret);
>+		return ret;
>+	}
>+
>+	return 0;
>+}
>+
>+/**
>+ * ten64_controller_10g_enable_command() - Sends a 10G (Retimer) enable
>+command
>+ * to the microcontroller.
>+ * @ucdev: The microcontroller udevice
>+ * @value: The value flag for the 10G state  */ static int
>+ten64_controller_10g_enable_command(struct udevice *ucdev, u8 value) {
>+	int ret;
>+	struct t64uc_board_10g_enable enable_msg;
>+
>+	enable_msg.control = value;
>+
>+	ret = ten64_controller_send_command(ucdev,
>TEN64_UC_CMD_ENABLE_10G,
>+					    &enable_msg, sizeof(enable_msg));
>+	if (ret) {
>+		dev_err(ucdev, "ERROR sending uC 10G Enable message: %d\n",
>ret);
>+		return -1;
>+	}
>+
>+	return 0;
>+}
>+
>+int ten64_controller_call(struct udevice *dev, int msgid, void *tx_msg, int
>tx_size,
>+			  void *rx_msg, int rx_size)
>+{
>+	switch (msgid) {
>+	case TEN64_CNTRL_GET_BOARD_INFO:
>+		return ten64_controller_get_board_info(dev, (struct
>t64uc_board_info *)rx_msg);
>+	case TEN64_CNTRL_10G_OFF:
>+		return ten64_controller_10g_enable_command(dev,
>T64_CTRL_IO_CLEAR);
>+	case TEN64_CNTRL_10G_ON:
>+		return ten64_controller_10g_enable_command(dev,
>T64_CTRL_IO_SET);
>+	default:
>+		dev_err(dev, "%s: Unknown operation %d\n", __func__, msgid);
>+	}
>+	return -EINVAL;
>+}
>+
>+static struct misc_ops ten64_ctrl_ops  = {
>+	.call = ten64_controller_call
>+};
>+
>+static const struct udevice_id ten64_controller_ids[] = {
>+	{.compatible = "traverse,ten64-controller"},
>+	{}
>+};
>+
>+U_BOOT_DRIVER(ten64_controller) = {
>+	.name = "ten64-controller-i2c",
>+	.id = UCLASS_MISC,
>+	.of_match = ten64_controller_ids,
>+	.ops = &ten64_ctrl_ops
>+};
>--
>2.30.1

Many checkpatch warnings and CHECKS in the series. Kindly help to fix.

Regards
Priyanka


More information about the U-Boot mailing list