blob: 344df9454b3b604afe678d96a4eae178955324fe [file] [log] [blame]
Lokesh Vutla5af02db2018-08-27 15:57:32 +05301// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Texas Instruments System Control Interface Protocol Driver
4 * Based on drivers/firmware/ti_sci.c from Linux.
5 *
Nishanth Menoneaa39c62023-11-01 15:56:03 -05006 * Copyright (C) 2018 Texas Instruments Incorporated - https://www.ti.com/
Lokesh Vutla5af02db2018-08-27 15:57:32 +05307 * Lokesh Vutla <lokeshvutla@ti.com>
8 */
9
Lokesh Vutla5af02db2018-08-27 15:57:32 +053010#include <dm.h>
11#include <errno.h>
Simon Glass0f2af882020-05-10 11:40:05 -060012#include <log.h>
Lokesh Vutla5af02db2018-08-27 15:57:32 +053013#include <mailbox.h>
Simon Glass9bc15642020-02-03 07:36:16 -070014#include <malloc.h>
Lokesh Vutla5af02db2018-08-27 15:57:32 +053015#include <dm/device.h>
Simon Glass9bc15642020-02-03 07:36:16 -070016#include <dm/device_compat.h>
Simon Glassd66c5f72020-02-03 07:36:15 -070017#include <dm/devres.h>
Andrew Davis1ed20d62024-04-02 11:09:07 -050018#include <dm/lists.h>
Simon Glass4dcacfc2020-05-10 11:40:13 -060019#include <linux/bitops.h>
Grygorii Strashkod64c5b22019-02-05 17:31:21 +053020#include <linux/compat.h>
Lokesh Vutla5af02db2018-08-27 15:57:32 +053021#include <linux/err.h>
22#include <linux/soc/ti/k3-sec-proxy.h>
23#include <linux/soc/ti/ti_sci_protocol.h>
24
25#include "ti_sci.h"
Vignesh Raghavendra4214a812021-06-07 19:47:48 +053026#include "ti_sci_static_data.h"
Lokesh Vutla5af02db2018-08-27 15:57:32 +053027
28/* List of all TI SCI devices active in system */
29static LIST_HEAD(ti_sci_list);
30
31/**
32 * struct ti_sci_xfer - Structure representing a message flow
33 * @tx_message: Transmit message
34 * @rx_len: Receive message length
35 */
36struct ti_sci_xfer {
37 struct k3_sec_proxy_msg tx_message;
38 u8 rx_len;
39};
40
41/**
Grygorii Strashkod64c5b22019-02-05 17:31:21 +053042 * struct ti_sci_rm_type_map - Structure representing TISCI Resource
43 * management representation of dev_ids.
44 * @dev_id: TISCI device ID
45 * @type: Corresponding id as identified by TISCI RM.
46 *
47 * Note: This is used only as a work around for using RM range apis
48 * for AM654 SoC. For future SoCs dev_id will be used as type
49 * for RM range APIs. In order to maintain ABI backward compatibility
50 * type is not being changed for AM654 SoC.
51 */
52struct ti_sci_rm_type_map {
53 u32 dev_id;
54 u16 type;
55};
56
57/**
Lokesh Vutla5af02db2018-08-27 15:57:32 +053058 * struct ti_sci_desc - Description of SoC integration
Grygorii Strashkod64c5b22019-02-05 17:31:21 +053059 * @default_host_id: Host identifier representing the compute entity
60 * @max_rx_timeout_ms: Timeout for communication with SoC (in Milliseconds)
61 * @max_msgs: Maximum number of messages that can be pending
62 * simultaneously in the system
63 * @max_msg_size: Maximum size of data per message that can be handled.
Lokesh Vutla5af02db2018-08-27 15:57:32 +053064 */
65struct ti_sci_desc {
Grygorii Strashkod64c5b22019-02-05 17:31:21 +053066 u8 default_host_id;
67 int max_rx_timeout_ms;
68 int max_msgs;
Lokesh Vutla5af02db2018-08-27 15:57:32 +053069 int max_msg_size;
70};
71
72/**
73 * struct ti_sci_info - Structure representing a TI SCI instance
74 * @dev: Device pointer
75 * @desc: SoC description for this instance
76 * @handle: Instance of TI SCI handle to send to clients.
77 * @chan_tx: Transmit mailbox channel
78 * @chan_rx: Receive mailbox channel
79 * @xfer: xfer info
80 * @list: list head
81 * @is_secure: Determines if the communication is through secure threads.
82 * @host_id: Host identifier representing the compute entity
83 * @seq: Seq id used for verification for tx and rx message.
84 */
85struct ti_sci_info {
86 struct udevice *dev;
87 const struct ti_sci_desc *desc;
88 struct ti_sci_handle handle;
89 struct mbox_chan chan_tx;
90 struct mbox_chan chan_rx;
91 struct mbox_chan chan_notify;
92 struct ti_sci_xfer xfer;
93 struct list_head list;
Lokesh Vutla0d0412a2019-06-07 19:24:41 +053094 struct list_head dev_list;
Lokesh Vutla5af02db2018-08-27 15:57:32 +053095 bool is_secure;
96 u8 host_id;
97 u8 seq;
98};
99
Lokesh Vutla0d0412a2019-06-07 19:24:41 +0530100struct ti_sci_exclusive_dev {
101 u32 id;
102 u32 count;
103 struct list_head list;
104};
105
Lokesh Vutla5af02db2018-08-27 15:57:32 +0530106#define handle_to_ti_sci_info(h) container_of(h, struct ti_sci_info, handle)
107
108/**
109 * ti_sci_setup_one_xfer() - Setup one message type
110 * @info: Pointer to SCI entity information
111 * @msg_type: Message type
112 * @msg_flags: Flag to set for the message
113 * @buf: Buffer to be send to mailbox channel
114 * @tx_message_size: transmit message size
Andreas Dannenbergca08cb32019-06-07 19:24:40 +0530115 * @rx_message_size: receive message size. may be set to zero for send-only
116 * transactions.
Lokesh Vutla5af02db2018-08-27 15:57:32 +0530117 *
118 * Helper function which is used by various command functions that are
119 * exposed to clients of this driver for allocating a message traffic event.
120 *
121 * Return: Corresponding ti_sci_xfer pointer if all went fine,
122 * else appropriate error pointer.
123 */
124static struct ti_sci_xfer *ti_sci_setup_one_xfer(struct ti_sci_info *info,
125 u16 msg_type, u32 msg_flags,
126 u32 *buf,
127 size_t tx_message_size,
128 size_t rx_message_size)
129{
130 struct ti_sci_xfer *xfer = &info->xfer;
131 struct ti_sci_msg_hdr *hdr;
132
133 /* Ensure we have sane transfer sizes */
134 if (rx_message_size > info->desc->max_msg_size ||
135 tx_message_size > info->desc->max_msg_size ||
Andreas Dannenbergca08cb32019-06-07 19:24:40 +0530136 (rx_message_size > 0 && rx_message_size < sizeof(*hdr)) ||
Andrew Davis22563722022-07-25 20:25:04 -0500137 tx_message_size < sizeof(*hdr)) {
138 dev_err(info->dev, "TI-SCI message transfer size not sane\n");
Lokesh Vutla5af02db2018-08-27 15:57:32 +0530139 return ERR_PTR(-ERANGE);
Andrew Davis22563722022-07-25 20:25:04 -0500140 }
141
Lokesh Vutla5af02db2018-08-27 15:57:32 +0530142 info->seq = ~info->seq;
143 xfer->tx_message.buf = buf;
144 xfer->tx_message.len = tx_message_size;
145 xfer->rx_len = (u8)rx_message_size;
146
147 hdr = (struct ti_sci_msg_hdr *)buf;
148 hdr->seq = info->seq;
149 hdr->type = msg_type;
150 hdr->host = info->host_id;
151 hdr->flags = msg_flags;
152
153 return xfer;
154}
155
156/**
157 * ti_sci_get_response() - Receive response from mailbox channel
158 * @info: Pointer to SCI entity information
159 * @xfer: Transfer to initiate and wait for response
160 * @chan: Channel to receive the response
161 *
162 * Return: -ETIMEDOUT in case of no response, if transmit error,
163 * return corresponding error, else if all goes well,
164 * return 0.
165 */
Andrew Davisb3e71b72022-07-25 20:25:05 -0500166static int ti_sci_get_response(struct ti_sci_info *info,
Lokesh Vutla5af02db2018-08-27 15:57:32 +0530167 struct ti_sci_xfer *xfer,
168 struct mbox_chan *chan)
169{
170 struct k3_sec_proxy_msg *msg = &xfer->tx_message;
171 struct ti_sci_secure_msg_hdr *secure_hdr;
172 struct ti_sci_msg_hdr *hdr;
173 int ret;
174
175 /* Receive the response */
Andreas Dannenberg607d4ca2019-04-24 14:20:08 -0500176 ret = mbox_recv(chan, msg, info->desc->max_rx_timeout_ms * 1000);
Lokesh Vutla5af02db2018-08-27 15:57:32 +0530177 if (ret) {
178 dev_err(info->dev, "%s: Message receive failed. ret = %d\n",
179 __func__, ret);
180 return ret;
181 }
182
183 /* ToDo: Verify checksum */
184 if (info->is_secure) {
185 secure_hdr = (struct ti_sci_secure_msg_hdr *)msg->buf;
186 msg->buf = (u32 *)((void *)msg->buf + sizeof(*secure_hdr));
187 }
188
189 /* msg is updated by mailbox driver */
190 hdr = (struct ti_sci_msg_hdr *)msg->buf;
191
192 /* Sanity check for message response */
193 if (hdr->seq != info->seq) {
194 dev_dbg(info->dev, "%s: Message for %d is not expected\n",
195 __func__, hdr->seq);
196 return ret;
197 }
198
199 if (msg->len > info->desc->max_msg_size) {
200 dev_err(info->dev, "%s: Unable to handle %zu xfer (max %d)\n",
201 __func__, msg->len, info->desc->max_msg_size);
202 return -EINVAL;
203 }
204
205 if (msg->len < xfer->rx_len) {
206 dev_err(info->dev, "%s: Recv xfer %zu < expected %d length\n",
207 __func__, msg->len, xfer->rx_len);
208 }
209
210 return ret;
211}
212
213/**
Andrew Davis04e43932022-07-25 20:25:06 -0500214 * ti_sci_is_response_ack() - Generic ACK/NACK message checkup
215 * @r: pointer to response buffer
216 *
217 * Return: true if the response was an ACK, else returns false.
218 */
219static bool ti_sci_is_response_ack(void *r)
220{
221 struct ti_sci_msg_hdr *hdr = r;
222
223 return hdr->flags & TI_SCI_FLAG_RESP_GENERIC_ACK ? true : false;
224}
225
226/**
Lokesh Vutla5af02db2018-08-27 15:57:32 +0530227 * ti_sci_do_xfer() - Do one transfer
228 * @info: Pointer to SCI entity information
229 * @xfer: Transfer to initiate and wait for response
230 *
231 * Return: 0 if all went fine, else return appropriate error.
232 */
Andrew Davisb3e71b72022-07-25 20:25:05 -0500233static int ti_sci_do_xfer(struct ti_sci_info *info,
Lokesh Vutla5af02db2018-08-27 15:57:32 +0530234 struct ti_sci_xfer *xfer)
235{
236 struct k3_sec_proxy_msg *msg = &xfer->tx_message;
237 u8 secure_buf[info->desc->max_msg_size];
Dhruva Goled3341022024-01-30 20:29:59 +0530238 struct ti_sci_secure_msg_hdr *secure_hdr = (struct ti_sci_secure_msg_hdr *)secure_buf;
Lokesh Vutla5af02db2018-08-27 15:57:32 +0530239 int ret;
240
Dhruva Gole5452ebd2024-01-30 20:30:00 +0530241 /*
242 * The reason why we need the is_secure code is because of boot R5.
243 * boot R5 starts off in "secure mode" when it hands off from Boot
244 * ROM over to the Secondary bootloader. The initial set of calls
245 * we have to make need to be on a secure pipe.
246 */
Lokesh Vutla5af02db2018-08-27 15:57:32 +0530247 if (info->is_secure) {
248 /* ToDo: get checksum of the entire message */
Dhruva Goled3341022024-01-30 20:29:59 +0530249 secure_hdr->checksum = 0;
250 secure_hdr->reserved = 0;
251 memcpy(&secure_buf[sizeof(*secure_hdr)], xfer->tx_message.buf,
Lokesh Vutla5af02db2018-08-27 15:57:32 +0530252 xfer->tx_message.len);
253
254 xfer->tx_message.buf = (u32 *)secure_buf;
Dhruva Goled3341022024-01-30 20:29:59 +0530255 xfer->tx_message.len += sizeof(*secure_hdr);
Andreas Dannenbergca08cb32019-06-07 19:24:40 +0530256
257 if (xfer->rx_len)
Dhruva Goled3341022024-01-30 20:29:59 +0530258 xfer->rx_len += sizeof(*secure_hdr);
Lokesh Vutla5af02db2018-08-27 15:57:32 +0530259 }
260
261 /* Send the message */
262 ret = mbox_send(&info->chan_tx, msg);
263 if (ret) {
264 dev_err(info->dev, "%s: Message sending failed. ret = %d\n",
265 __func__, ret);
266 return ret;
267 }
268
Andreas Dannenbergca08cb32019-06-07 19:24:40 +0530269 /* Get response if requested */
Andrew Davis04e43932022-07-25 20:25:06 -0500270 if (xfer->rx_len) {
Andreas Dannenbergca08cb32019-06-07 19:24:40 +0530271 ret = ti_sci_get_response(info, xfer, &info->chan_rx);
Andrew Davis04e43932022-07-25 20:25:06 -0500272 if (!ti_sci_is_response_ack(xfer->tx_message.buf)) {
Andreas Dannenberg831b73f2023-05-09 16:38:13 -0500273 dev_err(info->dev, "Message not acknowledged\n");
Andrew Davis04e43932022-07-25 20:25:06 -0500274 ret = -ENODEV;
275 }
276 }
Andreas Dannenbergca08cb32019-06-07 19:24:40 +0530277
278 return ret;
Lokesh Vutla5af02db2018-08-27 15:57:32 +0530279}
280
281/**
282 * ti_sci_cmd_get_revision() - command to get the revision of the SCI entity
283 * @handle: pointer to TI SCI handle
284 *
285 * Updates the SCI information in the internal data structure.
286 *
287 * Return: 0 if all went fine, else return appropriate error.
288 */
289static int ti_sci_cmd_get_revision(struct ti_sci_handle *handle)
290{
291 struct ti_sci_msg_resp_version *rev_info;
292 struct ti_sci_version_info *ver;
293 struct ti_sci_msg_hdr hdr;
294 struct ti_sci_info *info;
295 struct ti_sci_xfer *xfer;
296 int ret;
297
298 if (IS_ERR(handle))
299 return PTR_ERR(handle);
300 if (!handle)
301 return -EINVAL;
302
303 info = handle_to_ti_sci_info(handle);
304
Andrew F. Davis8928fbd2019-04-29 09:04:11 -0400305 xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_VERSION,
306 TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
Lokesh Vutla5af02db2018-08-27 15:57:32 +0530307 (u32 *)&hdr, sizeof(struct ti_sci_msg_hdr),
308 sizeof(*rev_info));
309 if (IS_ERR(xfer)) {
310 ret = PTR_ERR(xfer);
Lokesh Vutla5af02db2018-08-27 15:57:32 +0530311 return ret;
312 }
313
314 ret = ti_sci_do_xfer(info, xfer);
Andrew Davis771a16f2022-07-25 20:25:03 -0500315 if (ret)
Lokesh Vutla5af02db2018-08-27 15:57:32 +0530316 return ret;
Lokesh Vutla5af02db2018-08-27 15:57:32 +0530317
318 rev_info = (struct ti_sci_msg_resp_version *)xfer->tx_message.buf;
319
320 ver = &handle->version;
321 ver->abi_major = rev_info->abi_major;
322 ver->abi_minor = rev_info->abi_minor;
323 ver->firmware_revision = rev_info->firmware_revision;
324 strncpy(ver->firmware_description, rev_info->firmware_description,
325 sizeof(ver->firmware_description));
326
327 return 0;
328}
329
330/**
Andreas Dannenberg5299c4c2018-08-27 15:57:33 +0530331 * cmd_set_board_config_using_msg() - Common command to send board configuration
332 * message
333 * @handle: pointer to TI SCI handle
334 * @msg_type: One of the TISCI message types to set board configuration
335 * @addr: Address where the board config structure is located
336 * @size: Size of the board config structure
337 *
338 * Return: 0 if all went well, else returns appropriate error value.
339 */
340static int cmd_set_board_config_using_msg(const struct ti_sci_handle *handle,
341 u16 msg_type, u64 addr, u32 size)
342{
343 struct ti_sci_msg_board_config req;
344 struct ti_sci_msg_hdr *resp;
345 struct ti_sci_info *info;
346 struct ti_sci_xfer *xfer;
347 int ret = 0;
348
349 if (IS_ERR(handle))
350 return PTR_ERR(handle);
351 if (!handle)
352 return -EINVAL;
353
354 info = handle_to_ti_sci_info(handle);
355
356 xfer = ti_sci_setup_one_xfer(info, msg_type,
357 TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
358 (u32 *)&req, sizeof(req), sizeof(*resp));
359 if (IS_ERR(xfer)) {
360 ret = PTR_ERR(xfer);
Andreas Dannenberg5299c4c2018-08-27 15:57:33 +0530361 return ret;
362 }
363 req.boardcfgp_high = (addr >> 32) & 0xffffffff;
364 req.boardcfgp_low = addr & 0xffffffff;
365 req.boardcfg_size = size;
366
367 ret = ti_sci_do_xfer(info, xfer);
Andrew Davis771a16f2022-07-25 20:25:03 -0500368 if (ret)
Andreas Dannenberg5299c4c2018-08-27 15:57:33 +0530369 return ret;
Andreas Dannenberg5299c4c2018-08-27 15:57:33 +0530370
Andreas Dannenberg5299c4c2018-08-27 15:57:33 +0530371 return ret;
372}
373
374/**
375 * ti_sci_cmd_set_board_config() - Command to send board configuration message
376 * @handle: pointer to TI SCI handle
377 * @addr: Address where the board config structure is located
378 * @size: Size of the board config structure
379 *
380 * Return: 0 if all went well, else returns appropriate error value.
381 */
382static int ti_sci_cmd_set_board_config(const struct ti_sci_handle *handle,
383 u64 addr, u32 size)
384{
385 return cmd_set_board_config_using_msg(handle,
386 TI_SCI_MSG_BOARD_CONFIG,
387 addr, size);
388}
389
390/**
391 * ti_sci_cmd_set_board_config_rm() - Command to send board resource
392 * management configuration
393 * @handle: pointer to TI SCI handle
394 * @addr: Address where the board RM config structure is located
395 * @size: Size of the RM config structure
396 *
397 * Return: 0 if all went well, else returns appropriate error value.
398 */
399static
400int ti_sci_cmd_set_board_config_rm(const struct ti_sci_handle *handle,
401 u64 addr, u32 size)
402{
403 return cmd_set_board_config_using_msg(handle,
404 TI_SCI_MSG_BOARD_CONFIG_RM,
405 addr, size);
406}
407
408/**
409 * ti_sci_cmd_set_board_config_security() - Command to send board security
410 * configuration message
411 * @handle: pointer to TI SCI handle
412 * @addr: Address where the board security config structure is located
413 * @size: Size of the security config structure
414 *
415 * Return: 0 if all went well, else returns appropriate error value.
416 */
417static
418int ti_sci_cmd_set_board_config_security(const struct ti_sci_handle *handle,
419 u64 addr, u32 size)
420{
421 return cmd_set_board_config_using_msg(handle,
422 TI_SCI_MSG_BOARD_CONFIG_SECURITY,
423 addr, size);
424}
425
426/**
427 * ti_sci_cmd_set_board_config_pm() - Command to send board power and clock
428 * configuration message
429 * @handle: pointer to TI SCI handle
430 * @addr: Address where the board PM config structure is located
431 * @size: Size of the PM config structure
432 *
433 * Return: 0 if all went well, else returns appropriate error value.
434 */
435static int ti_sci_cmd_set_board_config_pm(const struct ti_sci_handle *handle,
436 u64 addr, u32 size)
437{
438 return cmd_set_board_config_using_msg(handle,
439 TI_SCI_MSG_BOARD_CONFIG_PM,
440 addr, size);
441}
442
Lokesh Vutla0d0412a2019-06-07 19:24:41 +0530443static struct ti_sci_exclusive_dev
444*ti_sci_get_exclusive_dev(struct list_head *dev_list, u32 id)
445{
446 struct ti_sci_exclusive_dev *dev;
447
448 list_for_each_entry(dev, dev_list, list)
449 if (dev->id == id)
450 return dev;
451
452 return NULL;
453}
454
455static void ti_sci_add_exclusive_dev(struct ti_sci_info *info, u32 id)
456{
457 struct ti_sci_exclusive_dev *dev;
458
459 dev = ti_sci_get_exclusive_dev(&info->dev_list, id);
460 if (dev) {
461 dev->count++;
462 return;
463 }
464
465 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
466 dev->id = id;
467 dev->count = 1;
468 INIT_LIST_HEAD(&dev->list);
469 list_add_tail(&dev->list, &info->dev_list);
470}
471
472static void ti_sci_delete_exclusive_dev(struct ti_sci_info *info, u32 id)
473{
474 struct ti_sci_exclusive_dev *dev;
475
476 dev = ti_sci_get_exclusive_dev(&info->dev_list, id);
477 if (!dev)
478 return;
479
480 if (dev->count > 0)
481 dev->count--;
482}
483
Andreas Dannenberg24a4d5e2018-08-27 15:57:34 +0530484/**
485 * ti_sci_set_device_state() - Set device state helper
486 * @handle: pointer to TI SCI handle
487 * @id: Device identifier
488 * @flags: flags to setup for the device
489 * @state: State to move the device to
490 *
491 * Return: 0 if all went well, else returns appropriate error value.
492 */
493static int ti_sci_set_device_state(const struct ti_sci_handle *handle,
494 u32 id, u32 flags, u8 state)
495{
496 struct ti_sci_msg_req_set_device_state req;
497 struct ti_sci_msg_hdr *resp;
498 struct ti_sci_info *info;
499 struct ti_sci_xfer *xfer;
500 int ret = 0;
501
502 if (IS_ERR(handle))
503 return PTR_ERR(handle);
504 if (!handle)
505 return -EINVAL;
506
507 info = handle_to_ti_sci_info(handle);
508
509 xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_SET_DEVICE_STATE,
510 flags | TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
511 (u32 *)&req, sizeof(req), sizeof(*resp));
512 if (IS_ERR(xfer)) {
513 ret = PTR_ERR(xfer);
Andreas Dannenberg24a4d5e2018-08-27 15:57:34 +0530514 return ret;
515 }
516 req.id = id;
517 req.state = state;
518
519 ret = ti_sci_do_xfer(info, xfer);
Andrew Davis771a16f2022-07-25 20:25:03 -0500520 if (ret)
Andreas Dannenberg24a4d5e2018-08-27 15:57:34 +0530521 return ret;
Andreas Dannenberg24a4d5e2018-08-27 15:57:34 +0530522
Lokesh Vutla0d0412a2019-06-07 19:24:41 +0530523 if (state == MSG_DEVICE_SW_STATE_AUTO_OFF)
524 ti_sci_delete_exclusive_dev(info, id);
525 else if (flags & MSG_FLAG_DEVICE_EXCLUSIVE)
526 ti_sci_add_exclusive_dev(info, id);
527
Andreas Dannenberg24a4d5e2018-08-27 15:57:34 +0530528 return ret;
529}
530
531/**
Andreas Dannenbergca08cb32019-06-07 19:24:40 +0530532 * ti_sci_set_device_state_no_wait() - Set device state helper without
533 * requesting or waiting for a response.
534 * @handle: pointer to TI SCI handle
535 * @id: Device identifier
536 * @flags: flags to setup for the device
537 * @state: State to move the device to
538 *
539 * Return: 0 if all went well, else returns appropriate error value.
540 */
541static int ti_sci_set_device_state_no_wait(const struct ti_sci_handle *handle,
542 u32 id, u32 flags, u8 state)
543{
544 struct ti_sci_msg_req_set_device_state req;
545 struct ti_sci_info *info;
546 struct ti_sci_xfer *xfer;
547 int ret = 0;
548
549 if (IS_ERR(handle))
550 return PTR_ERR(handle);
551 if (!handle)
552 return -EINVAL;
553
554 info = handle_to_ti_sci_info(handle);
555
556 xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_SET_DEVICE_STATE,
557 flags | TI_SCI_FLAG_REQ_GENERIC_NORESPONSE,
558 (u32 *)&req, sizeof(req), 0);
559 if (IS_ERR(xfer)) {
560 ret = PTR_ERR(xfer);
Andreas Dannenbergca08cb32019-06-07 19:24:40 +0530561 return ret;
562 }
563 req.id = id;
564 req.state = state;
565
566 ret = ti_sci_do_xfer(info, xfer);
567 if (ret)
Andrew Davis771a16f2022-07-25 20:25:03 -0500568 return ret;
Andreas Dannenbergca08cb32019-06-07 19:24:40 +0530569
570 return ret;
571}
572
573/**
Andreas Dannenberg24a4d5e2018-08-27 15:57:34 +0530574 * ti_sci_get_device_state() - Get device state helper
575 * @handle: Handle to the device
576 * @id: Device Identifier
577 * @clcnt: Pointer to Context Loss Count
578 * @resets: pointer to resets
579 * @p_state: pointer to p_state
580 * @c_state: pointer to c_state
581 *
582 * Return: 0 if all went fine, else return appropriate error.
583 */
584static int ti_sci_get_device_state(const struct ti_sci_handle *handle,
585 u32 id, u32 *clcnt, u32 *resets,
586 u8 *p_state, u8 *c_state)
587{
588 struct ti_sci_msg_resp_get_device_state *resp;
589 struct ti_sci_msg_req_get_device_state req;
590 struct ti_sci_info *info;
591 struct ti_sci_xfer *xfer;
592 int ret = 0;
593
594 if (IS_ERR(handle))
595 return PTR_ERR(handle);
596 if (!handle)
597 return -EINVAL;
598
599 if (!clcnt && !resets && !p_state && !c_state)
600 return -EINVAL;
601
602 info = handle_to_ti_sci_info(handle);
603
Andrew F. Davis8928fbd2019-04-29 09:04:11 -0400604 xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_GET_DEVICE_STATE,
605 TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
Andreas Dannenberg24a4d5e2018-08-27 15:57:34 +0530606 (u32 *)&req, sizeof(req), sizeof(*resp));
607 if (IS_ERR(xfer)) {
608 ret = PTR_ERR(xfer);
Andreas Dannenberg24a4d5e2018-08-27 15:57:34 +0530609 return ret;
610 }
611 req.id = id;
612
613 ret = ti_sci_do_xfer(info, xfer);
Andrew Davis771a16f2022-07-25 20:25:03 -0500614 if (ret)
Andreas Dannenberg24a4d5e2018-08-27 15:57:34 +0530615 return ret;
Andreas Dannenberg24a4d5e2018-08-27 15:57:34 +0530616
617 resp = (struct ti_sci_msg_resp_get_device_state *)xfer->tx_message.buf;
Andreas Dannenberg24a4d5e2018-08-27 15:57:34 +0530618
619 if (clcnt)
620 *clcnt = resp->context_loss_count;
621 if (resets)
622 *resets = resp->resets;
623 if (p_state)
624 *p_state = resp->programmed_state;
625 if (c_state)
626 *c_state = resp->current_state;
627
628 return ret;
629}
630
631/**
632 * ti_sci_cmd_get_device() - command to request for device managed by TISCI
633 * @handle: Pointer to TISCI handle as retrieved by *ti_sci_get_handle
634 * @id: Device Identifier
635 *
636 * Request for the device - NOTE: the client MUST maintain integrity of
637 * usage count by balancing get_device with put_device. No refcounting is
638 * managed by driver for that purpose.
639 *
640 * NOTE: The request is for exclusive access for the processor.
641 *
642 * Return: 0 if all went fine, else return appropriate error.
643 */
644static int ti_sci_cmd_get_device(const struct ti_sci_handle *handle, u32 id)
645{
Lokesh Vutlaf5613002019-06-07 19:24:39 +0530646 return ti_sci_set_device_state(handle, id, 0,
647 MSG_DEVICE_SW_STATE_ON);
648}
649
650static int ti_sci_cmd_get_device_exclusive(const struct ti_sci_handle *handle,
651 u32 id)
652{
653 return ti_sci_set_device_state(handle, id, MSG_FLAG_DEVICE_EXCLUSIVE,
Andreas Dannenberg24a4d5e2018-08-27 15:57:34 +0530654 MSG_DEVICE_SW_STATE_ON);
655}
656
657/**
658 * ti_sci_cmd_idle_device() - Command to idle a device managed by TISCI
659 * @handle: Pointer to TISCI handle as retrieved by *ti_sci_get_handle
660 * @id: Device Identifier
661 *
662 * Request for the device - NOTE: the client MUST maintain integrity of
663 * usage count by balancing get_device with put_device. No refcounting is
664 * managed by driver for that purpose.
665 *
666 * Return: 0 if all went fine, else return appropriate error.
667 */
668static int ti_sci_cmd_idle_device(const struct ti_sci_handle *handle, u32 id)
669{
670 return ti_sci_set_device_state(handle, id,
Lokesh Vutlaf5613002019-06-07 19:24:39 +0530671 0,
Andreas Dannenberg24a4d5e2018-08-27 15:57:34 +0530672 MSG_DEVICE_SW_STATE_RETENTION);
673}
674
Lokesh Vutlaf5613002019-06-07 19:24:39 +0530675static int ti_sci_cmd_idle_device_exclusive(const struct ti_sci_handle *handle,
676 u32 id)
677{
678 return ti_sci_set_device_state(handle, id, MSG_FLAG_DEVICE_EXCLUSIVE,
679 MSG_DEVICE_SW_STATE_RETENTION);
680}
681
Andreas Dannenberg24a4d5e2018-08-27 15:57:34 +0530682/**
683 * ti_sci_cmd_put_device() - command to release a device managed by TISCI
684 * @handle: Pointer to TISCI handle as retrieved by *ti_sci_get_handle
685 * @id: Device Identifier
686 *
687 * Request for the device - NOTE: the client MUST maintain integrity of
688 * usage count by balancing get_device with put_device. No refcounting is
689 * managed by driver for that purpose.
690 *
691 * Return: 0 if all went fine, else return appropriate error.
692 */
693static int ti_sci_cmd_put_device(const struct ti_sci_handle *handle, u32 id)
694{
Lokesh Vutlaf5613002019-06-07 19:24:39 +0530695 return ti_sci_set_device_state(handle, id, 0,
696 MSG_DEVICE_SW_STATE_AUTO_OFF);
Andreas Dannenberg24a4d5e2018-08-27 15:57:34 +0530697}
698
Nishanth Menona15ff772025-04-07 07:15:54 -0500699static int ti_sci_cmd_release_exclusive_devices(void)
Lokesh Vutla0d0412a2019-06-07 19:24:41 +0530700{
701 struct ti_sci_exclusive_dev *dev, *tmp;
702 struct ti_sci_info *info;
703 int i, cnt;
704
Nishanth Menona15ff772025-04-07 07:15:54 -0500705 /*
706 * Scan all ti_sci_list registrations, since with FIT images, we could
707 * have started with one device tree registration and switched over
708 * to a final version. This prevents exclusive devices identified
709 * during the first probe to be left orphan.
710 */
711 list_for_each_entry(info, &ti_sci_list, list) {
712 list_for_each_entry_safe(dev, tmp, &info->dev_list, list) {
713 cnt = dev->count;
714 debug("%s: id = %d, cnt = %d\n", __func__, dev->id, cnt);
715 for (i = 0; i < cnt; i++)
716 ti_sci_cmd_put_device(&info->handle, dev->id);
717 }
Lokesh Vutla0d0412a2019-06-07 19:24:41 +0530718 }
719
720 return 0;
721}
722
Andreas Dannenberg24a4d5e2018-08-27 15:57:34 +0530723/**
724 * ti_sci_cmd_dev_is_valid() - Is the device valid
725 * @handle: Pointer to TISCI handle as retrieved by *ti_sci_get_handle
726 * @id: Device Identifier
727 *
728 * Return: 0 if all went fine and the device ID is valid, else return
729 * appropriate error.
730 */
731static int ti_sci_cmd_dev_is_valid(const struct ti_sci_handle *handle, u32 id)
732{
733 u8 unused;
734
735 /* check the device state which will also tell us if the ID is valid */
736 return ti_sci_get_device_state(handle, id, NULL, NULL, NULL, &unused);
737}
738
739/**
740 * ti_sci_cmd_dev_get_clcnt() - Get context loss counter
741 * @handle: Pointer to TISCI handle
742 * @id: Device Identifier
743 * @count: Pointer to Context Loss counter to populate
744 *
745 * Return: 0 if all went fine, else return appropriate error.
746 */
747static int ti_sci_cmd_dev_get_clcnt(const struct ti_sci_handle *handle, u32 id,
748 u32 *count)
749{
750 return ti_sci_get_device_state(handle, id, count, NULL, NULL, NULL);
751}
752
753/**
754 * ti_sci_cmd_dev_is_idle() - Check if the device is requested to be idle
755 * @handle: Pointer to TISCI handle
756 * @id: Device Identifier
757 * @r_state: true if requested to be idle
758 *
759 * Return: 0 if all went fine, else return appropriate error.
760 */
761static int ti_sci_cmd_dev_is_idle(const struct ti_sci_handle *handle, u32 id,
762 bool *r_state)
763{
764 int ret;
765 u8 state;
766
767 if (!r_state)
768 return -EINVAL;
769
770 ret = ti_sci_get_device_state(handle, id, NULL, NULL, &state, NULL);
771 if (ret)
772 return ret;
773
774 *r_state = (state == MSG_DEVICE_SW_STATE_RETENTION);
775
776 return 0;
777}
778
779/**
780 * ti_sci_cmd_dev_is_stop() - Check if the device is requested to be stopped
781 * @handle: Pointer to TISCI handle
782 * @id: Device Identifier
783 * @r_state: true if requested to be stopped
784 * @curr_state: true if currently stopped.
785 *
786 * Return: 0 if all went fine, else return appropriate error.
787 */
788static int ti_sci_cmd_dev_is_stop(const struct ti_sci_handle *handle, u32 id,
789 bool *r_state, bool *curr_state)
790{
791 int ret;
792 u8 p_state, c_state;
793
794 if (!r_state && !curr_state)
795 return -EINVAL;
796
797 ret =
798 ti_sci_get_device_state(handle, id, NULL, NULL, &p_state, &c_state);
799 if (ret)
800 return ret;
801
802 if (r_state)
803 *r_state = (p_state == MSG_DEVICE_SW_STATE_AUTO_OFF);
804 if (curr_state)
805 *curr_state = (c_state == MSG_DEVICE_HW_STATE_OFF);
806
807 return 0;
808}
809
810/**
811 * ti_sci_cmd_dev_is_on() - Check if the device is requested to be ON
812 * @handle: Pointer to TISCI handle
813 * @id: Device Identifier
814 * @r_state: true if requested to be ON
815 * @curr_state: true if currently ON and active
816 *
817 * Return: 0 if all went fine, else return appropriate error.
818 */
819static int ti_sci_cmd_dev_is_on(const struct ti_sci_handle *handle, u32 id,
820 bool *r_state, bool *curr_state)
821{
822 int ret;
823 u8 p_state, c_state;
824
825 if (!r_state && !curr_state)
826 return -EINVAL;
827
828 ret =
829 ti_sci_get_device_state(handle, id, NULL, NULL, &p_state, &c_state);
830 if (ret)
831 return ret;
832
833 if (r_state)
834 *r_state = (p_state == MSG_DEVICE_SW_STATE_ON);
835 if (curr_state)
836 *curr_state = (c_state == MSG_DEVICE_HW_STATE_ON);
837
838 return 0;
839}
840
841/**
842 * ti_sci_cmd_dev_is_trans() - Check if the device is currently transitioning
843 * @handle: Pointer to TISCI handle
844 * @id: Device Identifier
845 * @curr_state: true if currently transitioning.
846 *
847 * Return: 0 if all went fine, else return appropriate error.
848 */
849static int ti_sci_cmd_dev_is_trans(const struct ti_sci_handle *handle, u32 id,
850 bool *curr_state)
851{
852 int ret;
853 u8 state;
854
855 if (!curr_state)
856 return -EINVAL;
857
858 ret = ti_sci_get_device_state(handle, id, NULL, NULL, NULL, &state);
859 if (ret)
860 return ret;
861
862 *curr_state = (state == MSG_DEVICE_HW_STATE_TRANS);
863
864 return 0;
865}
866
867/**
868 * ti_sci_cmd_set_device_resets() - command to set resets for device managed
869 * by TISCI
870 * @handle: Pointer to TISCI handle as retrieved by *ti_sci_get_handle
871 * @id: Device Identifier
872 * @reset_state: Device specific reset bit field
873 *
874 * Return: 0 if all went fine, else return appropriate error.
875 */
876static int ti_sci_cmd_set_device_resets(const struct ti_sci_handle *handle,
877 u32 id, u32 reset_state)
878{
879 struct ti_sci_msg_req_set_device_resets req;
880 struct ti_sci_msg_hdr *resp;
881 struct ti_sci_info *info;
882 struct ti_sci_xfer *xfer;
883 int ret = 0;
884
885 if (IS_ERR(handle))
886 return PTR_ERR(handle);
887 if (!handle)
888 return -EINVAL;
889
890 info = handle_to_ti_sci_info(handle);
891
892 xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_SET_DEVICE_RESETS,
893 TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
894 (u32 *)&req, sizeof(req), sizeof(*resp));
895 if (IS_ERR(xfer)) {
896 ret = PTR_ERR(xfer);
Andreas Dannenberg24a4d5e2018-08-27 15:57:34 +0530897 return ret;
898 }
899 req.id = id;
900 req.resets = reset_state;
901
902 ret = ti_sci_do_xfer(info, xfer);
Andrew Davis771a16f2022-07-25 20:25:03 -0500903 if (ret)
Andreas Dannenberg24a4d5e2018-08-27 15:57:34 +0530904 return ret;
Andreas Dannenberg24a4d5e2018-08-27 15:57:34 +0530905
Andreas Dannenberg24a4d5e2018-08-27 15:57:34 +0530906 return ret;
907}
908
909/**
910 * ti_sci_cmd_get_device_resets() - Get reset state for device managed
911 * by TISCI
912 * @handle: Pointer to TISCI handle
913 * @id: Device Identifier
914 * @reset_state: Pointer to reset state to populate
915 *
916 * Return: 0 if all went fine, else return appropriate error.
917 */
918static int ti_sci_cmd_get_device_resets(const struct ti_sci_handle *handle,
919 u32 id, u32 *reset_state)
920{
921 return ti_sci_get_device_state(handle, id, NULL, reset_state, NULL,
922 NULL);
923}
924
Lokesh Vutlad10c80c2018-08-27 15:57:35 +0530925/**
926 * ti_sci_set_clock_state() - Set clock state helper
927 * @handle: pointer to TI SCI handle
928 * @dev_id: Device identifier this request is for
929 * @clk_id: Clock identifier for the device for this request.
930 * Each device has it's own set of clock inputs. This indexes
931 * which clock input to modify.
932 * @flags: Header flags as needed
933 * @state: State to request for the clock.
934 *
935 * Return: 0 if all went well, else returns appropriate error value.
936 */
937static int ti_sci_set_clock_state(const struct ti_sci_handle *handle,
938 u32 dev_id, u8 clk_id,
939 u32 flags, u8 state)
940{
941 struct ti_sci_msg_req_set_clock_state req;
942 struct ti_sci_msg_hdr *resp;
943 struct ti_sci_info *info;
944 struct ti_sci_xfer *xfer;
945 int ret = 0;
946
947 if (IS_ERR(handle))
948 return PTR_ERR(handle);
949 if (!handle)
950 return -EINVAL;
951
952 info = handle_to_ti_sci_info(handle);
953
954 xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_SET_CLOCK_STATE,
955 flags | TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
956 (u32 *)&req, sizeof(req), sizeof(*resp));
957 if (IS_ERR(xfer)) {
958 ret = PTR_ERR(xfer);
Lokesh Vutlad10c80c2018-08-27 15:57:35 +0530959 return ret;
960 }
961 req.dev_id = dev_id;
962 req.clk_id = clk_id;
963 req.request_state = state;
964
965 ret = ti_sci_do_xfer(info, xfer);
Andrew Davis771a16f2022-07-25 20:25:03 -0500966 if (ret)
Lokesh Vutlad10c80c2018-08-27 15:57:35 +0530967 return ret;
Lokesh Vutlad10c80c2018-08-27 15:57:35 +0530968
Lokesh Vutlad10c80c2018-08-27 15:57:35 +0530969 return ret;
970}
971
972/**
973 * ti_sci_cmd_get_clock_state() - Get clock state helper
974 * @handle: pointer to TI SCI handle
975 * @dev_id: Device identifier this request is for
976 * @clk_id: Clock identifier for the device for this request.
977 * Each device has it's own set of clock inputs. This indexes
978 * which clock input to modify.
979 * @programmed_state: State requested for clock to move to
980 * @current_state: State that the clock is currently in
981 *
982 * Return: 0 if all went well, else returns appropriate error value.
983 */
984static int ti_sci_cmd_get_clock_state(const struct ti_sci_handle *handle,
985 u32 dev_id, u8 clk_id,
986 u8 *programmed_state, u8 *current_state)
987{
988 struct ti_sci_msg_resp_get_clock_state *resp;
989 struct ti_sci_msg_req_get_clock_state req;
990 struct ti_sci_info *info;
991 struct ti_sci_xfer *xfer;
992 int ret = 0;
993
994 if (IS_ERR(handle))
995 return PTR_ERR(handle);
996 if (!handle)
997 return -EINVAL;
998
999 if (!programmed_state && !current_state)
1000 return -EINVAL;
1001
1002 info = handle_to_ti_sci_info(handle);
1003
1004 xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_GET_CLOCK_STATE,
1005 TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1006 (u32 *)&req, sizeof(req), sizeof(*resp));
1007 if (IS_ERR(xfer)) {
1008 ret = PTR_ERR(xfer);
Lokesh Vutlad10c80c2018-08-27 15:57:35 +05301009 return ret;
1010 }
1011 req.dev_id = dev_id;
1012 req.clk_id = clk_id;
1013
1014 ret = ti_sci_do_xfer(info, xfer);
Andrew Davis771a16f2022-07-25 20:25:03 -05001015 if (ret)
Lokesh Vutlad10c80c2018-08-27 15:57:35 +05301016 return ret;
Lokesh Vutlad10c80c2018-08-27 15:57:35 +05301017
1018 resp = (struct ti_sci_msg_resp_get_clock_state *)xfer->tx_message.buf;
1019
Lokesh Vutlad10c80c2018-08-27 15:57:35 +05301020 if (programmed_state)
1021 *programmed_state = resp->programmed_state;
1022 if (current_state)
1023 *current_state = resp->current_state;
1024
1025 return ret;
1026}
1027
1028/**
1029 * ti_sci_cmd_get_clock() - Get control of a clock from TI SCI
1030 * @handle: pointer to TI SCI handle
1031 * @dev_id: Device identifier this request is for
1032 * @clk_id: Clock identifier for the device for this request.
1033 * Each device has it's own set of clock inputs. This indexes
1034 * which clock input to modify.
1035 * @needs_ssc: 'true' if Spread Spectrum clock is desired, else 'false'
1036 * @can_change_freq: 'true' if frequency change is desired, else 'false'
1037 * @enable_input_term: 'true' if input termination is desired, else 'false'
1038 *
1039 * Return: 0 if all went well, else returns appropriate error value.
1040 */
1041static int ti_sci_cmd_get_clock(const struct ti_sci_handle *handle, u32 dev_id,
1042 u8 clk_id, bool needs_ssc, bool can_change_freq,
1043 bool enable_input_term)
1044{
1045 u32 flags = 0;
1046
1047 flags |= needs_ssc ? MSG_FLAG_CLOCK_ALLOW_SSC : 0;
1048 flags |= can_change_freq ? MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE : 0;
1049 flags |= enable_input_term ? MSG_FLAG_CLOCK_INPUT_TERM : 0;
1050
1051 return ti_sci_set_clock_state(handle, dev_id, clk_id, flags,
1052 MSG_CLOCK_SW_STATE_REQ);
1053}
1054
1055/**
1056 * ti_sci_cmd_idle_clock() - Idle a clock which is in our control
1057 * @handle: pointer to TI SCI handle
1058 * @dev_id: Device identifier this request is for
1059 * @clk_id: Clock identifier for the device for this request.
1060 * Each device has it's own set of clock inputs. This indexes
1061 * which clock input to modify.
1062 *
1063 * NOTE: This clock must have been requested by get_clock previously.
1064 *
1065 * Return: 0 if all went well, else returns appropriate error value.
1066 */
1067static int ti_sci_cmd_idle_clock(const struct ti_sci_handle *handle,
1068 u32 dev_id, u8 clk_id)
1069{
1070 return ti_sci_set_clock_state(handle, dev_id, clk_id, 0,
1071 MSG_CLOCK_SW_STATE_UNREQ);
1072}
1073
1074/**
1075 * ti_sci_cmd_put_clock() - Release a clock from our control back to TISCI
1076 * @handle: pointer to TI SCI handle
1077 * @dev_id: Device identifier this request is for
1078 * @clk_id: Clock identifier for the device for this request.
1079 * Each device has it's own set of clock inputs. This indexes
1080 * which clock input to modify.
1081 *
1082 * NOTE: This clock must have been requested by get_clock previously.
1083 *
1084 * Return: 0 if all went well, else returns appropriate error value.
1085 */
1086static int ti_sci_cmd_put_clock(const struct ti_sci_handle *handle,
1087 u32 dev_id, u8 clk_id)
1088{
1089 return ti_sci_set_clock_state(handle, dev_id, clk_id, 0,
1090 MSG_CLOCK_SW_STATE_AUTO);
1091}
1092
1093/**
1094 * ti_sci_cmd_clk_is_auto() - Is the clock being auto managed
1095 * @handle: pointer to TI SCI handle
1096 * @dev_id: Device identifier this request is for
1097 * @clk_id: Clock identifier for the device for this request.
1098 * Each device has it's own set of clock inputs. This indexes
1099 * which clock input to modify.
1100 * @req_state: state indicating if the clock is auto managed
1101 *
1102 * Return: 0 if all went well, else returns appropriate error value.
1103 */
1104static int ti_sci_cmd_clk_is_auto(const struct ti_sci_handle *handle,
1105 u32 dev_id, u8 clk_id, bool *req_state)
1106{
1107 u8 state = 0;
1108 int ret;
1109
1110 if (!req_state)
1111 return -EINVAL;
1112
1113 ret = ti_sci_cmd_get_clock_state(handle, dev_id, clk_id, &state, NULL);
1114 if (ret)
1115 return ret;
1116
1117 *req_state = (state == MSG_CLOCK_SW_STATE_AUTO);
1118 return 0;
1119}
1120
1121/**
1122 * ti_sci_cmd_clk_is_on() - Is the clock ON
1123 * @handle: pointer to TI SCI handle
1124 * @dev_id: Device identifier this request is for
1125 * @clk_id: Clock identifier for the device for this request.
1126 * Each device has it's own set of clock inputs. This indexes
1127 * which clock input to modify.
1128 * @req_state: state indicating if the clock is managed by us and enabled
1129 * @curr_state: state indicating if the clock is ready for operation
1130 *
1131 * Return: 0 if all went well, else returns appropriate error value.
1132 */
1133static int ti_sci_cmd_clk_is_on(const struct ti_sci_handle *handle, u32 dev_id,
1134 u8 clk_id, bool *req_state, bool *curr_state)
1135{
1136 u8 c_state = 0, r_state = 0;
1137 int ret;
1138
1139 if (!req_state && !curr_state)
1140 return -EINVAL;
1141
1142 ret = ti_sci_cmd_get_clock_state(handle, dev_id, clk_id,
1143 &r_state, &c_state);
1144 if (ret)
1145 return ret;
1146
1147 if (req_state)
1148 *req_state = (r_state == MSG_CLOCK_SW_STATE_REQ);
1149 if (curr_state)
1150 *curr_state = (c_state == MSG_CLOCK_HW_STATE_READY);
1151 return 0;
1152}
1153
1154/**
1155 * ti_sci_cmd_clk_is_off() - Is the clock OFF
1156 * @handle: pointer to TI SCI handle
1157 * @dev_id: Device identifier this request is for
1158 * @clk_id: Clock identifier for the device for this request.
1159 * Each device has it's own set of clock inputs. This indexes
1160 * which clock input to modify.
1161 * @req_state: state indicating if the clock is managed by us and disabled
1162 * @curr_state: state indicating if the clock is NOT ready for operation
1163 *
1164 * Return: 0 if all went well, else returns appropriate error value.
1165 */
1166static int ti_sci_cmd_clk_is_off(const struct ti_sci_handle *handle, u32 dev_id,
1167 u8 clk_id, bool *req_state, bool *curr_state)
1168{
1169 u8 c_state = 0, r_state = 0;
1170 int ret;
1171
1172 if (!req_state && !curr_state)
1173 return -EINVAL;
1174
1175 ret = ti_sci_cmd_get_clock_state(handle, dev_id, clk_id,
1176 &r_state, &c_state);
1177 if (ret)
1178 return ret;
1179
1180 if (req_state)
1181 *req_state = (r_state == MSG_CLOCK_SW_STATE_UNREQ);
1182 if (curr_state)
1183 *curr_state = (c_state == MSG_CLOCK_HW_STATE_NOT_READY);
1184 return 0;
1185}
1186
1187/**
1188 * ti_sci_cmd_clk_set_parent() - Set the clock source of a specific device clock
1189 * @handle: pointer to TI SCI handle
1190 * @dev_id: Device identifier this request is for
1191 * @clk_id: Clock identifier for the device for this request.
1192 * Each device has it's own set of clock inputs. This indexes
1193 * which clock input to modify.
1194 * @parent_id: Parent clock identifier to set
1195 *
1196 * Return: 0 if all went well, else returns appropriate error value.
1197 */
1198static int ti_sci_cmd_clk_set_parent(const struct ti_sci_handle *handle,
1199 u32 dev_id, u8 clk_id, u8 parent_id)
1200{
1201 struct ti_sci_msg_req_set_clock_parent req;
1202 struct ti_sci_msg_hdr *resp;
1203 struct ti_sci_info *info;
1204 struct ti_sci_xfer *xfer;
1205 int ret = 0;
1206
1207 if (IS_ERR(handle))
1208 return PTR_ERR(handle);
1209 if (!handle)
1210 return -EINVAL;
1211
1212 info = handle_to_ti_sci_info(handle);
1213
1214 xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_SET_CLOCK_PARENT,
1215 TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1216 (u32 *)&req, sizeof(req), sizeof(*resp));
1217 if (IS_ERR(xfer)) {
1218 ret = PTR_ERR(xfer);
Lokesh Vutlad10c80c2018-08-27 15:57:35 +05301219 return ret;
1220 }
1221 req.dev_id = dev_id;
1222 req.clk_id = clk_id;
1223 req.parent_id = parent_id;
1224
1225 ret = ti_sci_do_xfer(info, xfer);
Andrew Davis771a16f2022-07-25 20:25:03 -05001226 if (ret)
Lokesh Vutlad10c80c2018-08-27 15:57:35 +05301227 return ret;
Lokesh Vutlad10c80c2018-08-27 15:57:35 +05301228
Lokesh Vutlad10c80c2018-08-27 15:57:35 +05301229 return ret;
1230}
1231
1232/**
1233 * ti_sci_cmd_clk_get_parent() - Get current parent clock source
1234 * @handle: pointer to TI SCI handle
1235 * @dev_id: Device identifier this request is for
1236 * @clk_id: Clock identifier for the device for this request.
1237 * Each device has it's own set of clock inputs. This indexes
1238 * which clock input to modify.
1239 * @parent_id: Current clock parent
1240 *
1241 * Return: 0 if all went well, else returns appropriate error value.
1242 */
1243static int ti_sci_cmd_clk_get_parent(const struct ti_sci_handle *handle,
1244 u32 dev_id, u8 clk_id, u8 *parent_id)
1245{
1246 struct ti_sci_msg_resp_get_clock_parent *resp;
1247 struct ti_sci_msg_req_get_clock_parent req;
1248 struct ti_sci_info *info;
1249 struct ti_sci_xfer *xfer;
1250 int ret = 0;
1251
1252 if (IS_ERR(handle))
1253 return PTR_ERR(handle);
1254 if (!handle || !parent_id)
1255 return -EINVAL;
1256
1257 info = handle_to_ti_sci_info(handle);
1258
1259 xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_GET_CLOCK_PARENT,
1260 TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1261 (u32 *)&req, sizeof(req), sizeof(*resp));
1262 if (IS_ERR(xfer)) {
1263 ret = PTR_ERR(xfer);
Lokesh Vutlad10c80c2018-08-27 15:57:35 +05301264 return ret;
1265 }
1266 req.dev_id = dev_id;
1267 req.clk_id = clk_id;
1268
1269 ret = ti_sci_do_xfer(info, xfer);
Andrew Davis771a16f2022-07-25 20:25:03 -05001270 if (ret)
Lokesh Vutlad10c80c2018-08-27 15:57:35 +05301271 return ret;
Lokesh Vutlad10c80c2018-08-27 15:57:35 +05301272
Andrew Davis04e43932022-07-25 20:25:06 -05001273 *parent_id = resp->parent_id;
Lokesh Vutlad10c80c2018-08-27 15:57:35 +05301274
1275 return ret;
1276}
1277
1278/**
1279 * ti_sci_cmd_clk_get_num_parents() - Get num parents of the current clk source
1280 * @handle: pointer to TI SCI handle
1281 * @dev_id: Device identifier this request is for
1282 * @clk_id: Clock identifier for the device for this request.
1283 * Each device has it's own set of clock inputs. This indexes
1284 * which clock input to modify.
1285 * @num_parents: Returns he number of parents to the current clock.
1286 *
1287 * Return: 0 if all went well, else returns appropriate error value.
1288 */
1289static int ti_sci_cmd_clk_get_num_parents(const struct ti_sci_handle *handle,
1290 u32 dev_id, u8 clk_id,
1291 u8 *num_parents)
1292{
1293 struct ti_sci_msg_resp_get_clock_num_parents *resp;
1294 struct ti_sci_msg_req_get_clock_num_parents req;
1295 struct ti_sci_info *info;
1296 struct ti_sci_xfer *xfer;
1297 int ret = 0;
1298
1299 if (IS_ERR(handle))
1300 return PTR_ERR(handle);
1301 if (!handle || !num_parents)
1302 return -EINVAL;
1303
1304 info = handle_to_ti_sci_info(handle);
1305
1306 xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_GET_NUM_CLOCK_PARENTS,
1307 TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1308 (u32 *)&req, sizeof(req), sizeof(*resp));
1309 if (IS_ERR(xfer)) {
1310 ret = PTR_ERR(xfer);
Lokesh Vutlad10c80c2018-08-27 15:57:35 +05301311 return ret;
1312 }
1313 req.dev_id = dev_id;
1314 req.clk_id = clk_id;
1315
1316 ret = ti_sci_do_xfer(info, xfer);
Andrew Davis771a16f2022-07-25 20:25:03 -05001317 if (ret)
Lokesh Vutlad10c80c2018-08-27 15:57:35 +05301318 return ret;
Lokesh Vutlad10c80c2018-08-27 15:57:35 +05301319
1320 resp = (struct ti_sci_msg_resp_get_clock_num_parents *)
1321 xfer->tx_message.buf;
1322
Andrew Davis04e43932022-07-25 20:25:06 -05001323 *num_parents = resp->num_parents;
Lokesh Vutlad10c80c2018-08-27 15:57:35 +05301324
1325 return ret;
1326}
1327
1328/**
1329 * ti_sci_cmd_clk_get_match_freq() - Find a good match for frequency
1330 * @handle: pointer to TI SCI handle
1331 * @dev_id: Device identifier this request is for
1332 * @clk_id: Clock identifier for the device for this request.
1333 * Each device has it's own set of clock inputs. This indexes
1334 * which clock input to modify.
1335 * @min_freq: The minimum allowable frequency in Hz. This is the minimum
1336 * allowable programmed frequency and does not account for clock
1337 * tolerances and jitter.
1338 * @target_freq: The target clock frequency in Hz. A frequency will be
1339 * processed as close to this target frequency as possible.
1340 * @max_freq: The maximum allowable frequency in Hz. This is the maximum
1341 * allowable programmed frequency and does not account for clock
1342 * tolerances and jitter.
1343 * @match_freq: Frequency match in Hz response.
1344 *
1345 * Return: 0 if all went well, else returns appropriate error value.
1346 */
1347static int ti_sci_cmd_clk_get_match_freq(const struct ti_sci_handle *handle,
1348 u32 dev_id, u8 clk_id, u64 min_freq,
1349 u64 target_freq, u64 max_freq,
1350 u64 *match_freq)
1351{
1352 struct ti_sci_msg_resp_query_clock_freq *resp;
1353 struct ti_sci_msg_req_query_clock_freq req;
1354 struct ti_sci_info *info;
1355 struct ti_sci_xfer *xfer;
1356 int ret = 0;
1357
1358 if (IS_ERR(handle))
1359 return PTR_ERR(handle);
1360 if (!handle || !match_freq)
1361 return -EINVAL;
1362
1363 info = handle_to_ti_sci_info(handle);
1364
1365 xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_QUERY_CLOCK_FREQ,
1366 TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1367 (u32 *)&req, sizeof(req), sizeof(*resp));
1368 if (IS_ERR(xfer)) {
1369 ret = PTR_ERR(xfer);
Lokesh Vutlad10c80c2018-08-27 15:57:35 +05301370 return ret;
1371 }
1372 req.dev_id = dev_id;
1373 req.clk_id = clk_id;
1374 req.min_freq_hz = min_freq;
1375 req.target_freq_hz = target_freq;
1376 req.max_freq_hz = max_freq;
1377
1378 ret = ti_sci_do_xfer(info, xfer);
Andrew Davis771a16f2022-07-25 20:25:03 -05001379 if (ret)
Lokesh Vutlad10c80c2018-08-27 15:57:35 +05301380 return ret;
Lokesh Vutlad10c80c2018-08-27 15:57:35 +05301381
1382 resp = (struct ti_sci_msg_resp_query_clock_freq *)xfer->tx_message.buf;
1383
Andrew Davis04e43932022-07-25 20:25:06 -05001384 *match_freq = resp->freq_hz;
Lokesh Vutlad10c80c2018-08-27 15:57:35 +05301385
1386 return ret;
1387}
1388
1389/**
1390 * ti_sci_cmd_clk_set_freq() - Set a frequency for clock
1391 * @handle: pointer to TI SCI handle
1392 * @dev_id: Device identifier this request is for
1393 * @clk_id: Clock identifier for the device for this request.
1394 * Each device has it's own set of clock inputs. This indexes
1395 * which clock input to modify.
1396 * @min_freq: The minimum allowable frequency in Hz. This is the minimum
1397 * allowable programmed frequency and does not account for clock
1398 * tolerances and jitter.
1399 * @target_freq: The target clock frequency in Hz. A frequency will be
1400 * processed as close to this target frequency as possible.
1401 * @max_freq: The maximum allowable frequency in Hz. This is the maximum
1402 * allowable programmed frequency and does not account for clock
1403 * tolerances and jitter.
1404 *
1405 * Return: 0 if all went well, else returns appropriate error value.
1406 */
1407static int ti_sci_cmd_clk_set_freq(const struct ti_sci_handle *handle,
1408 u32 dev_id, u8 clk_id, u64 min_freq,
1409 u64 target_freq, u64 max_freq)
1410{
1411 struct ti_sci_msg_req_set_clock_freq req;
1412 struct ti_sci_msg_hdr *resp;
1413 struct ti_sci_info *info;
1414 struct ti_sci_xfer *xfer;
1415 int ret = 0;
1416
1417 if (IS_ERR(handle))
1418 return PTR_ERR(handle);
1419 if (!handle)
1420 return -EINVAL;
1421
1422 info = handle_to_ti_sci_info(handle);
1423
1424 xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_SET_CLOCK_FREQ,
1425 TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1426 (u32 *)&req, sizeof(req), sizeof(*resp));
1427 if (IS_ERR(xfer)) {
1428 ret = PTR_ERR(xfer);
Lokesh Vutlad10c80c2018-08-27 15:57:35 +05301429 return ret;
1430 }
1431 req.dev_id = dev_id;
1432 req.clk_id = clk_id;
1433 req.min_freq_hz = min_freq;
1434 req.target_freq_hz = target_freq;
1435 req.max_freq_hz = max_freq;
1436
1437 ret = ti_sci_do_xfer(info, xfer);
Andrew Davis771a16f2022-07-25 20:25:03 -05001438 if (ret)
Lokesh Vutlad10c80c2018-08-27 15:57:35 +05301439 return ret;
Lokesh Vutlad10c80c2018-08-27 15:57:35 +05301440
Lokesh Vutlad10c80c2018-08-27 15:57:35 +05301441 return ret;
1442}
1443
1444/**
1445 * ti_sci_cmd_clk_get_freq() - Get current frequency
1446 * @handle: pointer to TI SCI handle
1447 * @dev_id: Device identifier this request is for
1448 * @clk_id: Clock identifier for the device for this request.
1449 * Each device has it's own set of clock inputs. This indexes
1450 * which clock input to modify.
1451 * @freq: Currently frequency in Hz
1452 *
1453 * Return: 0 if all went well, else returns appropriate error value.
1454 */
1455static int ti_sci_cmd_clk_get_freq(const struct ti_sci_handle *handle,
1456 u32 dev_id, u8 clk_id, u64 *freq)
1457{
1458 struct ti_sci_msg_resp_get_clock_freq *resp;
1459 struct ti_sci_msg_req_get_clock_freq req;
1460 struct ti_sci_info *info;
1461 struct ti_sci_xfer *xfer;
1462 int ret = 0;
1463
1464 if (IS_ERR(handle))
1465 return PTR_ERR(handle);
1466 if (!handle || !freq)
1467 return -EINVAL;
1468
1469 info = handle_to_ti_sci_info(handle);
1470
1471 xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_GET_CLOCK_FREQ,
1472 TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1473 (u32 *)&req, sizeof(req), sizeof(*resp));
1474 if (IS_ERR(xfer)) {
1475 ret = PTR_ERR(xfer);
Lokesh Vutlad10c80c2018-08-27 15:57:35 +05301476 return ret;
1477 }
1478 req.dev_id = dev_id;
1479 req.clk_id = clk_id;
1480
1481 ret = ti_sci_do_xfer(info, xfer);
Andrew Davis771a16f2022-07-25 20:25:03 -05001482 if (ret)
Lokesh Vutlad10c80c2018-08-27 15:57:35 +05301483 return ret;
Lokesh Vutlad10c80c2018-08-27 15:57:35 +05301484
1485 resp = (struct ti_sci_msg_resp_get_clock_freq *)xfer->tx_message.buf;
1486
Andrew Davis04e43932022-07-25 20:25:06 -05001487 *freq = resp->freq_hz;
Lokesh Vutlad10c80c2018-08-27 15:57:35 +05301488
1489 return ret;
1490}
1491
Andreas Dannenberg5bd08372018-08-27 15:57:36 +05301492/**
1493 * ti_sci_cmd_core_reboot() - Command to request system reset
1494 * @handle: pointer to TI SCI handle
1495 *
1496 * Return: 0 if all went well, else returns appropriate error value.
1497 */
1498static int ti_sci_cmd_core_reboot(const struct ti_sci_handle *handle)
1499{
1500 struct ti_sci_msg_req_reboot req;
1501 struct ti_sci_msg_hdr *resp;
1502 struct ti_sci_info *info;
1503 struct ti_sci_xfer *xfer;
1504 int ret = 0;
1505
1506 if (IS_ERR(handle))
1507 return PTR_ERR(handle);
1508 if (!handle)
1509 return -EINVAL;
1510
1511 info = handle_to_ti_sci_info(handle);
1512
1513 xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_SYS_RESET,
1514 TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1515 (u32 *)&req, sizeof(req), sizeof(*resp));
1516 if (IS_ERR(xfer)) {
1517 ret = PTR_ERR(xfer);
Andreas Dannenberg5bd08372018-08-27 15:57:36 +05301518 return ret;
1519 }
Dave Gerlach366df4e2021-05-13 20:10:55 -05001520 req.domain = 0;
Andreas Dannenberg5bd08372018-08-27 15:57:36 +05301521
1522 ret = ti_sci_do_xfer(info, xfer);
Andrew Davis771a16f2022-07-25 20:25:03 -05001523 if (ret)
Andreas Dannenberg5bd08372018-08-27 15:57:36 +05301524 return ret;
Andreas Dannenberg5bd08372018-08-27 15:57:36 +05301525
Andreas Dannenberg5bd08372018-08-27 15:57:36 +05301526 return ret;
1527}
1528
Grygorii Strashkod64c5b22019-02-05 17:31:21 +05301529/**
1530 * ti_sci_get_resource_range - Helper to get a range of resources assigned
1531 * to a host. Resource is uniquely identified by
1532 * type and subtype.
1533 * @handle: Pointer to TISCI handle.
1534 * @dev_id: TISCI device ID.
1535 * @subtype: Resource assignment subtype that is being requested
1536 * from the given device.
1537 * @s_host: Host processor ID to which the resources are allocated
1538 * @range_start: Start index of the resource range
1539 * @range_num: Number of resources in the range
1540 *
1541 * Return: 0 if all went fine, else return appropriate error.
1542 */
1543static int ti_sci_get_resource_range(const struct ti_sci_handle *handle,
1544 u32 dev_id, u8 subtype, u8 s_host,
1545 u16 *range_start, u16 *range_num)
1546{
1547 struct ti_sci_msg_resp_get_resource_range *resp;
1548 struct ti_sci_msg_req_get_resource_range req;
1549 struct ti_sci_xfer *xfer;
1550 struct ti_sci_info *info;
Grygorii Strashkod64c5b22019-02-05 17:31:21 +05301551 int ret = 0;
1552
1553 if (IS_ERR(handle))
1554 return PTR_ERR(handle);
1555 if (!handle)
1556 return -EINVAL;
1557
1558 info = handle_to_ti_sci_info(handle);
1559
1560 xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_GET_RESOURCE_RANGE,
1561 TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1562 (u32 *)&req, sizeof(req), sizeof(*resp));
1563 if (IS_ERR(xfer)) {
1564 ret = PTR_ERR(xfer);
Grygorii Strashkod64c5b22019-02-05 17:31:21 +05301565 return ret;
1566 }
1567
Grygorii Strashkod64c5b22019-02-05 17:31:21 +05301568 req.secondary_host = s_host;
Lokesh Vutla0acf1dc2020-08-17 11:00:48 +05301569 req.type = dev_id & MSG_RM_RESOURCE_TYPE_MASK;
Grygorii Strashkod64c5b22019-02-05 17:31:21 +05301570 req.subtype = subtype & MSG_RM_RESOURCE_SUBTYPE_MASK;
1571
1572 ret = ti_sci_do_xfer(info, xfer);
Andrew Davis771a16f2022-07-25 20:25:03 -05001573 if (ret)
Grygorii Strashkod64c5b22019-02-05 17:31:21 +05301574 goto fail;
Grygorii Strashkod64c5b22019-02-05 17:31:21 +05301575
1576 resp = (struct ti_sci_msg_resp_get_resource_range *)xfer->tx_message.buf;
Andrew Davis04e43932022-07-25 20:25:06 -05001577 if (!resp->range_start && !resp->range_num) {
Grygorii Strashkod64c5b22019-02-05 17:31:21 +05301578 ret = -ENODEV;
1579 } else {
1580 *range_start = resp->range_start;
1581 *range_num = resp->range_num;
1582 };
1583
1584fail:
1585 return ret;
1586}
1587
Vignesh Raghavendra4214a812021-06-07 19:47:48 +05301588static int __maybe_unused
Vignesh Raghavendraaa0e3fc2021-06-07 19:47:49 +05301589ti_sci_cmd_get_resource_range_static(const struct ti_sci_handle *handle,
1590 u32 dev_id, u8 subtype,
1591 u16 *range_start, u16 *range_num)
Vignesh Raghavendra4214a812021-06-07 19:47:48 +05301592{
1593 struct ti_sci_resource_static_data *data;
1594 int i = 0;
1595
1596 while (1) {
1597 data = &rm_static_data[i];
1598
1599 if (!data->dev_id)
1600 return -EINVAL;
1601
1602 if (data->dev_id != dev_id || data->subtype != subtype) {
1603 i++;
1604 continue;
1605 }
1606
1607 *range_start = data->range_start;
1608 *range_num = data->range_num;
1609
1610 return 0;
1611 }
1612
1613 return -EINVAL;
1614}
1615
Grygorii Strashkod64c5b22019-02-05 17:31:21 +05301616/**
1617 * ti_sci_cmd_get_resource_range - Get a range of resources assigned to host
1618 * that is same as ti sci interface host.
1619 * @handle: Pointer to TISCI handle.
1620 * @dev_id: TISCI device ID.
1621 * @subtype: Resource assignment subtype that is being requested
1622 * from the given device.
1623 * @range_start: Start index of the resource range
1624 * @range_num: Number of resources in the range
1625 *
1626 * Return: 0 if all went fine, else return appropriate error.
1627 */
1628static int ti_sci_cmd_get_resource_range(const struct ti_sci_handle *handle,
1629 u32 dev_id, u8 subtype,
1630 u16 *range_start, u16 *range_num)
1631{
1632 return ti_sci_get_resource_range(handle, dev_id, subtype,
1633 TI_SCI_IRQ_SECONDARY_HOST_INVALID,
1634 range_start, range_num);
1635}
1636
1637/**
1638 * ti_sci_cmd_get_resource_range_from_shost - Get a range of resources
1639 * assigned to a specified host.
1640 * @handle: Pointer to TISCI handle.
1641 * @dev_id: TISCI device ID.
1642 * @subtype: Resource assignment subtype that is being requested
1643 * from the given device.
1644 * @s_host: Host processor ID to which the resources are allocated
1645 * @range_start: Start index of the resource range
1646 * @range_num: Number of resources in the range
1647 *
1648 * Return: 0 if all went fine, else return appropriate error.
1649 */
1650static
1651int ti_sci_cmd_get_resource_range_from_shost(const struct ti_sci_handle *handle,
1652 u32 dev_id, u8 subtype, u8 s_host,
1653 u16 *range_start, u16 *range_num)
1654{
1655 return ti_sci_get_resource_range(handle, dev_id, subtype, s_host,
1656 range_start, range_num);
1657}
1658
Lokesh Vutlab8856af2018-08-27 15:57:37 +05301659/**
Lokesh Vutla032dce82019-03-08 11:47:32 +05301660 * ti_sci_cmd_query_msmc() - Command to query currently available msmc memory
1661 * @handle: pointer to TI SCI handle
1662 * @msms_start: MSMC start as returned by tisci
1663 * @msmc_end: MSMC end as returned by tisci
1664 *
1665 * Return: 0 if all went well, else returns appropriate error value.
1666 */
1667static int ti_sci_cmd_query_msmc(const struct ti_sci_handle *handle,
1668 u64 *msmc_start, u64 *msmc_end)
1669{
1670 struct ti_sci_msg_resp_query_msmc *resp;
1671 struct ti_sci_msg_hdr req;
1672 struct ti_sci_info *info;
1673 struct ti_sci_xfer *xfer;
1674 int ret = 0;
1675
1676 if (IS_ERR(handle))
1677 return PTR_ERR(handle);
1678 if (!handle)
1679 return -EINVAL;
1680
1681 info = handle_to_ti_sci_info(handle);
1682
1683 xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_QUERY_MSMC,
1684 TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1685 (u32 *)&req, sizeof(req), sizeof(*resp));
1686 if (IS_ERR(xfer)) {
1687 ret = PTR_ERR(xfer);
Lokesh Vutla032dce82019-03-08 11:47:32 +05301688 return ret;
1689 }
1690
1691 ret = ti_sci_do_xfer(info, xfer);
Andrew Davis771a16f2022-07-25 20:25:03 -05001692 if (ret)
Lokesh Vutla032dce82019-03-08 11:47:32 +05301693 return ret;
Lokesh Vutla032dce82019-03-08 11:47:32 +05301694
1695 resp = (struct ti_sci_msg_resp_query_msmc *)xfer->tx_message.buf;
1696
Lokesh Vutla032dce82019-03-08 11:47:32 +05301697 *msmc_start = ((u64)resp->msmc_start_high << TISCI_ADDR_HIGH_SHIFT) |
1698 resp->msmc_start_low;
1699 *msmc_end = ((u64)resp->msmc_end_high << TISCI_ADDR_HIGH_SHIFT) |
1700 resp->msmc_end_low;
1701
1702 return ret;
1703}
1704
1705/**
Lokesh Vutlab8856af2018-08-27 15:57:37 +05301706 * ti_sci_cmd_proc_request() - Command to request a physical processor control
1707 * @handle: Pointer to TI SCI handle
1708 * @proc_id: Processor ID this request is for
1709 *
1710 * Return: 0 if all went well, else returns appropriate error value.
1711 */
1712static int ti_sci_cmd_proc_request(const struct ti_sci_handle *handle,
1713 u8 proc_id)
1714{
1715 struct ti_sci_msg_req_proc_request req;
1716 struct ti_sci_msg_hdr *resp;
1717 struct ti_sci_info *info;
1718 struct ti_sci_xfer *xfer;
1719 int ret = 0;
1720
1721 if (IS_ERR(handle))
1722 return PTR_ERR(handle);
1723 if (!handle)
1724 return -EINVAL;
1725
1726 info = handle_to_ti_sci_info(handle);
1727
1728 xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_PROC_REQUEST,
1729 TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1730 (u32 *)&req, sizeof(req), sizeof(*resp));
1731 if (IS_ERR(xfer)) {
1732 ret = PTR_ERR(xfer);
Lokesh Vutlab8856af2018-08-27 15:57:37 +05301733 return ret;
1734 }
1735 req.processor_id = proc_id;
1736
1737 ret = ti_sci_do_xfer(info, xfer);
Andrew Davis771a16f2022-07-25 20:25:03 -05001738 if (ret)
Lokesh Vutlab8856af2018-08-27 15:57:37 +05301739 return ret;
Lokesh Vutlab8856af2018-08-27 15:57:37 +05301740
Lokesh Vutlab8856af2018-08-27 15:57:37 +05301741 return ret;
1742}
1743
1744/**
1745 * ti_sci_cmd_proc_release() - Command to release a physical processor control
1746 * @handle: Pointer to TI SCI handle
1747 * @proc_id: Processor ID this request is for
1748 *
1749 * Return: 0 if all went well, else returns appropriate error value.
1750 */
1751static int ti_sci_cmd_proc_release(const struct ti_sci_handle *handle,
1752 u8 proc_id)
1753{
1754 struct ti_sci_msg_req_proc_release req;
1755 struct ti_sci_msg_hdr *resp;
1756 struct ti_sci_info *info;
1757 struct ti_sci_xfer *xfer;
1758 int ret = 0;
1759
1760 if (IS_ERR(handle))
1761 return PTR_ERR(handle);
1762 if (!handle)
1763 return -EINVAL;
1764
1765 info = handle_to_ti_sci_info(handle);
1766
1767 xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_PROC_RELEASE,
1768 TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1769 (u32 *)&req, sizeof(req), sizeof(*resp));
1770 if (IS_ERR(xfer)) {
1771 ret = PTR_ERR(xfer);
Lokesh Vutlab8856af2018-08-27 15:57:37 +05301772 return ret;
1773 }
1774 req.processor_id = proc_id;
1775
1776 ret = ti_sci_do_xfer(info, xfer);
Andrew Davis771a16f2022-07-25 20:25:03 -05001777 if (ret)
Lokesh Vutlab8856af2018-08-27 15:57:37 +05301778 return ret;
Lokesh Vutlab8856af2018-08-27 15:57:37 +05301779
Lokesh Vutlab8856af2018-08-27 15:57:37 +05301780 return ret;
1781}
1782
1783/**
1784 * ti_sci_cmd_proc_handover() - Command to handover a physical processor
1785 * control to a host in the processor's access
1786 * control list.
1787 * @handle: Pointer to TI SCI handle
1788 * @proc_id: Processor ID this request is for
1789 * @host_id: Host ID to get the control of the processor
1790 *
1791 * Return: 0 if all went well, else returns appropriate error value.
1792 */
1793static int ti_sci_cmd_proc_handover(const struct ti_sci_handle *handle,
1794 u8 proc_id, u8 host_id)
1795{
1796 struct ti_sci_msg_req_proc_handover req;
1797 struct ti_sci_msg_hdr *resp;
1798 struct ti_sci_info *info;
1799 struct ti_sci_xfer *xfer;
1800 int ret = 0;
1801
1802 if (IS_ERR(handle))
1803 return PTR_ERR(handle);
1804 if (!handle)
1805 return -EINVAL;
1806
1807 info = handle_to_ti_sci_info(handle);
1808
1809 xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_PROC_HANDOVER,
1810 TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1811 (u32 *)&req, sizeof(req), sizeof(*resp));
1812 if (IS_ERR(xfer)) {
1813 ret = PTR_ERR(xfer);
Lokesh Vutlab8856af2018-08-27 15:57:37 +05301814 return ret;
1815 }
1816 req.processor_id = proc_id;
1817 req.host_id = host_id;
1818
1819 ret = ti_sci_do_xfer(info, xfer);
Andrew Davis771a16f2022-07-25 20:25:03 -05001820 if (ret)
Lokesh Vutlab8856af2018-08-27 15:57:37 +05301821 return ret;
Lokesh Vutlab8856af2018-08-27 15:57:37 +05301822
Lokesh Vutlab8856af2018-08-27 15:57:37 +05301823 return ret;
1824}
1825
1826/**
1827 * ti_sci_cmd_set_proc_boot_cfg() - Command to set the processor boot
1828 * configuration flags
1829 * @handle: Pointer to TI SCI handle
1830 * @proc_id: Processor ID this request is for
1831 * @config_flags_set: Configuration flags to be set
1832 * @config_flags_clear: Configuration flags to be cleared.
1833 *
1834 * Return: 0 if all went well, else returns appropriate error value.
1835 */
1836static int ti_sci_cmd_set_proc_boot_cfg(const struct ti_sci_handle *handle,
1837 u8 proc_id, u64 bootvector,
1838 u32 config_flags_set,
1839 u32 config_flags_clear)
1840{
1841 struct ti_sci_msg_req_set_proc_boot_config req;
1842 struct ti_sci_msg_hdr *resp;
1843 struct ti_sci_info *info;
1844 struct ti_sci_xfer *xfer;
1845 int ret = 0;
1846
1847 if (IS_ERR(handle))
1848 return PTR_ERR(handle);
1849 if (!handle)
1850 return -EINVAL;
1851
1852 info = handle_to_ti_sci_info(handle);
1853
1854 xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_SET_PROC_BOOT_CONFIG,
1855 TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1856 (u32 *)&req, sizeof(req), sizeof(*resp));
1857 if (IS_ERR(xfer)) {
1858 ret = PTR_ERR(xfer);
Lokesh Vutlab8856af2018-08-27 15:57:37 +05301859 return ret;
1860 }
1861 req.processor_id = proc_id;
1862 req.bootvector_low = bootvector & TISCI_ADDR_LOW_MASK;
1863 req.bootvector_high = (bootvector & TISCI_ADDR_HIGH_MASK) >>
1864 TISCI_ADDR_HIGH_SHIFT;
1865 req.config_flags_set = config_flags_set;
1866 req.config_flags_clear = config_flags_clear;
1867
1868 ret = ti_sci_do_xfer(info, xfer);
Andrew Davis771a16f2022-07-25 20:25:03 -05001869 if (ret)
Lokesh Vutlab8856af2018-08-27 15:57:37 +05301870 return ret;
Lokesh Vutlab8856af2018-08-27 15:57:37 +05301871
Lokesh Vutlab8856af2018-08-27 15:57:37 +05301872 return ret;
1873}
1874
1875/**
1876 * ti_sci_cmd_set_proc_boot_ctrl() - Command to set the processor boot
1877 * control flags
1878 * @handle: Pointer to TI SCI handle
1879 * @proc_id: Processor ID this request is for
1880 * @control_flags_set: Control flags to be set
1881 * @control_flags_clear: Control flags to be cleared
1882 *
1883 * Return: 0 if all went well, else returns appropriate error value.
1884 */
1885static int ti_sci_cmd_set_proc_boot_ctrl(const struct ti_sci_handle *handle,
1886 u8 proc_id, u32 control_flags_set,
1887 u32 control_flags_clear)
1888{
1889 struct ti_sci_msg_req_set_proc_boot_ctrl req;
1890 struct ti_sci_msg_hdr *resp;
1891 struct ti_sci_info *info;
1892 struct ti_sci_xfer *xfer;
1893 int ret = 0;
1894
1895 if (IS_ERR(handle))
1896 return PTR_ERR(handle);
1897 if (!handle)
1898 return -EINVAL;
1899
1900 info = handle_to_ti_sci_info(handle);
1901
1902 xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_SET_PROC_BOOT_CTRL,
1903 TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1904 (u32 *)&req, sizeof(req), sizeof(*resp));
1905 if (IS_ERR(xfer)) {
1906 ret = PTR_ERR(xfer);
Lokesh Vutlab8856af2018-08-27 15:57:37 +05301907 return ret;
1908 }
1909 req.processor_id = proc_id;
1910 req.control_flags_set = control_flags_set;
1911 req.control_flags_clear = control_flags_clear;
1912
1913 ret = ti_sci_do_xfer(info, xfer);
Andrew Davis771a16f2022-07-25 20:25:03 -05001914 if (ret)
Lokesh Vutlab8856af2018-08-27 15:57:37 +05301915 return ret;
Lokesh Vutlab8856af2018-08-27 15:57:37 +05301916
Lokesh Vutlab8856af2018-08-27 15:57:37 +05301917 return ret;
1918}
1919
1920/**
1921 * ti_sci_cmd_proc_auth_boot_image() - Command to authenticate and load the
1922 * image and then set the processor configuration flags.
1923 * @handle: Pointer to TI SCI handle
Andrew F. Davis7aa9a082019-04-12 12:54:44 -04001924 * @image_addr: Memory address at which payload image and certificate is
1925 * located in memory, this is updated if the image data is
1926 * moved during authentication.
1927 * @image_size: This is updated with the final size of the image after
1928 * authentication.
Lokesh Vutlab8856af2018-08-27 15:57:37 +05301929 *
1930 * Return: 0 if all went well, else returns appropriate error value.
1931 */
1932static int ti_sci_cmd_proc_auth_boot_image(const struct ti_sci_handle *handle,
Andrew F. Davis7aa9a082019-04-12 12:54:44 -04001933 u64 *image_addr, u32 *image_size)
Lokesh Vutlab8856af2018-08-27 15:57:37 +05301934{
1935 struct ti_sci_msg_req_proc_auth_boot_image req;
Andrew F. Davis7aa9a082019-04-12 12:54:44 -04001936 struct ti_sci_msg_resp_proc_auth_boot_image *resp;
Lokesh Vutlab8856af2018-08-27 15:57:37 +05301937 struct ti_sci_info *info;
1938 struct ti_sci_xfer *xfer;
1939 int ret = 0;
1940
1941 if (IS_ERR(handle))
1942 return PTR_ERR(handle);
1943 if (!handle)
1944 return -EINVAL;
1945
1946 info = handle_to_ti_sci_info(handle);
1947
Jorge Ramirez-Ortizb0373282023-01-10 18:29:48 +01001948 xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_PROC_AUTH_BOOT_IMAGE,
Lokesh Vutlab8856af2018-08-27 15:57:37 +05301949 TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1950 (u32 *)&req, sizeof(req), sizeof(*resp));
1951 if (IS_ERR(xfer)) {
1952 ret = PTR_ERR(xfer);
Lokesh Vutlab8856af2018-08-27 15:57:37 +05301953 return ret;
1954 }
Andrew F. Davis7aa9a082019-04-12 12:54:44 -04001955 req.cert_addr_low = *image_addr & TISCI_ADDR_LOW_MASK;
1956 req.cert_addr_high = (*image_addr & TISCI_ADDR_HIGH_MASK) >>
Lokesh Vutlab8856af2018-08-27 15:57:37 +05301957 TISCI_ADDR_HIGH_SHIFT;
1958
1959 ret = ti_sci_do_xfer(info, xfer);
Andrew Davis771a16f2022-07-25 20:25:03 -05001960 if (ret)
Lokesh Vutlab8856af2018-08-27 15:57:37 +05301961 return ret;
Lokesh Vutlab8856af2018-08-27 15:57:37 +05301962
Andrew F. Davis7aa9a082019-04-12 12:54:44 -04001963 resp = (struct ti_sci_msg_resp_proc_auth_boot_image *)xfer->tx_message.buf;
Lokesh Vutlab8856af2018-08-27 15:57:37 +05301964
Andrew F. Davis7aa9a082019-04-12 12:54:44 -04001965 *image_addr = (resp->image_addr_low & TISCI_ADDR_LOW_MASK) |
1966 (((u64)resp->image_addr_high <<
1967 TISCI_ADDR_HIGH_SHIFT) & TISCI_ADDR_HIGH_MASK);
1968 *image_size = resp->image_size;
Lokesh Vutlab8856af2018-08-27 15:57:37 +05301969
1970 return ret;
1971}
1972
1973/**
1974 * ti_sci_cmd_get_proc_boot_status() - Command to get the processor boot status
1975 * @handle: Pointer to TI SCI handle
1976 * @proc_id: Processor ID this request is for
1977 *
1978 * Return: 0 if all went well, else returns appropriate error value.
1979 */
1980static int ti_sci_cmd_get_proc_boot_status(const struct ti_sci_handle *handle,
1981 u8 proc_id, u64 *bv, u32 *cfg_flags,
1982 u32 *ctrl_flags, u32 *sts_flags)
1983{
1984 struct ti_sci_msg_resp_get_proc_boot_status *resp;
1985 struct ti_sci_msg_req_get_proc_boot_status req;
1986 struct ti_sci_info *info;
1987 struct ti_sci_xfer *xfer;
1988 int ret = 0;
1989
1990 if (IS_ERR(handle))
1991 return PTR_ERR(handle);
1992 if (!handle)
1993 return -EINVAL;
1994
1995 info = handle_to_ti_sci_info(handle);
1996
1997 xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_GET_PROC_BOOT_STATUS,
1998 TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1999 (u32 *)&req, sizeof(req), sizeof(*resp));
2000 if (IS_ERR(xfer)) {
2001 ret = PTR_ERR(xfer);
Lokesh Vutlab8856af2018-08-27 15:57:37 +05302002 return ret;
2003 }
2004 req.processor_id = proc_id;
2005
2006 ret = ti_sci_do_xfer(info, xfer);
Andrew Davis771a16f2022-07-25 20:25:03 -05002007 if (ret)
Lokesh Vutlab8856af2018-08-27 15:57:37 +05302008 return ret;
Lokesh Vutlab8856af2018-08-27 15:57:37 +05302009
2010 resp = (struct ti_sci_msg_resp_get_proc_boot_status *)
2011 xfer->tx_message.buf;
2012
Lokesh Vutlab8856af2018-08-27 15:57:37 +05302013 *bv = (resp->bootvector_low & TISCI_ADDR_LOW_MASK) |
2014 (((u64)resp->bootvector_high <<
2015 TISCI_ADDR_HIGH_SHIFT) & TISCI_ADDR_HIGH_MASK);
2016 *cfg_flags = resp->config_flags;
2017 *ctrl_flags = resp->control_flags;
2018 *sts_flags = resp->status_flags;
2019
Grygorii Strashkod64c5b22019-02-05 17:31:21 +05302020 return ret;
2021}
2022
2023/**
Andreas Dannenbergca08cb32019-06-07 19:24:40 +05302024 * ti_sci_proc_wait_boot_status_no_wait() - Helper function to wait for a
2025 * processor boot status without requesting or
2026 * waiting for a response.
2027 * @proc_id: Processor ID this request is for
2028 * @num_wait_iterations: Total number of iterations we will check before
2029 * we will timeout and give up
2030 * @num_match_iterations: How many iterations should we have continued
2031 * status to account for status bits glitching.
2032 * This is to make sure that match occurs for
2033 * consecutive checks. This implies that the
2034 * worst case should consider that the stable
2035 * time should at the worst be num_wait_iterations
2036 * num_match_iterations to prevent timeout.
2037 * @delay_per_iteration_us: Specifies how long to wait (in micro seconds)
2038 * between each status checks. This is the minimum
2039 * duration, and overhead of register reads and
2040 * checks are on top of this and can vary based on
2041 * varied conditions.
2042 * @delay_before_iterations_us: Specifies how long to wait (in micro seconds)
2043 * before the very first check in the first
2044 * iteration of status check loop. This is the
2045 * minimum duration, and overhead of register
2046 * reads and checks are.
2047 * @status_flags_1_set_all_wait:If non-zero, Specifies that all bits of the
2048 * status matching this field requested MUST be 1.
2049 * @status_flags_1_set_any_wait:If non-zero, Specifies that at least one of the
2050 * bits matching this field requested MUST be 1.
2051 * @status_flags_1_clr_all_wait:If non-zero, Specifies that all bits of the
2052 * status matching this field requested MUST be 0.
2053 * @status_flags_1_clr_any_wait:If non-zero, Specifies that at least one of the
2054 * bits matching this field requested MUST be 0.
2055 *
2056 * Return: 0 if all goes well, else appropriate error message
2057 */
2058static int
2059ti_sci_proc_wait_boot_status_no_wait(const struct ti_sci_handle *handle,
2060 u8 proc_id,
2061 u8 num_wait_iterations,
2062 u8 num_match_iterations,
2063 u8 delay_per_iteration_us,
2064 u8 delay_before_iterations_us,
2065 u32 status_flags_1_set_all_wait,
2066 u32 status_flags_1_set_any_wait,
2067 u32 status_flags_1_clr_all_wait,
2068 u32 status_flags_1_clr_any_wait)
2069{
2070 struct ti_sci_msg_req_wait_proc_boot_status req;
2071 struct ti_sci_info *info;
2072 struct ti_sci_xfer *xfer;
2073 int ret = 0;
2074
2075 if (IS_ERR(handle))
2076 return PTR_ERR(handle);
2077 if (!handle)
2078 return -EINVAL;
2079
2080 info = handle_to_ti_sci_info(handle);
2081
2082 xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_WAIT_PROC_BOOT_STATUS,
2083 TI_SCI_FLAG_REQ_GENERIC_NORESPONSE,
2084 (u32 *)&req, sizeof(req), 0);
2085 if (IS_ERR(xfer)) {
2086 ret = PTR_ERR(xfer);
Andreas Dannenbergca08cb32019-06-07 19:24:40 +05302087 return ret;
2088 }
2089 req.processor_id = proc_id;
2090 req.num_wait_iterations = num_wait_iterations;
2091 req.num_match_iterations = num_match_iterations;
2092 req.delay_per_iteration_us = delay_per_iteration_us;
2093 req.delay_before_iterations_us = delay_before_iterations_us;
2094 req.status_flags_1_set_all_wait = status_flags_1_set_all_wait;
2095 req.status_flags_1_set_any_wait = status_flags_1_set_any_wait;
2096 req.status_flags_1_clr_all_wait = status_flags_1_clr_all_wait;
2097 req.status_flags_1_clr_any_wait = status_flags_1_clr_any_wait;
2098
2099 ret = ti_sci_do_xfer(info, xfer);
2100 if (ret)
Andrew Davis771a16f2022-07-25 20:25:03 -05002101 return ret;
Andreas Dannenbergca08cb32019-06-07 19:24:40 +05302102
2103 return ret;
2104}
2105
2106/**
2107 * ti_sci_cmd_proc_shutdown_no_wait() - Command to shutdown a core without
2108 * requesting or waiting for a response. Note that this API call
2109 * should be followed by placing the respective processor into
2110 * either WFE or WFI mode.
2111 * @handle: Pointer to TI SCI handle
2112 * @proc_id: Processor ID this request is for
2113 *
2114 * Return: 0 if all went well, else returns appropriate error value.
2115 */
2116static int ti_sci_cmd_proc_shutdown_no_wait(const struct ti_sci_handle *handle,
2117 u8 proc_id)
2118{
2119 int ret;
Sean Anderson405dc242020-09-15 10:44:38 -04002120 struct ti_sci_info *info;
2121
2122 if (IS_ERR(handle))
2123 return PTR_ERR(handle);
2124 if (!handle)
2125 return -EINVAL;
2126
2127 info = handle_to_ti_sci_info(handle);
Andreas Dannenbergca08cb32019-06-07 19:24:40 +05302128
2129 /*
2130 * Send the core boot status wait message waiting for either WFE or
2131 * WFI without requesting or waiting for a TISCI response with the
2132 * maximum wait time to give us the best chance to get to the WFE/WFI
2133 * command that should follow the invocation of this API before the
2134 * DMSC-internal processing of this command times out. Note that
2135 * waiting for the R5 WFE/WFI flags will also work on an ARMV8 type
2136 * core as the related flag bit positions are the same.
2137 */
2138 ret = ti_sci_proc_wait_boot_status_no_wait(handle, proc_id,
2139 U8_MAX, 100, U8_MAX, U8_MAX,
2140 0, PROC_BOOT_STATUS_FLAG_R5_WFE | PROC_BOOT_STATUS_FLAG_R5_WFI,
2141 0, 0);
2142 if (ret) {
2143 dev_err(info->dev, "Sending core %u wait message fail %d\n",
2144 proc_id, ret);
2145 return ret;
2146 }
2147
2148 /*
2149 * Release a processor managed by TISCI without requesting or waiting
2150 * for a response.
2151 */
2152 ret = ti_sci_set_device_state_no_wait(handle, proc_id, 0,
2153 MSG_DEVICE_SW_STATE_AUTO_OFF);
2154 if (ret)
2155 dev_err(info->dev, "Sending core %u shutdown message fail %d\n",
2156 proc_id, ret);
2157
2158 return ret;
2159}
2160
2161/**
Grygorii Strashkod64c5b22019-02-05 17:31:21 +05302162 * ti_sci_cmd_ring_config() - configure RA ring
2163 * @handle: pointer to TI SCI handle
2164 * @valid_params: Bitfield defining validity of ring configuration parameters.
2165 * @nav_id: Device ID of Navigator Subsystem from which the ring is allocated
2166 * @index: Ring index.
2167 * @addr_lo: The ring base address lo 32 bits
2168 * @addr_hi: The ring base address hi 32 bits
2169 * @count: Number of ring elements.
2170 * @mode: The mode of the ring
2171 * @size: The ring element size.
2172 * @order_id: Specifies the ring's bus order ID.
2173 *
2174 * Return: 0 if all went well, else returns appropriate error value.
2175 *
2176 * See @ti_sci_msg_rm_ring_cfg_req for more info.
2177 */
2178static int ti_sci_cmd_ring_config(const struct ti_sci_handle *handle,
2179 u32 valid_params, u16 nav_id, u16 index,
2180 u32 addr_lo, u32 addr_hi, u32 count,
2181 u8 mode, u8 size, u8 order_id)
2182{
2183 struct ti_sci_msg_rm_ring_cfg_resp *resp;
2184 struct ti_sci_msg_rm_ring_cfg_req req;
2185 struct ti_sci_xfer *xfer;
2186 struct ti_sci_info *info;
2187 int ret = 0;
2188
2189 if (IS_ERR(handle))
2190 return PTR_ERR(handle);
2191 if (!handle)
2192 return -EINVAL;
2193
2194 info = handle_to_ti_sci_info(handle);
2195
2196 xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_RM_RING_CFG,
2197 TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
2198 (u32 *)&req, sizeof(req), sizeof(*resp));
2199 if (IS_ERR(xfer)) {
2200 ret = PTR_ERR(xfer);
Grygorii Strashkod64c5b22019-02-05 17:31:21 +05302201 return ret;
2202 }
2203 req.valid_params = valid_params;
2204 req.nav_id = nav_id;
2205 req.index = index;
2206 req.addr_lo = addr_lo;
2207 req.addr_hi = addr_hi;
2208 req.count = count;
2209 req.mode = mode;
2210 req.size = size;
2211 req.order_id = order_id;
2212
2213 ret = ti_sci_do_xfer(info, xfer);
Andrew Davis771a16f2022-07-25 20:25:03 -05002214 if (ret)
Grygorii Strashkod64c5b22019-02-05 17:31:21 +05302215 goto fail;
Grygorii Strashkod64c5b22019-02-05 17:31:21 +05302216
Grygorii Strashkod64c5b22019-02-05 17:31:21 +05302217fail:
2218 dev_dbg(info->dev, "RM_RA:config ring %u ret:%d\n", index, ret);
2219 return ret;
2220}
2221
Grygorii Strashkod64c5b22019-02-05 17:31:21 +05302222static int ti_sci_cmd_rm_psil_pair(const struct ti_sci_handle *handle,
2223 u32 nav_id, u32 src_thread, u32 dst_thread)
2224{
2225 struct ti_sci_msg_hdr *resp;
2226 struct ti_sci_msg_psil_pair req;
2227 struct ti_sci_xfer *xfer;
2228 struct ti_sci_info *info;
2229 int ret = 0;
2230
2231 if (IS_ERR(handle))
2232 return PTR_ERR(handle);
2233 if (!handle)
2234 return -EINVAL;
2235
2236 info = handle_to_ti_sci_info(handle);
2237
2238 xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_RM_PSIL_PAIR,
2239 TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
2240 (u32 *)&req, sizeof(req), sizeof(*resp));
2241 if (IS_ERR(xfer)) {
2242 ret = PTR_ERR(xfer);
Grygorii Strashkod64c5b22019-02-05 17:31:21 +05302243 return ret;
2244 }
2245 req.nav_id = nav_id;
2246 req.src_thread = src_thread;
2247 req.dst_thread = dst_thread;
2248
2249 ret = ti_sci_do_xfer(info, xfer);
Andrew Davis771a16f2022-07-25 20:25:03 -05002250 if (ret)
Grygorii Strashkod64c5b22019-02-05 17:31:21 +05302251 goto fail;
Grygorii Strashkod64c5b22019-02-05 17:31:21 +05302252
Grygorii Strashkod64c5b22019-02-05 17:31:21 +05302253fail:
2254 dev_dbg(info->dev, "RM_PSIL: nav: %u link pair %u->%u ret:%u\n",
2255 nav_id, src_thread, dst_thread, ret);
2256 return ret;
2257}
2258
2259static int ti_sci_cmd_rm_psil_unpair(const struct ti_sci_handle *handle,
2260 u32 nav_id, u32 src_thread, u32 dst_thread)
2261{
2262 struct ti_sci_msg_hdr *resp;
2263 struct ti_sci_msg_psil_unpair req;
2264 struct ti_sci_xfer *xfer;
2265 struct ti_sci_info *info;
2266 int ret = 0;
2267
2268 if (IS_ERR(handle))
2269 return PTR_ERR(handle);
2270 if (!handle)
2271 return -EINVAL;
2272
2273 info = handle_to_ti_sci_info(handle);
2274
2275 xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_RM_PSIL_UNPAIR,
2276 TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
2277 (u32 *)&req, sizeof(req), sizeof(*resp));
2278 if (IS_ERR(xfer)) {
2279 ret = PTR_ERR(xfer);
Grygorii Strashkod64c5b22019-02-05 17:31:21 +05302280 return ret;
2281 }
2282 req.nav_id = nav_id;
2283 req.src_thread = src_thread;
2284 req.dst_thread = dst_thread;
2285
2286 ret = ti_sci_do_xfer(info, xfer);
Andrew Davis771a16f2022-07-25 20:25:03 -05002287 if (ret)
Grygorii Strashkod64c5b22019-02-05 17:31:21 +05302288 goto fail;
Grygorii Strashkod64c5b22019-02-05 17:31:21 +05302289
Grygorii Strashkod64c5b22019-02-05 17:31:21 +05302290fail:
2291 dev_dbg(info->dev, "RM_PSIL: link unpair %u->%u ret:%u\n",
2292 src_thread, dst_thread, ret);
2293 return ret;
2294}
2295
2296static int ti_sci_cmd_rm_udmap_tx_ch_cfg(
2297 const struct ti_sci_handle *handle,
2298 const struct ti_sci_msg_rm_udmap_tx_ch_cfg *params)
2299{
2300 struct ti_sci_msg_rm_udmap_tx_ch_cfg_resp *resp;
2301 struct ti_sci_msg_rm_udmap_tx_ch_cfg_req req;
2302 struct ti_sci_xfer *xfer;
2303 struct ti_sci_info *info;
2304 int ret = 0;
2305
2306 if (IS_ERR(handle))
2307 return PTR_ERR(handle);
2308 if (!handle)
2309 return -EINVAL;
2310
2311 info = handle_to_ti_sci_info(handle);
2312
2313 xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_RM_UDMAP_TX_CH_CFG,
2314 TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
2315 (u32 *)&req, sizeof(req), sizeof(*resp));
2316 if (IS_ERR(xfer)) {
2317 ret = PTR_ERR(xfer);
Grygorii Strashkod64c5b22019-02-05 17:31:21 +05302318 return ret;
2319 }
2320 req.valid_params = params->valid_params;
2321 req.nav_id = params->nav_id;
2322 req.index = params->index;
2323 req.tx_pause_on_err = params->tx_pause_on_err;
2324 req.tx_filt_einfo = params->tx_filt_einfo;
2325 req.tx_filt_pswords = params->tx_filt_pswords;
2326 req.tx_atype = params->tx_atype;
2327 req.tx_chan_type = params->tx_chan_type;
2328 req.tx_supr_tdpkt = params->tx_supr_tdpkt;
2329 req.tx_fetch_size = params->tx_fetch_size;
2330 req.tx_credit_count = params->tx_credit_count;
2331 req.txcq_qnum = params->txcq_qnum;
2332 req.tx_priority = params->tx_priority;
2333 req.tx_qos = params->tx_qos;
2334 req.tx_orderid = params->tx_orderid;
2335 req.fdepth = params->fdepth;
2336 req.tx_sched_priority = params->tx_sched_priority;
Vignesh Raghavendraa8a2b8a2021-05-10 20:06:02 +05302337 req.tx_burst_size = params->tx_burst_size;
2338 req.tx_tdtype = params->tx_tdtype;
2339 req.extended_ch_type = params->extended_ch_type;
Grygorii Strashkod64c5b22019-02-05 17:31:21 +05302340
2341 ret = ti_sci_do_xfer(info, xfer);
Andrew Davis771a16f2022-07-25 20:25:03 -05002342 if (ret)
Grygorii Strashkod64c5b22019-02-05 17:31:21 +05302343 goto fail;
Grygorii Strashkod64c5b22019-02-05 17:31:21 +05302344
Grygorii Strashkod64c5b22019-02-05 17:31:21 +05302345fail:
2346 dev_dbg(info->dev, "TX_CH_CFG: chn %u ret:%u\n", params->index, ret);
2347 return ret;
2348}
2349
2350static int ti_sci_cmd_rm_udmap_rx_ch_cfg(
2351 const struct ti_sci_handle *handle,
2352 const struct ti_sci_msg_rm_udmap_rx_ch_cfg *params)
2353{
2354 struct ti_sci_msg_rm_udmap_rx_ch_cfg_resp *resp;
2355 struct ti_sci_msg_rm_udmap_rx_ch_cfg_req req;
2356 struct ti_sci_xfer *xfer;
2357 struct ti_sci_info *info;
2358 int ret = 0;
2359
2360 if (IS_ERR(handle))
2361 return PTR_ERR(handle);
2362 if (!handle)
2363 return -EINVAL;
2364
2365 info = handle_to_ti_sci_info(handle);
2366
2367 xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_RM_UDMAP_RX_CH_CFG,
2368 TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
2369 (u32 *)&req, sizeof(req), sizeof(*resp));
2370 if (IS_ERR(xfer)) {
2371 ret = PTR_ERR(xfer);
Grygorii Strashkod64c5b22019-02-05 17:31:21 +05302372 return ret;
2373 }
2374
2375 req.valid_params = params->valid_params;
2376 req.nav_id = params->nav_id;
2377 req.index = params->index;
2378 req.rx_fetch_size = params->rx_fetch_size;
2379 req.rxcq_qnum = params->rxcq_qnum;
2380 req.rx_priority = params->rx_priority;
2381 req.rx_qos = params->rx_qos;
2382 req.rx_orderid = params->rx_orderid;
2383 req.rx_sched_priority = params->rx_sched_priority;
2384 req.flowid_start = params->flowid_start;
2385 req.flowid_cnt = params->flowid_cnt;
2386 req.rx_pause_on_err = params->rx_pause_on_err;
2387 req.rx_atype = params->rx_atype;
2388 req.rx_chan_type = params->rx_chan_type;
2389 req.rx_ignore_short = params->rx_ignore_short;
2390 req.rx_ignore_long = params->rx_ignore_long;
2391
2392 ret = ti_sci_do_xfer(info, xfer);
Andrew Davis771a16f2022-07-25 20:25:03 -05002393 if (ret)
Grygorii Strashkod64c5b22019-02-05 17:31:21 +05302394 goto fail;
Grygorii Strashkod64c5b22019-02-05 17:31:21 +05302395
Grygorii Strashkod64c5b22019-02-05 17:31:21 +05302396fail:
2397 dev_dbg(info->dev, "RX_CH_CFG: chn %u ret:%d\n", params->index, ret);
2398 return ret;
2399}
2400
2401static int ti_sci_cmd_rm_udmap_rx_flow_cfg(
2402 const struct ti_sci_handle *handle,
2403 const struct ti_sci_msg_rm_udmap_flow_cfg *params)
2404{
2405 struct ti_sci_msg_rm_udmap_flow_cfg_resp *resp;
2406 struct ti_sci_msg_rm_udmap_flow_cfg_req req;
2407 struct ti_sci_xfer *xfer;
2408 struct ti_sci_info *info;
2409 int ret = 0;
2410
2411 if (IS_ERR(handle))
2412 return PTR_ERR(handle);
2413 if (!handle)
2414 return -EINVAL;
2415
2416 info = handle_to_ti_sci_info(handle);
2417
2418 xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_RM_UDMAP_FLOW_CFG,
2419 TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
2420 (u32 *)&req, sizeof(req), sizeof(*resp));
2421 if (IS_ERR(xfer)) {
2422 ret = PTR_ERR(xfer);
Grygorii Strashkod64c5b22019-02-05 17:31:21 +05302423 return ret;
2424 }
2425
2426 req.valid_params = params->valid_params;
2427 req.nav_id = params->nav_id;
2428 req.flow_index = params->flow_index;
2429 req.rx_einfo_present = params->rx_einfo_present;
2430 req.rx_psinfo_present = params->rx_psinfo_present;
2431 req.rx_error_handling = params->rx_error_handling;
2432 req.rx_desc_type = params->rx_desc_type;
2433 req.rx_sop_offset = params->rx_sop_offset;
2434 req.rx_dest_qnum = params->rx_dest_qnum;
2435 req.rx_src_tag_hi = params->rx_src_tag_hi;
2436 req.rx_src_tag_lo = params->rx_src_tag_lo;
2437 req.rx_dest_tag_hi = params->rx_dest_tag_hi;
2438 req.rx_dest_tag_lo = params->rx_dest_tag_lo;
2439 req.rx_src_tag_hi_sel = params->rx_src_tag_hi_sel;
2440 req.rx_src_tag_lo_sel = params->rx_src_tag_lo_sel;
2441 req.rx_dest_tag_hi_sel = params->rx_dest_tag_hi_sel;
2442 req.rx_dest_tag_lo_sel = params->rx_dest_tag_lo_sel;
2443 req.rx_fdq0_sz0_qnum = params->rx_fdq0_sz0_qnum;
2444 req.rx_fdq1_qnum = params->rx_fdq1_qnum;
2445 req.rx_fdq2_qnum = params->rx_fdq2_qnum;
2446 req.rx_fdq3_qnum = params->rx_fdq3_qnum;
2447 req.rx_ps_location = params->rx_ps_location;
2448
2449 ret = ti_sci_do_xfer(info, xfer);
Andrew Davis771a16f2022-07-25 20:25:03 -05002450 if (ret)
Grygorii Strashkod64c5b22019-02-05 17:31:21 +05302451 goto fail;
Grygorii Strashkod64c5b22019-02-05 17:31:21 +05302452
Grygorii Strashkod64c5b22019-02-05 17:31:21 +05302453fail:
2454 dev_dbg(info->dev, "RX_FL_CFG: %u ret:%d\n", params->flow_index, ret);
Lokesh Vutlab8856af2018-08-27 15:57:37 +05302455 return ret;
2456}
2457
Kishon Vijay Abraham Ie9876c82024-08-26 15:55:06 +05302458static int ti_sci_cmd_rm_udmap_rx_flow_cfg_noop(const struct ti_sci_handle *handle,
2459 const struct ti_sci_msg_rm_udmap_flow_cfg *params)
2460{
2461 return 0;
2462}
2463
Andrew F. Davis2aafc0c2019-04-12 12:54:43 -04002464/**
2465 * ti_sci_cmd_set_fwl_region() - Request for configuring a firewall region
2466 * @handle: pointer to TI SCI handle
2467 * @region: region configuration parameters
2468 *
2469 * Return: 0 if all went well, else returns appropriate error value.
2470 */
2471static int ti_sci_cmd_set_fwl_region(const struct ti_sci_handle *handle,
2472 const struct ti_sci_msg_fwl_region *region)
2473{
2474 struct ti_sci_msg_fwl_set_firewall_region_req req;
2475 struct ti_sci_msg_hdr *resp;
2476 struct ti_sci_info *info;
2477 struct ti_sci_xfer *xfer;
2478 int ret = 0;
2479
2480 if (IS_ERR(handle))
2481 return PTR_ERR(handle);
2482 if (!handle)
2483 return -EINVAL;
2484
2485 info = handle_to_ti_sci_info(handle);
2486
2487 xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_FWL_SET,
2488 TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
2489 (u32 *)&req, sizeof(req), sizeof(*resp));
2490 if (IS_ERR(xfer)) {
2491 ret = PTR_ERR(xfer);
Andrew F. Davis2aafc0c2019-04-12 12:54:43 -04002492 return ret;
2493 }
2494
2495 req.fwl_id = region->fwl_id;
2496 req.region = region->region;
2497 req.n_permission_regs = region->n_permission_regs;
2498 req.control = region->control;
2499 req.permissions[0] = region->permissions[0];
2500 req.permissions[1] = region->permissions[1];
2501 req.permissions[2] = region->permissions[2];
2502 req.start_address = region->start_address;
2503 req.end_address = region->end_address;
2504
2505 ret = ti_sci_do_xfer(info, xfer);
Andrew Davis771a16f2022-07-25 20:25:03 -05002506 if (ret)
Andrew F. Davis2aafc0c2019-04-12 12:54:43 -04002507 return ret;
Andrew F. Davis2aafc0c2019-04-12 12:54:43 -04002508
Andrew F. Davis2aafc0c2019-04-12 12:54:43 -04002509 return 0;
2510}
2511
2512/**
2513 * ti_sci_cmd_get_fwl_region() - Request for getting a firewall region
2514 * @handle: pointer to TI SCI handle
2515 * @region: region configuration parameters
2516 *
2517 * Return: 0 if all went well, else returns appropriate error value.
2518 */
2519static int ti_sci_cmd_get_fwl_region(const struct ti_sci_handle *handle,
2520 struct ti_sci_msg_fwl_region *region)
2521{
2522 struct ti_sci_msg_fwl_get_firewall_region_req req;
2523 struct ti_sci_msg_fwl_get_firewall_region_resp *resp;
2524 struct ti_sci_info *info;
2525 struct ti_sci_xfer *xfer;
2526 int ret = 0;
2527
2528 if (IS_ERR(handle))
2529 return PTR_ERR(handle);
2530 if (!handle)
2531 return -EINVAL;
2532
2533 info = handle_to_ti_sci_info(handle);
2534
2535 xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_FWL_GET,
2536 TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
2537 (u32 *)&req, sizeof(req), sizeof(*resp));
2538 if (IS_ERR(xfer)) {
2539 ret = PTR_ERR(xfer);
Andrew F. Davis2aafc0c2019-04-12 12:54:43 -04002540 return ret;
2541 }
2542
2543 req.fwl_id = region->fwl_id;
2544 req.region = region->region;
2545 req.n_permission_regs = region->n_permission_regs;
2546
2547 ret = ti_sci_do_xfer(info, xfer);
Andrew Davis771a16f2022-07-25 20:25:03 -05002548 if (ret)
Andrew F. Davis2aafc0c2019-04-12 12:54:43 -04002549 return ret;
Andrew F. Davis2aafc0c2019-04-12 12:54:43 -04002550
2551 resp = (struct ti_sci_msg_fwl_get_firewall_region_resp *)xfer->tx_message.buf;
2552
Andrew F. Davis2aafc0c2019-04-12 12:54:43 -04002553 region->fwl_id = resp->fwl_id;
2554 region->region = resp->region;
2555 region->n_permission_regs = resp->n_permission_regs;
2556 region->control = resp->control;
2557 region->permissions[0] = resp->permissions[0];
2558 region->permissions[1] = resp->permissions[1];
2559 region->permissions[2] = resp->permissions[2];
2560 region->start_address = resp->start_address;
2561 region->end_address = resp->end_address;
2562
2563 return 0;
2564}
2565
2566/**
2567 * ti_sci_cmd_change_fwl_owner() - Request for changing a firewall owner
2568 * @handle: pointer to TI SCI handle
2569 * @region: region configuration parameters
2570 *
2571 * Return: 0 if all went well, else returns appropriate error value.
2572 */
2573static int ti_sci_cmd_change_fwl_owner(const struct ti_sci_handle *handle,
2574 struct ti_sci_msg_fwl_owner *owner)
2575{
2576 struct ti_sci_msg_fwl_change_owner_info_req req;
2577 struct ti_sci_msg_fwl_change_owner_info_resp *resp;
2578 struct ti_sci_info *info;
2579 struct ti_sci_xfer *xfer;
2580 int ret = 0;
2581
2582 if (IS_ERR(handle))
2583 return PTR_ERR(handle);
2584 if (!handle)
2585 return -EINVAL;
2586
2587 info = handle_to_ti_sci_info(handle);
2588
Andrew F. Davis8928fbd2019-04-29 09:04:11 -04002589 xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_FWL_CHANGE_OWNER,
2590 TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
Andrew F. Davis2aafc0c2019-04-12 12:54:43 -04002591 (u32 *)&req, sizeof(req), sizeof(*resp));
2592 if (IS_ERR(xfer)) {
2593 ret = PTR_ERR(xfer);
Andrew F. Davis2aafc0c2019-04-12 12:54:43 -04002594 return ret;
2595 }
2596
2597 req.fwl_id = owner->fwl_id;
2598 req.region = owner->region;
2599 req.owner_index = owner->owner_index;
2600
2601 ret = ti_sci_do_xfer(info, xfer);
Andrew Davis771a16f2022-07-25 20:25:03 -05002602 if (ret)
Andrew F. Davis2aafc0c2019-04-12 12:54:43 -04002603 return ret;
Andrew F. Davis2aafc0c2019-04-12 12:54:43 -04002604
2605 resp = (struct ti_sci_msg_fwl_change_owner_info_resp *)xfer->tx_message.buf;
2606
Andrew F. Davis2aafc0c2019-04-12 12:54:43 -04002607 owner->fwl_id = resp->fwl_id;
2608 owner->region = resp->region;
2609 owner->owner_index = resp->owner_index;
2610 owner->owner_privid = resp->owner_privid;
2611 owner->owner_permission_bits = resp->owner_permission_bits;
2612
2613 return ret;
2614}
2615
Andreas Dannenberg5299c4c2018-08-27 15:57:33 +05302616/*
2617 * ti_sci_setup_ops() - Setup the operations structures
2618 * @info: pointer to TISCI pointer
2619 */
2620static void ti_sci_setup_ops(struct ti_sci_info *info)
2621{
2622 struct ti_sci_ops *ops = &info->handle.ops;
2623 struct ti_sci_board_ops *bops = &ops->board_ops;
Andreas Dannenberg24a4d5e2018-08-27 15:57:34 +05302624 struct ti_sci_dev_ops *dops = &ops->dev_ops;
Lokesh Vutlad10c80c2018-08-27 15:57:35 +05302625 struct ti_sci_clk_ops *cops = &ops->clk_ops;
Andreas Dannenberg5bd08372018-08-27 15:57:36 +05302626 struct ti_sci_core_ops *core_ops = &ops->core_ops;
Grygorii Strashkod64c5b22019-02-05 17:31:21 +05302627 struct ti_sci_rm_core_ops *rm_core_ops = &ops->rm_core_ops;
Lokesh Vutlab8856af2018-08-27 15:57:37 +05302628 struct ti_sci_proc_ops *pops = &ops->proc_ops;
Grygorii Strashkod64c5b22019-02-05 17:31:21 +05302629 struct ti_sci_rm_ringacc_ops *rops = &ops->rm_ring_ops;
2630 struct ti_sci_rm_psil_ops *psilops = &ops->rm_psil_ops;
2631 struct ti_sci_rm_udmap_ops *udmap_ops = &ops->rm_udmap_ops;
Andrew F. Davis2aafc0c2019-04-12 12:54:43 -04002632 struct ti_sci_fwl_ops *fwl_ops = &ops->fwl_ops;
Andreas Dannenberg5299c4c2018-08-27 15:57:33 +05302633
2634 bops->board_config = ti_sci_cmd_set_board_config;
2635 bops->board_config_rm = ti_sci_cmd_set_board_config_rm;
2636 bops->board_config_security = ti_sci_cmd_set_board_config_security;
2637 bops->board_config_pm = ti_sci_cmd_set_board_config_pm;
Andreas Dannenberg24a4d5e2018-08-27 15:57:34 +05302638
2639 dops->get_device = ti_sci_cmd_get_device;
Lokesh Vutlaf5613002019-06-07 19:24:39 +05302640 dops->get_device_exclusive = ti_sci_cmd_get_device_exclusive;
Andreas Dannenberg24a4d5e2018-08-27 15:57:34 +05302641 dops->idle_device = ti_sci_cmd_idle_device;
Lokesh Vutlaf5613002019-06-07 19:24:39 +05302642 dops->idle_device_exclusive = ti_sci_cmd_idle_device_exclusive;
Andreas Dannenberg24a4d5e2018-08-27 15:57:34 +05302643 dops->put_device = ti_sci_cmd_put_device;
2644 dops->is_valid = ti_sci_cmd_dev_is_valid;
2645 dops->get_context_loss_count = ti_sci_cmd_dev_get_clcnt;
2646 dops->is_idle = ti_sci_cmd_dev_is_idle;
2647 dops->is_stop = ti_sci_cmd_dev_is_stop;
2648 dops->is_on = ti_sci_cmd_dev_is_on;
2649 dops->is_transitioning = ti_sci_cmd_dev_is_trans;
2650 dops->set_device_resets = ti_sci_cmd_set_device_resets;
2651 dops->get_device_resets = ti_sci_cmd_get_device_resets;
Lokesh Vutla0d0412a2019-06-07 19:24:41 +05302652 dops->release_exclusive_devices = ti_sci_cmd_release_exclusive_devices;
Lokesh Vutlad10c80c2018-08-27 15:57:35 +05302653
2654 cops->get_clock = ti_sci_cmd_get_clock;
2655 cops->idle_clock = ti_sci_cmd_idle_clock;
2656 cops->put_clock = ti_sci_cmd_put_clock;
2657 cops->is_auto = ti_sci_cmd_clk_is_auto;
2658 cops->is_on = ti_sci_cmd_clk_is_on;
2659 cops->is_off = ti_sci_cmd_clk_is_off;
2660
2661 cops->set_parent = ti_sci_cmd_clk_set_parent;
2662 cops->get_parent = ti_sci_cmd_clk_get_parent;
2663 cops->get_num_parents = ti_sci_cmd_clk_get_num_parents;
2664
2665 cops->get_best_match_freq = ti_sci_cmd_clk_get_match_freq;
2666 cops->set_freq = ti_sci_cmd_clk_set_freq;
2667 cops->get_freq = ti_sci_cmd_clk_get_freq;
Andreas Dannenberg5bd08372018-08-27 15:57:36 +05302668
2669 core_ops->reboot_device = ti_sci_cmd_core_reboot;
Lokesh Vutla032dce82019-03-08 11:47:32 +05302670 core_ops->query_msmc = ti_sci_cmd_query_msmc;
Lokesh Vutlab8856af2018-08-27 15:57:37 +05302671
Grygorii Strashkod64c5b22019-02-05 17:31:21 +05302672 rm_core_ops->get_range = ti_sci_cmd_get_resource_range;
2673 rm_core_ops->get_range_from_shost =
2674 ti_sci_cmd_get_resource_range_from_shost;
2675
Lokesh Vutlab8856af2018-08-27 15:57:37 +05302676 pops->proc_request = ti_sci_cmd_proc_request;
2677 pops->proc_release = ti_sci_cmd_proc_release;
2678 pops->proc_handover = ti_sci_cmd_proc_handover;
2679 pops->set_proc_boot_cfg = ti_sci_cmd_set_proc_boot_cfg;
2680 pops->set_proc_boot_ctrl = ti_sci_cmd_set_proc_boot_ctrl;
2681 pops->proc_auth_boot_image = ti_sci_cmd_proc_auth_boot_image;
2682 pops->get_proc_boot_status = ti_sci_cmd_get_proc_boot_status;
Andreas Dannenbergca08cb32019-06-07 19:24:40 +05302683 pops->proc_shutdown_no_wait = ti_sci_cmd_proc_shutdown_no_wait;
Grygorii Strashkod64c5b22019-02-05 17:31:21 +05302684
2685 rops->config = ti_sci_cmd_ring_config;
Grygorii Strashkod64c5b22019-02-05 17:31:21 +05302686
2687 psilops->pair = ti_sci_cmd_rm_psil_pair;
2688 psilops->unpair = ti_sci_cmd_rm_psil_unpair;
2689
2690 udmap_ops->tx_ch_cfg = ti_sci_cmd_rm_udmap_tx_ch_cfg;
2691 udmap_ops->rx_ch_cfg = ti_sci_cmd_rm_udmap_rx_ch_cfg;
2692 udmap_ops->rx_flow_cfg = ti_sci_cmd_rm_udmap_rx_flow_cfg;
Andrew F. Davis2aafc0c2019-04-12 12:54:43 -04002693
2694 fwl_ops->set_fwl_region = ti_sci_cmd_set_fwl_region;
2695 fwl_ops->get_fwl_region = ti_sci_cmd_get_fwl_region;
2696 fwl_ops->change_fwl_owner = ti_sci_cmd_change_fwl_owner;
Andreas Dannenberg5299c4c2018-08-27 15:57:33 +05302697}
2698
2699/**
Lokesh Vutla5af02db2018-08-27 15:57:32 +05302700 * ti_sci_get_handle_from_sysfw() - Get the TI SCI handle of the SYSFW
2701 * @dev: Pointer to the SYSFW device
2702 *
2703 * Return: pointer to handle if successful, else EINVAL if invalid conditions
2704 * are encountered.
2705 */
2706const
2707struct ti_sci_handle *ti_sci_get_handle_from_sysfw(struct udevice *sci_dev)
2708{
Neha Malcom Francisc7dedd02023-09-27 18:39:53 +05302709 int ret;
2710
Lokesh Vutla5af02db2018-08-27 15:57:32 +05302711 if (!sci_dev)
2712 return ERR_PTR(-EINVAL);
2713
2714 struct ti_sci_info *info = dev_get_priv(sci_dev);
2715
2716 if (!info)
2717 return ERR_PTR(-EINVAL);
2718
2719 struct ti_sci_handle *handle = &info->handle;
2720
2721 if (!handle)
2722 return ERR_PTR(-EINVAL);
2723
Neha Malcom Francisc7dedd02023-09-27 18:39:53 +05302724 ret = ti_sci_cmd_get_revision(handle);
2725
2726 if (ret)
2727 return ERR_PTR(-EINVAL);
2728
Lokesh Vutla5af02db2018-08-27 15:57:32 +05302729 return handle;
2730}
2731
2732/**
2733 * ti_sci_get_handle() - Get the TI SCI handle for a device
2734 * @dev: Pointer to device for which we want SCI handle
2735 *
2736 * Return: pointer to handle if successful, else EINVAL if invalid conditions
2737 * are encountered.
2738 */
2739const struct ti_sci_handle *ti_sci_get_handle(struct udevice *dev)
2740{
2741 if (!dev)
2742 return ERR_PTR(-EINVAL);
2743
2744 struct udevice *sci_dev = dev_get_parent(dev);
2745
2746 return ti_sci_get_handle_from_sysfw(sci_dev);
2747}
2748
2749/**
2750 * ti_sci_get_by_phandle() - Get the TI SCI handle using DT phandle
2751 * @dev: device node
2752 * @propname: property name containing phandle on TISCI node
2753 *
2754 * Return: pointer to handle if successful, else appropriate error value.
2755 */
2756const struct ti_sci_handle *ti_sci_get_by_phandle(struct udevice *dev,
2757 const char *property)
2758{
2759 struct ti_sci_info *entry, *info = NULL;
2760 u32 phandle, err;
2761 ofnode node;
2762
2763 err = ofnode_read_u32(dev_ofnode(dev), property, &phandle);
2764 if (err)
2765 return ERR_PTR(err);
2766
2767 node = ofnode_get_by_phandle(phandle);
2768 if (!ofnode_valid(node))
2769 return ERR_PTR(-EINVAL);
2770
2771 list_for_each_entry(entry, &ti_sci_list, list)
2772 if (ofnode_equal(dev_ofnode(entry->dev), node)) {
2773 info = entry;
2774 break;
2775 }
2776
2777 if (!info)
2778 return ERR_PTR(-ENODEV);
2779
2780 return &info->handle;
2781}
2782
2783/**
2784 * ti_sci_of_to_info() - generate private data from device tree
2785 * @dev: corresponding system controller interface device
2786 * @info: pointer to driver specific private data
2787 *
2788 * Return: 0 if all goes good, else appropriate error message.
2789 */
2790static int ti_sci_of_to_info(struct udevice *dev, struct ti_sci_info *info)
2791{
2792 int ret;
2793
2794 ret = mbox_get_by_name(dev, "tx", &info->chan_tx);
2795 if (ret) {
2796 dev_err(dev, "%s: Acquiring Tx channel failed. ret = %d\n",
2797 __func__, ret);
2798 return ret;
2799 }
2800
2801 ret = mbox_get_by_name(dev, "rx", &info->chan_rx);
2802 if (ret) {
2803 dev_err(dev, "%s: Acquiring Rx channel failed. ret = %d\n",
2804 __func__, ret);
2805 return ret;
2806 }
2807
2808 /* Notify channel is optional. Enable only if populated */
2809 ret = mbox_get_by_name(dev, "notify", &info->chan_notify);
2810 if (ret) {
2811 dev_dbg(dev, "%s: Acquiring notify channel failed. ret = %d\n",
2812 __func__, ret);
2813 }
2814
2815 info->host_id = dev_read_u32_default(dev, "ti,host-id",
Grygorii Strashkod64c5b22019-02-05 17:31:21 +05302816 info->desc->default_host_id);
Lokesh Vutla5af02db2018-08-27 15:57:32 +05302817
2818 info->is_secure = dev_read_bool(dev, "ti,secure-host");
2819
2820 return 0;
2821}
2822
2823/**
2824 * ti_sci_probe() - Basic probe
2825 * @dev: corresponding system controller interface device
2826 *
2827 * Return: 0 if all goes good, else appropriate error message.
2828 */
2829static int ti_sci_probe(struct udevice *dev)
2830{
2831 struct ti_sci_info *info;
2832 int ret;
2833
2834 debug("%s(dev=%p)\n", __func__, dev);
2835
2836 info = dev_get_priv(dev);
2837 info->desc = (void *)dev_get_driver_data(dev);
2838
2839 ret = ti_sci_of_to_info(dev, info);
2840 if (ret) {
2841 dev_err(dev, "%s: Probe failed with error %d\n", __func__, ret);
2842 return ret;
2843 }
2844
2845 info->dev = dev;
2846 info->seq = 0xA;
2847
Udit Kumar24b11a42025-04-29 22:44:40 +05302848 INIT_LIST_HEAD(&info->dev_list);
2849
Lokesh Vutla5af02db2018-08-27 15:57:32 +05302850 list_add_tail(&info->list, &ti_sci_list);
Andreas Dannenberg5299c4c2018-08-27 15:57:33 +05302851 ti_sci_setup_ops(info);
Lokesh Vutla5af02db2018-08-27 15:57:32 +05302852
Andrew Davis1ed20d62024-04-02 11:09:07 -05002853 if (IS_ENABLED(CONFIG_SYSRESET_TI_SCI)) {
2854 ret = device_bind_driver(dev, "ti-sci-sysreset", "sysreset", NULL);
2855 if (ret)
2856 dev_warn(dev, "cannot bind SYSRESET (ret = %d)\n", ret);
2857 }
2858
Neha Malcom Francisc7dedd02023-09-27 18:39:53 +05302859 return 0;
Lokesh Vutla5af02db2018-08-27 15:57:32 +05302860}
2861
Vignesh Raghavendraaa0e3fc2021-06-07 19:47:49 +05302862/**
2863 * ti_sci_dm_probe() - Basic probe for DM to TIFS SCI
2864 * @dev: corresponding system controller interface device
2865 *
2866 * Return: 0 if all goes good, else appropriate error message.
2867 */
2868static __maybe_unused int ti_sci_dm_probe(struct udevice *dev)
2869{
2870 struct ti_sci_rm_core_ops *rm_core_ops;
2871 struct ti_sci_rm_udmap_ops *udmap_ops;
2872 struct ti_sci_rm_ringacc_ops *rops;
2873 struct ti_sci_rm_psil_ops *psilops;
2874 struct ti_sci_ops *ops;
2875 struct ti_sci_info *info;
2876 int ret;
2877
2878 debug("%s(dev=%p)\n", __func__, dev);
2879
2880 info = dev_get_priv(dev);
2881 info->desc = (void *)dev_get_driver_data(dev);
2882
2883 ret = ti_sci_of_to_info(dev, info);
2884 if (ret) {
2885 dev_err(dev, "%s: Probe failed with error %d\n", __func__, ret);
2886 return ret;
2887 }
2888
2889 info->dev = dev;
2890 info->seq = 0xA;
2891
Udit Kumar24b11a42025-04-29 22:44:40 +05302892 INIT_LIST_HEAD(&info->dev_list);
2893
Vignesh Raghavendraaa0e3fc2021-06-07 19:47:49 +05302894 list_add_tail(&info->list, &ti_sci_list);
2895
2896 ops = &info->handle.ops;
2897
2898 rm_core_ops = &ops->rm_core_ops;
2899 rm_core_ops->get_range = ti_sci_cmd_get_resource_range_static;
2900
2901 rops = &ops->rm_ring_ops;
2902 rops->config = ti_sci_cmd_ring_config;
2903
2904 psilops = &ops->rm_psil_ops;
2905 psilops->pair = ti_sci_cmd_rm_psil_pair;
2906 psilops->unpair = ti_sci_cmd_rm_psil_unpair;
2907
2908 udmap_ops = &ops->rm_udmap_ops;
2909 udmap_ops->tx_ch_cfg = ti_sci_cmd_rm_udmap_tx_ch_cfg;
2910 udmap_ops->rx_ch_cfg = ti_sci_cmd_rm_udmap_rx_ch_cfg;
Kishon Vijay Abraham Ie9876c82024-08-26 15:55:06 +05302911 udmap_ops->rx_flow_cfg = ti_sci_cmd_rm_udmap_rx_flow_cfg_noop;
Vignesh Raghavendraaa0e3fc2021-06-07 19:47:49 +05302912
2913 return ret;
2914}
2915
Grygorii Strashkod64c5b22019-02-05 17:31:21 +05302916/*
2917 * ti_sci_get_free_resource() - Get a free resource from TISCI resource.
2918 * @res: Pointer to the TISCI resource
2919 *
2920 * Return: resource num if all went ok else TI_SCI_RESOURCE_NULL.
2921 */
2922u16 ti_sci_get_free_resource(struct ti_sci_resource *res)
2923{
2924 u16 set, free_bit;
2925
2926 for (set = 0; set < res->sets; set++) {
2927 free_bit = find_first_zero_bit(res->desc[set].res_map,
2928 res->desc[set].num);
2929 if (free_bit != res->desc[set].num) {
2930 set_bit(free_bit, res->desc[set].res_map);
2931 return res->desc[set].start + free_bit;
2932 }
2933 }
2934
2935 return TI_SCI_RESOURCE_NULL;
2936}
2937
2938/**
2939 * ti_sci_release_resource() - Release a resource from TISCI resource.
2940 * @res: Pointer to the TISCI resource
2941 */
2942void ti_sci_release_resource(struct ti_sci_resource *res, u16 id)
2943{
2944 u16 set;
2945
2946 for (set = 0; set < res->sets; set++) {
2947 if (res->desc[set].start <= id &&
2948 (res->desc[set].num + res->desc[set].start) > id)
2949 clear_bit(id - res->desc[set].start,
2950 res->desc[set].res_map);
2951 }
2952}
2953
2954/**
2955 * devm_ti_sci_get_of_resource() - Get a TISCI resource assigned to a device
2956 * @handle: TISCI handle
2957 * @dev: Device pointer to which the resource is assigned
2958 * @of_prop: property name by which the resource are represented
2959 *
2960 * Note: This function expects of_prop to be in the form of tuples
2961 * <type, subtype>. Allocates and initializes ti_sci_resource structure
2962 * for each of_prop. Client driver can directly call
2963 * ti_sci_(get_free, release)_resource apis for handling the resource.
2964 *
2965 * Return: Pointer to ti_sci_resource if all went well else appropriate
2966 * error pointer.
2967 */
2968struct ti_sci_resource *
2969devm_ti_sci_get_of_resource(const struct ti_sci_handle *handle,
2970 struct udevice *dev, u32 dev_id, char *of_prop)
2971{
2972 u32 resource_subtype;
Grygorii Strashkod64c5b22019-02-05 17:31:21 +05302973 struct ti_sci_resource *res;
Vignesh Raghavendrae1164dd2019-08-05 12:26:44 -05002974 bool valid_set = false;
Grygorii Strashkod64c5b22019-02-05 17:31:21 +05302975 int sets, i, ret;
2976 u32 *temp;
2977
2978 res = devm_kzalloc(dev, sizeof(*res), GFP_KERNEL);
2979 if (!res)
2980 return ERR_PTR(-ENOMEM);
2981
2982 sets = dev_read_size(dev, of_prop);
2983 if (sets < 0) {
2984 dev_err(dev, "%s resource type ids not available\n", of_prop);
2985 return ERR_PTR(sets);
2986 }
2987 temp = malloc(sets);
2988 sets /= sizeof(u32);
2989 res->sets = sets;
2990
2991 res->desc = devm_kcalloc(dev, res->sets, sizeof(*res->desc),
2992 GFP_KERNEL);
2993 if (!res->desc)
2994 return ERR_PTR(-ENOMEM);
2995
Grygorii Strashkod64c5b22019-02-05 17:31:21 +05302996 ret = dev_read_u32_array(dev, of_prop, temp, res->sets);
2997 if (ret)
2998 return ERR_PTR(-EINVAL);
2999
3000 for (i = 0; i < res->sets; i++) {
3001 resource_subtype = temp[i];
3002 ret = handle->ops.rm_core_ops.get_range(handle, dev_id,
3003 resource_subtype,
3004 &res->desc[i].start,
3005 &res->desc[i].num);
3006 if (ret) {
Vignesh Raghavendrae1164dd2019-08-05 12:26:44 -05003007 dev_dbg(dev, "type %d subtype %d not allocated for host %d\n",
Lokesh Vutla0acf1dc2020-08-17 11:00:48 +05303008 dev_id, resource_subtype,
Grygorii Strashkod64c5b22019-02-05 17:31:21 +05303009 handle_to_ti_sci_info(handle)->host_id);
Vignesh Raghavendrae1164dd2019-08-05 12:26:44 -05003010 res->desc[i].start = 0;
3011 res->desc[i].num = 0;
3012 continue;
Grygorii Strashkod64c5b22019-02-05 17:31:21 +05303013 }
3014
Vignesh Raghavendrae1164dd2019-08-05 12:26:44 -05003015 valid_set = true;
Grygorii Strashkod64c5b22019-02-05 17:31:21 +05303016 dev_dbg(dev, "res type = %d, subtype = %d, start = %d, num = %d\n",
Lokesh Vutla0acf1dc2020-08-17 11:00:48 +05303017 dev_id, resource_subtype, res->desc[i].start,
Grygorii Strashkod64c5b22019-02-05 17:31:21 +05303018 res->desc[i].num);
3019
3020 res->desc[i].res_map =
3021 devm_kzalloc(dev, BITS_TO_LONGS(res->desc[i].num) *
3022 sizeof(*res->desc[i].res_map), GFP_KERNEL);
3023 if (!res->desc[i].res_map)
3024 return ERR_PTR(-ENOMEM);
3025 }
3026
Vignesh Raghavendrae1164dd2019-08-05 12:26:44 -05003027 if (valid_set)
3028 return res;
3029
3030 return ERR_PTR(-EINVAL);
Grygorii Strashkod64c5b22019-02-05 17:31:21 +05303031}
3032
3033/* Description for K2G */
3034static const struct ti_sci_desc ti_sci_pmmc_k2g_desc = {
3035 .default_host_id = 2,
3036 /* Conservative duration */
3037 .max_rx_timeout_ms = 10000,
3038 /* Limited by MBOX_TX_QUEUE_LEN. K2G can handle upto 128 messages! */
3039 .max_msgs = 20,
3040 .max_msg_size = 64,
Grygorii Strashkod64c5b22019-02-05 17:31:21 +05303041};
3042
Lokesh Vutla5af02db2018-08-27 15:57:32 +05303043/* Description for AM654 */
Grygorii Strashkod64c5b22019-02-05 17:31:21 +05303044static const struct ti_sci_desc ti_sci_pmmc_am654_desc = {
3045 .default_host_id = 12,
3046 /* Conservative duration */
3047 .max_rx_timeout_ms = 10000,
3048 /* Limited by MBOX_TX_QUEUE_LEN. K2G can handle upto 128 messages! */
3049 .max_msgs = 20,
Lokesh Vutla5af02db2018-08-27 15:57:32 +05303050 .max_msg_size = 60,
3051};
3052
Vignesh Raghavendraaa0e3fc2021-06-07 19:47:49 +05303053/* Description for J721e DM to DMSC communication */
3054static const struct ti_sci_desc ti_sci_dm_j721e_desc = {
3055 .default_host_id = 3,
3056 .max_rx_timeout_ms = 10000,
3057 .max_msgs = 20,
3058 .max_msg_size = 60,
3059};
3060
Lokesh Vutla5af02db2018-08-27 15:57:32 +05303061static const struct udevice_id ti_sci_ids[] = {
3062 {
3063 .compatible = "ti,k2g-sci",
Grygorii Strashkod64c5b22019-02-05 17:31:21 +05303064 .data = (ulong)&ti_sci_pmmc_k2g_desc
3065 },
3066 {
3067 .compatible = "ti,am654-sci",
3068 .data = (ulong)&ti_sci_pmmc_am654_desc
Lokesh Vutla5af02db2018-08-27 15:57:32 +05303069 },
3070 { /* Sentinel */ },
3071};
3072
Vignesh Raghavendraaa0e3fc2021-06-07 19:47:49 +05303073static __maybe_unused const struct udevice_id ti_sci_dm_ids[] = {
3074 {
3075 .compatible = "ti,j721e-dm-sci",
3076 .data = (ulong)&ti_sci_dm_j721e_desc
3077 },
3078 { /* Sentinel */ },
3079};
3080
Lokesh Vutla5af02db2018-08-27 15:57:32 +05303081U_BOOT_DRIVER(ti_sci) = {
3082 .name = "ti_sci",
3083 .id = UCLASS_FIRMWARE,
3084 .of_match = ti_sci_ids,
3085 .probe = ti_sci_probe,
Simon Glass8a2b47f2020-12-03 16:55:17 -07003086 .priv_auto = sizeof(struct ti_sci_info),
Manorit Chawdhry27f161c2024-12-17 14:24:37 +05303087 .flags = DM_FLAG_PRE_RELOC,
Lokesh Vutla5af02db2018-08-27 15:57:32 +05303088};
Vignesh Raghavendraaa0e3fc2021-06-07 19:47:49 +05303089
3090#if IS_ENABLED(CONFIG_K3_DM_FW)
3091U_BOOT_DRIVER(ti_sci_dm) = {
3092 .name = "ti_sci_dm",
3093 .id = UCLASS_FIRMWARE,
3094 .of_match = ti_sci_dm_ids,
3095 .probe = ti_sci_dm_probe,
3096 .priv_auto = sizeof(struct ti_sci_info),
3097};
3098#endif