Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

firmware: scmi: add base proto, scmi sample, smc/hvc transport and reset proto #78293

Closed
wants to merge 13 commits into from

Conversation

GrygiriiS
Copy link

Hi

The main intention of this work is to introduce ARM SCMI SMC/HVC based transport and SCMI sample application, So SCMI can be enabled on RPI5 platform with SCMI compliant firmware [1]. Particularly It's important in case Zephyr is executed in virtualized environment (under XEN in our case) , which requires HW partitioning.

This PR adds following major functionality to the SCMI code:

  • Base protocol support
  • Reset domain management protocol support
  • ARM SCMI SMC/HVC based transport layer
  • SCMI Sample application with shell interface (see example below)

Patches:

  • Patches 1-7 are updates/optimization for existing SCMI code in preparation of adding more functionality
  • patch 8 introduces support for SCMI Base protocol
  • patch 9 introduces SCMI sample application 'samples/drivers/firmware/arm_scmi' which demonstrates the usage of ARM SCMI. It provides access to the ARM SCMI shell interface for demo and testing purposes of different ARM SCMI protocols.
  • Patches 10-11 introduce support for SCMI SMC/HVC based transport.
  • Patches 12-13 introduce support for SCMI Reset domain management protocol

SCMI Sample application output:

	uart:~$ arm_scmi base
	base - SCMI Base proto commands.
	Subcommands:
	  revision           : SCMI Base get revision info
	                      Usage: arm_scmi base revision

	  discover_agent     : SCMI Base discover an agent
	                      Usage: arm_scmi base discover_agent [agent_id]

	  device_permission  : SCMI Base set an agent permissions to access device
	                      Usage: arm_scmi base discover_agent <agent_id> <device_id>
	                      <allow := 0|1>

	  reset_agent_cfg    : SCMI Base reset an agent configuration
	                      Usage: arm_scmi base reset_agent_cfg <agent_id>
	                      <reset_perm := 0|1>

	uart:~$ arm_scmi base revision
	ARM SCMI base protocol v0002.0000
	  vendor        :EPAM
	  subvendor     :
	  fw version    :0x40
	  protocols     :2
	  num_agents    :8

	uart:~$ arm_scmi reset
	reset - SCMI Reset proto commands.
	Subcommands:
	  revision   : SCMI Reset proto show revision information
	              Usage: arm_scmi reset revision

	  list       : SCMI Reset domains list
	              Usage: arm_scmi reset list

	  info       : SCMI Reset domain show info
	              Usage: arm_scmi reset info <domain_id>

	  assert     : SCMI Reset domain assert
	              Usage: arm_scmi reset assert <domain_id>

	  deassert   : SCMI Reset domain de-assert
	              Usage: arm_scmi reset deassert <domain_id>

	  autoreset  : SCMI Reset domain Autonomous reset
	              Usage: arm_scmi reset autoreset <domain_id>

        uart:~$ arm_scmi reset revision
	ARM SCMI Reset protocol version 0x0001.0000 num_domains:4

[1] https://github.com/xen-troops/arm-trusted-firmware/tree/rpi5_dev

@GrygiriiS
Copy link
Author

GrygiriiS commented Sep 11, 2024

@@ -17,6 +17,25 @@
#include <stdint.h>
#include <errno.h>

#define SCMI_MAX_STR_SIZE 64
#define SCMI_SHORT_NAME_MAX_SIZE 16

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think should be in a separate patch. Initial patch should be for removing SCMI_FIELD_MAKE.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've moved defines in Base proto patch (first user) and retested build of every patch.

Grygorii Strashko added 13 commits September 12, 2024 14:48
Move SCMI protocols Kconfig options into separate file Kconfig.proto to
improve code maintainability.

Signed-off-by: Grygorii Strashko <grygorii_strashko@epam.com>
The SCMI core defines custom SCMI_FIELD_MAKE macro while Zephyr provides
generic FIELD_GET/FIELD_PREP macro.

Hence, use generic FIELD_GET/FIELD_PREP and drop SCMI_FIELD_MAKE. This also
required to add proper SCMI message header definitions.

Signed-off-by: Grygorii Strashko <grygorii_strashko@epam.com>
Now the SCMI message header is constructed inside SCMI protocol helpers
APIs which doesn't know how to fill "token" field in SCMI message header.
As result the "token" considered to be always 0 in
scmi_shmem_read_message() wich compares RX header with TX header.

