remoteproc: Add zynqmp_r5 driver
v2 cover remoteproc: Add zynqmp_r5 driver
There are Cortex-R5 processors on Xilinx ZynqMP UltraScale+ MPSoC.
This patch is to add an Xilinx ZynqMP R5 remoteproc driver to enable Linux kernel to bringup R5, and enable communication between Linux kernel and R5.
Ben Levinsky (5):
firmware: xilinx: Add ZynqMP firmware ioctl enums for RPU
configuration.
firmware: xilinx: Add shutdown/wakeup APIs
firmware: xilinx: Add zynqmp_get_node_status API
dt-bindings: remoteproc: Add documentation for ZynqMP R5 rproc
bindings
remoteproc: Add initial zynqmp R5 remoteproc driver
Changes since v1:
- remove domain struct as per review from Mathieu
.../remoteproc/xilinx,zynqmp-r5-remoteproc.yaml | 119 +++ drivers/firmware/xilinx/zynqmp.c | 81 ++ drivers/remoteproc/Kconfig | 10 + drivers/remoteproc/Makefile | 1 + drivers/remoteproc/zynqmp_r5_remoteproc.c | 911 +++++++++++++++++++++ include/linux/firmware/xlnx-zynqmp.h | 30 + 6 files changed, 1152 insertions(+) create mode 100644 Documentation/devicetree/bindings/remoteproc/xilinx,zynqmp-r5-remoteproc.yaml create mode 100644 drivers/remoteproc/zynqmp_r5_remoteproc.c
Signature · 1 line
2.7.4
PATCH v2 1/5 firmware: xilinx: Add ZynqMP firmware ioctl enums for RPU configuration.
Add ZynqMP firmware ioctl enums for RPU configuration.
--- drivers/firmware/xilinx/zynqmp.c | 4 ++++ include/linux/firmware/xlnx-zynqmp.h | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+)
drivers/firmware/xilinx/zynqmp.c +4 -0
@@ -512,6 +512,10 @@ static int zynqmp_pm_clock_getparent(u32 clock_id, u32 *parent_id)static inline int zynqmp_is_valid_ioctl (u32 ioctl_id) {switch (ioctl_id) { +case IOCTL_GET_RPU_OPER_MODE : +case IOCTL_SET_RPU_OPER_MODE : +case IOCTL_RPU_BOOT_ADDR_CONFIG : +case IOCTL_TCM_COMB_CONFIG :case IOCTL_SD_DLL_RESET :case IOCTL_SET_SD_TAPDELAY :case IOCTL_SET_PLL_FRAC_MODE :
include/linux/firmware/xlnx-zynqmp.h +19 -0
@@ -101,6 +101,10 @@ enum pm_ret_status { };enum pm_ioctl_id { +IOCTL_GET_RPU_OPER_MODE =0 , +IOCTL_SET_RPU_OPER_MODE , +IOCTL_RPU_BOOT_ADDR_CONFIG , +IOCTL_TCM_COMB_CONFIG ,IOCTL_SD_DLL_RESET =6 ,IOCTL_SET_SD_TAPDELAY ,IOCTL_SET_PLL_FRAC_MODE ,
@@ -120,6 +124,21 @@ enum pm_query_id { PM_QID_CLOCK_GET_MAX_DIVISOR, }; +enum rpu_oper_mode { +PM_RPU_MODE_LOCKSTEP , +PM_RPU_MODE_SPLIT , +}; + +enum rpu_boot_mem { +PM_RPU_BOOTMEM_LOVEC , +PM_RPU_BOOTMEM_HIVEC , +}; + +enum rpu_tcm_comb { +PM_RPU_TCM_SPLIT , +PM_RPU_TCM_COMB , +}; +enum zynqmp_pm_reset_action {PM_RESET_ACTION_RELEASE ,PM_RESET_ACTION_ASSERT ,
Signature · 1 line
2.7.4
PATCH v2 2/5 firmware: xilinx: Add shutdown/wakeup APIs
In reply to Ben LevinskyAdd shutdown/wakeup a resource eemi operations to shutdown or bringup a resource.
--- drivers/firmware/xilinx/zynqmp.c | 35 +++++++++++++++++++++++++++++++++++ include/linux/firmware/xlnx-zynqmp.h | 8 ++++++++ 2 files changed, 43 insertions(+)
drivers/firmware/xilinx/zynqmp.c +35 -0
@@ -694,6 +694,39 @@ static int zynqmp_pm_release_node(const u32 node) }/** +* zynqmp_pm_force_powerdown - PM call to request for another PU or subsystem to +* be powered down forcefully +* @target: Node ID of the targeted PU or subsystem +* @ack: Flag to specify whether acknowledge is requested +* +* Return: Returns status, either success or error+reason +*/ +static int zynqmp_pm_force_powerdown (const u32 target, +const enum zynqmp_pm_request_ack ack) +{ +return zynqmp_pm_invoke_fn (PM_FORCE_POWERDOWN , target, ack,0 ,0 ,NULL ); +} + +/** +* zynqmp_pm_request_wakeup - PM call to wake up selected master or subsystem +* @node: Node ID of the master or subsystem +* @set_addr: Specifies whether the address argument is relevant +* @address: Address from which to resume when woken up +* @ack: Flag to specify whether acknowledge requested +* +* Return: Returns status, either success or error+reason +*/ +static int zynqmp_pm_request_wakeup (const u32 node, +const bool set_addr, +const u64 address, +const enum zynqmp_pm_request_ack ack) +{ +/* set_addr flag is encoded into 1st bit of address */ +return zynqmp_pm_invoke_fn (PM_REQUEST_WAKEUP , node, address | set_addr, + address >>32 , ack,NULL ); +} + +/** * zynqmp_pm_set_requirement() - PM call to set requirement for PM slaves * @node: Node ID of the slave * @capabilities: Requested capabilities of the slave
@@ -750,9 +783,11 @@ static const struct zynqmp_eemi_ops eemi_ops = { .clock_getrate = zynqmp_pm_clock_getrate, .clock_setparent = zynqmp_pm_clock_setparent, .clock_getparent = zynqmp_pm_clock_getparent, + .force_powerdown = zynqmp_pm_force_powerdown, .ioctl = zynqmp_pm_ioctl, .reset_assert = zynqmp_pm_reset_assert, .reset_get_status = zynqmp_pm_reset_get_status, + .request_wakeup = zynqmp_pm_request_wakeup, .init_finalize = zynqmp_pm_init_finalize, .set_suspend_mode = zynqmp_pm_set_suspend_mode, .request_node = zynqmp_pm_request_node,
include/linux/firmware/xlnx-zynqmp.h +8 -0
@@ -62,6 +62,8 @@enum pm_api_id {PM_GET_API_VERSION =1 , +PM_FORCE_POWERDOWN =8 , +PM_REQUEST_WAKEUP =10 ,PM_REQUEST_NODE =13 ,PM_RELEASE_NODE ,PM_SET_REQUIREMENT ,
@@ -338,6 +340,12 @@ struct zynqmp_eemi_ops {const u32 qos, const enum zynqmp_pm_request_ack ack);int (*release_node)(const u32 node); +int (*force_powerdown)(const u32 target, +const enum zynqmp_pm_request_ack ack); +int (*request_wakeup)(const u32 node, +const bool set_addr, +const u64 address, +const enum zynqmp_pm_request_ack ack); int (*set_requirement)(const u32 node, const u32 capabilities, const u32 qos,
Signature · 1 line
2.7.4
PATCH v2 3/5 firmware: xilinx: Add zynqmp_get_node_status API
In reply to Ben LevinskyThis patch adds a new API to provide access to the current power state of a sub-system on Zynqmp sub-system.
--- drivers/firmware/xilinx/zynqmp.c | 42 ++++++++++++++++++++++++++++++++++++ include/linux/firmware/xlnx-zynqmp.h | 3 +++ 2 files changed, 45 insertions(+)
drivers/firmware/xilinx/zynqmp.c +42 -0
@@ -727,6 +727,47 @@ static int zynqmp_pm_request_wakeup(const u32 node, }/** +* zynqmp_pm_get_node_status - PM call to request a node's current power state +* @node: ID of the component or sub-system in question +* @status: Current operating state of the requested node +* @requirements: Current requirements asserted on the node, +* used for slave nodes only. +* @usage: Usage information, used for slave nodes only: +* PM_USAGE_NO_MASTER - No master is currently using +* the node +* PM_USAGE_CURRENT_MASTER - Only requesting master is +* currently using the node +* PM_USAGE_OTHER_MASTER - Only other masters are +* currently using the node +* PM_USAGE_BOTH_MASTERS - Both the current and at least +* one other master is currently +* using the node +* +* Return: Returns status, either success or error+reason +*/ +static int zynqmp_pm_get_node_status (const u32 node,u32 *const status, +u32 *const requirements,u32 *const usage) +{ +u32 ret_payload[PAYLOAD_ARG_CNT ]; +int ret; + +if (!status) +return -EINVAL ; + + ret =zynqmp_pm_invoke_fn (PM_GET_NODE_STATUS , node,0 ,0 , +0 , ret_payload); +if (ret_payload[0 ] ==XST_PM_SUCCESS ) { + *status = ret_payload[1 ]; +if (requirements) + *requirements = ret_payload[2 ]; +if (usage) + *usage = ret_payload[3 ]; + } + +return ret; +} + +/** * zynqmp_pm_set_requirement() - PM call to set requirement for PM slaves * @node: Node ID of the slave * @capabilities: Requested capabilities of the slave
@@ -773,6 +814,7 @@ static int zynqmp_pm_aes_engine(const u64 address, u32 *out)static const struct zynqmp_eemi_ops eemi_ops = { .get_api_version = zynqmp_pm_get_api_version, .get_chipid = zynqmp_pm_get_chipid, + .get_node_status = zynqmp_pm_get_node_status, .query_data = zynqmp_pm_query_data, .clock_enable = zynqmp_pm_clock_enable, .clock_disable = zynqmp_pm_clock_disable,
include/linux/firmware/xlnx-zynqmp.h +3 -0
@@ -62,6 +62,7 @@enum pm_api_id {PM_GET_API_VERSION =1 , +PM_GET_NODE_STATUS =3 ,PM_FORCE_POWERDOWN =8 ,PM_REQUEST_WAKEUP =10 ,PM_REQUEST_NODE =13 ,
@@ -317,6 +318,8 @@ struct zynqmp_pm_query_data {struct zynqmp_eemi_ops {int (*get_api_version)(u32 *version);int (*get_chipid)(u32 *idcode,u32 *version); +int (*get_node_status)(const u32 node,u32 *const status, +u32 *const requirements,u32 *const usage);int (*fpga_load)(const u64 address,const u32 size,const u32 flags);int (*fpga_get_status)(u32 *value);int (*query_data)(struct zynqmp_pm_query_data qdata,u32 *out);
Signature · 1 line
2.7.4
PATCH v2 4/5 dt-bindings: remoteproc: Add documentation for ZynqMP R5 rproc bindings
In reply to Ben LevinskyAdd binding for ZynqMP R5 OpenAMP.
Represent the RPU domain resources in one device node. Each RPU processor is a subnode of the top RPU domain node.
--- .../remoteproc/xilinx,zynqmp-r5-remoteproc.yaml | 119 +++++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 Documentation/devicetree/bindings/remoteproc/xilinx,zynqmp-r5-remoteproc.yaml
Documentation/devicetree/bindings/remoteproc/xilinx,zynqmp-r5-remoteproc.yaml new file +119 -0
@@ -0,0 +1,119 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: "http://devicetree.org/schemas/remoteproc/xilinx,zynqmp-r5-remoteproc.yaml#" +$schema: "http://devicetree.org/meta-schemas/core.yaml#" + +title: Xilinx R5 remote processor controller bindings + +description: + This document defines the binding for the remoteproc component that loads and + boots firmwares on the Xilinx Zynqmp and Versal family chipset. + +maintainers: + - Ed Mooring <[email protected]> + - Ben Levinsky <[email protected]> + +properties: + compatible: + const: "xlnx,zynqmp-r5-remoteproc-1.0" + + core_conf: + description: + R5 core configuration (valid string - split or lock-step) + maxItems: 1 + + interrupts: + description: + Interrupt mapping for remoteproc IPI. It is required if the + user uses the remoteproc driver with the RPMsg kernel driver. + maxItems: 6 + + memory-region: + maxItems: 4 + minItems: 4 + pnode-id: + maxItems: 1 + mboxes: + maxItems: 2 + mbox-names: + maxItems: 2 + +additionalProperties: false + +examples: + - | + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + rpu0vdev0vring0: rpu0vdev0vring0@3ed40000 { + no-map; + reg = <0x0 0x3ed40000 0x0 0x4000>; + }; + rpu0vdev0vring1: rpu0vdev0vring1@3ed44000 { + no-map; + reg = <0x0 0x3ed44000 0x0 0x4000>; + }; + rpu0vdev0buffer: rpu0vdev0buffer@3ed48000 { + no-map; + reg = <0x0 0x3ed48000 0x0 0x100000>; + }; + rproc_0_reserved: rproc@3ed000000 { + no-map; + reg = <0x0 0x3ed00000 0x0 0x40000>; + }; + }; + + zynqmp-rpu { + compatible = "xlnx,zynqmp-r5-remoteproc-1.0"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + core_conf = "split"; + reg = <0x0 0xFF9A0000 0x0 0x10000>; + r5_0: r5@0 { + #address-cells = <2>; + #size-cells = <2>; + ranges; + memory-region = <&rproc_0_reserved>, <&rpu0vdev0buffer>, <&rpu0vdev0vring0>, <&rpu0vdev0vring1>; + pnode-id = <0x7>; + mboxes = <&ipi_mailbox_rpu0 0>, <&ipi_mailbox_rpu0 1>; + mbox-names = "tx", "rx"; + tcm_0_a: tcm_0@0 { + reg = <0x0 0xFFE00000 0x0 0x10000>; + pnode-id = <0xf>; + }; + tcm_0_b: tcm_0@1 { + reg = <0x0 0xFFE20000 0x0 0x10000>; + pnode-id = <0x10>; + }; + }; + }; + + + zynqmp_ipi1 { + compatible = "xlnx,zynqmp-ipi-mailbox"; + interrupt-parent = <&gic>; + interrupts = <0 29 4>; + xlnx,ipi-id = <7>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + /* APU<->RPU0 IPI mailbox controller */ + ipi_mailbox_rpu0: mailbox@ff90000 { + reg = <0xff990600 0x20>, + <0xff990620 0x20>, + <0xff9900c0 0x20>, + <0xff9900e0 0x20>; + reg-names = "local_request_region", + "local_response_region", + "remote_request_region", + "remote_response_region"; + #mbox-cells = <1>; + xlnx,ipi-id = <1>; + }; + }; + +...
Signature · 1 line
2.7.4
Rob Herring
maintainerRe: [PATCH v2 4/5] dt-bindings: remoteproc: Add documentation for ZynqMP R5 rproc bindings
Quoted 5 lines · Ben Levinsky
Add binding for ZynqMP R5 OpenAMP.
Represent the RPU domain resources in one device node. Each RPU processor is a subnode of the top RPU domain node.
Quoted 9 lines
Signed-off-by Ben Levinsky <[email protected]>Signed-off-by Jason Wu <[email protected]>Signed-off-by Wendy Liang <[email protected]>Signed-off-by Michal Simek <[email protected]>--- .../remoteproc/xilinx,zynqmp-r5-remoteproc.yaml | 119 +++++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 Documentation/devicetree/bindings/remoteproc/xilinx,zynqmp-r5-remoteproc.yaml
My bot found errors running 'make dt_binding_check' on your patch:
Documentation/devicetree/bindings/remoteproc/xilinx,zynqmp-r5-remoteproc.example.dts:20.14-21: Warning (ranges_format): /example-0/reserved-memory:ranges: empty "ranges" property but its #address-cells (2) differs from /example-0 (1) Documentation/devicetree/bindings/remoteproc/xilinx,zynqmp-r5-remoteproc.example.dts:20.14-21: Warning (ranges_format): /example-0/reserved-memory:ranges: empty "ranges" property but its #size-cells (2) differs from /example-0 (1) Documentation/devicetree/bindings/remoteproc/xilinx,zynqmp-r5-remoteproc.example.dts:43.14-21: Warning (ranges_format): /example-0/zynqmp-rpu:ranges: empty "ranges" property but its #address-cells (2) differs from /example-0 (1) Documentation/devicetree/bindings/remoteproc/xilinx,zynqmp-r5-remoteproc.example.dts:43.14-21: Warning (ranges_format): /example-0/zynqmp-rpu:ranges: empty "ranges" property but its #size-cells (2) differs from /example-0 (1) Documentation/devicetree/bindings/remoteproc/xilinx,zynqmp-r5-remoteproc.example.dts:39.20-63.11: Warning (unit_address_vs_reg): /example-0/zynqmp-rpu: node has a reg or ranges property, but no unit name Documentation/devicetree/bindings/remoteproc/xilinx,zynqmp-r5-remoteproc.example.dts:46.25-62.16: Warning (unit_address_vs_reg): /example-0/zynqmp-rpu/r5@0: node has a unit name, but no reg or ranges property /builds/robherring/linux-dt-review/Documentation/devicetree/bindings/remoteproc/xilinx,zynqmp-r5-remoteproc.example.dt.yaml: zynqmp-rpu: '#address-cells', '#size-cells', 'r5@0', 'ranges', 'reg' do not match any of the regexes: 'pinctrl-[0-9]+'
See https://patchwork.ozlabs.org/patch/1271919
If you already ran 'make dt_binding_check' and didn't see the above error(s), then make sure dt-schema is up to date:
pip3 install git+https://github.com/devicetree-org/dt-schema.git@master --upgrade
Please check and re-submit.
PATCH v2 5/5 remoteproc: Add initial zynqmp R5 remoteproc driver
In reply to Ben LevinskyR5 is included in Xilinx Zynq UltraScale MPSoC so by adding this remotproc driver, we can boot the R5 sub-system in different configurations.
---
Changes since v1:
- remove domain struct as per review from Mathieu
--- drivers/remoteproc/Kconfig | 10 + drivers/remoteproc/Makefile | 1 + drivers/remoteproc/zynqmp_r5_remoteproc.c | 911 ++++++++++++++++++++++++++++++ 3 files changed, 922 insertions(+) create mode 100644 drivers/remoteproc/zynqmp_r5_remoteproc.c
drivers/remoteproc/Kconfig +10 -0
@@ -222,6 +222,16 @@ config ST_REMOTEPROC processor framework. This can be either built-in or a loadable module. +config ZYNQMP_R5_REMOTEPROC + tristate "ZynqMP_r5 remoteproc support" + depends on ARM64 && PM && ARCH_ZYNQMP + select RPMSG_VIRTIO + select MAILBOX + select ZYNQMP_IPI_MBOX + help + Say y here to support ZynqMP R5 remote processors via the remote + processor framework. + config ST_SLIM_REMOTEPROC tristate
drivers/remoteproc/Makefile +1 -0
@@ -27,5 +27,6 @@ obj-$(CONFIG_QCOM_WCNSS_PIL) += qcom_wcnss_pil.o qcom_wcnss_pil-y += qcom_wcnss.o qcom_wcnss_pil-y += qcom_wcnss_iris.o obj-$(CONFIG_ST_REMOTEPROC) += st_remoteproc.o +obj-$(CONFIG_ZYNQMP_R5_REMOTEPROC) += zynqmp_r5_remoteproc.o obj-$(CONFIG_ST_SLIM_REMOTEPROC) += st_slim_rproc.o obj-$(CONFIG_STM32_RPROC) += stm32_rproc.o
drivers/remoteproc/zynqmp_r5_remoteproc.c new file +911 -0
911 lines not on this page · raw message
Signature · 1 line
2.7.4
Re: [PATCH v2 5/5] remoteproc: Add initial zynqmp R5 remoteproc driver
Quoted 110 lines · Ben Levinsky
R5 is included in Xilinx Zynq UltraScale MPSoC so by adding this remotproc driver, we can boot the R5 sub-system in different configurations.
Acked-by Ben Levinsky <[email protected]>Reviewed-by Radhey Shyam Pandey <[email protected]>Signed-off-by Ben Levinsky <[email protected]>Signed-off-by Wendy Liang <[email protected]>Signed-off-by Michal Simek <[email protected]>Signed-off-by Ed Mooring <[email protected]>Signed-off-by Jason Wu <[email protected]>Tested-by Ben Levinsky <[email protected]>---
Changes since v1:
- remove domain struct as per review from Mathieu--- drivers/remoteproc/Kconfig | 10 + drivers/remoteproc/Makefile | 1 + drivers/remoteproc/zynqmp_r5_remoteproc.c | 911 ++++++++++++++++++++++++++++++ 3 files changed, 922 insertions(+) create mode 100644 drivers/remoteproc/zynqmp_r5_remoteproc.cdrivers/remoteproc/Kconfig +10
-0@@ -222,6 +222,16 @@ config ST_REMOTEPROC processor framework. This can be either built-in or a loadable module. +config ZYNQMP_R5_REMOTEPROC + tristate "ZynqMP_r5 remoteproc support" + depends on ARM64 && PM && ARCH_ZYNQMP + select RPMSG_VIRTIO + select MAILBOX + select ZYNQMP_IPI_MBOX + help + Say y here to support ZynqMP R5 remote processors via the remote + processor framework. + config ST_SLIM_REMOTEPROC tristatedrivers/remoteproc/Makefile +1
-0@@ -27,5 +27,6 @@ obj-$(CONFIG_QCOM_WCNSS_PIL) += qcom_wcnss_pil.o qcom_wcnss_pil-y += qcom_wcnss.o qcom_wcnss_pil-y += qcom_wcnss_iris.o obj-$(CONFIG_ST_REMOTEPROC) += st_remoteproc.o +obj-$(CONFIG_ZYNQMP_R5_REMOTEPROC) += zynqmp_r5_remoteproc.o obj-$(CONFIG_ST_SLIM_REMOTEPROC) += st_slim_rproc.o obj-$(CONFIG_STM32_RPROC) += stm32_rproc.odrivers/remoteproc/zynqmp_r5_remoteproc.c new file +49
-0@@ -0,0 +1,911 @@ +// SPDX-License-Identifier: GPL-2.0 +/* +* Zynq R5 Remote Processor driver +* +* Copyright (C) 2015 - 2018 Xilinx Inc. +* Copyright (C) 2015 Jason Wu <[email protected]> +* +* Based on origin OMAP and Zynq Remote Processor driver +* +* Copyright (C) 2012 Michal Simek <[email protected]> +* Copyright (C) 2012 PetaLogix +* Copyright (C) 2011 Texas Instruments, Inc. +* Copyright (C) 2011 Google, Inc. +*/ + +#include <linux/atomic.h> +#include <linux/cpu.h> +#include <linux/dma-mapping.h> +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/firmware/xlnx-zynqmp.h> +#include <linux/genalloc.h> +#include <linux/idr.h> +#include <linux/interrupt.h> +#include <linux/kernel.h> +#include <linux/list.h> +#include <linux/mailbox_client.h> +#include <linux/mailbox/zynqmp-ipi-message.h> +#include <linux/module.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> +#include <linux/of_platform.h> +#include <linux/of_reserved_mem.h> +#include <linux/pfn.h> +#include <linux/platform_device.h> +#include <linux/remoteproc.h> +#include <linux/skbuff.h> +#include <linux/slab.h> +#include <linux/sysfs.h> + +#include "remoteproc_internal.h" + +#define MAX_RPROCS 2/* Support up to 2 RPU */ +#define MAX_MEM_PNODES 4/* Max power nodes for one RPU memory instance */ + +#define DEFAULT_FIRMWARE_NAME "rproc-rpu-fw" + +/* PM proc states */ +#define PM_PROC_STATE_ACTIVE 1U
drivers/remoteproc/zynqmp_r5_remoteproc.c line 59
Quoted 10 lines
drivers/remoteproc/zynqmp_r5_remoteproc.c new file +10
-0+ +/* IPI buffer MAX length */ +#define IPI_BUF_LEN_MAX 32U +/* RX mailbox client buffer max length */ +#define RX_MBOX_CLIENT_BUF_MAX (IPI_BUF_LEN_MAX + \ + sizeof(struct zynqmp_ipi_message)) + +static bool autoboot__read_mostly ; + +static const struct zynqmp_eemi_ops *eemi_ops;
Take a look at Jolly's series which she sent recently and use the same style as was recommended by Greg.
Thanks,
Michal