blob: b211bdf60bf7163f8718fb152f6ca98035b47010 [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 *
5 * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
6 *
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>
16
17#include <common/debug.h>
Andrew F. Davisa513b2a2018-05-04 19:06:09 +000018#include <sec_proxy.h>
19
20#include "ti_sci_protocol.h"
21#include "ti_sci.h"
22
23/**
24 * struct ti_sci_desc - Description of SoC integration
25 * @host_id: Host identifier representing the compute entity
26 * @max_msg_size: Maximum size of data per message that can be handled
27 */
28struct ti_sci_desc {
29 uint8_t host_id;
30 int max_msg_size;
31};
32
33/**
34 * struct ti_sci_info - Structure representing a TI SCI instance
35 * @desc: SoC description for this instance
36 * @seq: Seq id used for verification for tx and rx message
37 */
38struct ti_sci_info {
39 const struct ti_sci_desc desc;
40 uint8_t seq;
41};
42
43static struct ti_sci_info info = {
44 .desc = {
45 .host_id = TI_SCI_HOST_ID,
46 .max_msg_size = TI_SCI_MAX_MESSAGE_SIZE,
47 },
48 .seq = 0x0a,
49};
50
51/**
52 * struct ti_sci_xfer - Structure representing a message flow
53 * @tx_message: Transmit message
54 * @rx_message: Receive message
55 */
56struct ti_sci_xfer {
57 struct k3_sec_proxy_msg tx_message;
58 struct k3_sec_proxy_msg rx_message;
59};
60
61/**
62 * ti_sci_setup_one_xfer() - Setup one message type
63 *
64 * @msg_type: Message type
65 * @msg_flags: Flag to set for the message
66 * @tx_buf: Buffer to be sent to mailbox channel
67 * @tx_message_size: transmit message size
68 * @rx_buf: Buffer to be received from mailbox channel
69 * @rx_message_size: receive message size
70 *
71 * Helper function which is used by various command functions that are
72 * exposed to clients of this driver for allocating a message traffic event.
73 *
74 * Return: 0 if all goes well, else appropriate error message
75 */
76static int ti_sci_setup_one_xfer(uint16_t msg_type, uint32_t msg_flags,
77 void *tx_buf,
78 size_t tx_message_size,
79 void *rx_buf,
80 size_t rx_message_size,
81 struct ti_sci_xfer *xfer)
82{
83 struct ti_sci_msg_hdr *hdr;
84
85 /* Ensure we have sane transfer sizes */
86 if (rx_message_size > info.desc.max_msg_size ||
87 tx_message_size > info.desc.max_msg_size ||
88 rx_message_size < sizeof(*hdr) ||
89 tx_message_size < sizeof(*hdr))
90 return -ERANGE;
91
92 info.seq++;
93
94 hdr = (struct ti_sci_msg_hdr *)tx_buf;
95 hdr->seq = info.seq;
96 hdr->type = msg_type;
97 hdr->host = info.desc.host_id;
98 hdr->flags = msg_flags;
99
100 xfer->tx_message.buf = tx_buf;
101 xfer->tx_message.len = tx_message_size;
102
103 xfer->rx_message.buf = rx_buf;
104 xfer->rx_message.len = rx_message_size;
105
106 return 0;
107}
108
109/**
110 * ti_sci_get_response() - Receive response from mailbox channel
111 *
112 * @xfer: Transfer to initiate and wait for response
113 * @chan: Channel to receive the response
114 *
115 * Return: 0 if all goes well, else appropriate error message
116 */
117static inline int ti_sci_get_response(struct ti_sci_xfer *xfer,
118 enum k3_sec_proxy_chan_id chan)
119{
120 struct k3_sec_proxy_msg *msg = &xfer->rx_message;
121 struct ti_sci_msg_hdr *hdr;
122 int ret;
123
124 /* Receive the response */
125 ret = k3_sec_proxy_recv(chan, msg);
126 if (ret) {
127 ERROR("Message receive failed (%d)\n", ret);
128 return ret;
129 }
130
131 /* msg is updated by Secure Proxy driver */
132 hdr = (struct ti_sci_msg_hdr *)msg->buf;
133
134 /* Sanity check for message response */
135 if (hdr->seq != info.seq) {
136 ERROR("Message for %d is not expected\n", hdr->seq);
137 return -EINVAL;
138 }
139
140 if (msg->len > info.desc.max_msg_size) {
141 ERROR("Unable to handle %lu xfer (max %d)\n",
142 msg->len, info.desc.max_msg_size);
143 return -EINVAL;
144 }
145
146 return 0;
147}
148
149/**
150 * ti_sci_do_xfer() - Do one transfer
151 *
152 * @xfer: Transfer to initiate and wait for response
153 *
154 * Return: 0 if all goes well, else appropriate error message
155 */
156static inline int ti_sci_do_xfer(struct ti_sci_xfer *xfer)
157{
158 struct k3_sec_proxy_msg *msg = &xfer->tx_message;
159 int ret;
160
161 /* Send the message */
162 ret = k3_sec_proxy_send(SP_HIGH_PRIORITY, msg);
163 if (ret) {
164 ERROR("Message sending failed (%d)\n", ret);
165 return ret;
166 }
167
168 ret = ti_sci_get_response(xfer, SP_RESPONSE);
169 if (ret) {
170 ERROR("Failed to get response (%d)\n", ret);
171 return ret;
172 }
173
174 return 0;
175}
176
177/**
178 * ti_sci_get_revision() - Get the revision of the SCI entity
179 *
180 * Updates the SCI information in the internal data structure.
181 *
182 * Return: 0 if all goes well, else appropriate error message
183 */
184int ti_sci_get_revision(struct ti_sci_msg_resp_version *rev_info)
185{
186 struct ti_sci_msg_hdr hdr;
187 struct ti_sci_xfer xfer;
188 int ret;
189
190 ret = ti_sci_setup_one_xfer(TI_SCI_MSG_VERSION, 0x0,
191 &hdr, sizeof(hdr),
192 rev_info, sizeof(*rev_info),
193 &xfer);
194 if (ret) {
195 ERROR("Message alloc failed (%d)\n", ret);
196 return ret;
197 }
198
199 ret = ti_sci_do_xfer(&xfer);
200 if (ret) {
201 ERROR("Transfer send failed (%d)\n", ret);
202 return ret;
203 }
204
205 return 0;
206}
207
208/**
Andrew F. Davis4f2a0552018-05-04 19:06:10 +0000209 * ti_sci_is_response_ack() - Generic ACK/NACK message check
210 *
211 * @r: pointer to response buffer
212 *
213 * Return: true if the response was an ACK, else returns false
214 */
215static inline bool ti_sci_is_response_ack(void *r)
216{
217 struct ti_sci_msg_hdr *hdr = r;
218
219 return hdr->flags & TI_SCI_FLAG_RESP_GENERIC_ACK ? true : false;
220}
221
222/**
223 * ti_sci_device_set_state() - Set device state
224 *
225 * @id: Device identifier
226 * @flags: flags to setup for the device
227 * @state: State to move the device to
228 *
229 * Return: 0 if all goes well, else appropriate error message
230 */
231int ti_sci_device_set_state(uint32_t id, uint32_t flags, uint8_t state)
232{
233 struct ti_sci_msg_req_set_device_state req;
234 struct ti_sci_msg_hdr resp;
235
236 struct ti_sci_xfer xfer;
237 int ret;
238
239 ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SET_DEVICE_STATE,
240 flags | TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
241 &req, sizeof(req),
242 &resp, sizeof(resp),
243 &xfer);
244 if (ret) {
245 ERROR("Message alloc failed (%d)\n", ret);
246 return ret;
247 }
248
249 req.id = id;
250 req.state = state;
251
252 ret = ti_sci_do_xfer(&xfer);
253 if (ret) {
254 ERROR("Transfer send failed (%d)\n", ret);
255 return ret;
256 }
257
258 if (!ti_sci_is_response_ack(&resp))
259 return -ENODEV;
260
261 return 0;
262}
263
264/**
265 * ti_sci_device_get_state() - Get device state
266 *
267 * @id: Device Identifier
268 * @clcnt: Pointer to Context Loss Count
269 * @resets: pointer to resets
270 * @p_state: pointer to p_state
271 * @c_state: pointer to c_state
272 *
273 * Return: 0 if all goes well, else appropriate error message
274 */
275int ti_sci_device_get_state(uint32_t id, uint32_t *clcnt, uint32_t *resets,
276 uint8_t *p_state, uint8_t *c_state)
277{
278 struct ti_sci_msg_req_get_device_state req;
279 struct ti_sci_msg_resp_get_device_state resp;
280
281 struct ti_sci_xfer xfer;
282 int ret;
283
284 if (!clcnt && !resets && !p_state && !c_state)
285 return -EINVAL;
286
287 ret = ti_sci_setup_one_xfer(TI_SCI_MSG_GET_DEVICE_STATE, 0,
288 &req, sizeof(req),
289 &resp, sizeof(resp),
290 &xfer);
291 if (ret) {
292 ERROR("Message alloc failed (%d)\n", ret);
293 return ret;
294 }
295
296 req.id = id;
297
298 ret = ti_sci_do_xfer(&xfer);
299 if (ret) {
300 ERROR("Transfer send failed (%d)\n", ret);
301 return ret;
302 }
303
304 if (!ti_sci_is_response_ack(&resp))
305 return -ENODEV;
306
307 if (clcnt)
308 *clcnt = resp.context_loss_count;
309 if (resets)
310 *resets = resp.resets;
311 if (p_state)
312 *p_state = resp.programmed_state;
313 if (c_state)
314 *c_state = resp.current_state;
315
316 return 0;
317}
318
319/**
320 * ti_sci_device_get() - Request for device managed by TISCI
321 *
322 * @id: Device Identifier
323 *
324 * Request for the device - NOTE: the client MUST maintain integrity of
325 * usage count by balancing get_device with put_device. No refcounting is
326 * managed by driver for that purpose.
327 *
328 * NOTE: The request is for exclusive access for the processor.
329 *
330 * Return: 0 if all goes well, else appropriate error message
331 */
332int ti_sci_device_get(uint32_t id)
333{
334 return ti_sci_device_set_state(id,
335 MSG_FLAG_DEVICE_EXCLUSIVE,
336 MSG_DEVICE_SW_STATE_ON);
337}
338
339/**
340 * ti_sci_device_idle() - Idle a device managed by TISCI
341 *
342 * @id: Device Identifier
343 *
344 * Request for the device - NOTE: the client MUST maintain integrity of
345 * usage count by balancing get_device with put_device. No refcounting is
346 * managed by driver for that purpose.
347 *
348 * Return: 0 if all goes well, else appropriate error message
349 */
350int ti_sci_device_idle(uint32_t id)
351{
352 return ti_sci_device_set_state(id,
353 MSG_FLAG_DEVICE_EXCLUSIVE,
354 MSG_DEVICE_SW_STATE_RETENTION);
355}
356
357/**
358 * ti_sci_device_put() - Release a device managed by TISCI
359 *
360 * @id: Device Identifier
361 *
362 * Request for the device - NOTE: the client MUST maintain integrity of
363 * usage count by balancing get_device with put_device. No refcounting is
364 * managed by driver for that purpose.
365 *
366 * Return: 0 if all goes well, else appropriate error message
367 */
368int ti_sci_device_put(uint32_t id)
369{
370 return ti_sci_device_set_state(id, 0, MSG_DEVICE_SW_STATE_AUTO_OFF);
371}
372
373/**
374 * ti_sci_device_is_valid() - Is the device valid
375 *
376 * @id: Device Identifier
377 *
378 * Return: 0 if all goes well and the device ID is valid, else return
379 * appropriate error
380 */
381int ti_sci_device_is_valid(uint32_t id)
382{
383 uint8_t unused;
384
385 /* check the device state which will also tell us if the ID is valid */
386 return ti_sci_device_get_state(id, NULL, NULL, NULL, &unused);
387}
388
389/**
390 * ti_sci_device_get_clcnt() - Get context loss counter
391 *
392 * @id: Device Identifier
393 * @count: Pointer to Context Loss counter to populate
394 *
395 * Return: 0 if all goes well, else appropriate error message
396 */
397int ti_sci_device_get_clcnt(uint32_t id, uint32_t *count)
398{
399 return ti_sci_device_get_state(id, count, NULL, NULL, NULL);
400}
401
402/**
403 * ti_sci_device_is_idle() - Check if the device is requested to be idle
404 *
405 * @id: Device Identifier
406 * @r_state: true if requested to be idle
407 *
408 * Return: 0 if all goes well, else appropriate error message
409 */
410int ti_sci_device_is_idle(uint32_t id, bool *r_state)
411{
412 int ret;
413 uint8_t state;
414
415 if (!r_state)
416 return -EINVAL;
417
418 ret = ti_sci_device_get_state(id, NULL, NULL, &state, NULL);
419 if (ret)
420 return ret;
421
422 *r_state = (state == MSG_DEVICE_SW_STATE_RETENTION);
423
424 return 0;
425}
426
427/**
428 * ti_sci_device_is_stop() - Check if the device is requested to be stopped
429 *
430 * @id: Device Identifier
431 * @r_state: true if requested to be stopped
432 * @curr_state: true if currently stopped
433 *
434 * Return: 0 if all goes well, else appropriate error message
435 */
436int ti_sci_device_is_stop(uint32_t id, bool *r_state, bool *curr_state)
437{
438 int ret;
439 uint8_t p_state, c_state;
440
441 if (!r_state && !curr_state)
442 return -EINVAL;
443
444 ret = ti_sci_device_get_state(id, NULL, NULL, &p_state, &c_state);
445 if (ret)
446 return ret;
447
448 if (r_state)
449 *r_state = (p_state == MSG_DEVICE_SW_STATE_AUTO_OFF);
450 if (curr_state)
451 *curr_state = (c_state == MSG_DEVICE_HW_STATE_OFF);
452
453 return 0;
454}
455
456/**
457 * ti_sci_device_is_on() - Check if the device is requested to be ON
458 *
459 * @id: Device Identifier
460 * @r_state: true if requested to be ON
461 * @curr_state: true if currently ON and active
462 *
463 * Return: 0 if all goes well, else appropriate error message
464 */
465int ti_sci_device_is_on(uint32_t id, bool *r_state, bool *curr_state)
466{
467 int ret;
468 uint8_t p_state, c_state;
469
470 if (!r_state && !curr_state)
471 return -EINVAL;
472
473 ret =
474 ti_sci_device_get_state(id, NULL, NULL, &p_state, &c_state);
475 if (ret)
476 return ret;
477
478 if (r_state)
479 *r_state = (p_state == MSG_DEVICE_SW_STATE_ON);
480 if (curr_state)
481 *curr_state = (c_state == MSG_DEVICE_HW_STATE_ON);
482
483 return 0;
484}
485
486/**
487 * ti_sci_device_is_trans() - Check if the device is currently transitioning
488 *
489 * @id: Device Identifier
490 * @curr_state: true if currently transitioning
491 *
492 * Return: 0 if all goes well, else appropriate error message
493 */
494int ti_sci_device_is_trans(uint32_t id, bool *curr_state)
495{
496 int ret;
497 uint8_t state;
498
499 if (!curr_state)
500 return -EINVAL;
501
502 ret = ti_sci_device_get_state(id, NULL, NULL, NULL, &state);
503 if (ret)
504 return ret;
505
506 *curr_state = (state == MSG_DEVICE_HW_STATE_TRANS);
507
508 return 0;
509}
510
511/**
512 * ti_sci_device_set_resets() - Set resets for device managed by TISCI
513 *
514 * @id: Device Identifier
515 * @reset_state: Device specific reset bit field
516 *
517 * Return: 0 if all goes well, else appropriate error message
518 */
519int ti_sci_device_set_resets(uint32_t id, uint32_t reset_state)
520{
521 struct ti_sci_msg_req_set_device_resets req;
522 struct ti_sci_msg_hdr resp;
523
524 struct ti_sci_xfer xfer;
525 int ret;
526
527 ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SET_DEVICE_RESETS,
528 TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
529 &req, sizeof(req),
530 &resp, sizeof(resp),
531 &xfer);
532 if (ret) {
533 ERROR("Message alloc failed (%d)\n", ret);
534 return ret;
535 }
536
537 req.id = id;
538 req.resets = reset_state;
539
540 ret = ti_sci_do_xfer(&xfer);
541 if (ret) {
542 ERROR("Transfer send failed (%d)\n", ret);
543 return ret;
544 }
545
546 if (!ti_sci_is_response_ack(&resp))
547 return -ENODEV;
548
549 return 0;
550}
551
552/**
553 * ti_sci_device_get_resets() - Get reset state for device managed by TISCI
554 *
555 * @id: Device Identifier
556 * @reset_state: Pointer to reset state to populate
557 *
558 * Return: 0 if all goes well, else appropriate error message
559 */
560int ti_sci_device_get_resets(uint32_t id, uint32_t *reset_state)
561{
562 return ti_sci_device_get_state(id, NULL, reset_state, NULL, NULL);
563}
564
565/**
Andrew F. Davisdc08adf2018-05-04 19:06:11 +0000566 * ti_sci_clock_set_state() - Set clock state helper
567 *
568 * @dev_id: Device identifier this request is for
569 * @clk_id: Clock identifier for the device for this request,
570 * Each device has its own set of clock inputs, This indexes
571 * which clock input to modify
572 * @flags: Header flags as needed
573 * @state: State to request for the clock
574 *
575 * Return: 0 if all goes well, else appropriate error message
576 */
577int ti_sci_clock_set_state(uint32_t dev_id, uint8_t clk_id,
578 uint32_t flags, uint8_t state)
579{
580 struct ti_sci_msg_req_set_clock_state req;
581 struct ti_sci_msg_hdr resp;
582
583 struct ti_sci_xfer xfer;
584 int ret;
585
586 ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SET_CLOCK_STATE,
587 flags | TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
588 &req, sizeof(req),
589 &resp, sizeof(resp),
590 &xfer);
591 if (ret) {
592 ERROR("Message alloc failed (%d)\n", ret);
593 return ret;
594 }
595
596 req.dev_id = dev_id;
597 req.clk_id = clk_id;
598 req.request_state = state;
599
600 ret = ti_sci_do_xfer(&xfer);
601 if (ret) {
602 ERROR("Transfer send failed (%d)\n", ret);
603 return ret;
604 }
605
606 if (!ti_sci_is_response_ack(&resp))
607 return -ENODEV;
608
609 return 0;
610}
611
612/**
613 * ti_sci_clock_get_state() - Get clock state helper
614 *
615 * @dev_id: Device identifier this request is for
616 * @clk_id: Clock identifier for the device for this request.
617 * Each device has its own set of clock inputs. This indexes
618 * which clock input to modify.
619 * @programmed_state: State requested for clock to move to
620 * @current_state: State that the clock is currently in
621 *
622 * Return: 0 if all goes well, else appropriate error message
623 */
624int ti_sci_clock_get_state(uint32_t dev_id, uint8_t clk_id,
625 uint8_t *programmed_state,
626 uint8_t *current_state)
627{
628 struct ti_sci_msg_req_get_clock_state req;
629 struct ti_sci_msg_resp_get_clock_state resp;
630
631 struct ti_sci_xfer xfer;
632 int ret;
633
634 if (!programmed_state && !current_state)
635 return -EINVAL;
636
637 ret = ti_sci_setup_one_xfer(TI_SCI_MSG_GET_CLOCK_STATE,
638 TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
639 &req, sizeof(req),
640 &resp, sizeof(resp),
641 &xfer);
642 if (ret) {
643 ERROR("Message alloc failed (%d)\n", ret);
644 return ret;
645 }
646
647 req.dev_id = dev_id;
648 req.clk_id = clk_id;
649
650 ret = ti_sci_do_xfer(&xfer);
651 if (ret) {
652 ERROR("Transfer send failed (%d)\n", ret);
653 return ret;
654 }
655
656 if (!ti_sci_is_response_ack(&resp))
657 return -ENODEV;
658
659 if (programmed_state)
660 *programmed_state = resp.programmed_state;
661 if (current_state)
662 *current_state = resp.current_state;
663
664 return 0;
665}
666
667/**
668 * ti_sci_clock_get() - Get control of a clock from TI SCI
669
670 * @dev_id: Device identifier this request is for
671 * @clk_id: Clock identifier for the device for this request.
672 * Each device has its own set of clock inputs. This indexes
673 * which clock input to modify.
674 * @needs_ssc: 'true' iff Spread Spectrum clock is desired
675 * @can_change_freq: 'true' iff frequency change is desired
676 * @enable_input_term: 'true' iff input termination is desired
677 *
678 * Return: 0 if all goes well, else appropriate error message
679 */
680int ti_sci_clock_get(uint32_t dev_id, uint8_t clk_id,
681 bool needs_ssc, bool can_change_freq,
682 bool enable_input_term)
683{
684 uint32_t flags = 0;
685
686 flags |= needs_ssc ? MSG_FLAG_CLOCK_ALLOW_SSC : 0;
687 flags |= can_change_freq ? MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE : 0;
688 flags |= enable_input_term ? MSG_FLAG_CLOCK_INPUT_TERM : 0;
689
690 return ti_sci_clock_set_state(dev_id, clk_id, flags,
691 MSG_CLOCK_SW_STATE_REQ);
692}
693
694/**
695 * ti_sci_clock_idle() - Idle a clock which is in our control
696
697 * @dev_id: Device identifier this request is for
698 * @clk_id: Clock identifier for the device for this request.
699 * Each device has its own set of clock inputs. This indexes
700 * which clock input to modify.
701 *
702 * NOTE: This clock must have been requested by get_clock previously.
703 *
704 * Return: 0 if all goes well, else appropriate error message
705 */
706int ti_sci_clock_idle(uint32_t dev_id, uint8_t clk_id)
707{
708 return ti_sci_clock_set_state(dev_id, clk_id, 0,
709 MSG_CLOCK_SW_STATE_UNREQ);
710}
711
712/**
713 * ti_sci_clock_put() - Release a clock from our control
714 *
715 * @dev_id: Device identifier this request is for
716 * @clk_id: Clock identifier for the device for this request.
717 * Each device has its own set of clock inputs. This indexes
718 * which clock input to modify.
719 *
720 * NOTE: This clock must have been requested by get_clock previously.
721 *
722 * Return: 0 if all goes well, else appropriate error message
723 */
724int ti_sci_clock_put(uint32_t dev_id, uint8_t clk_id)
725{
726 return ti_sci_clock_set_state(dev_id, clk_id, 0,
727 MSG_CLOCK_SW_STATE_AUTO);
728}
729
730/**
731 * ti_sci_clock_is_auto() - Is the clock being auto managed
732 *
733 * @dev_id: Device identifier this request is for
734 * @clk_id: Clock identifier for the device for this request.
735 * Each device has its own set of clock inputs. This indexes
736 * which clock input to modify.
737 * @req_state: state indicating if the clock is auto managed
738 *
739 * Return: 0 if all goes well, else appropriate error message
740 */
741int ti_sci_clock_is_auto(uint32_t dev_id, uint8_t clk_id, bool *req_state)
742{
743 uint8_t state = 0;
744 int ret;
745
746 if (!req_state)
747 return -EINVAL;
748
749 ret = ti_sci_clock_get_state(dev_id, clk_id, &state, NULL);
750 if (ret)
751 return ret;
752
753 *req_state = (state == MSG_CLOCK_SW_STATE_AUTO);
754
755 return 0;
756}
757
758/**
759 * ti_sci_clock_is_on() - Is the clock ON
760 *
761 * @dev_id: Device identifier this request is for
762 * @clk_id: Clock identifier for the device for this request.
763 * Each device has its own set of clock inputs. This indexes
764 * which clock input to modify.
765 * @req_state: state indicating if the clock is managed by us and enabled
766 * @curr_state: state indicating if the clock is ready for operation
767 *
768 * Return: 0 if all goes well, else appropriate error message
769 */
770int ti_sci_clock_is_on(uint32_t dev_id, uint8_t clk_id,
771 bool *req_state, bool *curr_state)
772{
773 uint8_t c_state = 0, r_state = 0;
774 int ret;
775
776 if (!req_state && !curr_state)
777 return -EINVAL;
778
779 ret = ti_sci_clock_get_state(dev_id, clk_id, &r_state, &c_state);
780 if (ret)
781 return ret;
782
783 if (req_state)
784 *req_state = (r_state == MSG_CLOCK_SW_STATE_REQ);
785 if (curr_state)
786 *curr_state = (c_state == MSG_CLOCK_HW_STATE_READY);
787
788 return 0;
789}
790
791/**
792 * ti_sci_clock_is_off() - Is the clock OFF
793 *
794 * @dev_id: Device identifier this request is for
795 * @clk_id: Clock identifier for the device for this request.
796 * Each device has its own set of clock inputs. This indexes
797 * which clock input to modify.
798 * @req_state: state indicating if the clock is managed by us and disabled
799 * @curr_state: state indicating if the clock is NOT ready for operation
800 *
801 * Return: 0 if all goes well, else appropriate error message
802 */
803int ti_sci_clock_is_off(uint32_t dev_id, uint8_t clk_id,
804 bool *req_state, bool *curr_state)
805{
806 uint8_t c_state = 0, r_state = 0;
807 int ret;
808
809 if (!req_state && !curr_state)
810 return -EINVAL;
811
812 ret = ti_sci_clock_get_state(dev_id, clk_id, &r_state, &c_state);
813 if (ret)
814 return ret;
815
816 if (req_state)
817 *req_state = (r_state == MSG_CLOCK_SW_STATE_UNREQ);
818 if (curr_state)
819 *curr_state = (c_state == MSG_CLOCK_HW_STATE_NOT_READY);
820
821 return 0;
822}
823
824/**
825 * ti_sci_clock_set_parent() - Set the clock source of a specific device clock
826 *
827 * @dev_id: Device identifier this request is for
828 * @clk_id: Clock identifier for the device for this request.
829 * Each device has its own set of clock inputs. This indexes
830 * which clock input to modify.
831 * @parent_id: Parent clock identifier to set
832 *
833 * Return: 0 if all goes well, else appropriate error message
834 */
835int ti_sci_clock_set_parent(uint32_t dev_id, uint8_t clk_id, uint8_t parent_id)
836{
837 struct ti_sci_msg_req_set_clock_parent req;
838 struct ti_sci_msg_hdr resp;
839
840 struct ti_sci_xfer xfer;
841 int ret;
842
843 ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SET_CLOCK_PARENT,
844 TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
845 &req, sizeof(req),
846 &resp, sizeof(resp),
847 &xfer);
848 if (ret) {
849 ERROR("Message alloc failed (%d)\n", ret);
850 return ret;
851 }
852
853 req.dev_id = dev_id;
854 req.clk_id = clk_id;
855 req.parent_id = parent_id;
856
857 ret = ti_sci_do_xfer(&xfer);
858 if (ret) {
859 ERROR("Transfer send failed (%d)\n", ret);
860 return ret;
861 }
862
863 if (!ti_sci_is_response_ack(&resp))
864 return -ENODEV;
865
866 return 0;
867}
868
869/**
870 * ti_sci_clock_get_parent() - Get current parent clock source
871 *
872 * @dev_id: Device identifier this request is for
873 * @clk_id: Clock identifier for the device for this request.
874 * Each device has its own set of clock inputs. This indexes
875 * which clock input to modify.
876 * @parent_id: Current clock parent
877 *
878 * Return: 0 if all goes well, else appropriate error message
879 */
880int ti_sci_clock_get_parent(uint32_t dev_id, uint8_t clk_id, uint8_t *parent_id)
881{
882 struct ti_sci_msg_req_get_clock_parent req;
883 struct ti_sci_msg_resp_get_clock_parent resp;
884
885 struct ti_sci_xfer xfer;
886 int ret;
887
888 ret = ti_sci_setup_one_xfer(TI_SCI_MSG_GET_CLOCK_PARENT,
889 TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
890 &req, sizeof(req),
891 &resp, sizeof(resp),
892 &xfer);
893 if (ret) {
894 ERROR("Message alloc failed (%d)\n", ret);
895 return ret;
896 }
897
898 req.dev_id = dev_id;
899 req.clk_id = clk_id;
900
901 ret = ti_sci_do_xfer(&xfer);
902 if (ret) {
903 ERROR("Transfer send failed (%d)\n", ret);
904 return ret;
905 }
906
907 if (!ti_sci_is_response_ack(&resp))
908 return -ENODEV;
909
910 *parent_id = resp.parent_id;
911
912 return 0;
913}
914
915/**
916 * ti_sci_clock_get_num_parents() - Get num parents of the current clk source
917 *
918 * @dev_id: Device identifier this request is for
919 * @clk_id: Clock identifier for the device for this request.
920 * Each device has its own set of clock inputs. This indexes
921 * which clock input to modify.
922 * @num_parents: Returns he number of parents to the current clock.
923 *
924 * Return: 0 if all goes well, else appropriate error message
925 */
926int ti_sci_clock_get_num_parents(uint32_t dev_id, uint8_t clk_id,
927 uint8_t *num_parents)
928{
929 struct ti_sci_msg_req_get_clock_num_parents req;
930 struct ti_sci_msg_resp_get_clock_num_parents resp;
931
932 struct ti_sci_xfer xfer;
933 int ret;
934
935 ret = ti_sci_setup_one_xfer(TI_SCI_MSG_GET_NUM_CLOCK_PARENTS,
936 TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
937 &req, sizeof(req),
938 &resp, sizeof(resp),
939 &xfer);
940 if (ret) {
941 ERROR("Message alloc failed (%d)\n", ret);
942 return ret;
943 }
944
945 req.dev_id = dev_id;
946 req.clk_id = clk_id;
947
948 ret = ti_sci_do_xfer(&xfer);
949 if (ret) {
950 ERROR("Transfer send failed (%d)\n", ret);
951 return ret;
952 }
953
954 if (!ti_sci_is_response_ack(&resp))
955 return -ENODEV;
956
957 *num_parents = resp.num_parents;
958
959 return 0;
960}
961
962/**
963 * ti_sci_clock_get_match_freq() - Find a good match for frequency
964 *
965 * @dev_id: Device identifier this request is for
966 * @clk_id: Clock identifier for the device for this request.
967 * Each device has its own set of clock inputs. This indexes
968 * which clock input to modify.
969 * @min_freq: The minimum allowable frequency in Hz. This is the minimum
970 * allowable programmed frequency and does not account for clock
971 * tolerances and jitter.
972 * @target_freq: The target clock frequency in Hz. A frequency will be
973 * processed as close to this target frequency as possible.
974 * @max_freq: The maximum allowable frequency in Hz. This is the maximum
975 * allowable programmed frequency and does not account for clock
976 * tolerances and jitter.
977 * @match_freq: Frequency match in Hz response.
978 *
979 * Return: 0 if all goes well, else appropriate error message
980 */
981int ti_sci_clock_get_match_freq(uint32_t dev_id, uint8_t clk_id,
982 uint64_t min_freq, uint64_t target_freq,
983 uint64_t max_freq, uint64_t *match_freq)
984{
985 struct ti_sci_msg_req_query_clock_freq req;
986 struct ti_sci_msg_resp_query_clock_freq resp;
987
988 struct ti_sci_xfer xfer;
989 int ret;
990
991 ret = ti_sci_setup_one_xfer(TI_SCI_MSG_QUERY_CLOCK_FREQ,
992 TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
993 &req, sizeof(req),
994 &resp, sizeof(resp),
995 &xfer);
996 if (ret) {
997 ERROR("Message alloc failed (%d)\n", ret);
998 return ret;
999 }
1000
1001 req.dev_id = dev_id;
1002 req.clk_id = clk_id;
1003 req.min_freq_hz = min_freq;
1004 req.target_freq_hz = target_freq;
1005 req.max_freq_hz = max_freq;
1006
1007 ret = ti_sci_do_xfer(&xfer);
1008 if (ret) {
1009 ERROR("Transfer send failed (%d)\n", ret);
1010 return ret;
1011 }
1012
1013 if (!ti_sci_is_response_ack(&resp))
1014 return -ENODEV;
1015
1016 *match_freq = resp.freq_hz;
1017
1018 return 0;
1019}
1020
1021/**
1022 * ti_sci_clock_set_freq() - Set a frequency for clock
1023 *
1024 * @dev_id: Device identifier this request is for
1025 * @clk_id: Clock identifier for the device for this request.
1026 * Each device has its own set of clock inputs. This indexes
1027 * which clock input to modify.
1028 * @min_freq: The minimum allowable frequency in Hz. This is the minimum
1029 * allowable programmed frequency and does not account for clock
1030 * tolerances and jitter.
1031 * @target_freq: The target clock frequency in Hz. A frequency will be
1032 * processed as close to this target frequency as possible.
1033 * @max_freq: The maximum allowable frequency in Hz. This is the maximum
1034 * allowable programmed frequency and does not account for clock
1035 * tolerances and jitter.
1036 *
1037 * Return: 0 if all goes well, else appropriate error message
1038 */
1039int ti_sci_clock_set_freq(uint32_t dev_id, uint8_t clk_id, uint64_t min_freq,
1040 uint64_t target_freq, uint64_t max_freq)
1041{
1042 struct ti_sci_msg_req_set_clock_freq req;
1043 struct ti_sci_msg_hdr resp;
1044
1045 struct ti_sci_xfer xfer;
1046 int ret;
1047
1048 ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SET_CLOCK_FREQ,
1049 TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1050 &req, sizeof(req),
1051 &resp, sizeof(resp),
1052 &xfer);
1053 if (ret) {
1054 ERROR("Message alloc failed (%d)\n", ret);
1055 return ret;
1056 }
1057 req.dev_id = dev_id;
1058 req.clk_id = clk_id;
1059 req.min_freq_hz = min_freq;
1060 req.target_freq_hz = target_freq;
1061 req.max_freq_hz = max_freq;
1062
1063 ret = ti_sci_do_xfer(&xfer);
1064 if (ret) {
1065 ERROR("Transfer send failed (%d)\n", ret);
1066 return ret;
1067 }
1068
1069 if (!ti_sci_is_response_ack(&resp))
1070 return -ENODEV;
1071
1072 return 0;
1073}
1074
1075/**
1076 * ti_sci_clock_get_freq() - Get current frequency
1077 *
1078 * @dev_id: Device identifier this request is for
1079 * @clk_id: Clock identifier for the device for this request.
1080 * Each device has its own set of clock inputs. This indexes
1081 * which clock input to modify.
1082 * @freq: Currently frequency in Hz
1083 *
1084 * Return: 0 if all goes well, else appropriate error message
1085 */
1086int ti_sci_clock_get_freq(uint32_t dev_id, uint8_t clk_id, uint64_t *freq)
1087{
1088 struct ti_sci_msg_req_get_clock_freq req;
1089 struct ti_sci_msg_resp_get_clock_freq resp;
1090
1091 struct ti_sci_xfer xfer;
1092 int ret;
1093
1094 ret = ti_sci_setup_one_xfer(TI_SCI_MSG_GET_CLOCK_FREQ,
1095 TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1096 &req, sizeof(req),
1097 &resp, sizeof(resp),
1098 &xfer);
1099 if (ret) {
1100 ERROR("Message alloc failed (%d)\n", ret);
1101 return ret;
1102 }
1103
1104 req.dev_id = dev_id;
1105 req.clk_id = clk_id;
1106
1107 ret = ti_sci_do_xfer(&xfer);
1108 if (ret) {
1109 ERROR("Transfer send failed (%d)\n", ret);
1110 return ret;
1111 }
1112
1113 if (!ti_sci_is_response_ack(&resp))
1114 return -ENODEV;
1115
1116 *freq = resp.freq_hz;
1117
1118 return 0;
1119}
1120
1121/**
Andrew F. Davis0d449302018-05-04 19:06:12 +00001122 * ti_sci_core_reboot() - Command to request system reset
1123 *
1124 * Return: 0 if all goes well, else appropriate error message
1125 */
1126int ti_sci_core_reboot(void)
1127{
1128 struct ti_sci_msg_req_reboot req;
1129 struct ti_sci_msg_hdr resp;
1130
1131 struct ti_sci_xfer xfer;
1132 int ret;
1133
1134 ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SYS_RESET,
1135 TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1136 &req, sizeof(req),
1137 &resp, sizeof(resp),
1138 &xfer);
1139 if (ret) {
1140 ERROR("Message alloc failed (%d)\n", ret);
1141 return ret;
1142 }
1143
1144 ret = ti_sci_do_xfer(&xfer);
1145 if (ret) {
1146 ERROR("Transfer send failed (%d)\n", ret);
1147 return ret;
1148 }
1149
1150 if (!ti_sci_is_response_ack(&resp))
1151 return -ENODEV;
1152
1153 return 0;
1154}
1155
1156/**
Andrew F. Davisd92fdfb2018-05-04 19:06:13 +00001157 * ti_sci_proc_request() - Request a physical processor control
1158 *
1159 * @proc_id: Processor ID this request is for
1160 *
1161 * Return: 0 if all goes well, else appropriate error message
1162 */
1163int ti_sci_proc_request(uint8_t proc_id)
1164{
1165 struct ti_sci_msg_req_proc_request req;
1166 struct ti_sci_msg_hdr resp;
1167
1168 struct ti_sci_xfer xfer;
1169 int ret;
1170
1171 ret = ti_sci_setup_one_xfer(TISCI_MSG_PROC_REQUEST,
1172 TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1173 &req, sizeof(req),
1174 &resp, sizeof(resp),
1175 &xfer);
1176 if (ret) {
1177 ERROR("Message alloc failed (%d)\n", ret);
1178 return ret;
1179 }
1180
1181 req.processor_id = proc_id;
1182
1183 ret = ti_sci_do_xfer(&xfer);
1184 if (ret) {
1185 ERROR("Transfer send failed (%d)\n", ret);
1186 return ret;
1187 }
1188
1189 if (!ti_sci_is_response_ack(&resp))
1190 return -ENODEV;
1191
1192 return 0;
1193}
1194
1195/**
1196 * ti_sci_proc_release() - Release a physical processor control
1197 *
1198 * @proc_id: Processor ID this request is for
1199 *
1200 * Return: 0 if all goes well, else appropriate error message
1201 */
1202int ti_sci_proc_release(uint8_t proc_id)
1203{
1204 struct ti_sci_msg_req_proc_release req;
1205 struct ti_sci_msg_hdr resp;
1206
1207 struct ti_sci_xfer xfer;
1208 int ret;
1209
1210 ret = ti_sci_setup_one_xfer(TISCI_MSG_PROC_RELEASE,
1211 TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1212 &req, sizeof(req),
1213 &resp, sizeof(resp),
1214 &xfer);
1215 if (ret) {
1216 ERROR("Message alloc failed (%d)\n", ret);
1217 return ret;
1218 }
1219
1220 req.processor_id = proc_id;
1221
1222 ret = ti_sci_do_xfer(&xfer);
1223 if (ret) {
1224 ERROR("Transfer send failed (%d)\n", ret);
1225 return ret;
1226 }
1227
1228 if (!ti_sci_is_response_ack(&resp))
1229 return -ENODEV;
1230
1231 return 0;
1232}
1233
1234/**
1235 * ti_sci_proc_handover() - Handover a physical processor control to a host in
1236 * the processor's access control list.
1237 *
1238 * @proc_id: Processor ID this request is for
1239 * @host_id: Host ID to get the control of the processor
1240 *
1241 * Return: 0 if all goes well, else appropriate error message
1242 */
1243int ti_sci_proc_handover(uint8_t proc_id, uint8_t host_id)
1244{
1245 struct ti_sci_msg_req_proc_handover req;
1246 struct ti_sci_msg_hdr resp;
1247
1248 struct ti_sci_xfer xfer;
1249 int ret;
1250
1251 ret = ti_sci_setup_one_xfer(TISCI_MSG_PROC_HANDOVER,
1252 TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1253 &req, sizeof(req),
1254 &resp, sizeof(resp),
1255 &xfer);
1256 if (ret) {
1257 ERROR("Message alloc failed (%d)\n", ret);
1258 return ret;
1259 }
1260
1261 req.processor_id = proc_id;
1262 req.host_id = host_id;
1263
1264 ret = ti_sci_do_xfer(&xfer);
1265 if (ret) {
1266 ERROR("Transfer send failed (%d)\n", ret);
1267 return ret;
1268 }
1269
1270 if (!ti_sci_is_response_ack(&resp))
1271 return -ENODEV;
1272
1273 return 0;
1274}
1275
1276/**
1277 * ti_sci_proc_set_boot_cfg() - Set the processor boot configuration flags
1278 *
1279 * @proc_id: Processor ID this request is for
1280 * @config_flags_set: Configuration flags to be set
1281 * @config_flags_clear: Configuration flags to be cleared
1282 *
1283 * Return: 0 if all goes well, else appropriate error message
1284 */
1285int ti_sci_proc_set_boot_cfg(uint8_t proc_id, uint64_t bootvector,
1286 uint32_t config_flags_set,
1287 uint32_t config_flags_clear)
1288{
1289 struct ti_sci_msg_req_set_proc_boot_config req;
1290 struct ti_sci_msg_hdr resp;
1291
1292 struct ti_sci_xfer xfer;
1293 int ret;
1294
1295 ret = ti_sci_setup_one_xfer(TISCI_MSG_SET_PROC_BOOT_CONFIG,
1296 TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1297 &req, sizeof(req),
1298 &resp, sizeof(resp),
1299 &xfer);
1300 if (ret) {
1301 ERROR("Message alloc failed (%d)\n", ret);
1302 return ret;
1303 }
1304
1305 req.processor_id = proc_id;
1306 req.bootvector_low = bootvector & TISCI_ADDR_LOW_MASK;
1307 req.bootvector_high = (bootvector & TISCI_ADDR_HIGH_MASK) >>
1308 TISCI_ADDR_HIGH_SHIFT;
1309 req.config_flags_set = config_flags_set;
1310 req.config_flags_clear = config_flags_clear;
1311
1312 ret = ti_sci_do_xfer(&xfer);
1313 if (ret) {
1314 ERROR("Transfer send failed (%d)\n", ret);
1315 return ret;
1316 }
1317
1318 if (!ti_sci_is_response_ack(&resp))
1319 return -ENODEV;
1320
1321 return 0;
1322}
1323
1324/**
1325 * ti_sci_proc_set_boot_ctrl() - Set the processor boot control flags
1326 *
1327 * @proc_id: Processor ID this request is for
1328 * @control_flags_set: Control flags to be set
1329 * @control_flags_clear: Control flags to be cleared
1330 *
1331 * Return: 0 if all goes well, else appropriate error message
1332 */
1333int ti_sci_proc_set_boot_ctrl(uint8_t proc_id, uint32_t control_flags_set,
1334 uint32_t control_flags_clear)
1335{
1336 struct ti_sci_msg_req_set_proc_boot_ctrl req;
1337 struct ti_sci_msg_hdr resp;
1338
1339 struct ti_sci_xfer xfer;
1340 int ret;
1341
1342 ret = ti_sci_setup_one_xfer(TISCI_MSG_SET_PROC_BOOT_CTRL,
1343 TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1344 &req, sizeof(req),
1345 &resp, sizeof(resp),
1346 &xfer);
1347 if (ret) {
1348 ERROR("Message alloc failed (%d)\n", ret);
1349 return ret;
1350 }
1351
1352 req.processor_id = proc_id;
1353 req.control_flags_set = control_flags_set;
1354 req.control_flags_clear = control_flags_clear;
1355
1356 ret = ti_sci_do_xfer(&xfer);
1357 if (ret) {
1358 ERROR("Transfer send failed (%d)\n", ret);
1359 return ret;
1360 }
1361
1362 if (!ti_sci_is_response_ack(&resp))
1363 return -ENODEV;
1364
1365 return 0;
1366}
1367
1368/**
1369 * ti_sci_proc_auth_boot_image() - Authenticate and load image and then set the
1370 * processor configuration flags
1371 *
1372 * @proc_id: Processor ID this request is for
1373 * @cert_addr: Memory address at which payload image certificate is located
1374 *
1375 * Return: 0 if all goes well, else appropriate error message
1376 */
1377int ti_sci_proc_auth_boot_image(uint8_t proc_id, uint64_t cert_addr)
1378{
1379 struct ti_sci_msg_req_proc_auth_boot_image req;
1380 struct ti_sci_msg_hdr resp;
1381
1382 struct ti_sci_xfer xfer;
1383 int ret;
1384
1385 ret = ti_sci_setup_one_xfer(TISCI_MSG_PROC_AUTH_BOOT_IMIAGE,
1386 TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1387 &req, sizeof(req),
1388 &resp, sizeof(resp),
1389 &xfer);
1390 if (ret) {
1391 ERROR("Message alloc failed (%d)\n", ret);
1392 return ret;
1393 }
1394
1395 req.processor_id = proc_id;
1396 req.cert_addr_low = cert_addr & TISCI_ADDR_LOW_MASK;
1397 req.cert_addr_high = (cert_addr & TISCI_ADDR_HIGH_MASK) >>
1398 TISCI_ADDR_HIGH_SHIFT;
1399
1400 ret = ti_sci_do_xfer(&xfer);
1401 if (ret) {
1402 ERROR("Transfer send failed (%d)\n", ret);
1403 return ret;
1404 }
1405
1406 if (!ti_sci_is_response_ack(&resp))
1407 return -ENODEV;
1408
1409 return 0;
1410}
1411
1412/**
1413 * ti_sci_proc_get_boot_status() - Get the processor boot status
1414 *
1415 * @proc_id: Processor ID this request is for
1416 *
1417 * Return: 0 if all goes well, else appropriate error message
1418 */
1419int ti_sci_proc_get_boot_status(uint8_t proc_id, uint64_t *bv,
1420 uint32_t *cfg_flags,
1421 uint32_t *ctrl_flags,
1422 uint32_t *sts_flags)
1423{
1424 struct ti_sci_msg_req_get_proc_boot_status req;
1425 struct ti_sci_msg_resp_get_proc_boot_status resp;
1426
1427 struct ti_sci_xfer xfer;
1428 int ret;
1429
1430 ret = ti_sci_setup_one_xfer(TISCI_MSG_GET_PROC_BOOT_STATUS,
1431 TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
1432 &req, sizeof(req),
1433 &resp, sizeof(resp),
1434 &xfer);
1435 if (ret) {
1436 ERROR("Message alloc failed (%d)\n", ret);
1437 return ret;
1438 }
1439
1440 req.processor_id = proc_id;
1441
1442 ret = ti_sci_do_xfer(&xfer);
1443 if (ret) {
1444 ERROR("Transfer send failed (%d)\n", ret);
1445 return ret;
1446 }
1447
1448 if (!ti_sci_is_response_ack(&resp))
1449 return -ENODEV;
1450
1451 *bv = (resp.bootvector_low & TISCI_ADDR_LOW_MASK) |
1452 (((uint64_t)resp.bootvector_high << TISCI_ADDR_HIGH_SHIFT) &
1453 TISCI_ADDR_HIGH_MASK);
1454 *cfg_flags = resp.config_flags;
1455 *ctrl_flags = resp.control_flags;
1456 *sts_flags = resp.status_flags;
1457
1458 return 0;
1459}
1460
1461/**
Andrew F. Davisa513b2a2018-05-04 19:06:09 +00001462 * ti_sci_init() - Basic initialization
1463 *
1464 * Return: 0 if all goes well, else appropriate error message
1465 */
1466int ti_sci_init(void)
1467{
1468 struct ti_sci_msg_resp_version rev_info;
1469 int ret;
1470
1471 ret = ti_sci_get_revision(&rev_info);
1472 if (ret) {
1473 ERROR("Unable to communicate with control firmware (%d)\n", ret);
1474 return ret;
1475 }
1476
1477 INFO("SYSFW ABI: %d.%d (firmware rev 0x%04x '%s')\n",
1478 rev_info.abi_major, rev_info.abi_minor,
1479 rev_info.firmware_revision,
1480 rev_info.firmware_description);
1481
1482 return 0;
1483}