This patch adds possibility to generate and process "token" filed of
the SCMI message header as part of transport layer functionality.
The new callback .channel_get_token() and transport API
scmi_transport_channel_get_token() is introduced, so transport layer can
provide "token" value to the SCMI core which is injected in the SCMI
message header during transfer.

The SCMI mailbox transport driver updated with stub which always returns 0
to keep existing behavior intact.

Signed-off-by: Grygorii Strashko <grygorii_strashko@epam.com>
Add debug prints to SCMI shmem driver to see shmem contents before/after
xfer.

Signed-off-by: Grygorii Strashko <grygorii_strashko@epam.com>
Now the SCMI shmem driver expects that Platfrom will return exactly the
same amount of data as specified in RX struct scmi_message-> len.
But that is not true, as for some SCMI messages amount of return data can
vary (for example: BASE_DISCOVER_LIST_PROTOCOLS or CLOCK_DESCRIBE_RATES).
It can be less than rx_msg->len.

In general, the Platform will try to fill as more reply data as shmem can
fit, but no more than maximum SCMI msg size which is Platform specific
(often 128 bytes).

Hence, fix SCMI shmem driver to account that the Platform may return less
data than expected, but still fail if it's more that rx_msg->len.

Signed-off-by: Grygorii Strashko <grygorii_strashko@epam.com>
The SCMI protocols defines the "status" field for every reply (RX
message, type SCMI_COMMAND).
The current SCMI implementation defines "status" field for every reply (RX
message) also and handles it in Protocol helpers which adds a lot of
repeated code. The same can be done at transport layer which allows to
simplify SCMI code.

This patch adds "status' field to the struct scmi_message, which is filled
by SCMI shmem driver and processed by .read_message() callbacks.
The Protocol helpers do not need to process "status" any more as
scmi_send_message() will return proper error code if Platform fails.

Signed-off-by: Grygorii Strashko <grygorii_strashko@epam.com>
Completely drop RX message "status" processing from protocol helpers.

Signed-off-by: Grygorii Strashko <grygorii_strashko@epam.com>
This patch adds support for SCMI Base protocol.
It provides helpers for:
- obtaining SCMI firmware revision information: only base protocol version
or full if CONFIG_ARM_SCMI_BASE_EXT_REV=y
- agent management helpers if CONFIG_ARM_SCMI_BASE_AGENT_HELPERS=y.
  scmi_base_discover_agent()
  scmi_base_device_permission()
  scmi_base_reset_agent_cfg()

Signed-off-by: Grygorii Strashko <grygorii_strashko@epam.com>
Add ARM SCMI shell sample application.

Signed-off-by: Grygorii Strashko <grygorii_strashko@epam.com>
Add DT bindings for ARM System Control and Management Interface (SCMI)
with SMC/HVC shmem based transport and for Reset domain management
protocol.

Signed-off-by: Grygorii Strashko <grygorii_strashko@epam.com>
This patch adds SCMI SMC/HVC shmem based transport which works with SCMI
compliant ARM TF firmware with ARM SMC/HVC transport.

The SCMI core updated to support the case when it should always work in
polling mode as the SMC/HVC transport always completes request on exit
from SMC/HVC call.

Signed-off-by: Grygorii Strashko <grygorii_strashko@epam.com>
This patch adds SCMI Reset domain management protocol helpers and Zephyr
Reset Controller driver, which uses these helpers.

Signed-off-by: Grygorii Strashko <grygorii_strashko@epam.com>
Add ARM SCMI Reset shell interface for demo and testing purposes, which is
defined as sub-command of *arm_scmi* command.

The ARM SCMI Reset shell interface defined as following:

  $arm_scmi reset
  reset - SCMI Reset proto commands.
  Subcommands:
    revision   : SCMI Reset proto show revision information
                Usage: arm_scmi reset revision

    list       : SCMI Reset domains list
                Usage: arm_scmi reset list

    info       : SCMI Reset domain show info
                Usage: arm_scmi reset info <domain_id>

    assert     : SCMI Reset domain assert
                Usage: arm_scmi reset assert <domain_id>

    deassert   : SCMI Reset domain de-assert
                Usage: arm_scmi reset deassert <domain_id>

    autoreset  : SCMI Reset domain Autonomous reset
                Usage: arm_scmi reset autoreset <domain_id>

Signed-off-by: Grygorii Strashko <grygorii_strashko@epam.com>
@GrygiriiS
Copy link
Author

Also forgot to note that some generic changes in this PR will conflict with #77437.

Copy link
Collaborator

