This document describes the end-to-end flow for adding new PM API firmware and how it can be used in any Linux driver.
Table of Contents
Prerequisites
Knowledge of Versal ACAP Platform Management Software Architecture. Please refer below sections from Versal ACAP system software developers guide
Adding a new PM API
To add a new API, changes in the below components are required.
XilPM server
ATF
Linux ZynqMP Firmware driver
ZynqMP Firmware Driver is used for both ZynqMP and Versal Platform
Changes in XilPM server
Define new PM API ID
Firs, user need to define new PM API ID.
For Versal PM API IDs are defined in xpm_defs.h
Example: API ID: PM_IOCTL
Add new PM API ID at the end of list like PM_ACTIVATE_SUBSYSTEM in list.
Update PM_API_MAX as per new PM API ID in xpm_defs.h at here.
Implement the PM API function
Once a new PM API ID is defined, implement the API function
Declare a function prototype in xpm_api.h.
Example of Function Declaration: XPm_DevIoctl().
Define the function in xpm_api.c.
Example of Function Definition: XPm_DevIoctl() and XPm_Ioctl().
Add a new switch case in XPm_ProcessCmd() of xpm_api.c and call implemented function from there.
Example of Process IPI request came for PM_IOCTL API: switch case for PM_IOCTL.
Add new PM API as Valid feature
Feature check API is used to determine compatibility between firmware, ATF and Linux. If there is a change in the existing PM API interface such as arguments, version of that API should be updated in the feature check, otherwise the client (i.e. ATF/Linux) would be using different argument so the PM API may not work properly. To identify this version gap, feature check is an important function that takes care of this check. So, it is required to add new PM API as a valid feature and its version.
Add the newly added PM API as a valid feature and return API version in XPm_FeatureCheck().
Example of Marking PM_IOCTL as valid feature: PM_IOCTL in XPm_FeatureCheck().
Changes in ATF
Add PM API ID in ATF
Add the same PM API ID defined in xilpm/server.
For Versal API IDs in ATF are defined at pm_defs.h
Add new API ID at the end of list at here in pm_defs.h
Example API ID: PM_IOCTL in pm_defs.h
Implement the PM API function
Once the PM API ID is defined, implement the API function.
Declare function in pm_api_sys.h
Example of Function Declaration: pm_api_ioctl()
Define the function to create a payload with the new API ID and required argument, write that payload in the IPI buffer and trigger an IPI message in pm_api_sys.c
Example of Function Definition: pm_api_ioctl()
Add a new switch case in pm_smc_handler() from pm_svc_main.c to call the newly added API
Example of Process SMC from Linux to send IPI request for PM_IOCTL : PM_IOCTL
Add new PM API as Valid feature in ATF
Add the newly added API as a valid feature and return the appropriate API version in pm_feature_check().
The feature check function in ATF provides the version of the PM API defined in ATF. This is to make sure the API in firmware, ATF and Linux are in sync.
Example of Marking PM_IOCTL as valid feature in ATF: PM_IOCTL
Changes in Linux ZynqMP Firmware Driver
Add PM API ID in Linux
Add in the same API ID defined in xilpm/server and ATF.
API IDs are defined in xlnx-zynqmp.h
Add the new API ID at the end of the List before PM_API_MAX as enum in pm_api_id{}
As per Linux guideline from mainline communityy, enum values should be assigned explicitly
Function to be used by another driver to call PM API
Declaration
Declare a function which can be used by another driver to call PM API.
Functions are declared in xlnx-zynqmp.h
Right now there is also eemi_ops (zynqmp_eemi_ops structure which holds callback to functions which can be used by other driver to call PM API), will be removed so do not use it.
Example of Function declaration: ioctl (Please note that here it is used as callback function but in new Linux kernel it will be direct call)
Examples for declaring a function which can be called directly by another driver: zynqmp_pm_clock_enable()
Definition
Define a function to send the PM API request to ATF via SMC. Functions are defined in zynqmp.c.
Example of Function definition: zynqmp_pm_ioctl()
Example of Function definition in new kernel: zynqmp_pm_clock_enable()
Example of PM API usage by another driver
Example of MMC driver use the IOCTL API in sdhci_zynqmp_sdcardclk_set_phase()
Example of PLL driver use the clock API in new kernel (with direct call) ยท zynqmp_pll_enable()
Example for end-to-end implementation of PM IOCTL API
Adding a new IOCTL in PM IOCTL API?
Many times, it is not required to add a whole new PM API for minimal operations such as providing access to a register from secure register space to the Non-Secure Application or OS, which might not have direct access to such registers. For these trivial tasks, one can use the existing PM IOCTL API and just add a new IOCTL ID to perform that operation.
For more details, please refer XPm_DevIoctl Operations
Example
No change in ATF is required if you are just adding new IOCTL ID