xref: /openbmc/u-boot/drivers/firmware/ti_sci.c (revision 32cd2512)
1*32cd2512SLokesh Vutla // SPDX-License-Identifier: GPL-2.0+
2*32cd2512SLokesh Vutla /*
3*32cd2512SLokesh Vutla  * Texas Instruments System Control Interface Protocol Driver
4*32cd2512SLokesh Vutla  * Based on drivers/firmware/ti_sci.c from Linux.
5*32cd2512SLokesh Vutla  *
6*32cd2512SLokesh Vutla  * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
7*32cd2512SLokesh Vutla  *	Lokesh Vutla <lokeshvutla@ti.com>
8*32cd2512SLokesh Vutla  */
9*32cd2512SLokesh Vutla 
10*32cd2512SLokesh Vutla #include <common.h>
11*32cd2512SLokesh Vutla #include <dm.h>
12*32cd2512SLokesh Vutla #include <errno.h>
13*32cd2512SLokesh Vutla #include <mailbox.h>
14*32cd2512SLokesh Vutla #include <dm/device.h>
15*32cd2512SLokesh Vutla #include <linux/err.h>
16*32cd2512SLokesh Vutla #include <linux/soc/ti/k3-sec-proxy.h>
17*32cd2512SLokesh Vutla #include <linux/soc/ti/ti_sci_protocol.h>
18*32cd2512SLokesh Vutla 
19*32cd2512SLokesh Vutla #include "ti_sci.h"
20*32cd2512SLokesh Vutla 
21*32cd2512SLokesh Vutla /* List of all TI SCI devices active in system */
22*32cd2512SLokesh Vutla static LIST_HEAD(ti_sci_list);
23*32cd2512SLokesh Vutla 
24*32cd2512SLokesh Vutla /**
25*32cd2512SLokesh Vutla  * struct ti_sci_xfer - Structure representing a message flow
26*32cd2512SLokesh Vutla  * @tx_message:	Transmit message
27*32cd2512SLokesh Vutla  * @rx_len:	Receive message length
28*32cd2512SLokesh Vutla  */
29*32cd2512SLokesh Vutla struct ti_sci_xfer {
30*32cd2512SLokesh Vutla 	struct k3_sec_proxy_msg tx_message;
31*32cd2512SLokesh Vutla 	u8 rx_len;
32*32cd2512SLokesh Vutla };
33*32cd2512SLokesh Vutla 
34*32cd2512SLokesh Vutla /**
35*32cd2512SLokesh Vutla  * struct ti_sci_desc - Description of SoC integration
36*32cd2512SLokesh Vutla  * @host_id:		Host identifier representing the compute entity
37*32cd2512SLokesh Vutla  * @max_rx_timeout_us:	Timeout for communication with SoC (in Microseconds)
38*32cd2512SLokesh Vutla  * @max_msg_size:	Maximum size of data per message that can be handled.
39*32cd2512SLokesh Vutla  */
40*32cd2512SLokesh Vutla struct ti_sci_desc {
41*32cd2512SLokesh Vutla 	u8 host_id;
42*32cd2512SLokesh Vutla 	int max_rx_timeout_us;
43*32cd2512SLokesh Vutla 	int max_msg_size;
44*32cd2512SLokesh Vutla };
45*32cd2512SLokesh Vutla 
46*32cd2512SLokesh Vutla /**
47*32cd2512SLokesh Vutla  * struct ti_sci_info - Structure representing a TI SCI instance
48*32cd2512SLokesh Vutla  * @dev:	Device pointer
49*32cd2512SLokesh Vutla  * @desc:	SoC description for this instance
50*32cd2512SLokesh Vutla  * @handle:	Instance of TI SCI handle to send to clients.
51*32cd2512SLokesh Vutla  * @chan_tx:	Transmit mailbox channel
52*32cd2512SLokesh Vutla  * @chan_rx:	Receive mailbox channel
53*32cd2512SLokesh Vutla  * @xfer:	xfer info
54*32cd2512SLokesh Vutla  * @list:	list head
55*32cd2512SLokesh Vutla  * @is_secure:	Determines if the communication is through secure threads.
56*32cd2512SLokesh Vutla  * @host_id:	Host identifier representing the compute entity
57*32cd2512SLokesh Vutla  * @seq:	Seq id used for verification for tx and rx message.
58*32cd2512SLokesh Vutla  */
59*32cd2512SLokesh Vutla struct ti_sci_info {
60*32cd2512SLokesh Vutla 	struct udevice *dev;
61*32cd2512SLokesh Vutla 	const struct ti_sci_desc *desc;
62*32cd2512SLokesh Vutla 	struct ti_sci_handle handle;
63*32cd2512SLokesh Vutla 	struct mbox_chan chan_tx;
64*32cd2512SLokesh Vutla 	struct mbox_chan chan_rx;
65*32cd2512SLokesh Vutla 	struct mbox_chan chan_notify;
66*32cd2512SLokesh Vutla 	struct ti_sci_xfer xfer;
67*32cd2512SLokesh Vutla 	struct list_head list;
68*32cd2512SLokesh Vutla 	bool is_secure;
69*32cd2512SLokesh Vutla 	u8 host_id;
70*32cd2512SLokesh Vutla 	u8 seq;
71*32cd2512SLokesh Vutla };
72*32cd2512SLokesh Vutla 
73*32cd2512SLokesh Vutla #define handle_to_ti_sci_info(h) container_of(h, struct ti_sci_info, handle)
74*32cd2512SLokesh Vutla 
75*32cd2512SLokesh Vutla /**
76*32cd2512SLokesh Vutla  * ti_sci_setup_one_xfer() - Setup one message type
77*32cd2512SLokesh Vutla  * @info:	Pointer to SCI entity information
78*32cd2512SLokesh Vutla  * @msg_type:	Message type
79*32cd2512SLokesh Vutla  * @msg_flags:	Flag to set for the message
80*32cd2512SLokesh Vutla  * @buf:	Buffer to be send to mailbox channel
81*32cd2512SLokesh Vutla  * @tx_message_size: transmit message size
82*32cd2512SLokesh Vutla  * @rx_message_size: receive message size
83*32cd2512SLokesh Vutla  *
84*32cd2512SLokesh Vutla  * Helper function which is used by various command functions that are
85*32cd2512SLokesh Vutla  * exposed to clients of this driver for allocating a message traffic event.
86*32cd2512SLokesh Vutla  *
87*32cd2512SLokesh Vutla  * Return: Corresponding ti_sci_xfer pointer if all went fine,
88*32cd2512SLokesh Vutla  *	   else appropriate error pointer.
89*32cd2512SLokesh Vutla  */
90*32cd2512SLokesh Vutla static struct ti_sci_xfer *ti_sci_setup_one_xfer(struct ti_sci_info *info,
91*32cd2512SLokesh Vutla 						 u16 msg_type, u32 msg_flags,
92*32cd2512SLokesh Vutla 						 u32 *buf,
93*32cd2512SLokesh Vutla 						 size_t tx_message_size,
94*32cd2512SLokesh Vutla 						 size_t rx_message_size)
95*32cd2512SLokesh Vutla {
96*32cd2512SLokesh Vutla 	struct ti_sci_xfer *xfer = &info->xfer;
97*32cd2512SLokesh Vutla 	struct ti_sci_msg_hdr *hdr;
98*32cd2512SLokesh Vutla 
99*32cd2512SLokesh Vutla 	/* Ensure we have sane transfer sizes */
100*32cd2512SLokesh Vutla 	if (rx_message_size > info->desc->max_msg_size ||
101*32cd2512SLokesh Vutla 	    tx_message_size > info->desc->max_msg_size ||
102*32cd2512SLokesh Vutla 	    rx_message_size < sizeof(*hdr) || tx_message_size < sizeof(*hdr))
103*32cd2512SLokesh Vutla 		return ERR_PTR(-ERANGE);
104*32cd2512SLokesh Vutla 
105*32cd2512SLokesh Vutla 	info->seq = ~info->seq;
106*32cd2512SLokesh Vutla 	xfer->tx_message.buf = buf;
107*32cd2512SLokesh Vutla 	xfer->tx_message.len = tx_message_size;
108*32cd2512SLokesh Vutla 	xfer->rx_len = (u8)rx_message_size;
109*32cd2512SLokesh Vutla 
110*32cd2512SLokesh Vutla 	hdr = (struct ti_sci_msg_hdr *)buf;
111*32cd2512SLokesh Vutla 	hdr->seq = info->seq;
112*32cd2512SLokesh Vutla 	hdr->type = msg_type;
113*32cd2512SLokesh Vutla 	hdr->host = info->host_id;
114*32cd2512SLokesh Vutla 	hdr->flags = msg_flags;
115*32cd2512SLokesh Vutla 
116*32cd2512SLokesh Vutla 	return xfer;
117*32cd2512SLokesh Vutla }
118*32cd2512SLokesh Vutla 
119*32cd2512SLokesh Vutla /**
120*32cd2512SLokesh Vutla  * ti_sci_get_response() - Receive response from mailbox channel
121*32cd2512SLokesh Vutla  * @info:	Pointer to SCI entity information
122*32cd2512SLokesh Vutla  * @xfer:	Transfer to initiate and wait for response
123*32cd2512SLokesh Vutla  * @chan:	Channel to receive the response
124*32cd2512SLokesh Vutla  *
125*32cd2512SLokesh Vutla  * Return: -ETIMEDOUT in case of no response, if transmit error,
126*32cd2512SLokesh Vutla  *	   return corresponding error, else if all goes well,
127*32cd2512SLokesh Vutla  *	   return 0.
128*32cd2512SLokesh Vutla  */
129*32cd2512SLokesh Vutla static inline int ti_sci_get_response(struct ti_sci_info *info,
130*32cd2512SLokesh Vutla 				      struct ti_sci_xfer *xfer,
131*32cd2512SLokesh Vutla 				      struct mbox_chan *chan)
132*32cd2512SLokesh Vutla {
133*32cd2512SLokesh Vutla 	struct k3_sec_proxy_msg *msg = &xfer->tx_message;
134*32cd2512SLokesh Vutla 	struct ti_sci_secure_msg_hdr *secure_hdr;
135*32cd2512SLokesh Vutla 	struct ti_sci_msg_hdr *hdr;
136*32cd2512SLokesh Vutla 	int ret;
137*32cd2512SLokesh Vutla 
138*32cd2512SLokesh Vutla 	/* Receive the response */
139*32cd2512SLokesh Vutla 	ret = mbox_recv(chan, msg, info->desc->max_rx_timeout_us);
140*32cd2512SLokesh Vutla 	if (ret) {
141*32cd2512SLokesh Vutla 		dev_err(info->dev, "%s: Message receive failed. ret = %d\n",
142*32cd2512SLokesh Vutla 			__func__, ret);
143*32cd2512SLokesh Vutla 		return ret;
144*32cd2512SLokesh Vutla 	}
145*32cd2512SLokesh Vutla 
146*32cd2512SLokesh Vutla 	/* ToDo: Verify checksum */
147*32cd2512SLokesh Vutla 	if (info->is_secure) {
148*32cd2512SLokesh Vutla 		secure_hdr = (struct ti_sci_secure_msg_hdr *)msg->buf;
149*32cd2512SLokesh Vutla 		msg->buf = (u32 *)((void *)msg->buf + sizeof(*secure_hdr));
150*32cd2512SLokesh Vutla 	}
151*32cd2512SLokesh Vutla 
152*32cd2512SLokesh Vutla 	/* msg is updated by mailbox driver */
153*32cd2512SLokesh Vutla 	hdr = (struct ti_sci_msg_hdr *)msg->buf;
154*32cd2512SLokesh Vutla 
155*32cd2512SLokesh Vutla 	/* Sanity check for message response */
156*32cd2512SLokesh Vutla 	if (hdr->seq != info->seq) {
157*32cd2512SLokesh Vutla 		dev_dbg(info->dev, "%s: Message for %d is not expected\n",
158*32cd2512SLokesh Vutla 			__func__, hdr->seq);
159*32cd2512SLokesh Vutla 		return ret;
160*32cd2512SLokesh Vutla 	}
161*32cd2512SLokesh Vutla 
162*32cd2512SLokesh Vutla 	if (msg->len > info->desc->max_msg_size) {
163*32cd2512SLokesh Vutla 		dev_err(info->dev, "%s: Unable to handle %zu xfer (max %d)\n",
164*32cd2512SLokesh Vutla 			__func__, msg->len, info->desc->max_msg_size);
165*32cd2512SLokesh Vutla 		return -EINVAL;
166*32cd2512SLokesh Vutla 	}
167*32cd2512SLokesh Vutla 
168*32cd2512SLokesh Vutla 	if (msg->len < xfer->rx_len) {
169*32cd2512SLokesh Vutla 		dev_err(info->dev, "%s: Recv xfer %zu < expected %d length\n",
170*32cd2512SLokesh Vutla 			__func__, msg->len, xfer->rx_len);
171*32cd2512SLokesh Vutla 	}
172*32cd2512SLokesh Vutla 
173*32cd2512SLokesh Vutla 	return ret;
174*32cd2512SLokesh Vutla }
175*32cd2512SLokesh Vutla 
176*32cd2512SLokesh Vutla /**
177*32cd2512SLokesh Vutla  * ti_sci_do_xfer() - Do one transfer
178*32cd2512SLokesh Vutla  * @info:	Pointer to SCI entity information
179*32cd2512SLokesh Vutla  * @xfer:	Transfer to initiate and wait for response
180*32cd2512SLokesh Vutla  *
181*32cd2512SLokesh Vutla  * Return: 0 if all went fine, else return appropriate error.
182*32cd2512SLokesh Vutla  */
183*32cd2512SLokesh Vutla static inline int ti_sci_do_xfer(struct ti_sci_info *info,
184*32cd2512SLokesh Vutla 				 struct ti_sci_xfer *xfer)
185*32cd2512SLokesh Vutla {
186*32cd2512SLokesh Vutla 	struct k3_sec_proxy_msg *msg = &xfer->tx_message;
187*32cd2512SLokesh Vutla 	u8 secure_buf[info->desc->max_msg_size];
188*32cd2512SLokesh Vutla 	struct ti_sci_secure_msg_hdr secure_hdr;
189*32cd2512SLokesh Vutla 	int ret;
190*32cd2512SLokesh Vutla 
191*32cd2512SLokesh Vutla 	if (info->is_secure) {
192*32cd2512SLokesh Vutla 		/* ToDo: get checksum of the entire message */
193*32cd2512SLokesh Vutla 		secure_hdr.checksum = 0;
194*32cd2512SLokesh Vutla 		secure_hdr.reserved = 0;
195*32cd2512SLokesh Vutla 		memcpy(&secure_buf[sizeof(secure_hdr)], xfer->tx_message.buf,
196*32cd2512SLokesh Vutla 		       xfer->tx_message.len);
197*32cd2512SLokesh Vutla 
198*32cd2512SLokesh Vutla 		xfer->tx_message.buf = (u32 *)secure_buf;
199*32cd2512SLokesh Vutla 		xfer->tx_message.len += sizeof(secure_hdr);
200*32cd2512SLokesh Vutla 		xfer->rx_len += sizeof(secure_hdr);
201*32cd2512SLokesh Vutla 	}
202*32cd2512SLokesh Vutla 
203*32cd2512SLokesh Vutla 	/* Send the message */
204*32cd2512SLokesh Vutla 	ret = mbox_send(&info->chan_tx, msg);
205*32cd2512SLokesh Vutla 	if (ret) {
206*32cd2512SLokesh Vutla 		dev_err(info->dev, "%s: Message sending failed. ret = %d\n",
207*32cd2512SLokesh Vutla 			__func__, ret);
208*32cd2512SLokesh Vutla 		return ret;
209*32cd2512SLokesh Vutla 	}
210*32cd2512SLokesh Vutla 
211*32cd2512SLokesh Vutla 	return ti_sci_get_response(info, xfer, &info->chan_rx);
212*32cd2512SLokesh Vutla }
213*32cd2512SLokesh Vutla 
214*32cd2512SLokesh Vutla /**
215*32cd2512SLokesh Vutla  * ti_sci_cmd_get_revision() - command to get the revision of the SCI entity
216*32cd2512SLokesh Vutla  * @handle:	pointer to TI SCI handle
217*32cd2512SLokesh Vutla  *
218*32cd2512SLokesh Vutla  * Updates the SCI information in the internal data structure.
219*32cd2512SLokesh Vutla  *
220*32cd2512SLokesh Vutla  * Return: 0 if all went fine, else return appropriate error.
221*32cd2512SLokesh Vutla  */
222*32cd2512SLokesh Vutla static int ti_sci_cmd_get_revision(struct ti_sci_handle *handle)
223*32cd2512SLokesh Vutla {
224*32cd2512SLokesh Vutla 	struct ti_sci_msg_resp_version *rev_info;
225*32cd2512SLokesh Vutla 	struct ti_sci_version_info *ver;
226*32cd2512SLokesh Vutla 	struct ti_sci_msg_hdr hdr;
227*32cd2512SLokesh Vutla 	struct ti_sci_info *info;
228*32cd2512SLokesh Vutla 	struct ti_sci_xfer *xfer;
229*32cd2512SLokesh Vutla 	int ret;
230*32cd2512SLokesh Vutla 
231*32cd2512SLokesh Vutla 	if (IS_ERR(handle))
232*32cd2512SLokesh Vutla 		return PTR_ERR(handle);
233*32cd2512SLokesh Vutla 	if (!handle)
234*32cd2512SLokesh Vutla 		return -EINVAL;
235*32cd2512SLokesh Vutla 
236*32cd2512SLokesh Vutla 	info = handle_to_ti_sci_info(handle);
237*32cd2512SLokesh Vutla 
238*32cd2512SLokesh Vutla 	xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_VERSION, 0x0,
239*32cd2512SLokesh Vutla 				     (u32 *)&hdr, sizeof(struct ti_sci_msg_hdr),
240*32cd2512SLokesh Vutla 				     sizeof(*rev_info));
241*32cd2512SLokesh Vutla 	if (IS_ERR(xfer)) {
242*32cd2512SLokesh Vutla 		ret = PTR_ERR(xfer);
243*32cd2512SLokesh Vutla 		dev_err(info->dev, "Message alloc failed(%d)\n", ret);
244*32cd2512SLokesh Vutla 		return ret;
245*32cd2512SLokesh Vutla 	}
246*32cd2512SLokesh Vutla 
247*32cd2512SLokesh Vutla 	ret = ti_sci_do_xfer(info, xfer);
248*32cd2512SLokesh Vutla 	if (ret) {
249*32cd2512SLokesh Vutla 		dev_err(info->dev, "Mbox communication fail %d\n", ret);
250*32cd2512SLokesh Vutla 		return ret;
251*32cd2512SLokesh Vutla 	}
252*32cd2512SLokesh Vutla 
253*32cd2512SLokesh Vutla 	rev_info = (struct ti_sci_msg_resp_version *)xfer->tx_message.buf;
254*32cd2512SLokesh Vutla 
255*32cd2512SLokesh Vutla 	ver = &handle->version;
256*32cd2512SLokesh Vutla 	ver->abi_major = rev_info->abi_major;
257*32cd2512SLokesh Vutla 	ver->abi_minor = rev_info->abi_minor;
258*32cd2512SLokesh Vutla 	ver->firmware_revision = rev_info->firmware_revision;
259*32cd2512SLokesh Vutla 	strncpy(ver->firmware_description, rev_info->firmware_description,
260*32cd2512SLokesh Vutla 		sizeof(ver->firmware_description));
261*32cd2512SLokesh Vutla 
262*32cd2512SLokesh Vutla 	return 0;
263*32cd2512SLokesh Vutla }
264*32cd2512SLokesh Vutla 
265*32cd2512SLokesh Vutla /**
266*32cd2512SLokesh Vutla  * ti_sci_is_response_ack() - Generic ACK/NACK message checkup
267*32cd2512SLokesh Vutla  * @r:	pointer to response buffer
268*32cd2512SLokesh Vutla  *
269*32cd2512SLokesh Vutla  * Return: true if the response was an ACK, else returns false.
270*32cd2512SLokesh Vutla  */
271*32cd2512SLokesh Vutla static inline bool ti_sci_is_response_ack(void *r)
272*32cd2512SLokesh Vutla {
273*32cd2512SLokesh Vutla 	struct ti_sci_msg_hdr *hdr = r;
274*32cd2512SLokesh Vutla 
275*32cd2512SLokesh Vutla 	return hdr->flags & TI_SCI_FLAG_RESP_GENERIC_ACK ? true : false;
276*32cd2512SLokesh Vutla }
277*32cd2512SLokesh Vutla 
278*32cd2512SLokesh Vutla /**
279*32cd2512SLokesh Vutla  * ti_sci_get_handle_from_sysfw() - Get the TI SCI handle of the SYSFW
280*32cd2512SLokesh Vutla  * @dev:	Pointer to the SYSFW device
281*32cd2512SLokesh Vutla  *
282*32cd2512SLokesh Vutla  * Return: pointer to handle if successful, else EINVAL if invalid conditions
283*32cd2512SLokesh Vutla  *         are encountered.
284*32cd2512SLokesh Vutla  */
285*32cd2512SLokesh Vutla const
286*32cd2512SLokesh Vutla struct ti_sci_handle *ti_sci_get_handle_from_sysfw(struct udevice *sci_dev)
287*32cd2512SLokesh Vutla {
288*32cd2512SLokesh Vutla 	if (!sci_dev)
289*32cd2512SLokesh Vutla 		return ERR_PTR(-EINVAL);
290*32cd2512SLokesh Vutla 
291*32cd2512SLokesh Vutla 	struct ti_sci_info *info = dev_get_priv(sci_dev);
292*32cd2512SLokesh Vutla 
293*32cd2512SLokesh Vutla 	if (!info)
294*32cd2512SLokesh Vutla 		return ERR_PTR(-EINVAL);
295*32cd2512SLokesh Vutla 
296*32cd2512SLokesh Vutla 	struct ti_sci_handle *handle = &info->handle;
297*32cd2512SLokesh Vutla 
298*32cd2512SLokesh Vutla 	if (!handle)
299*32cd2512SLokesh Vutla 		return ERR_PTR(-EINVAL);
300*32cd2512SLokesh Vutla 
301*32cd2512SLokesh Vutla 	return handle;
302*32cd2512SLokesh Vutla }
303*32cd2512SLokesh Vutla 
304*32cd2512SLokesh Vutla /**
305*32cd2512SLokesh Vutla  * ti_sci_get_handle() - Get the TI SCI handle for a device
306*32cd2512SLokesh Vutla  * @dev:	Pointer to device for which we want SCI handle
307*32cd2512SLokesh Vutla  *
308*32cd2512SLokesh Vutla  * Return: pointer to handle if successful, else EINVAL if invalid conditions
309*32cd2512SLokesh Vutla  *         are encountered.
310*32cd2512SLokesh Vutla  */
311*32cd2512SLokesh Vutla const struct ti_sci_handle *ti_sci_get_handle(struct udevice *dev)
312*32cd2512SLokesh Vutla {
313*32cd2512SLokesh Vutla 	if (!dev)
314*32cd2512SLokesh Vutla 		return ERR_PTR(-EINVAL);
315*32cd2512SLokesh Vutla 
316*32cd2512SLokesh Vutla 	struct udevice *sci_dev = dev_get_parent(dev);
317*32cd2512SLokesh Vutla 
318*32cd2512SLokesh Vutla 	return ti_sci_get_handle_from_sysfw(sci_dev);
319*32cd2512SLokesh Vutla }
320*32cd2512SLokesh Vutla 
321*32cd2512SLokesh Vutla /**
322*32cd2512SLokesh Vutla  * ti_sci_get_by_phandle() - Get the TI SCI handle using DT phandle
323*32cd2512SLokesh Vutla  * @dev:	device node
324*32cd2512SLokesh Vutla  * @propname:	property name containing phandle on TISCI node
325*32cd2512SLokesh Vutla  *
326*32cd2512SLokesh Vutla  * Return: pointer to handle if successful, else appropriate error value.
327*32cd2512SLokesh Vutla  */
328*32cd2512SLokesh Vutla const struct ti_sci_handle *ti_sci_get_by_phandle(struct udevice *dev,
329*32cd2512SLokesh Vutla 						  const char *property)
330*32cd2512SLokesh Vutla {
331*32cd2512SLokesh Vutla 	struct ti_sci_info *entry, *info = NULL;
332*32cd2512SLokesh Vutla 	u32 phandle, err;
333*32cd2512SLokesh Vutla 	ofnode node;
334*32cd2512SLokesh Vutla 
335*32cd2512SLokesh Vutla 	err = ofnode_read_u32(dev_ofnode(dev), property, &phandle);
336*32cd2512SLokesh Vutla 	if (err)
337*32cd2512SLokesh Vutla 		return ERR_PTR(err);
338*32cd2512SLokesh Vutla 
339*32cd2512SLokesh Vutla 	node = ofnode_get_by_phandle(phandle);
340*32cd2512SLokesh Vutla 	if (!ofnode_valid(node))
341*32cd2512SLokesh Vutla 		return ERR_PTR(-EINVAL);
342*32cd2512SLokesh Vutla 
343*32cd2512SLokesh Vutla 	list_for_each_entry(entry, &ti_sci_list, list)
344*32cd2512SLokesh Vutla 		if (ofnode_equal(dev_ofnode(entry->dev), node)) {
345*32cd2512SLokesh Vutla 			info = entry;
346*32cd2512SLokesh Vutla 			break;
347*32cd2512SLokesh Vutla 		}
348*32cd2512SLokesh Vutla 
349*32cd2512SLokesh Vutla 	if (!info)
350*32cd2512SLokesh Vutla 		return ERR_PTR(-ENODEV);
351*32cd2512SLokesh Vutla 
352*32cd2512SLokesh Vutla 	return &info->handle;
353*32cd2512SLokesh Vutla }
354*32cd2512SLokesh Vutla 
355*32cd2512SLokesh Vutla /**
356*32cd2512SLokesh Vutla  * ti_sci_of_to_info() - generate private data from device tree
357*32cd2512SLokesh Vutla  * @dev:	corresponding system controller interface device
358*32cd2512SLokesh Vutla  * @info:	pointer to driver specific private data
359*32cd2512SLokesh Vutla  *
360*32cd2512SLokesh Vutla  * Return: 0 if all goes good, else appropriate error message.
361*32cd2512SLokesh Vutla  */
362*32cd2512SLokesh Vutla static int ti_sci_of_to_info(struct udevice *dev, struct ti_sci_info *info)
363*32cd2512SLokesh Vutla {
364*32cd2512SLokesh Vutla 	int ret;
365*32cd2512SLokesh Vutla 
366*32cd2512SLokesh Vutla 	ret = mbox_get_by_name(dev, "tx", &info->chan_tx);
367*32cd2512SLokesh Vutla 	if (ret) {
368*32cd2512SLokesh Vutla 		dev_err(dev, "%s: Acquiring Tx channel failed. ret = %d\n",
369*32cd2512SLokesh Vutla 			__func__, ret);
370*32cd2512SLokesh Vutla 		return ret;
371*32cd2512SLokesh Vutla 	}
372*32cd2512SLokesh Vutla 
373*32cd2512SLokesh Vutla 	ret = mbox_get_by_name(dev, "rx", &info->chan_rx);
374*32cd2512SLokesh Vutla 	if (ret) {
375*32cd2512SLokesh Vutla 		dev_err(dev, "%s: Acquiring Rx channel failed. ret = %d\n",
376*32cd2512SLokesh Vutla 			__func__, ret);
377*32cd2512SLokesh Vutla 		return ret;
378*32cd2512SLokesh Vutla 	}
379*32cd2512SLokesh Vutla 
380*32cd2512SLokesh Vutla 	/* Notify channel is optional. Enable only if populated */
381*32cd2512SLokesh Vutla 	ret = mbox_get_by_name(dev, "notify", &info->chan_notify);
382*32cd2512SLokesh Vutla 	if (ret) {
383*32cd2512SLokesh Vutla 		dev_dbg(dev, "%s: Acquiring notify channel failed. ret = %d\n",
384*32cd2512SLokesh Vutla 			__func__, ret);
385*32cd2512SLokesh Vutla 	}
386*32cd2512SLokesh Vutla 
387*32cd2512SLokesh Vutla 	info->host_id = dev_read_u32_default(dev, "ti,host-id",
388*32cd2512SLokesh Vutla 					     info->desc->host_id);
389*32cd2512SLokesh Vutla 
390*32cd2512SLokesh Vutla 	info->is_secure = dev_read_bool(dev, "ti,secure-host");
391*32cd2512SLokesh Vutla 
392*32cd2512SLokesh Vutla 	return 0;
393*32cd2512SLokesh Vutla }
394*32cd2512SLokesh Vutla 
395*32cd2512SLokesh Vutla /**
396*32cd2512SLokesh Vutla  * ti_sci_probe() - Basic probe
397*32cd2512SLokesh Vutla  * @dev:	corresponding system controller interface device
398*32cd2512SLokesh Vutla  *
399*32cd2512SLokesh Vutla  * Return: 0 if all goes good, else appropriate error message.
400*32cd2512SLokesh Vutla  */
401*32cd2512SLokesh Vutla static int ti_sci_probe(struct udevice *dev)
402*32cd2512SLokesh Vutla {
403*32cd2512SLokesh Vutla 	struct ti_sci_info *info;
404*32cd2512SLokesh Vutla 	int ret;
405*32cd2512SLokesh Vutla 
406*32cd2512SLokesh Vutla 	debug("%s(dev=%p)\n", __func__, dev);
407*32cd2512SLokesh Vutla 
408*32cd2512SLokesh Vutla 	info = dev_get_priv(dev);
409*32cd2512SLokesh Vutla 	info->desc = (void *)dev_get_driver_data(dev);
410*32cd2512SLokesh Vutla 
411*32cd2512SLokesh Vutla 	ret = ti_sci_of_to_info(dev, info);
412*32cd2512SLokesh Vutla 	if (ret) {
413*32cd2512SLokesh Vutla 		dev_err(dev, "%s: Probe failed with error %d\n", __func__, ret);
414*32cd2512SLokesh Vutla 		return ret;
415*32cd2512SLokesh Vutla 	}
416*32cd2512SLokesh Vutla 
417*32cd2512SLokesh Vutla 	info->dev = dev;
418*32cd2512SLokesh Vutla 	info->seq = 0xA;
419*32cd2512SLokesh Vutla 
420*32cd2512SLokesh Vutla 	list_add_tail(&info->list, &ti_sci_list);
421*32cd2512SLokesh Vutla 
422*32cd2512SLokesh Vutla 	ret = ti_sci_cmd_get_revision(&info->handle);
423*32cd2512SLokesh Vutla 
424*32cd2512SLokesh Vutla 	return ret;
425*32cd2512SLokesh Vutla }
426*32cd2512SLokesh Vutla 
427*32cd2512SLokesh Vutla /* Description for AM654 */
428*32cd2512SLokesh Vutla static const struct ti_sci_desc ti_sci_sysfw_am654_desc = {
429*32cd2512SLokesh Vutla 	.host_id = 4,
430*32cd2512SLokesh Vutla 	.max_rx_timeout_us = 1000000,
431*32cd2512SLokesh Vutla 	.max_msg_size = 60,
432*32cd2512SLokesh Vutla };
433*32cd2512SLokesh Vutla 
434*32cd2512SLokesh Vutla static const struct udevice_id ti_sci_ids[] = {
435*32cd2512SLokesh Vutla 	{
436*32cd2512SLokesh Vutla 		.compatible = "ti,k2g-sci",
437*32cd2512SLokesh Vutla 		.data = (ulong)&ti_sci_sysfw_am654_desc
438*32cd2512SLokesh Vutla 	},
439*32cd2512SLokesh Vutla 	{ /* Sentinel */ },
440*32cd2512SLokesh Vutla };
441*32cd2512SLokesh Vutla 
442*32cd2512SLokesh Vutla U_BOOT_DRIVER(ti_sci) = {
443*32cd2512SLokesh Vutla 	.name = "ti_sci",
444*32cd2512SLokesh Vutla 	.id = UCLASS_FIRMWARE,
445*32cd2512SLokesh Vutla 	.of_match = ti_sci_ids,
446*32cd2512SLokesh Vutla 	.probe = ti_sci_probe,
447*32cd2512SLokesh Vutla 	.priv_auto_alloc_size = sizeof(struct ti_sci_info),
448*32cd2512SLokesh Vutla };
449