From 97dbf16bd2564952d0e432aa3d62bb3ea7038762 Mon Sep 17 00:00:00 2001 From: Steven Portley Date: Fri, 1 May 2026 15:48:27 -0700 Subject: [PATCH] Add host command setting GPIO drive strength This adds htool support for sending a host command for changing the drive strength for any pad on Earlgrey. --- examples/BUILD | 1 + examples/htool.c | 47 ++++++++++++++++++++++++++++++++++ protocol/BUILD | 10 ++++++++ protocol/gpio_drive_strength.c | 31 ++++++++++++++++++++++ protocol/gpio_drive_strength.h | 41 +++++++++++++++++++++++++++++ protocol/meson.build | 3 ++- 6 files changed, 132 insertions(+), 1 deletion(-) create mode 100644 protocol/gpio_drive_strength.c create mode 100644 protocol/gpio_drive_strength.h diff --git a/examples/BUILD b/examples/BUILD index 97b393b..f92b9e7 100644 --- a/examples/BUILD +++ b/examples/BUILD @@ -243,6 +243,7 @@ cc_binary( "//protocol:authz_record", "//protocol:chipinfo", "//protocol:console", + "//protocol:gpio_drive_strength", "//protocol:controlled_storage", "//protocol:dfu_check", "//protocol:dfu_hostcmd", diff --git a/examples/htool.c b/examples/htool.c index 22ec4c7..4cd8393 100644 --- a/examples/htool.c +++ b/examples/htool.c @@ -60,6 +60,7 @@ #include "protocol/chipinfo.h" #include "protocol/console.h" #include "protocol/controlled_storage.h" +#include "protocol/gpio_drive_strength.h" #include "protocol/hello.h" #include "protocol/opentitan_version.h" #include "protocol/progress.h" @@ -759,6 +760,33 @@ int htool_controlled_storage_delete(const struct htool_invocation* inv) { return libhoth_controlled_storage_delete(dev, slot); } +static int command_set_gpio_drive_strength(const struct htool_invocation* inv) { + struct libhoth_device* dev = htool_libhoth_device(); + if (!dev) { + return -1; + } + + uint32_t pad; + uint32_t strength; + + if (htool_get_param_u32(inv, "pad", &pad) || + htool_get_param_u32(inv, "strength", &strength)) { + return -1; + } + + if (strength > MAX_GPIO_DRIVE_STRENGTH) { + fprintf(stderr, "Drive strength can only be up to 15.\n"); + return -1; + } + + if (pad > 255) { + fprintf(stderr, "Pad must be a single byte.\n"); + return -1; + } + + return libhoth_set_gpio_drive_strength(dev, (uint8_t)pad, (uint8_t)strength); +} + static int command_hello(const struct htool_invocation* inv) { struct libhoth_device* dev = htool_libhoth_device(); if (!dev) { @@ -1565,6 +1593,25 @@ static const struct htool_cmd CMDS[] = { {}}, .func = htool_controlled_storage_delete, }, + { + .verbs = (const char*[]){"gpio", "set_drive_strength", NULL}, + .desc = "Set GPIO drive strength", + .params = + (const struct htool_param[]){ + {.type = HTOOL_FLAG_VALUE, + .ch = 'p', + .name = "pad", + .default_value = NULL, + .desc = "The GPIO pad to configure. (0-8 => IOA0-8 | 9-21 => " + "IOB0-12 | 22-34 => IOC0-12 | 35-46 => IOR0-13)"}, + {.type = HTOOL_FLAG_VALUE, + .ch = 's', + .name = "strength", + .default_value = NULL, + .desc = "The drive strength to set from 0 - 15"}, + {}}, + .func = command_set_gpio_drive_strength, + }, { .verbs = (const char*[]){"hello", NULL}, .desc = "A test function to send and receive an integer", diff --git a/protocol/BUILD b/protocol/BUILD index 3c15d63..21a550f 100644 --- a/protocol/BUILD +++ b/protocol/BUILD @@ -406,6 +406,16 @@ cc_test( ], ) +cc_library( + name = "gpio_drive_strength", + srcs = ["gpio_drive_strength.c"], + hdrs = ["gpio_drive_strength.h"], + deps = [ + ":host_cmd", + "//transports:libhoth_device", + ], +) + cc_library( name = "opentitan_version", srcs = ["opentitan_version.c"], diff --git a/protocol/gpio_drive_strength.c b/protocol/gpio_drive_strength.c new file mode 100644 index 0000000..ac3845a --- /dev/null +++ b/protocol/gpio_drive_strength.c @@ -0,0 +1,31 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "protocol/gpio_drive_strength.h" + +#include +#include + +#include "protocol/host_cmd.h" + +int libhoth_set_gpio_drive_strength(struct libhoth_device* const dev, + const uint8_t pad, const uint8_t strength) { + const struct hoth_request_set_gpio_drive_strength request = { + .pad = pad, + .strength = strength, + }; + return libhoth_hostcmd_exec(dev, HOTH_CMD_SET_GPIO_DRIVE_STRENGTH, + /*version=*/0, &request, sizeof(request), + /*response=*/NULL, /*response_size=*/0, NULL); +} diff --git a/protocol/gpio_drive_strength.h b/protocol/gpio_drive_strength.h new file mode 100644 index 0000000..6f30dff --- /dev/null +++ b/protocol/gpio_drive_strength.h @@ -0,0 +1,41 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _LIBHOTH_PROTOCOL_GPIO_DRIVE_STRENGTH_H_ +#define _LIBHOTH_PROTOCOL_GPIO_DRIVE_STRENGTH_H_ + +#include + +#include "protocol/host_cmd.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define HOTH_CMD_SET_GPIO_DRIVE_STRENGTH 0x3E56 +#define MAX_GPIO_DRIVE_STRENGTH 0xF + +struct hoth_request_set_gpio_drive_strength { + uint8_t pad; + uint8_t strength; +} __hoth_align1; + +int libhoth_set_gpio_drive_strength(struct libhoth_device* dev, uint8_t pad, + uint8_t strength); + +#ifdef __cplusplus +} +#endif + +#endif // _LIBHOTH_PROTOCOL_GPIO_DRIVE_STRENGTH_H_ diff --git a/protocol/meson.build b/protocol/meson.build index 86c0eaf..64b1b33 100644 --- a/protocol/meson.build +++ b/protocol/meson.build @@ -24,7 +24,8 @@ protocol_srcs = [ 'dfu_check.c', 'firmware_update.c', 'util.c', - 'console.c' + 'console.c', + 'gpio_drive_strength.c' ] incdir = libhoth_include_dirs