@LaurentiuM1234 LaurentiuM1234 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work! Loving the new samples. Messed around a bit with them on the imx95 board.
Left some comments below.

Also, can you please update the documentation? I think it would be worth mentioning the newly supported protocols and perhaps the samples?

@bjarki-andreasen can you please have a look as well? Thanks!

LE: can you please rebase as well? The imx95 support (another SCMI-based platform) was merged recently and might require a rebase for the twister tests to run for that as well.

(SCMI_FIELD_MAKE(fid_valid, BIT(1), 10) | \
SCMI_FIELD_MAKE(cfg_num, GENMASK(7, 0), 2) | \
SCMI_FIELD_MAKE(selector, GENMASK(1, 0), 0))
#define SCMI_PINCTRL_CONFIG_ATTRIBUTES(fid_valid, cfg_num, selector) \
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be:

#define SCMI_PINCTRL_CONFIG_ATTRIBUTES(fid_valid, cfg_num, selector)\
             (FIELD_PREP(BIT(10), fid_valid) | FIELD_PREP(GENMASK(9, 2), cfg_num) |
              FIELD_PREP(GENMASK(1, 0), selector))

@@ -76,6 +76,8 @@ int scmi_shmem_read_message(const struct device *shmem, struct scmi_message *msg
return -EINVAL;
}

LOG_HEXDUMP_DBG((void *)layout, 64, "shmem before read");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if shmem size if < 64 bytes? Should use MIN(64, shmem_size).
Also, should probably add a macro for the magic number. Something like SHMEM_DEBUG_DUMP_BYTES.

@@ -180,6 +184,7 @@ static int scmi_shmem_init(const struct device *dev)
}

device_map(&data->regmap, cfg->phys_addr, cfg->size, K_MEM_CACHE_NONE);
LOG_DBG("shmem phys:%lx dev:%lx", cfg->phys_addr, data->regmap);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be virt instead of dev.

Also, is this really useful? You should be able to see the shmem area in the DTS.


mbox_chan = chan->data;

return scmi_shmem_read_message(mbox_chan->shmem, msg);
ret = scmi_shmem_read_message(mbox_chan->shmem, msg);
if (!ret && msg->status != SCMI_SUCCESS) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand that this removes some redundant code from protocols but I really don't think the transport layer should be responsible for checking the status of the messages. IMO all it should do is check if there were errors with the data transmission/retrieval.

Also, what if ret != 0?

@@ -98,8 +98,10 @@ int scmi_shmem_read_message(const struct device *shmem, struct scmi_message *msg
return -EINVAL;
}

msg->status = SCMI_SUCCESS;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's this for? You're overwriting the message status anyways.


config ARM_SCMI_BASE_HELPERS
bool "Helper functions for SCMI base protocol"
default y
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should depend on one of the transports

if (ret < 0) {
LOG_ERR("failed to wait for msg reply");
goto out_release_mutex;
if (!scmi_transport_channel_is_polling(proto->transport, proto->tx)) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All transport channels should support polling mode because the send_message function is forced to poll in PRE_KERNEL so this function should always return true. As such, I suggest renaming to scmi_transport_channel_is_polling_only.

}
} else {
while (!scmi_transport_channel_is_free(proto->transport, proto->tx)) {
k_cpu_idle();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why go into idle mode? What if there's more work to do? I'd suggest using k_yield.

#include <zephyr/drivers/reset.h>
#include <zephyr/shell/shell.h>

#if defined(CONFIG_DT_HAS_ARM_SCMI_RESET_ENABLED)
Copy link
Collaborator

@LaurentiuM1234 LaurentiuM1234 Sep 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should rather depend on RESET_ARM_SCMI otherwise you'd just end up with a build error if built w/o CONFIG_RESET=y. Also, might be able to handle this using Kconfig/CMakeLists.txt.

LE: if that's not possible then can just check if CONFIG_RESET_ARM_SCMI is set. Otherwise, just have a build assert failure.


#include <zephyr/drivers/firmware/scmi/reset.h>
#include <zephyr/drivers/reset.h>
#include <zephyr/shell/shell.h>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we have this under a reset directory? Same as base basically.

Copy link

This pull request has been marked as stale because it has been open (more than) 60 days with no activity. Remove the stale label or add a comment saying that you would like to have the label removed otherwise this pull request will automatically be closed in 14 days. Note, that you can always re-open a closed pull request at any time.

@github-actions github-actions bot added the Stale label Jan 18, 2025
@github-actions github-actions bot closed this Feb 1, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants