blob: 8b77050da9adc2943fcf3c7bb38140982c01d2d9 [file] [log] [blame]
Andrew F. Davisa513b2a2018-05-04 19:06:09 +00001/*
2 * Texas Instruments System Control Interface Driver
3 * Based on Linux and U-Boot implementation
4 *
Manorit Chawdhry7660cb52024-01-29 12:40:54 +05305 * Copyright (C) 2018-2024 Texas Instruments Incorporated - https://www.ti.com/
Andrew F. Davisa513b2a2018-05-04 19:06:09 +00006 *
7 * SPDX-License-Identifier: BSD-3-Clause
8 */
9
Andrew F. Davisa513b2a2018-05-04 19:06:09 +000010#include <errno.h>
Andrew F. Davisa513b2a2018-05-04 19:06:09 +000011#include <stdbool.h>
12#include <stddef.h>
13#include <string.h>
14
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000015#include <platform_def.h>
Andrew Davis617d0352023-03-13 13:56:27 -050016#include <lib/bakery_lock.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000017
18#include <common/debug.h>
Andrew F. Davisa513b2a2018-05-04 19:06:09 +000019#include <sec_proxy.h>
20
21#include "ti_sci_protocol.h"
22#include "ti_sci.h"
23
Andrew F. Davise1bcbd42020-01-16 15:58:34 -060024#if USE_COHERENT_MEM
Chris Kay33bfc5e2023-02-14 11:30:04 +000025__section(".tzfw_coherent_mem")
Andrew F. Davise1bcbd42020-01-16 15:58:34 -060026#endif
Andrew F. Davis5daafa12020-01-16 15:34:31 -060027static uint8_t message_sequence;
Andrew F. Davisa513b2a2018-05-04 19:06:09 +000028
Andrew Davis617d0352023-03-13 13:56:27 -050029DEFINE_BAKERY_LOCK(ti_sci_xfer_lock);
30
Andrew F. Davisa513b2a2018-05-04 19:06:09 +000031/**
32 * struct ti_sci_xfer - Structure representing a message flow
33 * @tx_message: Transmit message
34 * @rx_message: Receive message
35 */
36struct ti_sci_xfer {
37 struct k3_sec_proxy_msg tx_message;
38 struct k3_sec_proxy_msg rx_message;
39};
40
41/**
42 * ti_sci_setup_one_xfer() - Setup one message type
43 *
44 * @msg_type: Message type
45 * @msg_flags: Flag to set for the message
46 * @tx_buf: Buffer to be sent to mailbox channel
47 * @tx_message_size: transmit message size
48 * @rx_buf: Buffer to be received from mailbox channel
49 * @rx_message_size: receive message size
50 *
51 * Helper function which is used by various command functions that are
52 * exposed to clients of this driver for allocating a message traffic event.
53 *
54 * Return: 0 if all goes well, else appropriate error message
55 */
56static int ti_sci_setup_one_xfer(uint16_t msg_type, uint32_t msg_flags,
57 void *tx_buf,
58 size_t tx_message_size,
59 void *rx_buf,
60 size_t rx_message_size,
61 struct ti_sci_xfer *xfer)
62{
63 struct ti_sci_msg_hdr *hdr;
64
65 /* Ensure we have sane transfer sizes */
Andrew F. Davis5daafa12020-01-16 15:34:31 -060066 if (rx_message_size > TI_SCI_MAX_MESSAGE_SIZE ||
67 tx_message_size > TI_SCI_MAX_MESSAGE_SIZE ||
Andrew F. Davisa513b2a2018-05-04 19:06:09 +000068 tx_message_size < sizeof(*hdr))
69 return -ERANGE;
70
Andrew F. Davisa513b2a2018-05-04 19:06:09 +000071 hdr = (struct ti_sci_msg_hdr *)tx_buf;
Andrew F. Davis5daafa12020-01-16 15:34:31 -060072 hdr->seq = ++message_sequence;
Andrew F. Davisa513b2a2018-05-04 19:06:09 +000073 hdr->type = msg_type;
Andrew F. Davis5daafa12020-01-16 15:34:31 -060074 hdr->host = TI_SCI_HOST_ID;
Andrew Davise0a676c2022-05-16 13:17:02 -050075 hdr->flags = msg_flags;
76 /* Request a response if rx_message_size is non-zero */
77 if (rx_message_size != 0U) {
78 hdr->flags |= TI_SCI_FLAG_REQ_ACK_ON_PROCESSED;
79 }
Andrew F. Davisa513b2a2018-05-04 19:06:09 +000080
81 xfer->tx_message.buf = tx_buf;
82 xfer->tx_message.len = tx_message_size;
83
84 xfer->rx_message.buf = rx_buf;
85 xfer->rx_message.len = rx_message_size;
86
87 return 0;
88}
89
90/**
91 * ti_sci_get_response() - Receive response from mailbox channel
92 *
93 * @xfer: Transfer to initiate and wait for response
94 * @chan: Channel to receive the response
95 *
96 * Return: 0 if all goes well, else appropriate error message
97 */
Andrew Davis817bdbb2022-11-11 12:49:38 -060098static int ti_sci_get_response(struct k3_sec_proxy_msg *msg,
99 enum k3_sec_proxy_chan_id chan)
Andrew F. Davisa513b2a2018-05-04 19:06:09 +0000100{
Andrew F. Davisa513b2a2018-05-04 19:06:09 +0000101 struct ti_sci_msg_hdr *hdr;
Andrew F. Davisdff11822019-04-10 12:40:12 -0400102 unsigned int retry = 5;
Andrew F. Davisa513b2a2018-05-04 19:06:09 +0000103 int ret;
104
Andrew F. Davisdff11822019-04-10 12:40:12 -0400105 for (; retry > 0; retry--) {
106 /* Receive the response */
107 ret = k3_sec_proxy_recv(chan, msg);
108 if (ret) {
109 ERROR("Message receive failed (%d)\n", ret);
110 return ret;
111 }
Andrew F. Davisa513b2a2018-05-04 19:06:09 +0000112
Andrew F. Davisdff11822019-04-10 12:40:12 -0400113 /* msg is updated by Secure Proxy driver */
114 hdr = (struct ti_sci_msg_hdr *)msg->buf;
Andrew F. Davisa513b2a2018-05-04 19:06:09 +0000115
Andrew F. Davisdff11822019-04-10 12:40:12 -0400116 /* Sanity check for message response */
Andrew F. Davis5daafa12020-01-16 15:34:31 -0600117 if (hdr->seq == message_sequence)
Andrew F. Davisdff11822019-04-10 12:40:12 -0400118 break;
119 else
120 WARN("Message with sequence ID %u is not expected\n", hdr->seq);
121 }
122 if (!retry) {
123 ERROR("Timed out waiting for message\n");
Andrew F. Davisa513b2a2018-05-04 19:06:09 +0000124 return -EINVAL;
125 }
126
Andrew F. Davis5daafa12020-01-16 15:34:31 -0600127 if (msg->len > TI_SCI_MAX_MESSAGE_SIZE) {
Andrew F. Davisa513b2a2018-05-04 19:06:09 +0000128 ERROR("Unable to handle %lu xfer (max %d)\n",
Andrew F. Davis5daafa12020-01-16 15:34:31 -0600129 msg->len, TI_SCI_MAX_MESSAGE_SIZE);
Andrew F. Davisa513b2a2018-05-04 19:06:09 +0000130 return -EINVAL;
131 }
132
Andrew F. Davis06b30522019-02-11 13:44:31 -0600133 if (!(hdr->flags & TI_SCI_FLAG_RESP_GENERIC_ACK))
134 return -ENODEV;
135
Andrew F. Davisa513b2a2018-05-04 19:06:09 +0000136 return 0;
137}
138
139/**
140 * ti_sci_do_xfer() - Do one transfer
141 *
142 * @xfer: Transfer to initiate and wait for response
143 *
144 * Return: 0 if all goes well, else appropriate error message
145 */
Andrew Davis817bdbb2022-11-11 12:49:38 -0600146static int ti_sci_do_xfer(struct ti_sci_xfer *xfer)
Andrew F. Davisa513b2a2018-05-04 19:06:09 +0000147{
Andrew Davise0a676c2022-05-16 13:17:02 -0500148 struct k3_sec_proxy_msg *tx_msg = &xfer->tx_message;
149 struct k3_sec_proxy_msg *rx_msg = &xfer->rx_message;
Andrew F. Davisa513b2a2018-05-04 19:06:09 +0000150 int ret;
151
Andrew Davis617d0352023-03-13 13:56:27 -0500152 bakery_lock_get(&ti_sci_xfer_lock);
153
Andrew F. Davis18d371d2019-01-04 12:49:16 -0600154 /* Clear any spurious messages in receive queue */
155 ret = k3_sec_proxy_clear_rx_thread(SP_RESPONSE);
156 if (ret) {
157 ERROR("Could not clear response queue (%d)\n", ret);
Andrew Davisaf38ab22023-10-31 10:18:35 -0500158 goto unlock;
Andrew F. Davis18d371d2019-01-04 12:49:16 -0600159 }
160
Andrew F. Davisa513b2a2018-05-04 19:06:09 +0000161 /* Send the message */
Andrew Davise0a676c2022-05-16 13:17:02 -0500162 ret = k3_sec_proxy_send(SP_HIGH_PRIORITY, tx_msg);
Andrew F. Davisa513b2a2018-05-04 19:06:09 +0000163 if (ret) {
164 ERROR("Message sending failed (%d)\n", ret);
Andrew Davisaf38ab22023-10-31 10:18:35 -0500165 goto unlock;
Andrew F. Davisa513b2a2018-05-04 19:06:09 +0000166 }
167
Andrew Davise0a676c2022-05-16 13:17:02 -0500168 /* Get the response if requested */
169 if (rx_msg->len != 0U) {
170 ret = ti_sci_get_response(rx_msg, SP_RESPONSE);
171 if (ret != 0U) {
172 ERROR("Failed to get response (%d)\n", ret);
Andrew Davisaf38ab22023-10-31 10:18:35 -0500173 goto unlock;
Andrew Davise0a676c2022-05-16 13:17:02 -0500174 }
Andrew F. Davisa513b2a2018-05-04 19:06:09 +0000175 }
176
Andrew Davisaf38ab22023-10-31 10:18:35 -0500177unlock:
Andrew Davis617d0352023-03-13 13:56:27 -0500178 bakery_lock_release(&ti_sci_xfer_lock);
179
Andrew Davisaf38ab22023-10-31 10:18:35 -0500180 return ret;
Andrew F. Davisa513b2a2018-05-04 19:06:09 +0000181}
182
183/**
184 * ti_sci_get_revision() - Get the revision of the SCI entity
185 *
186 * Updates the SCI information in the internal data structure.
187 *
Manorit Chawdhry7660cb52024-01-29 12:40:54 +0530188 * @version: Structure containing the version info
189 *
Andrew F. Davisa513b2a2018-05-04 19:06:09 +0000190 * Return: 0 if all goes well, else appropriate error message
191 */
Manorit Chawdhry7660cb52024-01-29 12:40:54 +0530192int ti_sci_get_revision(struct ti_sci_msg_version *version)
Andrew F. Davisa513b2a2018-05-04 19:06:09 +0000193{
Manorit Chawdhry7660cb52024-01-29 12:40:54 +0530194 struct ti_sci_msg_resp_version rev_info;
Andrew F. Davisa513b2a2018-05-04 19:06:09 +0000195 struct ti_sci_msg_hdr hdr;
196 struct ti_sci_xfer xfer;
197 int ret;
198
199 ret = ti_sci_setup_one_xfer(TI_SCI_MSG_VERSION, 0x0,
200 &hdr, sizeof(hdr),
Manorit Chawdhry7660cb52024-01-29 12:40:54 +0530201 &rev_info, sizeof(rev_info),
Andrew F. Davisa513b2a2018-05-04 19:06:09 +0000202 &xfer);
203 if (ret) {
204 ERROR("Message alloc failed (%d)\n", ret);
205 return ret;
206 }
207
208 ret = ti_sci_do_xfer(&xfer);
209 if (ret) {
210 ERROR("Transfer send failed (%d)\n", ret);
211 return ret;
212 }
213
Manorit Chawdhry7660cb52024-01-29 12:40:54 +0530214 memcpy(version->firmware_description, rev_info.firmware_description,
215 sizeof(rev_info.firmware_description));
216 version->abi_major = rev_info.abi_major;
217 version->abi_minor = rev_info.abi_minor;
218 version->firmware_revision = rev_info.firmware_revision;
219 version->sub_version = rev_info.sub_version;
220 version->patch_version = rev_info.patch_version;
221
Andrew F. Davisa513b2a2018-05-04 19:06:09 +0000222 return 0;
223}
224
225/**
Andrew Davis10d67f92023-06-26 12:49:17 -0500226 * ti_sci_query_fw_caps() - Get the FW/SoC capabilities
227 * @handle: Pointer to TI SCI handle
228 * @fw_caps: Each bit in fw_caps indicating one FW/SOC capability
229 *
230 * Return: 0 if all went well, else returns appropriate error value.
231 */
232int ti_sci_query_fw_caps(uint64_t *fw_caps)
233{
234 struct ti_sci_msg_hdr req;
235 struct ti_sci_msg_resp_query_fw_caps resp;
236
237 struct ti_sci_xfer xfer;
238 int ret;
239
240 ret = ti_sci_setup_one_xfer(TI_SCI_MSG_QUERY_FW_CAPS, 0,
241 &req, sizeof(req),
242 &resp, sizeof(resp),
243 &xfer);
244 if (ret != 0U) {
245 ERROR("Message alloc failed (%d)\n", ret);
246 return ret;
247 }
248
249 ret = ti_sci_do_xfer(&xfer);
250 if (ret != 0U) {
251 ERROR("Transfer send failed (%d)\n", ret);
252 return ret;
253 }
254
255 if (fw_caps)
256 *fw_caps = resp.fw_caps;
257
258 return 0;
259}
260
261/**
Andrew F. Davis4f2a0552018-05-04 19:06:10 +0000262 * ti_sci_device_set_state() - Set device state
263 *
264 * @id: Device identifier
265 * @flags: flags to setup for the device
266 * @state: State to move the device to
267 *
268 * Return: 0 if all goes well, else appropriate error message
269 */
Andrew F. Davis8335bc22019-02-11 12:55:25 -0600270static int ti_sci_device_set_state(uint32_t id, uint32_t flags, uint8_t state)
Andrew F. Davis4f2a0552018-05-04 19:06:10 +0000271{
272 struct ti_sci_msg_req_set_device_state req;
273 struct ti_sci_msg_hdr resp;
274
275 struct ti_sci_xfer xfer;
276 int ret;
277
Andrew F. Davis06b30522019-02-11 13:44:31 -0600278 ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SET_DEVICE_STATE, flags,
Andrew F. Davis4f2a0552018-05-04 19:06:10 +0000279 &req, sizeof(req),
280 &resp, sizeof(resp),
281 &xfer);
282 if (ret) {
283 ERROR("Message alloc failed (%d)\n", ret);
284 return ret;
285 }
286
287 req.id = id;
288 req.state = state;
289
290 ret = ti_sci_do_xfer(&xfer);
291 if (ret) {
292 ERROR("Transfer send failed (%d)\n", ret);
293 return ret;
294 }
295
Andrew F. Davis4f2a0552018-05-04 19:06:10 +0000296 return 0;
297}
298
299/**
300 * ti_sci_device_get_state() - Get device state
301 *
302 * @id: Device Identifier
303 * @clcnt: Pointer to Context Loss Count
304 * @resets: pointer to resets
305 * @p_state: pointer to p_state
306 * @c_state: pointer to c_state
307 *
308 * Return: 0 if all goes well, else appropriate error message
309 */
Andrew F. Davis8335bc22019-02-11 12:55:25 -0600310static int ti_sci_device_get_state(uint32_t id, uint32_t *clcnt,
311 uint32_t *resets, uint8_t *p_state,
312 uint8_t *c_state)
Andrew F. Davis4f2a0552018-05-04 19:06:10 +0000313{
314 struct ti_sci_msg_req_get_device_state req;
315 struct ti_sci_msg_resp_get_device_state resp;
316
317 struct ti_sci_xfer xfer;
318 int ret;
319
320 if (!clcnt && !resets && !p_state && !c_state)
321 return -EINVAL;
322
323 ret = ti_sci_setup_one_xfer(TI_SCI_MSG_GET_DEVICE_STATE, 0,
324 &req, sizeof(req),
325 &resp, sizeof(resp),
326 &xfer);
327 if (ret) {
328 ERROR("Message alloc failed (%d)\n", ret);
329 return ret;
330 }
331
332 req.id = id;
333
334 ret = ti_sci_do_xfer(&xfer);
335 if (ret) {
336 ERROR("Transfer send failed (%d)\n", ret);
337 return ret;
338 }
339
Andrew F. Davis4f2a0552018-05-04 19:06:10 +0000340 if (clcnt)
341 *clcnt = resp.context_loss_count;
342 if (resets)
343 *resets = resp.resets;
344 if (p_state)
345 *p_state = resp.programmed_state;
346 if (c_state)
347 *c_state = resp.current_state;
348
349 return 0;
350}
351
352/**
353 * ti_sci_device_get() - Request for device managed by TISCI
354 *
355 * @id: Device Identifier
356 *
357 * Request for the device - NOTE: the client MUST maintain integrity of
358 * usage count by balancing get_device with put_device. No refcounting is
359 * managed by driver for that purpose.
360 *
Andrew F. Davis4f2a0552018-05-04 19:06:10 +0000361 * Return: 0 if all goes well, else appropriate error message
362 */
363int ti_sci_device_get(uint32_t id)
364{
Andrew F. Davisfbe6c062019-02-11 12:58:32 -0600365 return ti_sci_device_set_state(id, 0, MSG_DEVICE_SW_STATE_ON);
366}
367
368/**
369 * ti_sci_device_get_exclusive() - Exclusive request for device managed by TISCI
370 *
371 * @id: Device Identifier
372 *
373 * Request for the device - NOTE: the client MUST maintain integrity of
374 * usage count by balancing get_device with put_device. No refcounting is
375 * managed by driver for that purpose.
376 *
377 * NOTE: This _exclusive version of the get API is for exclusive access to the
378 * device. Any other host in the system will fail to get this device after this
379 * call until exclusive access is released with device_put or a non-exclusive
380 * set call.
381 *
382 * Return: 0 if all goes well, else appropriate error message
383 */
384int ti_sci_device_get_exclusive(uint32_t id)
385{
Andrew F. Davis4f2a0552018-05-04 19:06:10 +0000386 return ti_sci_device_set_state(id,
387 MSG_FLAG_DEVICE_EXCLUSIVE,
388 MSG_DEVICE_SW_STATE_ON);
389}
390
391/**
392 * ti_sci_device_idle() - Idle a device managed by TISCI
393 *
394 * @id: Device Identifier
395 *
396 * Request for the device - NOTE: the client MUST maintain integrity of
397 * usage count by balancing get_device with put_device. No refcounting is
398 * managed by driver for that purpose.
399 *
400 * Return: 0 if all goes well, else appropriate error message
401 */
402int ti_sci_device_idle(uint32_t id)
403{
Andrew F. Davisfbe6c062019-02-11 12:58:32 -0600404 return ti_sci_device_set_state(id, 0, MSG_DEVICE_SW_STATE_RETENTION);
405}
406
407/**
408 * ti_sci_device_idle_exclusive() - Exclusive idle a device managed by TISCI
409 *
410 * @id: Device Identifier
411 *
412 * Request for the device - NOTE: the client MUST maintain integrity of
413 * usage count by balancing get_device with put_device. No refcounting is
414 * managed by driver for that purpose.
415 *
416 * NOTE: This _exclusive version of the idle API is for exclusive access to
417 * the device. Any other host in the system will fail to get this device after
418 * this call until exclusive access is released with device_put or a
419 * non-exclusive set call.
420 *
421 * Return: 0 if all goes well, else appropriate error message
422 */
423int ti_sci_device_idle_exclusive(uint32_t id)
424{
Andrew F. Davis4f2a0552018-05-04 19:06:10 +0000425 return ti_sci_device_set_state(id,
426 MSG_FLAG_DEVICE_EXCLUSIVE,
427 MSG_DEVICE_SW_STATE_RETENTION);
428}
429
430/**
431 * ti_sci_device_put() - Release a device managed by TISCI
432 *
433 * @id: Device Identifier
434 *
435 * Request for the device - NOTE: the client MUST maintain integrity of
436 * usage count by balancing get_device with put_device. No refcounting is
437 * managed by driver for that purpose.
438 *
439 * Return: 0 if all goes well, else appropriate error message
440 */
441int ti_sci_device_put(uint32_t id)
442{
443 return ti_sci_device_set_state(id, 0, MSG_DEVICE_SW_STATE_AUTO_OFF);
444}
445
446/**
Andrew F. Davisa29578d2019-02-11 14:18:53 -0600447 * ti_sci_device_put_no_wait() - Release a device without requesting or waiting
448 * for a response.
449 *
450 * @id: Device Identifier
451 *
452 * Request for the device - NOTE: the client MUST maintain integrity of
453 * usage count by balancing get_device with put_device. No refcounting is
454 * managed by driver for that purpose.
455 *
456 * Return: 0 if all goes well, else appropriate error message
457 */
458int ti_sci_device_put_no_wait(uint32_t id)
459{
460 struct ti_sci_msg_req_set_device_state req;
Andrew Davise0a676c2022-05-16 13:17:02 -0500461 struct ti_sci_xfer xfer;
Andrew F. Davisa29578d2019-02-11 14:18:53 -0600462 int ret;
463
Manorit Chawdhry24993b52023-08-22 16:15:40 +0530464 ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SET_DEVICE_STATE, 0,
Andrew Davise0a676c2022-05-16 13:17:02 -0500465 &req, sizeof(req),
466 NULL, 0,
467 &xfer);
468 if (ret != 0U) {
469 ERROR("Message alloc failed (%d)\n", ret);
470 return ret;
471 }
Andrew F. Davisa29578d2019-02-11 14:18:53 -0600472
473 req.id = id;
474 req.state = MSG_DEVICE_SW_STATE_AUTO_OFF;
475
Andrew Davise0a676c2022-05-16 13:17:02 -0500476 ret = ti_sci_do_xfer(&xfer);
477 if (ret != 0U) {
478 ERROR("Transfer send failed (%d)\n", ret);
Andrew F. Davisa29578d2019-02-11 14:18:53 -0600479 return ret;
480 }
481
Andrew F. Davisa29578d2019-02-11 14:18:53 -0600482 return 0;
483}
484
485/**
Andrew F. Davis4f2a0552018-05-04 19:06:10 +0000486 * ti_sci_device_is_valid() - Is the device valid
487 *
488 * @id: Device Identifier
489 *
490 * Return: 0 if all goes well and the device ID is valid, else return
491 * appropriate error
492 */
493int ti_sci_device_is_valid(uint32_t id)
494{
495 uint8_t unused;
496
497 /* check the device state which will also tell us if the ID is valid */
498 return ti_sci_device_get_state(id, NULL, NULL, NULL, &unused);
499}
500
501/**
502 * ti_sci_device_get_clcnt() - Get context loss counter
503 *
504 * @id: Device Identifier
505 * @count: Pointer to Context Loss counter to populate
506 *
507 * Return: 0 if all goes well, else appropriate error message
508 */
509int ti_sci_device_get_clcnt(uint32_t id, uint32_t *count)
510{
511 return ti_sci_device_get_state(id, count, NULL, NULL, NULL);
512}
513
514/**
515 * ti_sci_device_is_idle() - Check if the device is requested to be idle
516 *
517 * @id: Device Identifier
518 * @r_state: true if requested to be idle
519 *
520 * Return: 0 if all goes well, else appropriate error message
521 */
522int ti_sci_device_is_idle(uint32_t id, bool *r_state)
523{
524 int ret;
525 uint8_t state;
526
527 if (!r_state)
528 return -EINVAL;
529
530 ret = ti_sci_device_get_state(id, NULL, NULL, &state, NULL);
531 if (ret)
532 return ret;
533
534 *r_state = (state == MSG_DEVICE_SW_STATE_RETENTION);
535
536 return 0;
537}
538
539/**
540 * ti_sci_device_is_stop() - Check if the device is requested to be stopped
541 *
542 * @id: Device Identifier
543 * @r_state: true if requested to be stopped
544 * @curr_state: true if currently stopped
545 *
546 * Return: 0 if all goes well, else appropriate error message
547 */
548int ti_sci_device_is_stop(uint32_t id, bool *r_state, bool *curr_state)
549{
550 int ret;
551 uint8_t p_state, c_state;
552
553 if (!r_state && !curr_state)
554 return -EINVAL;
555
556 ret = ti_sci_device_get_state(id, NULL, NULL, &p_state, &c_state);
557 if (ret)
558 return ret;
559
560 if (r_state)
561 *r_state = (p_state == MSG_DEVICE_SW_STATE_AUTO_OFF);
562 if (curr_state)
563 *curr_state = (c_state == MSG_DEVICE_HW_STATE_OFF);
564
565 return 0;
566}
567
568/**
569 * ti_sci_device_is_on() - Check if the device is requested to be ON
570 *
571 * @id: Device Identifier
572 * @r_state: true if requested to be ON
573 * @curr_state: true if currently ON and active
574 *
575 * Return: 0 if all goes well, else appropriate error message
576 */
577int ti_sci_device_is_on(uint32_t id, bool *r_state, bool *curr_state)
578{
579 int ret;
580 uint8_t p_state, c_state;
581
582 if (!r_state && !curr_state)
583 return -EINVAL;
584
585 ret =
586 ti_sci_device_get_state(id, NULL, NULL, &p_state, &c_state);
587 if (ret)
588 return ret;
589
590 if (r_state)
591 *r_state = (p_state == MSG_DEVICE_SW_STATE_ON);
592 if (curr_state)
593 *curr_state = (c_state == MSG_DEVICE_HW_STATE_ON);
594
595 return 0;
596}
597
598/**
599 * ti_sci_device_is_trans() - Check if the device is currently transitioning
600 *
601 * @id: Device Identifier
602 * @curr_state: true if currently transitioning
603 *
604 * Return: 0 if all goes well, else appropriate error message
605 */
606int ti_sci_device_is_trans(uint32_t id, bool *curr_state)
607{
608 int ret;
609 uint8_t state;
610
611 if (!curr_state)
612 return -EINVAL;
613
614 ret = ti_sci_device_get_state(id, NULL, NULL, NULL, &state);
615 if (ret)
616 return ret;
617
618 *curr_state = (state == MSG_DEVICE_HW_STATE_TRANS);
619
620 return 0;
621}
622
623/**
624 * ti_sci_device_set_resets() - Set resets for device managed by TISCI
625 *
626 * @id: Device Identifier
627 * @reset_state: Device specific reset bit field
628 *
629 * Return: 0 if all goes well, else appropriate error message
630 */
631int ti_sci_device_set_resets(uint32_t id, uint32_t reset_state)
632{
633 struct ti_sci_msg_req_set_device_resets req;
634 struct ti_sci_msg_hdr resp;
635
636 struct ti_sci_xfer xfer;
637 int ret;
638
Andrew F. Davis06b30522019-02-11 13:44:31 -0600639 ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SET_DEVICE_RESETS, 0,
Andrew F. Davis4f2a0552018-05-04 19:06:10 +0000640 &req, sizeof(req),
641 &resp, sizeof(resp),
642 &xfer);
643 if (ret) {
644 ERROR("Message alloc failed (%d)\n", ret);
645 return ret;
646 }
647
648 req.id = id;
649 req.resets = reset_state;
650
651 ret = ti_sci_do_xfer(&xfer);
652 if (ret) {
653 ERROR("Transfer send failed (%d)\n", ret);
654 return ret;
655 }
656
Andrew F. Davis4f2a0552018-05-04 19:06:10 +0000657 return 0;
658}
659
660/**
661 * ti_sci_device_get_resets() - Get reset state for device managed by TISCI
662 *
663 * @id: Device Identifier
664 * @reset_state: Pointer to reset state to populate
665 *
666 * Return: 0 if all goes well, else appropriate error message
667 */
668int ti_sci_device_get_resets(uint32_t id, uint32_t *reset_state)
669{
670 return ti_sci_device_get_state(id, NULL, reset_state, NULL, NULL);
671}
672
673/**
Andrew F. Davisdc08adf2018-05-04 19:06:11 +0000674 * ti_sci_clock_set_state() - Set clock state helper
675 *
676 * @dev_id: Device identifier this request is for
677 * @clk_id: Clock identifier for the device for this request,
678 * Each device has its own set of clock inputs, This indexes
679 * which clock input to modify
680 * @flags: Header flags as needed
681 * @state: State to request for the clock
682 *
683 * Return: 0 if all goes well, else appropriate error message
684 */
685int ti_sci_clock_set_state(uint32_t dev_id, uint8_t clk_id,
686 uint32_t flags, uint8_t state)
687{
688 struct ti_sci_msg_req_set_clock_state req;
689 struct ti_sci_msg_hdr resp;
690
691 struct ti_sci_xfer xfer;
692 int ret;
693
Andrew F. Davis06b30522019-02-11 13:44:31 -0600694 ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SET_CLOCK_STATE, flags,
Andrew F. Davisdc08adf2018-05-04 19:06:11 +0000695 &req, sizeof(req),
696 &resp, sizeof(resp),
697 &xfer);
698 if (ret) {
699 ERROR("Message alloc failed (%d)\n", ret);
700 return ret;
701 }
702
703 req.dev_id = dev_id;
704 req.clk_id = clk_id;
705 req.request_state = state;
706
707 ret = ti_sci_do_xfer(&xfer);
708 if (ret) {
709 ERROR("Transfer send failed (%d)\n", ret);
710 return ret;
711 }
712
Andrew F. Davisdc08adf2018-05-04 19:06:11 +0000713 return 0;
714}
715
716/**
717 * ti_sci_clock_get_state() - Get clock state helper
718 *
719 * @dev_id: Device identifier this request is for
720 * @clk_id: Clock identifier for the device for this request.
721 * Each device has its own set of clock inputs. This indexes
722 * which clock input to modify.
723 * @programmed_state: State requested for clock to move to
724 * @current_state: State that the clock is currently in
725 *
726 * Return: 0 if all goes well, else appropriate error message
727 */
728int ti_sci_clock_get_state(uint32_t dev_id, uint8_t clk_id,
729 uint8_t *programmed_state,
730 uint8_t *current_state)
731{
732 struct ti_sci_msg_req_get_clock_state req;
733 struct ti_sci_msg_resp_get_clock_state resp;
734
735 struct ti_sci_xfer xfer;
736 int ret;
737
738 if (!programmed_state && !current_state)
739 return -EINVAL;
740
Andrew F. Davis06b30522019-02-11 13:44:31 -0600741 ret = ti_sci_setup_one_xfer(TI_SCI_MSG_GET_CLOCK_STATE, 0,
Andrew F. Davisdc08adf2018-05-04 19:06:11 +0000742 &req, sizeof(req),
743 &resp, sizeof(resp),
744 &xfer);
745 if (ret) {
746 ERROR("Message alloc failed (%d)\n", ret);
747 return ret;
748 }
749
750 req.dev_id = dev_id;
751 req.clk_id = clk_id;
752
753 ret = ti_sci_do_xfer(&xfer);
754 if (ret) {
755 ERROR("Transfer send failed (%d)\n", ret);
756 return ret;
757 }
758
Andrew F. Davisdc08adf2018-05-04 19:06:11 +0000759 if (programmed_state)
760 *programmed_state = resp.programmed_state;
761 if (current_state)
762 *current_state = resp.current_state;
763
764 return 0;
765}
766
767/**
768 * ti_sci_clock_get() - Get control of a clock from TI SCI
769
770 * @dev_id: Device identifier this request is for
771 * @clk_id: Clock identifier for the device for this request.
772 * Each device has its own set of clock inputs. This indexes
773 * which clock input to modify.
774 * @needs_ssc: 'true' iff Spread Spectrum clock is desired
775 * @can_change_freq: 'true' iff frequency change is desired
776 * @enable_input_term: 'true' iff input termination is desired
777 *
778 * Return: 0 if all goes well, else appropriate error message
779 */
780int ti_sci_clock_get(uint32_t dev_id, uint8_t clk_id,
781 bool needs_ssc, bool can_change_freq,
782 bool enable_input_term)
783{
784 uint32_t flags = 0;
785
786 flags |= needs_ssc ? MSG_FLAG_CLOCK_ALLOW_SSC : 0;
787 flags |= can_change_freq ? MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE : 0;
788 flags |= enable_input_term ? MSG_FLAG_CLOCK_INPUT_TERM : 0;
789
790 return ti_sci_clock_set_state(dev_id, clk_id, flags,
791 MSG_CLOCK_SW_STATE_REQ);
792}
793
794/**
795 * ti_sci_clock_idle() - Idle a clock which is in our control
796
797 * @dev_id: Device identifier this request is for
798 * @clk_id: Clock identifier for the device for this request.
799 * Each device has its own set of clock inputs. This indexes
800 * which clock input to modify.
801 *
802 * NOTE: This clock must have been requested by get_clock previously.
803 *
804 * Return: 0 if all goes well, else appropriate error message
805 */
806int ti_sci_clock_idle(uint32_t dev_id, uint8_t clk_id)
807{
808 return ti_sci_clock_set_state(dev_id, clk_id, 0,
809 MSG_CLOCK_SW_STATE_UNREQ);
810}
811
812/**
813 * ti_sci_clock_put() - Release a clock from our control
814 *
815 * @dev_id: Device identifier this request is for
816 * @clk_id: Clock identifier for the device for this request.
817 * Each device has its own set of clock inputs. This indexes
818 * which clock input to modify.
819 *
820 * NOTE: This clock must have been requested by get_clock previously.
821 *
822 * Return: 0 if all goes well, else appropriate error message
823 */
824int ti_sci_clock_put(uint32_t dev_id, uint8_t clk_id)
825{
826 return ti_sci_clock_set_state(dev_id, clk_id, 0,
827 MSG_CLOCK_SW_STATE_AUTO);
828}
829
830/**
831 * ti_sci_clock_is_auto() - Is the clock being auto managed
832 *
833 * @dev_id: Device identifier this request is for
834 * @clk_id: Clock identifier for the device for this request.
835 * Each device has its own set of clock inputs. This indexes
836 * which clock input to modify.
837 * @req_state: state indicating if the clock is auto managed
838 *
839 * Return: 0 if all goes well, else appropriate error message
840 */
841int ti_sci_clock_is_auto(uint32_t dev_id, uint8_t clk_id, bool *req_state)
842{
843 uint8_t state = 0;
844 int ret;
845
846 if (!req_state)
847 return -EINVAL;
848
849 ret = ti_sci_clock_get_state(dev_id, clk_id, &state, NULL);
850 if (ret)
851 return ret;
852
853 *req_state = (state == MSG_CLOCK_SW_STATE_AUTO);
854
855 return 0;
856}
857
858/**
859 * ti_sci_clock_is_on() - Is the clock ON
860 *
861 * @dev_id: Device identifier this request is for
862 * @clk_id: Clock identifier for the device for this request.
863 * Each device has its own set of clock inputs. This indexes
864 * which clock input to modify.
865 * @req_state: state indicating if the clock is managed by us and enabled
866 * @curr_state: state indicating if the clock is ready for operation
867 *
868 * Return: 0 if all goes well, else appropriate error message
869 */
870int ti_sci_clock_is_on(uint32_t dev_id, uint8_t clk_id,
871 bool *req_state, bool *curr_state)
872{
873 uint8_t c_state = 0, r_state = 0;
874 int ret;
875
876 if (!req_state && !curr_state)
877 return -EINVAL;
878
879 ret = ti_sci_clock_get_state(dev_id, clk_id, &r_state, &c_state);
880 if (ret)
881 return ret;
882
883 if (req_state)
884 *req_state = (r_state == MSG_CLOCK_SW_STATE_REQ);
885 if (curr_state)
886 *curr_state = (c_state == MSG_CLOCK_HW_STATE_READY);
887
888 return 0;
889}
890
891/**
892 * ti_sci_clock_is_off() - Is the clock OFF
893 *
894 * @dev_id: Device identifier this request is for
895 * @clk_id: Clock identifier for the device for this request.
896 * Each device has its own set of clock inputs. This indexes
897 * which clock input to modify.
898 * @req_state: state indicating if the clock is managed by us and disabled
899 * @curr_state: state indicating if the clock is NOT ready for operation
900 *
901 * Return: 0 if all goes well, else appropriate error message
902 */
903int ti_sci_clock_is_off(uint32_t dev_id, uint8_t clk_id,
904 bool *req_state, bool *curr_state)
905{
906 uint8_t c_state = 0, r_state = 0;
907 int ret;
908
909 if (!req_state && !curr_state)
910 return -EINVAL;
911
912 ret = ti_sci_clock_get_state(dev_id, clk_id, &r_state, &c_state);
913 if (ret)
914 return ret;
915
916 if (req_state)
917 *req_state = (r_state == MSG_CLOCK_SW_STATE_UNREQ);
918 if (curr_state)
919 *curr_state = (c_state == MSG_CLOCK_HW_STATE_NOT_READY);
920
921 return 0;
922}
923
924/**
925 * ti_sci_clock_set_parent() - Set the clock source of a specific device clock
926 *
927 * @dev_id: Device identifier this request is for
928 * @clk_id: Clock identifier for the device for this request.
929 * Each device has its own set of clock inputs. This indexes
930 * which clock input to modify.
931 * @parent_id: Parent clock identifier to set
932 *
933 * Return: 0 if all goes well, else appropriate error message
934 */
935int ti_sci_clock_set_parent(uint32_t dev_id, uint8_t clk_id, uint8_t parent_id)
936{
937 struct ti_sci_msg_req_set_clock_parent req;
938 struct ti_sci_msg_hdr resp;
939
940 struct ti_sci_xfer xfer;
941 int ret;
942
Andrew F. Davis06b30522019-02-11 13:44:31 -0600943 ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SET_CLOCK_PARENT, 0,
Andrew F. Davisdc08adf2018-05-04 19:06:11 +0000944 &req, sizeof(req),
945 &resp, sizeof(resp),
946 &xfer);
947 if (ret) {
948 ERROR("Message alloc failed (%d)\n", ret);
949 return ret;
950 }
951
952 req.dev_id = dev_id;
953 req.clk_id = clk_id;
954 req.parent_id = parent_id;
955
956 ret = ti_sci_do_xfer(&xfer);
957 if (ret) {
958 ERROR("Transfer send failed (%d)\n", ret);
959 return ret;
960 }
961
Andrew F. Davisdc08adf2018-05-04 19:06:11 +0000962 return 0;
963}
964
965/**
966 * ti_sci_clock_get_parent() - Get current parent clock source
967 *
968 * @dev_id: Device identifier this request is for
969 * @clk_id: Clock identifier for the device for this request.
970 * Each device has its own set of clock inputs. This indexes
971 * which clock input to modify.
972 * @parent_id: Current clock parent
973 *
974 * Return: 0 if all goes well, else appropriate error message
975 */
976int ti_sci_clock_get_parent(uint32_t dev_id, uint8_t clk_id, uint8_t *parent_id)
977{
978 struct ti_sci_msg_req_get_clock_parent req;
979 struct ti_sci_msg_resp_get_clock_parent resp;
980
981 struct ti_sci_xfer xfer;
982 int ret;
983
Andrew F. Davis06b30522019-02-11 13:44:31 -0600984 ret = ti_sci_setup_one_xfer(TI_SCI_MSG_GET_CLOCK_PARENT, 0,
Andrew F. Davisdc08adf2018-05-04 19:06:11 +0000985 &req, sizeof(req),
986 &resp, sizeof(resp),
987 &xfer);
988 if (ret) {
989 ERROR("Message alloc failed (%d)\n", ret);
990 return ret;
991 }
992
993 req.dev_id = dev_id;
994 req.clk_id = clk_id;
995
996 ret = ti_sci_do_xfer(&xfer);
997 if (ret) {
998 ERROR("Transfer send failed (%d)\n", ret);
999 return ret;
1000 }
1001
Andrew F. Davisdc08adf2018-05-04 19:06:11 +00001002 *parent_id = resp.parent_id;
1003
1004 return 0;
1005}
1006
1007/**
1008 * ti_sci_clock_get_num_parents() - Get num parents of the current clk source
1009 *
1010 * @dev_id: Device identifier this request is for
1011 * @clk_id: Clock identifier for the device for this request.
1012 * Each device has its own set of clock inputs. This indexes
1013 * which clock input to modify.
1014 * @num_parents: Returns he number of parents to the current clock.
1015 *
1016 * Return: 0 if all goes well, else appropriate error message
1017 */
1018int ti_sci_clock_get_num_parents(uint32_t dev_id, uint8_t clk_id,
1019 uint8_t *num_parents)
1020{
1021 struct ti_sci_msg_req_get_clock_num_parents req;
1022 struct ti_sci_msg_resp_get_clock_num_parents resp;
1023
1024 struct ti_sci_xfer xfer;
1025 int ret;
1026
Andrew F. Davis06b30522019-02-11 13:44:31 -06001027 ret = ti_sci_setup_one_xfer(TI_SCI_MSG_GET_NUM_CLOCK_PARENTS, 0,
Andrew F. Davisdc08adf2018-05-04 19:06:11 +00001028 &req, sizeof(req),
1029 &resp, sizeof(resp),
1030 &xfer);
1031 if (ret) {
1032 ERROR("Message alloc failed (%d)\n", ret);
1033 return ret;
1034 }
1035
1036 req.dev_id = dev_id;
1037 req.clk_id = clk_id;
1038
1039 ret = ti_sci_do_xfer(&xfer);
1040 if (ret) {
1041 ERROR("Transfer send failed (%d)\n", ret);
1042 return ret;
1043 }
1044
Andrew F. Davisdc08adf2018-05-04 19:06:11 +00001045 *num_parents = resp.num_parents;
1046
1047 return 0;
1048}
1049
1050/**
1051 * ti_sci_clock_get_match_freq() - Find a good match for frequency
1052 *
1053 * @dev_id: Device identifier this request is for
1054 * @clk_id: Clock identifier for the device for this request.
1055 * Each device has its own set of clock inputs. This indexes
1056 * which clock input to modify.
1057 * @min_freq: The minimum allowable frequency in Hz. This is the minimum
1058 * allowable programmed frequency and does not account for clock
1059 * tolerances and jitter.
1060 * @target_freq: The target clock frequency in Hz. A frequency will be
1061 * processed as close to this target frequency as possible.
1062 * @max_freq: The maximum allowable frequency in Hz. This is the maximum
1063 * allowable programmed frequency and does not account for clock
1064 * tolerances and jitter.
1065 * @match_freq: Frequency match in Hz response.
1066 *
1067 * Return: 0 if all goes well, else appropriate error message
1068 */
1069int ti_sci_clock_get_match_freq(uint32_t dev_id, uint8_t clk_id,
1070 uint64_t min_freq, uint64_t target_freq,
1071 uint64_t max_freq, uint64_t *match_freq)
1072{
1073 struct ti_sci_msg_req_query_clock_freq req;
1074 struct ti_sci_msg_resp_query_clock_freq resp;
1075
1076 struct ti_sci_xfer xfer;
1077 int ret;
1078
Andrew F. Davis06b30522019-02-11 13:44:31 -06001079 ret = ti_sci_setup_one_xfer(TI_SCI_MSG_QUERY_CLOCK_FREQ, 0,
Andrew F. Davisdc08adf2018-05-04 19:06:11 +00001080 &req, sizeof(req),
1081 &resp, sizeof(resp),
1082 &xfer);
1083 if (ret) {
1084 ERROR("Message alloc failed (%d)\n", ret);
1085 return ret;
1086 }
1087
1088 req.dev_id = dev_id;
1089 req.clk_id = clk_id;
1090 req.min_freq_hz = min_freq;
1091 req.target_freq_hz = target_freq;
1092 req.max_freq_hz = max_freq;
1093
1094 ret = ti_sci_do_xfer(&xfer);
1095 if (ret) {
1096 ERROR("Transfer send failed (%d)\n", ret);
1097 return ret;
1098 }
1099
Andrew F. Davisdc08adf2018-05-04 19:06:11 +00001100 *match_freq = resp.freq_hz;
1101
1102 return 0;
1103}
1104
1105/**
1106 * ti_sci_clock_set_freq() - Set a frequency for clock
1107 *
1108 * @dev_id: Device identifier this request is for
1109 * @clk_id: Clock identifier for the device for this request.
1110 * Each device has its own set of clock inputs. This indexes
1111 * which clock input to modify.
1112 * @min_freq: The minimum allowable frequency in Hz. This is the minimum
1113 * allowable programmed frequency and does not account for clock
1114 * tolerances and jitter.
1115 * @target_freq: The target clock frequency in Hz. A frequency will be
1116 * processed as close to this target frequency as possible.
1117 * @max_freq: The maximum allowable frequency in Hz. This is the maximum
1118 * allowable programmed frequency and does not account for clock
1119 * tolerances and jitter.
1120 *
1121 * Return: 0 if all goes well, else appropriate error message
1122 */
1123int ti_sci_clock_set_freq(uint32_t dev_id, uint8_t clk_id, uint64_t min_freq,
1124 uint64_t target_freq, uint64_t max_freq)
1125{
1126 struct ti_sci_msg_req_set_clock_freq req;
1127 struct ti_sci_msg_hdr resp;
1128
1129 struct ti_sci_xfer xfer;
1130 int ret;
1131
Andrew F. Davis06b30522019-02-11 13:44:31 -06001132 ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SET_CLOCK_FREQ, 0,
Andrew F. Davisdc08adf2018-05-04 19:06:11 +00001133 &req, sizeof(req),
1134 &resp, sizeof(resp),
1135 &xfer);
1136 if (ret) {
1137 ERROR("Message alloc failed (%d)\n", ret);
1138 return ret;
1139 }
1140 req.dev_id = dev_id;
1141 req.clk_id = clk_id;
1142 req.min_freq_hz = min_freq;
1143 req.target_freq_hz = target_freq;
1144 req.max_freq_hz = max_freq;
1145
1146 ret = ti_sci_do_xfer(&xfer);
1147 if (ret) {
1148 ERROR("Transfer send failed (%d)\n", ret);
1149 return ret;
1150 }
1151
Andrew F. Davisdc08adf2018-05-04 19:06:11 +00001152 return 0;
1153}
1154
1155/**
1156 * ti_sci_clock_get_freq() - Get current frequency
1157 *
1158 * @dev_id: Device identifier this request is for
1159 * @clk_id: Clock identifier for the device for this request.
1160 * Each device has its own set of clock inputs. This indexes
1161 * which clock input to modify.
1162 * @freq: Currently frequency in Hz
1163 *
1164 * Return: 0 if all goes well, else appropriate error message
1165 */
1166int ti_sci_clock_get_freq(uint32_t dev_id, uint8_t clk_id, uint64_t *freq)
1167{
1168 struct ti_sci_msg_req_get_clock_freq req;
1169 struct ti_sci_msg_resp_get_clock_freq resp;
1170
1171 struct ti_sci_xfer xfer;
1172 int ret;
1173
Andrew F. Davis06b30522019-02-11 13:44:31 -06001174 ret = ti_sci_setup_one_xfer(TI_SCI_MSG_GET_CLOCK_FREQ, 0,
Andrew F. Davisdc08adf2018-05-04 19:06:11 +00001175 &req, sizeof(req),
1176 &resp, sizeof(resp),
1177 &xfer);
1178 if (ret) {
1179 ERROR("Message alloc failed (%d)\n", ret);
1180 return ret;
1181 }
1182
1183 req.dev_id = dev_id;
1184 req.clk_id = clk_id;
1185
1186 ret = ti_sci_do_xfer(&xfer);
1187 if (ret) {
1188 ERROR("Transfer send failed (%d)\n", ret);
1189 return ret;
1190 }
1191
Andrew F. Davisdc08adf2018-05-04 19:06:11 +00001192 *freq = resp.freq_hz;
1193
1194 return 0;
1195}
1196
1197/**
Andrew F. Davis0d449302018-05-04 19:06:12 +00001198 * ti_sci_core_reboot() - Command to request system reset
1199 *
1200 * Return: 0 if all goes well, else appropriate error message
1201 */
1202int ti_sci_core_reboot(void)
1203{
1204 struct ti_sci_msg_req_reboot req;
1205 struct ti_sci_msg_hdr resp;
1206
1207 struct ti_sci_xfer xfer;
1208 int ret;
1209
Andrew F. Davis06b30522019-02-11 13:44:31 -06001210 ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SYS_RESET, 0,
Andrew F. Davis0d449302018-05-04 19:06:12 +00001211 &req, sizeof(req),
1212 &resp, sizeof(resp),
1213 &xfer);
1214 if (ret) {
1215 ERROR("Message alloc failed (%d)\n", ret);
1216 return ret;
1217 }
Suman Anna0cb2bb12020-10-24 01:28:54 +00001218 req.domain = TI_SCI_DOMAIN_FULL_SOC_RESET;
Andrew F. Davis0d449302018-05-04 19:06:12 +00001219
1220 ret = ti_sci_do_xfer(&xfer);
1221 if (ret) {
1222 ERROR("Transfer send failed (%d)\n", ret);
1223 return ret;
1224 }
1225
Andrew F. Davis0d449302018-05-04 19:06:12 +00001226 return 0;
1227}
1228
1229/**
Andrew F. Davisd92fdfb2018-05-04 19:06:13 +00001230 * ti_sci_proc_request() - Request a physical processor control
1231 *
1232 * @proc_id: Processor ID this request is for
1233 *
1234 * Return: 0 if all goes well, else appropriate error message
1235 */
1236int ti_sci_proc_request(uint8_t proc_id)
1237{
1238 struct ti_sci_msg_req_proc_request req;
1239 struct ti_sci_msg_hdr resp;
1240
1241 struct ti_sci_xfer xfer;
1242 int ret;
1243
Andrew F. Davis06b30522019-02-11 13:44:31 -06001244 ret = ti_sci_setup_one_xfer(TISCI_MSG_PROC_REQUEST, 0,
Andrew F. Davisd92fdfb2018-05-04 19:06:13 +00001245 &req, sizeof(req),
1246 &resp, sizeof(resp),
1247 &xfer);
1248 if (ret) {
1249 ERROR("Message alloc failed (%d)\n", ret);
1250 return ret;
1251 }
1252
1253 req.processor_id = proc_id;
1254
1255 ret = ti_sci_do_xfer(&xfer);
1256 if (ret) {
1257 ERROR("Transfer send failed (%d)\n", ret);
1258 return ret;
1259 }
1260
Andrew F. Davisd92fdfb2018-05-04 19:06:13 +00001261 return 0;
1262}
1263
1264/**
1265 * ti_sci_proc_release() - Release a physical processor control
1266 *
1267 * @proc_id: Processor ID this request is for
1268 *
1269 * Return: 0 if all goes well, else appropriate error message
1270 */
1271int ti_sci_proc_release(uint8_t proc_id)
1272{
1273 struct ti_sci_msg_req_proc_release req;
1274 struct ti_sci_msg_hdr resp;
1275
1276 struct ti_sci_xfer xfer;
1277 int ret;
1278
Andrew F. Davis06b30522019-02-11 13:44:31 -06001279 ret = ti_sci_setup_one_xfer(TISCI_MSG_PROC_RELEASE, 0,
Andrew F. Davisd92fdfb2018-05-04 19:06:13 +00001280 &req, sizeof(req),
1281 &resp, sizeof(resp),
1282 &xfer);
1283 if (ret) {
1284 ERROR("Message alloc failed (%d)\n", ret);
1285 return ret;
1286 }
1287
1288 req.processor_id = proc_id;
1289
1290 ret = ti_sci_do_xfer(&xfer);
1291 if (ret) {
1292 ERROR("Transfer send failed (%d)\n", ret);
1293 return ret;
1294 }
1295
Andrew F. Davisd92fdfb2018-05-04 19:06:13 +00001296 return 0;
1297}
1298
1299/**
1300 * ti_sci_proc_handover() - Handover a physical processor control to a host in
1301 * the processor's access control list.
1302 *
1303 * @proc_id: Processor ID this request is for
1304 * @host_id: Host ID to get the control of the processor
1305 *
1306 * Return: 0 if all goes well, else appropriate error message
1307 */
1308int ti_sci_proc_handover(uint8_t proc_id, uint8_t host_id)
1309{
1310 struct ti_sci_msg_req_proc_handover req;
1311 struct ti_sci_msg_hdr resp;
1312
1313 struct ti_sci_xfer xfer;
1314 int ret;
1315
Andrew F. Davis06b30522019-02-11 13:44:31 -06001316 ret = ti_sci_setup_one_xfer(TISCI_MSG_PROC_HANDOVER, 0,
Andrew F. Davisd92fdfb2018-05-04 19:06:13 +00001317 &req, sizeof(req),
1318 &resp, sizeof(resp),
1319 &xfer);
1320 if (ret) {
1321 ERROR("Message alloc failed (%d)\n", ret);
1322 return ret;
1323 }
1324
1325 req.processor_id = proc_id;
1326 req.host_id = host_id;
1327
1328 ret = ti_sci_do_xfer(&xfer);
1329 if (ret) {
1330 ERROR("Transfer send failed (%d)\n", ret);
1331 return ret;
1332 }
1333
Andrew F. Davisd92fdfb2018-05-04 19:06:13 +00001334 return 0;
1335}
1336
1337/**
1338 * ti_sci_proc_set_boot_cfg() - Set the processor boot configuration flags
1339 *
1340 * @proc_id: Processor ID this request is for
1341 * @config_flags_set: Configuration flags to be set
1342 * @config_flags_clear: Configuration flags to be cleared
1343 *
1344 * Return: 0 if all goes well, else appropriate error message
1345 */
1346int ti_sci_proc_set_boot_cfg(uint8_t proc_id, uint64_t bootvector,
1347 uint32_t config_flags_set,
1348 uint32_t config_flags_clear)
1349{
1350 struct ti_sci_msg_req_set_proc_boot_config req;
1351 struct ti_sci_msg_hdr resp;
1352
1353 struct ti_sci_xfer xfer;
1354 int ret;
1355
Andrew F. Davis06b30522019-02-11 13:44:31 -06001356 ret = ti_sci_setup_one_xfer(TISCI_MSG_SET_PROC_BOOT_CONFIG, 0,
Andrew F. Davisd92fdfb2018-05-04 19:06:13 +00001357 &req, sizeof(req),
1358 &resp, sizeof(resp),
1359 &xfer);
1360 if (ret) {
1361 ERROR("Message alloc failed (%d)\n", ret);
1362 return ret;
1363 }
1364
1365 req.processor_id = proc_id;
1366 req.bootvector_low = bootvector & TISCI_ADDR_LOW_MASK;
1367 req.bootvector_high = (bootvector & TISCI_ADDR_HIGH_MASK) >>
1368 TISCI_ADDR_HIGH_SHIFT;
1369 req.config_flags_set = config_flags_set;
1370 req.config_flags_clear = config_flags_clear;
1371
1372 ret = ti_sci_do_xfer(&xfer);
1373 if (ret) {
1374 ERROR("Transfer send failed (%d)\n", ret);
1375 return ret;
1376 }
1377
Andrew F. Davisd92fdfb2018-05-04 19:06:13 +00001378 return 0;
1379}
1380
1381/**
1382 * ti_sci_proc_set_boot_ctrl() - Set the processor boot control flags
1383 *
1384 * @proc_id: Processor ID this request is for
1385 * @control_flags_set: Control flags to be set
1386 * @control_flags_clear: Control flags to be cleared
1387 *
1388 * Return: 0 if all goes well, else appropriate error message
1389 */
1390int ti_sci_proc_set_boot_ctrl(uint8_t proc_id, uint32_t control_flags_set,
1391 uint32_t control_flags_clear)
1392{
1393 struct ti_sci_msg_req_set_proc_boot_ctrl req;
1394 struct ti_sci_msg_hdr resp;
1395
1396 struct ti_sci_xfer xfer;
1397 int ret;
1398
Andrew F. Davis06b30522019-02-11 13:44:31 -06001399 ret = ti_sci_setup_one_xfer(TISCI_MSG_SET_PROC_BOOT_CTRL, 0,
Andrew F. Davisd92fdfb2018-05-04 19:06:13 +00001400 &req, sizeof(req),
1401 &resp, sizeof(resp),
1402 &xfer);
1403 if (ret) {
1404 ERROR("Message alloc failed (%d)\n", ret);
1405 return ret;
1406 }
1407
1408 req.processor_id = proc_id;
1409 req.control_flags_set = control_flags_set;
1410 req.control_flags_clear = control_flags_clear;
1411
1412 ret = ti_sci_do_xfer(&xfer);
1413 if (ret) {
1414 ERROR("Transfer send failed (%d)\n", ret);
1415 return ret;
1416 }
1417
Andrew F. Davisd92fdfb2018-05-04 19:06:13 +00001418 return 0;
1419}
1420
1421/**
Andrew F. Davisa29578d2019-02-11 14:18:53 -06001422 * ti_sci_proc_set_boot_ctrl_no_wait() - Set the processor boot control flags
1423 * without requesting or waiting for a
1424 * response.
1425 *
1426 * @proc_id: Processor ID this request is for
1427 * @control_flags_set: Control flags to be set
1428 * @control_flags_clear: Control flags to be cleared
1429 *
1430 * Return: 0 if all goes well, else appropriate error message
1431 */
1432int ti_sci_proc_set_boot_ctrl_no_wait(uint8_t proc_id,
1433 uint32_t control_flags_set,
1434 uint32_t control_flags_clear)
1435{
1436 struct ti_sci_msg_req_set_proc_boot_ctrl req;
Andrew Davise0a676c2022-05-16 13:17:02 -05001437 struct ti_sci_xfer xfer;
Andrew F. Davisa29578d2019-02-11 14:18:53 -06001438 int ret;
1439
Manorit Chawdhry24993b52023-08-22 16:15:40 +05301440 ret = ti_sci_setup_one_xfer(TISCI_MSG_SET_PROC_BOOT_CTRL, 0,
Andrew Davise0a676c2022-05-16 13:17:02 -05001441 &req, sizeof(req),
1442 NULL, 0,
1443 &xfer);
1444 if (ret != 0U) {
1445 ERROR("Message alloc failed (%d)\n", ret);
1446 return ret;
1447 }
Andrew F. Davisa29578d2019-02-11 14:18:53 -06001448
1449 req.processor_id = proc_id;
1450 req.control_flags_set = control_flags_set;
1451 req.control_flags_clear = control_flags_clear;
1452
Andrew Davise0a676c2022-05-16 13:17:02 -05001453 ret = ti_sci_do_xfer(&xfer);
1454 if (ret != 0U) {
1455 ERROR("Transfer send failed (%d)\n", ret);
Andrew F. Davisa29578d2019-02-11 14:18:53 -06001456 return ret;
1457 }
1458
Andrew F. Davisa29578d2019-02-11 14:18:53 -06001459 return 0;
1460}
1461
1462/**
Andrew F. Davisd92fdfb2018-05-04 19:06:13 +00001463 * ti_sci_proc_auth_boot_image() - Authenticate and load image and then set the
1464 * processor configuration flags
1465 *
1466 * @proc_id: Processor ID this request is for
1467 * @cert_addr: Memory address at which payload image certificate is located
1468 *
1469 * Return: 0 if all goes well, else appropriate error message
1470 */
1471int ti_sci_proc_auth_boot_image(uint8_t proc_id, uint64_t cert_addr)
1472{
1473 struct ti_sci_msg_req_proc_auth_boot_image req;
1474 struct ti_sci_msg_hdr resp;
1475
1476 struct ti_sci_xfer xfer;
1477 int ret;
1478
Andrew Davisc39841f2023-01-10 12:34:20 -06001479 ret = ti_sci_setup_one_xfer(TISCI_MSG_PROC_AUTH_BOOT_IMAGE, 0,
Andrew F. Davisd92fdfb2018-05-04 19:06:13 +00001480 &req, sizeof(req),
1481 &resp, sizeof(resp),
1482 &xfer);
1483 if (ret) {
1484 ERROR("Message alloc failed (%d)\n", ret);
1485 return ret;
1486 }
1487
1488 req.processor_id = proc_id;
1489 req.cert_addr_low = cert_addr & TISCI_ADDR_LOW_MASK;
1490 req.cert_addr_high = (cert_addr & TISCI_ADDR_HIGH_MASK) >>
1491 TISCI_ADDR_HIGH_SHIFT;
1492
1493 ret = ti_sci_do_xfer(&xfer);
1494 if (ret) {
1495 ERROR("Transfer send failed (%d)\n", ret);
1496 return ret;
1497 }
1498
Andrew F. Davisd92fdfb2018-05-04 19:06:13 +00001499 return 0;
1500}
1501
1502/**
1503 * ti_sci_proc_get_boot_status() - Get the processor boot status
1504 *
1505 * @proc_id: Processor ID this request is for
1506 *
1507 * Return: 0 if all goes well, else appropriate error message
1508 */
1509int ti_sci_proc_get_boot_status(uint8_t proc_id, uint64_t *bv,
1510 uint32_t *cfg_flags,
1511 uint32_t *ctrl_flags,
1512 uint32_t *sts_flags)
1513{
1514 struct ti_sci_msg_req_get_proc_boot_status req;
1515 struct ti_sci_msg_resp_get_proc_boot_status resp;
1516
1517 struct ti_sci_xfer xfer;
1518 int ret;
1519
Andrew F. Davis06b30522019-02-11 13:44:31 -06001520 ret = ti_sci_setup_one_xfer(TISCI_MSG_GET_PROC_BOOT_STATUS, 0,
Andrew F. Davisd92fdfb2018-05-04 19:06:13 +00001521 &req, sizeof(req),
1522 &resp, sizeof(resp),
1523 &xfer);
1524 if (ret) {
1525 ERROR("Message alloc failed (%d)\n", ret);
1526 return ret;
1527 }
1528
1529 req.processor_id = proc_id;
1530
1531 ret = ti_sci_do_xfer(&xfer);
1532 if (ret) {
1533 ERROR("Transfer send failed (%d)\n", ret);
1534 return ret;
1535 }
1536
Andrew F. Davisd92fdfb2018-05-04 19:06:13 +00001537 *bv = (resp.bootvector_low & TISCI_ADDR_LOW_MASK) |
1538 (((uint64_t)resp.bootvector_high << TISCI_ADDR_HIGH_SHIFT) &
1539 TISCI_ADDR_HIGH_MASK);
1540 *cfg_flags = resp.config_flags;
1541 *ctrl_flags = resp.control_flags;
1542 *sts_flags = resp.status_flags;
1543
1544 return 0;
1545}
1546
1547/**
Andrew F. Davisb62cc1e2018-12-18 13:21:12 -06001548 * ti_sci_proc_wait_boot_status() - Wait for a processor boot status
1549 *
1550 * @proc_id: Processor ID this request is for
1551 * @num_wait_iterations Total number of iterations we will check before
1552 * we will timeout and give up
1553 * @num_match_iterations How many iterations should we have continued
1554 * status to account for status bits glitching.
1555 * This is to make sure that match occurs for
1556 * consecutive checks. This implies that the
1557 * worst case should consider that the stable
1558 * time should at the worst be num_wait_iterations
1559 * num_match_iterations to prevent timeout.
1560 * @delay_per_iteration_us Specifies how long to wait (in micro seconds)
1561 * between each status checks. This is the minimum
1562 * duration, and overhead of register reads and
1563 * checks are on top of this and can vary based on
1564 * varied conditions.
1565 * @delay_before_iterations_us Specifies how long to wait (in micro seconds)
1566 * before the very first check in the first
1567 * iteration of status check loop. This is the
1568 * minimum duration, and overhead of register
1569 * reads and checks are.
1570 * @status_flags_1_set_all_wait If non-zero, Specifies that all bits of the
1571 * status matching this field requested MUST be 1.
1572 * @status_flags_1_set_any_wait If non-zero, Specifies that at least one of the
1573 * bits matching this field requested MUST be 1.
1574 * @status_flags_1_clr_all_wait If non-zero, Specifies that all bits of the
1575 * status matching this field requested MUST be 0.
1576 * @status_flags_1_clr_any_wait If non-zero, Specifies that at least one of the
1577 * bits matching this field requested MUST be 0.
1578 *
1579 * Return: 0 if all goes well, else appropriate error message
1580 */
1581int ti_sci_proc_wait_boot_status(uint8_t proc_id, uint8_t num_wait_iterations,
1582 uint8_t num_match_iterations,
1583 uint8_t delay_per_iteration_us,
1584 uint8_t delay_before_iterations_us,
1585 uint32_t status_flags_1_set_all_wait,
1586 uint32_t status_flags_1_set_any_wait,
1587 uint32_t status_flags_1_clr_all_wait,
1588 uint32_t status_flags_1_clr_any_wait)
1589{
1590 struct ti_sci_msg_req_wait_proc_boot_status req;
1591 struct ti_sci_msg_hdr resp;
1592
1593 struct ti_sci_xfer xfer;
1594 int ret;
1595
Andrew F. Davis06b30522019-02-11 13:44:31 -06001596 ret = ti_sci_setup_one_xfer(TISCI_MSG_WAIT_PROC_BOOT_STATUS, 0,
Andrew F. Davisb62cc1e2018-12-18 13:21:12 -06001597 &req, sizeof(req),
1598 &resp, sizeof(resp),
1599 &xfer);
1600 if (ret) {
1601 ERROR("Message alloc failed (%d)\n", ret);
1602 return ret;
1603 }
1604
1605 req.processor_id = proc_id;
1606 req.num_wait_iterations = num_wait_iterations;
1607 req.num_match_iterations = num_match_iterations;
1608 req.delay_per_iteration_us = delay_per_iteration_us;
1609 req.delay_before_iterations_us = delay_before_iterations_us;
1610 req.status_flags_1_set_all_wait = status_flags_1_set_all_wait;
1611 req.status_flags_1_set_any_wait = status_flags_1_set_any_wait;
1612 req.status_flags_1_clr_all_wait = status_flags_1_clr_all_wait;
1613 req.status_flags_1_clr_any_wait = status_flags_1_clr_any_wait;
1614
1615 ret = ti_sci_do_xfer(&xfer);
1616 if (ret) {
1617 ERROR("Transfer send failed (%d)\n", ret);
1618 return ret;
1619 }
1620
Andrew F. Davisa29578d2019-02-11 14:18:53 -06001621 return 0;
1622}
1623
1624/**
1625 * ti_sci_proc_wait_boot_status_no_wait() - Wait for a processor boot status
1626 * without requesting or waiting for
1627 * a response.
1628 *
1629 * @proc_id: Processor ID this request is for
1630 * @num_wait_iterations Total number of iterations we will check before
1631 * we will timeout and give up
1632 * @num_match_iterations How many iterations should we have continued
1633 * status to account for status bits glitching.
1634 * This is to make sure that match occurs for
1635 * consecutive checks. This implies that the
1636 * worst case should consider that the stable
1637 * time should at the worst be num_wait_iterations
1638 * num_match_iterations to prevent timeout.
1639 * @delay_per_iteration_us Specifies how long to wait (in micro seconds)
1640 * between each status checks. This is the minimum
1641 * duration, and overhead of register reads and
1642 * checks are on top of this and can vary based on
1643 * varied conditions.
1644 * @delay_before_iterations_us Specifies how long to wait (in micro seconds)
1645 * before the very first check in the first
1646 * iteration of status check loop. This is the
1647 * minimum duration, and overhead of register
1648 * reads and checks are.
1649 * @status_flags_1_set_all_wait If non-zero, Specifies that all bits of the
1650 * status matching this field requested MUST be 1.
1651 * @status_flags_1_set_any_wait If non-zero, Specifies that at least one of the
1652 * bits matching this field requested MUST be 1.
1653 * @status_flags_1_clr_all_wait If non-zero, Specifies that all bits of the
1654 * status matching this field requested MUST be 0.
1655 * @status_flags_1_clr_any_wait If non-zero, Specifies that at least one of the
1656 * bits matching this field requested MUST be 0.
1657 *
1658 * Return: 0 if all goes well, else appropriate error message
1659 */
1660int ti_sci_proc_wait_boot_status_no_wait(uint8_t proc_id,
1661 uint8_t num_wait_iterations,
1662 uint8_t num_match_iterations,
1663 uint8_t delay_per_iteration_us,
1664 uint8_t delay_before_iterations_us,
1665 uint32_t status_flags_1_set_all_wait,
1666 uint32_t status_flags_1_set_any_wait,
1667 uint32_t status_flags_1_clr_all_wait,
1668 uint32_t status_flags_1_clr_any_wait)
1669{
1670 struct ti_sci_msg_req_wait_proc_boot_status req;
Andrew Davise0a676c2022-05-16 13:17:02 -05001671 struct ti_sci_xfer xfer;
Andrew F. Davisa29578d2019-02-11 14:18:53 -06001672 int ret;
1673
Manorit Chawdhry24993b52023-08-22 16:15:40 +05301674 ret = ti_sci_setup_one_xfer(TISCI_MSG_WAIT_PROC_BOOT_STATUS, 0,
Andrew Davise0a676c2022-05-16 13:17:02 -05001675 &req, sizeof(req),
1676 NULL, 0,
1677 &xfer);
1678 if (ret != 0U) {
1679 ERROR("Message alloc failed (%d)\n", ret);
1680 return ret;
1681 }
Andrew F. Davisa29578d2019-02-11 14:18:53 -06001682
1683 req.processor_id = proc_id;
1684 req.num_wait_iterations = num_wait_iterations;
1685 req.num_match_iterations = num_match_iterations;
1686 req.delay_per_iteration_us = delay_per_iteration_us;
1687 req.delay_before_iterations_us = delay_before_iterations_us;
1688 req.status_flags_1_set_all_wait = status_flags_1_set_all_wait;
1689 req.status_flags_1_set_any_wait = status_flags_1_set_any_wait;
1690 req.status_flags_1_clr_all_wait = status_flags_1_clr_all_wait;
1691 req.status_flags_1_clr_any_wait = status_flags_1_clr_any_wait;
1692
Andrew Davise0a676c2022-05-16 13:17:02 -05001693 ret = ti_sci_do_xfer(&xfer);
1694 if (ret != 0U) {
1695 ERROR("Transfer send failed (%d)\n", ret);
Andrew F. Davisa29578d2019-02-11 14:18:53 -06001696 return ret;
1697 }
1698
Andrew F. Davisb62cc1e2018-12-18 13:21:12 -06001699 return 0;
1700}
1701
1702/**
Dave Gerlach7a94ce82021-11-30 15:35:08 -06001703 * ti_sci_enter_sleep - Command to initiate system transition into suspend.
1704 *
1705 * @proc_id: Processor ID.
1706 * @mode: Low power mode to enter.
1707 * @core_resume_addr: Address that core should be
1708 * resumed from after low power transition.
1709 *
1710 * Return: 0 if all goes well, else appropriate error message
1711 */
1712int ti_sci_enter_sleep(uint8_t proc_id,
1713 uint8_t mode,
1714 uint64_t core_resume_addr)
1715{
1716 struct ti_sci_msg_req_enter_sleep req;
Andrew Davise0a676c2022-05-16 13:17:02 -05001717 struct ti_sci_xfer xfer;
Dave Gerlach7a94ce82021-11-30 15:35:08 -06001718 int ret;
1719
Manorit Chawdhry24993b52023-08-22 16:15:40 +05301720 ret = ti_sci_setup_one_xfer(TI_SCI_MSG_ENTER_SLEEP, 0,
Andrew Davise0a676c2022-05-16 13:17:02 -05001721 &req, sizeof(req),
1722 NULL, 0,
1723 &xfer);
1724 if (ret != 0U) {
1725 ERROR("Message alloc failed (%d)\n", ret);
1726 return ret;
Dave Gerlach7a94ce82021-11-30 15:35:08 -06001727 }
1728
Dave Gerlach7a94ce82021-11-30 15:35:08 -06001729 req.processor_id = proc_id;
1730 req.mode = mode;
1731 req.core_resume_lo = core_resume_addr & TISCI_ADDR_LOW_MASK;
1732 req.core_resume_hi = (core_resume_addr & TISCI_ADDR_HIGH_MASK) >>
1733 TISCI_ADDR_HIGH_SHIFT;
1734
Andrew Davise0a676c2022-05-16 13:17:02 -05001735 ret = ti_sci_do_xfer(&xfer);
1736 if (ret != 0U) {
1737 ERROR("Transfer send failed (%d)\n", ret);
Dave Gerlach7a94ce82021-11-30 15:35:08 -06001738 return ret;
1739 }
1740
Dave Gerlach7a94ce82021-11-30 15:35:08 -06001741 return 0;
1742}