[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