1 // SPDX-License-Identifier: GPL-2.0
3 * System Control and Management Interface (SCMI) Message SMC/HVC
9 #include <linux/arm-smccc.h>
10 #include <linux/device.h>
11 #include <linux/err.h>
12 #include <linux/mutex.h>
14 #include <linux/of_address.h>
15 #include <linux/slab.h>
20 * struct scmi_smc - Structure representing a SCMI smc transport
22 * @cinfo: SCMI channel info
23 * @shmem: Transmit/Receive shared memory area
24 * @shmem_lock: Lock to protect access to Tx/Rx shared memory area
25 * @func_id: smc/hvc call function id
29 struct scmi_chan_info
*cinfo
;
30 struct scmi_shared_mem __iomem
*shmem
;
31 struct mutex shmem_lock
;
35 static bool smc_chan_available(struct device
*dev
, int idx
)
37 struct device_node
*np
= of_parse_phandle(dev
->of_node
, "shmem", 0);
45 static int smc_chan_setup(struct scmi_chan_info
*cinfo
, struct device
*dev
,
48 struct device
*cdev
= cinfo
->dev
;
49 struct scmi_smc
*scmi_info
;
52 struct device_node
*np
;
59 scmi_info
= devm_kzalloc(dev
, sizeof(*scmi_info
), GFP_KERNEL
);
63 np
= of_parse_phandle(cdev
->of_node
, "shmem", 0);
64 ret
= of_address_to_resource(np
, 0, &res
);
67 dev_err(cdev
, "failed to get SCMI Tx shared memory\n");
71 size
= resource_size(&res
);
72 scmi_info
->shmem
= devm_ioremap(dev
, res
.start
, size
);
73 if (!scmi_info
->shmem
) {
74 dev_err(dev
, "failed to ioremap SCMI Tx shared memory\n");
75 return -EADDRNOTAVAIL
;
78 ret
= of_property_read_u32(dev
->of_node
, "arm,smc-id", &func_id
);
82 scmi_info
->func_id
= func_id
;
83 scmi_info
->cinfo
= cinfo
;
84 mutex_init(&scmi_info
->shmem_lock
);
85 cinfo
->transport_info
= scmi_info
;
90 static int smc_chan_free(int id
, void *p
, void *data
)
92 struct scmi_chan_info
*cinfo
= p
;
93 struct scmi_smc
*scmi_info
= cinfo
->transport_info
;
95 cinfo
->transport_info
= NULL
;
96 scmi_info
->cinfo
= NULL
;
98 scmi_free_channel(cinfo
, data
, id
);
103 static int smc_send_message(struct scmi_chan_info
*cinfo
,
104 struct scmi_xfer
*xfer
)
106 struct scmi_smc
*scmi_info
= cinfo
->transport_info
;
107 struct arm_smccc_res res
;
109 mutex_lock(&scmi_info
->shmem_lock
);
111 shmem_tx_prepare(scmi_info
->shmem
, xfer
);
113 arm_smccc_1_1_invoke(scmi_info
->func_id
, 0, 0, 0, 0, 0, 0, 0, &res
);
114 scmi_rx_callback(scmi_info
->cinfo
, shmem_read_header(scmi_info
->shmem
));
116 mutex_unlock(&scmi_info
->shmem_lock
);
118 /* Only SMCCC_RET_NOT_SUPPORTED is valid error code */
124 static void smc_fetch_response(struct scmi_chan_info
*cinfo
,
125 struct scmi_xfer
*xfer
)
127 struct scmi_smc
*scmi_info
= cinfo
->transport_info
;
129 shmem_fetch_response(scmi_info
->shmem
, xfer
);
133 smc_poll_done(struct scmi_chan_info
*cinfo
, struct scmi_xfer
*xfer
)
135 struct scmi_smc
*scmi_info
= cinfo
->transport_info
;
137 return shmem_poll_done(scmi_info
->shmem
, xfer
);
140 static const struct scmi_transport_ops scmi_smc_ops
= {
141 .chan_available
= smc_chan_available
,
142 .chan_setup
= smc_chan_setup
,
143 .chan_free
= smc_chan_free
,
144 .send_message
= smc_send_message
,
145 .fetch_response
= smc_fetch_response
,
146 .poll_done
= smc_poll_done
,
149 const struct scmi_desc scmi_smc_desc
= {
150 .ops
= &scmi_smc_ops
,
151 .max_rx_timeout_ms
= 30,